assuremind 1.3.0 → 1.4.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/dist/cli/index.js CHANGED
@@ -1,29 +1,29 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var qg=Object.create;var un=Object.defineProperty;var Xg=Object.getOwnPropertyDescriptor;var Kg=Object.getOwnPropertyNames;var Wg=Object.getPrototypeOf,Jg=Object.prototype.hasOwnProperty;var w=(r,e)=>()=>(r&&(e=r(r=0)),e);var xt=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),Q=(r,e)=>{for(var t in e)un(r,t,{get:e[t],enumerable:!0})},rc=(r,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Kg(e))!Jg.call(r,n)&&n!==t&&un(r,n,{get:()=>e[n],enumerable:!(s=Xg(e,n))||s.enumerable});return r};var x=(r,e,t)=>(t=r!=null?qg(Wg(r)):{},rc(e||!r||!r.__esModule?un(t,"default",{value:r,enumerable:!0}):t,r)),Qe=r=>rc(un({},"__esModule",{value:!0}),r);var Yg,y,p=w(()=>{"use strict";Yg=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,y=Yg()});function Ie(r){process.stdout.write(`${O.success("\u2713")} ${r}
3
- `)}function W(r){process.stderr.write(`${O.error("\u2717")} ${r}
4
- `)}function He(r){process.stdout.write(`${O.warn("\u26A0")} ${r}
5
- `)}function V(r){process.stdout.write(`${O.info("\u2139")} ${r}
6
- `)}function dn(r){process.stdout.write(`${O.dim("\u2013")} ${O.dim(r)}
7
- `)}function jt(r){let e=Math.max(...r.map(s=>s.length))+4,t=O.accent("\u2500".repeat(e));process.stdout.write(`
2
+ "use strict";var wf=Object.create;var hn=Object.defineProperty;var bf=Object.getOwnPropertyDescriptor;var vf=Object.getOwnPropertyNames;var xf=Object.getPrototypeOf,Sf=Object.prototype.hasOwnProperty;var b=(r,e)=>()=>(r&&(e=r(r=0)),e);var Et=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),Q=(r,e)=>{for(var t in e)hn(r,t,{get:e[t],enumerable:!0})},fc=(r,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of vf(e))!Sf.call(r,n)&&n!==t&&hn(r,n,{get:()=>e[n],enumerable:!(s=bf(e,n))||s.enumerable});return r};var x=(r,e,t)=>(t=r!=null?wf(xf(r)):{},fc(e||!r||!r.__esModule?hn(t,"default",{value:r,enumerable:!0}):t,r)),et=r=>fc(hn({},"__esModule",{value:!0}),r);var Cf,y,m=b(()=>{"use strict";Cf=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,y=Cf()});function Pe(r){process.stdout.write(`${L.success("\u2713")} ${r}
3
+ `)}function W(r){process.stderr.write(`${L.error("\u2717")} ${r}
4
+ `)}function Ge(r){process.stdout.write(`${L.warn("\u26A0")} ${r}
5
+ `)}function V(r){process.stdout.write(`${L.info("\u2139")} ${r}
6
+ `)}function yn(r){process.stdout.write(`${L.dim("\u2013")} ${L.dim(r)}
7
+ `)}function Ht(r){let e=Math.max(...r.map(s=>s.length))+4,t=L.accent("\u2500".repeat(e));process.stdout.write(`
8
8
  ${t}
9
9
  `);for(let s of r)process.stdout.write(` ${s}
10
10
  `);process.stdout.write(`${t}
11
11
 
12
- `)}function St(r){return(0,sc.default)({text:r,color:"cyan"})}function Ct(r){let e=r instanceof Error?r.message:String(r);W(e),process.exit(1)}var nr,sc,O,Bt=w(()=>{"use strict";p();nr=x(require("chalk")),sc=x(require("ora")),O={success:nr.default.green,error:nr.default.red,warn:nr.default.yellow,info:nr.default.cyan,dim:nr.default.dim,bold:nr.default.bold,accent:nr.default.hex("#00adf7")}});var mc={};Q(mc,{AutotestConfigSchema:()=>Er,BrowserNameSchema:()=>Vi,DEFAULT_CONFIG:()=>zi,EnvironmentProfileSchema:()=>pc,EnvironmentSchema:()=>Gi,EnvironmentUrlsSchema:()=>cc,HealingConfigSchema:()=>lc,PageLoadStrategySchema:()=>oc,ReportingConfigSchema:()=>uc,ScreenshotModeSchema:()=>nc,TraceModeSchema:()=>ac,VideoModeSchema:()=>ic,ViewportSchema:()=>dc});var A,nc,ic,ac,Vi,oc,Gi,cc,lc,uc,dc,pc,Er,zi,pn=w(()=>{"use strict";p();A=require("zod"),nc=A.z.enum(["off","on","only-on-failure"]),ic=A.z.enum(["off","on","on-first-retry","retain-on-failure"]),ac=A.z.enum(["off","on","on-first-retry","retain-on-failure"]),Vi=A.z.enum(["chromium","firefox","webkit"]),oc=A.z.enum(["commit","domcontentloaded","load","networkidle"]),Gi=A.z.enum(["dev","stage","test","prod"]),cc=A.z.object({dev:A.z.string().url().or(A.z.literal("")).default(""),stage:A.z.string().url().or(A.z.literal("")).default(""),test:A.z.string().url().or(A.z.literal("")).default(""),prod:A.z.string().url().or(A.z.literal("")).default("")}),lc=A.z.object({enabled:A.z.boolean(),maxLevel:A.z.number().int().min(1).max(5),dailyBudget:A.z.number().positive(),autoPR:A.z.boolean()}),uc=A.z.object({allure:A.z.boolean(),html:A.z.boolean(),json:A.z.boolean()}),dc=A.z.object({width:A.z.number().int().positive(),height:A.z.number().int().positive()}),pc=A.z.object({name:A.z.string().min(1),environment:Gi,baseUrl:A.z.string().url(),browsers:A.z.array(Vi).min(1),headless:A.z.boolean().optional()}),Er=A.z.object({baseUrl:A.z.string().url(),environment:Gi.default("stage"),environmentUrls:cc.default({dev:"",stage:"",test:"",prod:""}),browsers:A.z.array(Vi).min(1),headless:A.z.boolean(),viewport:dc.default({width:1280,height:720}),timeout:A.z.number().int().positive(),retries:A.z.number().int().min(0),parallel:A.z.number().int().positive(),pageLoad:oc.default("domcontentloaded"),screenshot:nc,video:ic,trace:ac,healing:lc,reporting:uc,studioPort:A.z.number().int().min(1024).max(65535),profiles:A.z.array(pc).default([]),activeProfile:A.z.string().optional(),device:A.z.string().optional(),rag:A.z.object({enabled:A.z.boolean(),codeCorpus:A.z.object({enabled:A.z.boolean(),maxEntries:A.z.number().int().positive(),similarityThreshold:A.z.number().min(0).max(1),directUseThreshold:A.z.number().min(0).max(1)}),healingCorpus:A.z.object({enabled:A.z.boolean(),maxEntries:A.z.number().int().positive(),similarityThreshold:A.z.number().min(0).max(1)}),errorCatalog:A.z.object({enabled:A.z.boolean(),maxEntries:A.z.number().int().positive()}),embedder:A.z.literal("tfidf")}).default({enabled:!0,codeCorpus:{enabled:!0,maxEntries:500,similarityThreshold:.65,directUseThreshold:.9},healingCorpus:{enabled:!0,maxEntries:300,similarityThreshold:.6},errorCatalog:{enabled:!0,maxEntries:200},embedder:"tfidf"}),mcp:A.z.object({enabled:A.z.boolean(),headless:A.z.boolean(),actThenScript:A.z.boolean(),proactiveHealing:A.z.boolean(),actionTimeout:A.z.number().int().positive(),idleTimeout:A.z.number().int().positive()}).default({enabled:!0,headless:!0,actThenScript:!1,proactiveHealing:!1,actionTimeout:15e3,idleTimeout:3e4})}),zi={baseUrl:"http://localhost:3000",environment:"stage",environmentUrls:{dev:"",stage:"http://localhost:3000",test:"",prod:""},browsers:["chromium"],headless:!0,viewport:{width:1280,height:720},timeout:3e4,retries:1,parallel:1,pageLoad:"domcontentloaded",screenshot:"only-on-failure",video:"off",trace:"on-first-retry",healing:{enabled:!0,maxLevel:5,dailyBudget:5,autoPR:!1},reporting:{allure:!0,html:!0,json:!0},studioPort:4400,profiles:[],rag:{enabled:!0,codeCorpus:{enabled:!0,maxEntries:500,similarityThreshold:.65,directUseThreshold:.9},healingCorpus:{enabled:!0,maxEntries:300,similarityThreshold:.6},errorCatalog:{enabled:!0,maxEntries:200},embedder:"tfidf"},mcp:{enabled:!0,headless:!0,actThenScript:!1,proactiveHealing:!1,actionTimeout:15e3,idleTimeout:3e4}}});var fc={};Q(fc,{runInit:()=>rf});function tf(){return mn.default.resolve(__dirname,"../../templates")}async function rf(r={}){await lt.default.pathExists("package.json")||Ct(`No package.json found in the current directory.
12
+ `)}function It(r){return(0,hc.default)({text:r,color:"cyan"})}function Pt(r){let e=r instanceof Error?r.message:String(r);W(e),process.exit(1)}var or,hc,L,Vt=b(()=>{"use strict";m();or=x(require("chalk")),hc=x(require("ora")),L={success:or.default.green,error:or.default.red,warn:or.default.yellow,info:or.default.cyan,dim:or.default.dim,bold:or.default.bold,accent:or.default.hex("#00adf7")}});var Pc={};Q(Pc,{AutotestConfigSchema:()=>Tr,BrowserNameSchema:()=>Yi,DEFAULT_CONFIG:()=>Zi,EnvironmentProfileSchema:()=>Ic,EnvironmentSchema:()=>Qi,EnvironmentUrlsSchema:()=>xc,HealingConfigSchema:()=>Sc,PageLoadStrategySchema:()=>vc,ReportingConfigSchema:()=>Cc,ScreenshotModeSchema:()=>yc,TraceModeSchema:()=>bc,VideoModeSchema:()=>wc,ViewportSchema:()=>Ec});var A,yc,wc,bc,Yi,vc,Qi,xc,Sc,Cc,Ec,Ic,Tr,Zi,wn=b(()=>{"use strict";m();A=require("zod"),yc=A.z.enum(["off","on","only-on-failure"]),wc=A.z.enum(["off","on","on-first-retry","retain-on-failure"]),bc=A.z.enum(["off","on","on-first-retry","retain-on-failure"]),Yi=A.z.enum(["chromium","firefox","webkit"]),vc=A.z.enum(["commit","domcontentloaded","load","networkidle"]),Qi=A.z.enum(["dev","stage","test","prod"]),xc=A.z.object({dev:A.z.string().url().or(A.z.literal("")).default(""),stage:A.z.string().url().or(A.z.literal("")).default(""),test:A.z.string().url().or(A.z.literal("")).default(""),prod:A.z.string().url().or(A.z.literal("")).default("")}),Sc=A.z.object({enabled:A.z.boolean(),maxLevel:A.z.number().int().min(1).max(5),dailyBudget:A.z.number().positive(),autoPR:A.z.boolean(),healAssertionLocators:A.z.boolean().default(!1)}),Cc=A.z.object({allure:A.z.boolean(),html:A.z.boolean(),json:A.z.boolean()}),Ec=A.z.object({width:A.z.number().int().positive(),height:A.z.number().int().positive()}),Ic=A.z.object({name:A.z.string().min(1),environment:Qi,baseUrl:A.z.string().url(),browsers:A.z.array(Yi).min(1),headless:A.z.boolean().optional()}),Tr=A.z.object({baseUrl:A.z.string().url(),environment:Qi.default("stage"),environmentUrls:xc.default({dev:"",stage:"",test:"",prod:""}),browsers:A.z.array(Yi).min(1),headless:A.z.boolean(),viewport:Ec.default({width:1280,height:720}),timeout:A.z.number().int().positive(),retries:A.z.number().int().min(0),parallel:A.z.number().int().positive(),pageLoad:vc.default("domcontentloaded"),screenshot:yc,video:wc,trace:bc,healing:Sc,reporting:Cc,studioPort:A.z.number().int().min(1024).max(65535),profiles:A.z.array(Ic).default([]),activeProfile:A.z.string().optional(),device:A.z.string().optional(),rag:A.z.object({enabled:A.z.boolean(),codeCorpus:A.z.object({enabled:A.z.boolean(),maxEntries:A.z.number().int().positive(),similarityThreshold:A.z.number().min(0).max(1),directUseThreshold:A.z.number().min(0).max(1)}),healingCorpus:A.z.object({enabled:A.z.boolean(),maxEntries:A.z.number().int().positive(),similarityThreshold:A.z.number().min(0).max(1)}),errorCatalog:A.z.object({enabled:A.z.boolean(),maxEntries:A.z.number().int().positive()}),embedder:A.z.literal("tfidf")}).default({enabled:!0,codeCorpus:{enabled:!0,maxEntries:500,similarityThreshold:.65,directUseThreshold:.9},healingCorpus:{enabled:!0,maxEntries:300,similarityThreshold:.6},errorCatalog:{enabled:!0,maxEntries:200},embedder:"tfidf"}),mcp:A.z.object({enabled:A.z.boolean(),headless:A.z.boolean(),actThenScript:A.z.boolean(),proactiveHealing:A.z.boolean(),actionTimeout:A.z.number().int().positive(),idleTimeout:A.z.number().int().positive()}).default({enabled:!0,headless:!0,actThenScript:!1,proactiveHealing:!1,actionTimeout:15e3,idleTimeout:3e4}),ci:A.z.object({writeToRepo:A.z.boolean()}).default({writeToRepo:!1})}),Zi={baseUrl:"http://localhost:3000",environment:"stage",environmentUrls:{dev:"",stage:"http://localhost:3000",test:"",prod:""},browsers:["chromium"],headless:!0,viewport:{width:1280,height:720},timeout:3e4,retries:1,parallel:1,pageLoad:"domcontentloaded",screenshot:"only-on-failure",video:"off",trace:"on-first-retry",healing:{enabled:!0,maxLevel:5,dailyBudget:5,autoPR:!1,healAssertionLocators:!1},reporting:{allure:!0,html:!0,json:!0},studioPort:4400,profiles:[],rag:{enabled:!0,codeCorpus:{enabled:!0,maxEntries:500,similarityThreshold:.65,directUseThreshold:.9},healingCorpus:{enabled:!0,maxEntries:300,similarityThreshold:.6},errorCatalog:{enabled:!0,maxEntries:200},embedder:"tfidf"},mcp:{enabled:!0,headless:!0,actThenScript:!1,proactiveHealing:!1,actionTimeout:15e3,idleTimeout:3e4},ci:{writeToRepo:!1}}});var Tc={};Q(Tc,{runInit:()=>Tf});function Rf(){return bn.default.resolve(__dirname,"../../templates")}async function Tf(r={}){await pt.default.pathExists("package.json")||Pt(`No package.json found in the current directory.
13
13
  How to fix: Run "npm init -y" first, then retry "npx assuremind init".`),V(`Initialising Assuremind in the current directory\u2026
14
- `),V("Creating directories\u2026");for(let t of Qg)await lt.default.ensureDir(t),(await lt.default.readdir(t)).length===0&&await lt.default.writeFile(mn.default.join(t,".gitkeep"),""),Ie(` ${t}/`);process.stdout.write(`
15
- `),V("Creating config files\u2026");let e=tf();for(let{dest:t,template:s}of Zg){if(await lt.default.pathExists(t)){dn(` ${t} (already exists)`);continue}let n=mn.default.join(e,s);await lt.default.copy(n,t),Ie(` ${t}`)}for(let t of ef){if(await lt.default.pathExists(t)){dn(` ${t} (already exists)`);continue}await lt.default.writeJson(t,{},{spaces:2}),Ie(` ${t}`)}if(await lt.default.pathExists("autotest.config.json"))dn(" autotest.config.json (already exists)");else{let{DEFAULT_CONFIG:t}=await Promise.resolve().then(()=>(pn(),mc));await lt.default.writeJson("autotest.config.json",t,{spaces:2}),Ie(" autotest.config.json")}if(!r.skipPlaywright){process.stdout.write(`
16
- `);let t=St("Installing Playwright browsers (Chromium, Firefox, WebKit)\u2026");t.start();try{(0,gc.execSync)("npx playwright install --with-deps",{stdio:"pipe"}),t.succeed("Playwright browsers installed")}catch(s){t.fail("Failed to install Playwright browsers");let n=s instanceof Error?s.message:String(s);process.stderr.write(` Run manually: npx playwright install --with-deps
14
+ `),V("Creating directories\u2026");for(let t of Ef)await pt.default.ensureDir(t),(await pt.default.readdir(t)).length===0&&await pt.default.writeFile(bn.default.join(t,".gitkeep"),""),Pe(` ${t}/`);process.stdout.write(`
15
+ `),V("Creating config files\u2026");let e=Rf();for(let{dest:t,template:s}of If){if(await pt.default.pathExists(t)){yn(` ${t} (already exists)`);continue}let n=bn.default.join(e,s);await pt.default.copy(n,t),Pe(` ${t}`)}for(let t of Pf){if(await pt.default.pathExists(t)){yn(` ${t} (already exists)`);continue}await pt.default.writeJson(t,{},{spaces:2}),Pe(` ${t}`)}if(await pt.default.pathExists("autotest.config.json"))yn(" autotest.config.json (already exists)");else{let{DEFAULT_CONFIG:t}=await Promise.resolve().then(()=>(wn(),Pc));await pt.default.writeJson("autotest.config.json",t,{spaces:2}),Pe(" autotest.config.json")}if(!r.skipPlaywright){process.stdout.write(`
16
+ `);let t=It("Installing Playwright browsers (Chromium, Firefox, WebKit)\u2026");t.start();try{(0,Rc.execSync)("npx playwright install --with-deps",{stdio:"pipe"}),t.succeed("Playwright browsers installed")}catch(s){t.fail("Failed to install Playwright browsers");let n=s instanceof Error?s.message:String(s);process.stderr.write(` Run manually: npx playwright install --with-deps
17
17
  Error: ${n}
18
- `)}}jt(["\u2705 Assuremind initialised!","","Next steps:"," 1. Edit .env with your AI provider key"," 2. Run: npx assuremind studio"," 3. Start creating tests in the browser!","","Docs: https://assuremind.dev/docs"])}var mn,lt,gc,Qg,Zg,ef,hc=w(()=>{"use strict";p();mn=x(require("path")),lt=x(require("fs-extra")),gc=require("child_process");Bt();Qg=["tests","variables","results","results/screenshots","results/videos","results/traces","results/reports","results/healing","fixtures","fixtures/auth","fixtures/data","docs"],Zg=[{dest:".env.example",template:"env.example"},{dest:".env",template:"env.minimal"},{dest:".gitignore",template:"gitignore"},{dest:"autotest.config.ts",template:"autotest.config.ts"},{dest:"variables/global.json",template:"global-variables.json"},{dest:"ASSUREMIND.md",template:"ASSUREMIND.md"},{dest:"docs/GETTING-STARTED.md",template:"docs/GETTING-STARTED.md"},{dest:"docs/STUDIO.md",template:"docs/STUDIO.md"},{dest:"docs/CLI-REFERENCE.md",template:"docs/CLI-REFERENCE.md"}],ef=["variables/dev.env.json","variables/staging.env.json","variables/prod.env.json"]});var ir,U,ye,X,ie,re=w(()=>{"use strict";p();ir=class extends Error{code;constructor(e,t){super(e),this.name="AssuremindError",this.code=t,Object.setPrototypeOf(this,new.target.prototype)}},U=class extends ir{provider;constructor(e,t,s="PROVIDER_ERROR"){super(e,s),this.name="ProviderError",this.provider=t}},ye=class extends ir{constructor(e,t="CONFIG_ERROR"){super(e,t),this.name="ConfigError"}},X=class extends ir{field;constructor(e,t,s="VALIDATION_ERROR"){super(e,s),this.name="ValidationError",this.field=t}},ie=class extends ir{path;constructor(e,t,s="STORAGE_ERROR"){super(e,s),this.name="StorageError",this.path=t}}});function Et(){if(gn!==null)return gn;let r=sf.safeParse(process.env);if(!r.success){let i=r.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
19
- `);throw new ye(`Missing or invalid environment variables:
18
+ `)}}Ht(["\u2705 Assuremind initialised!","","Next steps:"," 1. Edit .env with your AI provider key"," 2. Run: npx assuremind studio"," 3. Start creating tests in the browser!","","Docs: https://assuremind.dev/docs"])}var bn,pt,Rc,Ef,If,Pf,kc=b(()=>{"use strict";m();bn=x(require("path")),pt=x(require("fs-extra")),Rc=require("child_process");Vt();Ef=["tests","variables","results","results/screenshots","results/videos","results/traces","results/reports","results/healing","fixtures","fixtures/auth","fixtures/data","docs"],If=[{dest:".env.example",template:"env.example"},{dest:".env",template:"env.minimal"},{dest:".gitignore",template:"gitignore"},{dest:"autotest.config.ts",template:"autotest.config.ts"},{dest:"variables/global.json",template:"global-variables.json"},{dest:"ASSUREMIND.md",template:"ASSUREMIND.md"},{dest:"docs/GETTING-STARTED.md",template:"docs/GETTING-STARTED.md"},{dest:"docs/STUDIO.md",template:"docs/STUDIO.md"},{dest:"docs/CLI-REFERENCE.md",template:"docs/CLI-REFERENCE.md"}],Pf=["variables/dev.env.json","variables/staging.env.json","variables/prod.env.json"]});var cr,B,fe,X,oe,te=b(()=>{"use strict";m();cr=class extends Error{code;constructor(e,t){super(e),this.name="AssuremindError",this.code=t,Object.setPrototypeOf(this,new.target.prototype)}},B=class extends cr{provider;constructor(e,t,s="PROVIDER_ERROR"){super(e,s),this.name="ProviderError",this.provider=t}},fe=class extends cr{constructor(e,t="CONFIG_ERROR"){super(e,t),this.name="ConfigError"}},X=class extends cr{field;constructor(e,t,s="VALIDATION_ERROR"){super(e,s),this.name="ValidationError",this.field=t}},oe=class extends cr{path;constructor(e,t,s="STORAGE_ERROR"){super(e,s),this.name="StorageError",this.path=t}}});function Rt(){if(vn!==null)return vn;let r=kf.safeParse(process.env);if(!r.success){let i=r.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
19
+ `);throw new fe(`Missing or invalid environment variables:
20
20
  ${i}
21
21
 
22
- How to fix: Copy .env.example to .env and fill in your AI provider credentials.`,"ENV_VALIDATION_FAILED")}let e=r.data.AI_PROVIDER,s=yf[e].safeParse(process.env);if(!s.success){let i=s.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
23
- `);throw new ye(`Provider "${e}" is missing required environment variables:
22
+ How to fix: Copy .env.example to .env and fill in your AI provider credentials.`,"ENV_VALIDATION_FAILED")}let e=r.data.AI_PROVIDER,s=Hf[e].safeParse(process.env);if(!s.success){let i=s.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
23
+ `);throw new fe(`Provider "${e}" is missing required environment variables:
24
24
  ${i}
25
25
 
26
- How to fix: Check .env.example for the ${e} section and add the required keys to .env.`,"PROVIDER_ENV_MISSING")}return gn={...r.data,...s.data},gn}function Ut(){try{return Et()}catch{return null}}var wc,D,yc,sf,nf,af,of,cf,lf,uf,df,pf,mf,gf,ff,hf,yf,gn,ar=w(()=>{"use strict";p();wc=require("dotenv"),D=require("zod");re();(0,wc.config)();yc=["anthropic","openai","google","azure-openai","bedrock","deepseek","groq","together","qwen","perplexity","ollama","custom"],sf=D.z.object({NODE_ENV:D.z.enum(["development","production","test"]).default("development"),LOG_LEVEL:D.z.enum(["trace","debug","info","warn","error","fatal"]).default("info"),AI_PROVIDER:D.z.enum(yc),AI_TIERED_ENABLED:D.z.string().transform(r=>r==="true").default("false"),AI_TIERED_FAST_PROVIDER:D.z.enum(yc).optional(),AI_TIERED_FAST_MODEL:D.z.string().optional(),AI_TIMEOUT:D.z.coerce.number().int().positive().default(30),AI_MAX_RETRIES:D.z.coerce.number().int().min(0).max(10).default(2)}),nf=D.z.object({ANTHROPIC_API_KEY:D.z.string().min(1),ANTHROPIC_MODEL:D.z.string().default("claude-sonnet-4-20250514")}),af=D.z.object({OPENAI_API_KEY:D.z.string().min(1),OPENAI_MODEL:D.z.string().default("gpt-4o")}),of=D.z.object({GOOGLE_API_KEY:D.z.string().min(1),GOOGLE_MODEL:D.z.string().default("gemini-2.5-pro")}),cf=D.z.object({AZURE_OPENAI_API_KEY:D.z.string().min(1),AZURE_OPENAI_ENDPOINT:D.z.string().url(),AZURE_OPENAI_DEPLOYMENT:D.z.string().min(1),AZURE_OPENAI_API_VERSION:D.z.string().default("2024-10-21")}),lf=D.z.object({AWS_ACCESS_KEY_ID:D.z.string().min(1),AWS_SECRET_ACCESS_KEY:D.z.string().min(1),AWS_SESSION_TOKEN:D.z.string().optional(),AWS_REGION:D.z.string().default("us-east-1"),BEDROCK_MODEL:D.z.string().default("anthropic.claude-sonnet-4-20250514-v1:0")}),uf=D.z.object({DEEPSEEK_API_KEY:D.z.string().min(1),DEEPSEEK_MODEL:D.z.string().default("deepseek-chat")}),df=D.z.object({GROQ_API_KEY:D.z.string().min(1),GROQ_MODEL:D.z.string().default("llama-3.3-70b-versatile")}),pf=D.z.object({TOGETHER_API_KEY:D.z.string().min(1),TOGETHER_MODEL:D.z.string().default("meta-llama/Llama-3.3-70B-Instruct-Turbo")}),mf=D.z.object({QWEN_API_KEY:D.z.string().min(1),QWEN_BASE_URL:D.z.string().url().default("https://dashscope-intl.aliyuncs.com/compatible-mode/v1"),QWEN_MODEL:D.z.string().default("qwen-max")}),gf=D.z.object({PERPLEXITY_API_KEY:D.z.string().min(1),PERPLEXITY_MODEL:D.z.string().default("sonar-pro")}),ff=D.z.object({OLLAMA_BASE_URL:D.z.string().url().default("http://localhost:11434"),OLLAMA_MODEL:D.z.string().default("llama3.3")}),hf=D.z.object({CUSTOM_API_KEY:D.z.string().min(1),CUSTOM_BASE_URL:D.z.string().url(),CUSTOM_MODEL:D.z.string().min(1)}),yf={anthropic:nf,openai:af,google:of,"azure-openai":cf,bedrock:lf,deepseek:uf,groq:df,together:pf,qwen:mf,perplexity:gf,ollama:ff,custom:hf},gn=null});function E(r){return bf.child({component:r})}async function vc(r,e){let t=Ki.default.join(r,"results","logs");await Xi.default.ensureDir(t);let s=Ki.default.join(t,`run-${e}.log`),n=Xi.default.createWriteStream(s,{flags:"a",encoding:"utf-8"});return n.write(`=== Assuremind Test Run: ${e} ===
26
+ How to fix: Check .env.example for the ${e} section and add the required keys to .env.`,"PROVIDER_ENV_MISSING")}return vn={...r.data,...s.data},vn}function Gt(){try{return Rt()}catch{return null}}var $c,D,Ac,kf,Af,$f,_f,Lf,Of,Df,Ff,Nf,Mf,jf,Bf,Uf,Hf,vn,lr=b(()=>{"use strict";m();$c=require("dotenv"),D=require("zod");te();(0,$c.config)();Ac=["anthropic","openai","google","azure-openai","bedrock","deepseek","groq","together","qwen","perplexity","ollama","custom"],kf=D.z.object({NODE_ENV:D.z.enum(["development","production","test"]).default("development"),LOG_LEVEL:D.z.enum(["trace","debug","info","warn","error","fatal"]).default("info"),AI_PROVIDER:D.z.enum(Ac),AI_TIERED_ENABLED:D.z.string().transform(r=>r==="true").default("false"),AI_TIERED_FAST_PROVIDER:D.z.enum(Ac).optional(),AI_TIERED_FAST_MODEL:D.z.string().optional(),AI_TIMEOUT:D.z.coerce.number().int().positive().default(30),AI_MAX_RETRIES:D.z.coerce.number().int().min(0).max(10).default(2)}),Af=D.z.object({ANTHROPIC_API_KEY:D.z.string().min(1),ANTHROPIC_MODEL:D.z.string().default("claude-sonnet-4-20250514")}),$f=D.z.object({OPENAI_API_KEY:D.z.string().min(1),OPENAI_MODEL:D.z.string().default("gpt-4o")}),_f=D.z.object({GOOGLE_API_KEY:D.z.string().min(1),GOOGLE_MODEL:D.z.string().default("gemini-2.5-pro")}),Lf=D.z.object({AZURE_OPENAI_API_KEY:D.z.string().min(1),AZURE_OPENAI_ENDPOINT:D.z.string().url(),AZURE_OPENAI_DEPLOYMENT:D.z.string().min(1),AZURE_OPENAI_API_VERSION:D.z.string().default("2024-10-21")}),Of=D.z.object({AWS_ACCESS_KEY_ID:D.z.string().min(1),AWS_SECRET_ACCESS_KEY:D.z.string().min(1),AWS_SESSION_TOKEN:D.z.string().optional(),AWS_REGION:D.z.string().default("us-east-1"),BEDROCK_MODEL:D.z.string().default("anthropic.claude-sonnet-4-20250514-v1:0")}),Df=D.z.object({DEEPSEEK_API_KEY:D.z.string().min(1),DEEPSEEK_MODEL:D.z.string().default("deepseek-chat")}),Ff=D.z.object({GROQ_API_KEY:D.z.string().min(1),GROQ_MODEL:D.z.string().default("llama-3.3-70b-versatile")}),Nf=D.z.object({TOGETHER_API_KEY:D.z.string().min(1),TOGETHER_MODEL:D.z.string().default("meta-llama/Llama-3.3-70B-Instruct-Turbo")}),Mf=D.z.object({QWEN_API_KEY:D.z.string().min(1),QWEN_BASE_URL:D.z.string().url().default("https://dashscope-intl.aliyuncs.com/compatible-mode/v1"),QWEN_MODEL:D.z.string().default("qwen-max")}),jf=D.z.object({PERPLEXITY_API_KEY:D.z.string().min(1),PERPLEXITY_MODEL:D.z.string().default("sonar-pro")}),Bf=D.z.object({OLLAMA_BASE_URL:D.z.string().url().default("http://localhost:11434"),OLLAMA_MODEL:D.z.string().default("llama3.3")}),Uf=D.z.object({CUSTOM_API_KEY:D.z.string().min(1),CUSTOM_BASE_URL:D.z.string().url(),CUSTOM_MODEL:D.z.string().min(1)}),Hf={anthropic:Af,openai:$f,google:_f,"azure-openai":Lf,bedrock:Of,deepseek:Df,groq:Ff,together:Nf,qwen:Mf,perplexity:jf,ollama:Bf,custom:Uf},vn=null});function E(r){return Gf.child({component:r})}async function Lc(r,e){let t=ra.default.join(r,"results","logs");await ta.default.ensureDir(t);let s=ra.default.join(t,`run-${e}.log`),n=ta.default.createWriteStream(s,{flags:"a",encoding:"utf-8"});return n.write(`=== Assuremind Test Run: ${e} ===
27
27
  `),n.write(`Started: ${new Date().toISOString()}
28
28
  `),n.write("=".repeat(60)+`
29
29
 
@@ -31,13 +31,13 @@ How to fix: Check .env.example for the ${e} section and add the required keys to
31
31
  `)},close:()=>{n.write(`
32
32
  `+"=".repeat(60)+`
33
33
  `),n.write(`Completed: ${new Date().toISOString()}
34
- `),n.end()}}}var qi,Xi,Ki,wf,bc,bf,F=w(()=>{"use strict";p();qi=x(require("pino")),Xi=x(require("fs-extra")),Ki=x(require("path")),wf=process.env.NODE_ENV!=="production",bc=wf?{target:"pino-pretty",options:{colorize:!0,translateTime:"HH:MM:ss",ignore:"pid,hostname",messageFormat:"[assuremind] {msg}"}}:void 0,bf=(0,qi.default)({level:process.env.LOG_LEVEL??"info",base:{name:"assuremind"}},bc?qi.default.transport(bc):void 0)});async function K(r,e){let t=Wi.default.dirname(r);await Pt.default.ensureDir(t);let s=`${r}.${process.pid}.tmp`;try{await Pt.default.writeJson(s,e,{spaces:2}),await Pt.default.rename(s,r)}catch(n){throw await Pt.default.remove(s).catch(()=>{}),new ie(`Failed to write file "${r}": ${n instanceof Error?n.message:String(n)}`,r,"WRITE_FAILED")}}async function de(r){try{return await Pt.default.readJson(r)}catch(e){throw new ie(`Failed to read JSON file "${r}": ${e instanceof Error?e.message:String(e)}`,r,"READ_FAILED")}}async function xc(r,e){let t=Wi.default.dirname(r);await Pt.default.ensureDir(t);let s=`${r}.${process.pid}.tmp`;try{await Pt.default.writeFile(s,e,"utf8"),await Pt.default.rename(s,r)}catch(n){throw await Pt.default.remove(s).catch(()=>{}),new ie(`Failed to write file "${r}": ${n instanceof Error?n.message:String(n)}`,r,"WRITE_FAILED")}}var Wi,Pt,Ve=w(()=>{"use strict";p();Wi=x(require("path")),Pt=x(require("fs-extra"));re()});var Qi={};Q(Qi,{configExists:()=>xf,readConfig:()=>J,updateConfig:()=>vf,validateConfig:()=>Sf,writeConfig:()=>hn});async function J(r){let e=Vr.default.join(r,Yi);if(!await fn.default.pathExists(e))return Ji.debug({rootDir:r},"No autotest.config.json found \u2014 using defaults"),zi;let t=await de(e),s=Er.safeParse(t);if(!s.success){let n=s.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
34
+ `),n.end()}}}var ea,ta,ra,Vf,_c,Gf,N=b(()=>{"use strict";m();ea=x(require("pino")),ta=x(require("fs-extra")),ra=x(require("path")),Vf=process.env.NODE_ENV!=="production",_c=Vf?{target:"pino-pretty",options:{colorize:!0,translateTime:"HH:MM:ss",ignore:"pid,hostname",messageFormat:"[assuremind] {msg}"}}:void 0,Gf=(0,ea.default)({level:process.env.LOG_LEVEL??"info",base:{name:"assuremind"}},_c?ea.default.transport(_c):void 0)});async function K(r,e){let t=sa.default.dirname(r);await Tt.default.ensureDir(t);let s=`${r}.${process.pid}.tmp`;try{await Tt.default.writeJson(s,e,{spaces:2}),await Tt.default.rename(s,r)}catch(n){throw await Tt.default.remove(s).catch(()=>{}),new oe(`Failed to write file "${r}": ${n instanceof Error?n.message:String(n)}`,r,"WRITE_FAILED")}}async function ue(r){try{return await Tt.default.readJson(r)}catch(e){throw new oe(`Failed to read JSON file "${r}": ${e instanceof Error?e.message:String(e)}`,r,"READ_FAILED")}}async function Oc(r,e){let t=sa.default.dirname(r);await Tt.default.ensureDir(t);let s=`${r}.${process.pid}.tmp`;try{await Tt.default.writeFile(s,e,"utf8"),await Tt.default.rename(s,r)}catch(n){throw await Tt.default.remove(s).catch(()=>{}),new oe(`Failed to write file "${r}": ${n instanceof Error?n.message:String(n)}`,r,"WRITE_FAILED")}}var sa,Tt,ze=b(()=>{"use strict";m();sa=x(require("path")),Tt=x(require("fs-extra"));te()});var aa={};Q(aa,{configExists:()=>qf,readConfig:()=>G,updateConfig:()=>zf,validateConfig:()=>Xf,writeConfig:()=>Sn});async function G(r){let e=Kr.default.join(r,ia);if(!await xn.default.pathExists(e))return na.debug({rootDir:r},"No autotest.config.json found \u2014 using defaults"),Zi;let t=await ue(e),s=Tr.safeParse(t);if(!s.success){let n=s.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
35
35
  `);throw new X(`Invalid autotest.config.json at "${e}":
36
36
  ${n}
37
37
 
38
- How to fix: Run "npx assuremind init" to reset to defaults, or manually correct the file using autotest.config.ts as reference.`,"config","INVALID_CONFIG")}return s.data}async function hn(r,e){let t=Er.safeParse(e);if(!t.success){let i=t.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
38
+ How to fix: Run "npx assuremind init" to reset to defaults, or manually correct the file using autotest.config.ts as reference.`,"config","INVALID_CONFIG")}return s.data}async function Sn(r,e){let t=Tr.safeParse(e);if(!t.success){let i=t.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
39
39
  `);throw new X(`Cannot write invalid config:
40
- ${i}`,"config","INVALID_CONFIG")}let s=Vr.default.join(r,Yi);await K(s,t.data);let n=Vr.default.join(r,Sc);await xc(n,Cf(t.data)),Ji.info({rootDir:r},"Config saved")}async function vf(r,e){let t=await J(r),s={...t,...e,healing:{...t.healing,...e.healing??{}},reporting:{...t.reporting,...e.reporting??{}},environmentUrls:{...t.environmentUrls,...e.environmentUrls??{}}};return await hn(r,s),s}async function xf(r){let e=Vr.default.join(r,Yi),t=Vr.default.join(r,Sc);return await fn.default.pathExists(e)||await fn.default.pathExists(t)}async function Sf(r){let e=await J(r);if(!e.baseUrl)throw new ye('baseUrl is required in autotest.config.ts. Set it to your application URL, e.g. "http://localhost:3000".',"CONFIG_BASE_URL_MISSING");Ji.debug({config:e},"Config validated successfully")}function Cf(r){return`import { defineConfig } from 'assuremind';
40
+ ${i}`,"config","INVALID_CONFIG")}let s=Kr.default.join(r,ia);await K(s,t.data);let n=Kr.default.join(r,Dc);await Oc(n,Kf(t.data)),na.info({rootDir:r},"Config saved")}async function zf(r,e){let t=await G(r),s={...t,...e,healing:{...t.healing,...e.healing??{}},reporting:{...t.reporting,...e.reporting??{}},environmentUrls:{...t.environmentUrls,...e.environmentUrls??{}}};return await Sn(r,s),s}async function qf(r){let e=Kr.default.join(r,ia),t=Kr.default.join(r,Dc);return await xn.default.pathExists(e)||await xn.default.pathExists(t)}async function Xf(r){let e=await G(r);if(!e.baseUrl)throw new fe('baseUrl is required in autotest.config.ts. Set it to your application URL, e.g. "http://localhost:3000".',"CONFIG_BASE_URL_MISSING");na.debug({config:e},"Config validated successfully")}function Kf(r){return`import { defineConfig } from 'assuremind';
41
41
 
42
42
  export default defineConfig({
43
43
  baseUrl: '${r.baseUrl}',
@@ -62,7 +62,7 @@ export default defineConfig({
62
62
  },
63
63
  studioPort: ${r.studioPort},
64
64
  });
65
- `}var Vr,fn,Ji,Yi,Sc,_e=w(()=>{"use strict";p();Vr=x(require("path")),fn=x(require("fs-extra"));pn();re();F();Ve();Ji=E("config-store"),Yi="autotest.config.json",Sc="autotest.config.ts"});var Cc=w(()=>{"use strict";p()});var Zi,yn,Ec=w(()=>{"use strict";p();F();Zi=E("websocket"),yn=class{sockets=new Set;add(e){this.sockets.add(e),Zi.debug({total:this.sockets.size},"WS client connected"),e.on("close",()=>{this.sockets.delete(e),Zi.debug({total:this.sockets.size},"WS client disconnected")}),e.on("error",t=>{Zi.warn({err:t},"WS socket error"),this.sockets.delete(e)})}broadcast(e,t){if(this.sockets.size===0)return;let s=JSON.stringify({event:e,data:t,timestamp:Date.now()});for(let n of this.sockets)n.readyState===1&&n.send(s)}get clientCount(){return this.sockets.size}}});async function Pc(r,e){let{default:t}=await import("@fastify/static"),s=Ls.default.resolve(__dirname,"../../node_modules/playwright-core/lib/vite/traceViewer");await Gr.default.pathExists(s)?(await r.register(t,{root:s,prefix:"/trace/",decorateReply:!1}),Os.info({traceViewerDir:s},"Serving Playwright Trace Viewer at /trace/")):Os.warn({traceViewerDir:s},"Playwright Trace Viewer not found \u2014 skipping");let n=Ls.default.join(e,"results","allure-report");await Gr.default.ensureDir(n),Os.info({allureReportDir:n},"Per-run Allure reports will be served at /allure/<runId>");let i=Ls.default.resolve(__dirname,"../../ui/dist");await Gr.default.pathExists(i)?(await r.register(t,{root:i,prefix:"/",decorateReply:!0,index:"index.html"}),Os.info({uiDist:i},"Serving React UI"),r.setNotFoundHandler(async(o,c)=>{let{url:l,method:u}=o;if(u==="GET"&&l.startsWith("/allure/")){let g=l.slice(8).replace(/\/$/,"").split("/")[0];if(g){let m=Ls.default.join(e,"results","allure-report",g,"index.html");if(await Gr.default.pathExists(m)){let f=await Gr.default.readFile(m,"utf-8");return c.code(200).type("text/html").send(f)}}return c.code(200).type("text/html").send(`<!DOCTYPE html>
65
+ `}var Kr,xn,na,ia,Dc,Te=b(()=>{"use strict";m();Kr=x(require("path")),xn=x(require("fs-extra"));wn();te();N();ze();na=E("config-store"),ia="autotest.config.json",Dc="autotest.config.ts"});var Fc=b(()=>{"use strict";m()});var oa,Cn,Nc=b(()=>{"use strict";m();N();oa=E("websocket"),Cn=class{sockets=new Set;add(e){this.sockets.add(e),oa.debug({total:this.sockets.size},"WS client connected"),e.on("close",()=>{this.sockets.delete(e),oa.debug({total:this.sockets.size},"WS client disconnected")}),e.on("error",t=>{oa.warn({err:t},"WS socket error"),this.sockets.delete(e)})}broadcast(e,t){if(this.sockets.size===0)return;let s=JSON.stringify({event:e,data:t,timestamp:Date.now()});for(let n of this.sockets)n.readyState===1&&n.send(s)}get clientCount(){return this.sockets.size}}});async function Mc(r,e){let{default:t}=await import("@fastify/static"),s=Us.default.resolve(__dirname,"../../node_modules/playwright-core/lib/vite/traceViewer");await Wr.default.pathExists(s)?(await r.register(t,{root:s,prefix:"/trace/",decorateReply:!1}),Bs.info({traceViewerDir:s},"Serving Playwright Trace Viewer at /trace/")):Bs.warn({traceViewerDir:s},"Playwright Trace Viewer not found \u2014 skipping");let n=Us.default.join(e,"results","allure-report");await Wr.default.ensureDir(n),Bs.info({allureReportDir:n},"Per-run Allure reports will be served at /allure/<runId>");let i=Us.default.resolve(__dirname,"../../ui/dist");await Wr.default.pathExists(i)?(await r.register(t,{root:i,prefix:"/",decorateReply:!0,index:"index.html"}),Bs.info({uiDist:i},"Serving React UI"),r.setNotFoundHandler(async(o,c)=>{let{url:l,method:u}=o;if(u==="GET"&&l.startsWith("/allure/")){let p=l.slice(8).replace(/\/$/,"").split("/")[0];if(p){let g=Us.default.join(e,"results","allure-report",p,"index.html");if(await Wr.default.pathExists(g)){let f=await Wr.default.readFile(g,"utf-8");return c.code(200).type("text/html").send(f)}}return c.code(200).type("text/html").send(`<!DOCTYPE html>
66
66
  <html lang="en">
67
67
  <head><meta charset="UTF-8"><title>Allure Report \u2014 Not Generated</title>
68
68
  <style>
@@ -88,27 +88,30 @@ export default defineConfig({
88
88
  <p style="margin-top:1.2rem;font-size:.8rem;color:#94a3b8">Report directory: <code>results/allure-report/&lt;runId&gt;/</code></p>
89
89
  </div>
90
90
  </body>
91
- </html>`)}return u==="GET"&&!l.startsWith("/api/")&&!l.startsWith("/trace/")&&l!=="/ws"?c.sendFile("index.html"):c.code(404).send({message:`Route ${u}:${l} not found`,error:"Not Found",statusCode:404})})):(Os.warn({uiDist:i},'UI not built \u2014 serving placeholder. Run "npm run build:ui" first.'),r.get("/",(o,c)=>{c.type("application/json").send({message:"Assuremind Studio",status:"ui-not-built",note:'Run "npm run build:ui" to build the React UI, then restart the server.'})}))}var Ls,Gr,Os,Ic=w(()=>{"use strict";p();Ls=x(require("path")),Gr=x(require("fs-extra"));F();Os=E("static")});function b(r,e,t,s){let n=s instanceof ir?s.code:"INTERNAL_ERROR",i=s instanceof Error?s.message:s!==void 0?String(s):void 0,a=s instanceof ye||Ef.has(n),o=a?422:e,c=i?.includes("JIRA_NOT_CONFIGURED")||i?.includes("Jira not configured"),l=i?.includes("XRAY_NOT_CONFIGURED")||i?.includes("Xray not configured"),u=c?"JIRA_NOT_CONFIGURED":l?"XRAY_NOT_CONFIGURED":a?"AI_NOT_CONFIGURED":void 0;return o>=500?Rc.error({err:s},t):Rc.debug({err:s},t),r.status(o).send({error:t,...i&&i!==t&&{detail:i},code:n,...u&&{featureHint:u}})}var Rc,Ef,ae=w(()=>{"use strict";p();re();F();Rc=E("server"),Ef=new Set(["ENV_VALIDATION_FAILED","PROVIDER_ENV_MISSING","UNKNOWN_PROVIDER","CONFIG_ERROR"])});async function Tc(r){let e=r.rootDir;r.get("/config",async(t,s)=>{try{let n=await J(e);return s.send(n)}catch(n){return b(s,500,"Failed to read config",n)}}),r.put("/config",async(t,s)=>{let n=Pf.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid config",details:n.error.issues});try{let i=await J(e),a=Er.parse({...i,...n.data});return await hn(e,a),s.send(a)}catch(i){return b(s,500,"Failed to update config",i)}}),r.get("/ai-provider",async(t,s)=>{try{let n=Et(),i=String(n.AI_PROVIDER??"unknown"),a={anthropic:String(n.ANTHROPIC_MODEL??"claude-sonnet-4-20250514"),bedrock:String(n.BEDROCK_MODEL??"us.anthropic.claude-sonnet-4-20250514-v1:0"),openai:String(n.OPENAI_MODEL??"gpt-4o"),google:String(n.GOOGLE_MODEL??"gemini-2.5-flash"),"azure-openai":String(n.AZURE_OPENAI_DEPLOYMENT??"gpt-4o"),ollama:String(n.OLLAMA_MODEL??"codellama")};return s.send({provider:i,model:a[i]??"unknown"})}catch{return s.send({provider:"unknown",model:"unknown"})}}),r.get("/config/status",async(t,s)=>{let n=Ut(),i=process.env.JIRA_BASE_URL,a=process.env.JIRA_EMAIL,o=process.env.JIRA_API_TOKEN,c=!!(i&&a&&o),l=process.env.XRAY_PROJECT_KEY,u=c&&!!l;return s.send({ai:{configured:!!n,provider:n?String(n.AI_PROVIDER):null},jira:{configured:c},xray:{configured:u}})}),r.get("/mcp/status",async(t,s)=>{try{let n=await J(e),i=n.mcp?.enabled??!1,a=!1;try{require.resolve("@playwright/mcp"),a=!0}catch{}return s.send({enabled:i,packageAvailable:a,headless:n.mcp?.headless??!0,actThenScript:n.mcp?.actThenScript??!1,proactiveHealing:n.mcp?.proactiveHealing??!1})}catch(n){return b(s,500,"Failed to check MCP status",n)}})}var Pf,kc=w(()=>{"use strict";p();_e();pn();ar();ae();Pf=Er.partial()});var $,Ds,If,Ac,Rf,ea,ta,$c,ra,Ns=w(()=>{"use strict";p();$=require("zod"),Ds=$.z.object({id:$.z.string().min(1),order:$.z.number().int().positive(),instruction:$.z.string().min(1),generatedCode:$.z.string(),strategy:$.z.enum(["template","cache","rag","batch","fast","primary","recorder"]),stepType:$.z.enum(["ui","api","mock"]).default("ui"),lastHealed:$.z.string().nullable(),timeout:$.z.number().int().positive().optional(),retries:$.z.number().int().min(0).optional(),mockUrl:$.z.string().optional(),mockResponse:$.z.string().optional(),mockStatus:$.z.number().int().optional(),runAudit:$.z.boolean().optional(),soft:$.z.boolean().optional(),visualCheck:$.z.boolean().optional()}),If=$.z.object({type:$.z.enum(["inline","json-file","csv-file"]),path:$.z.string().optional(),data:$.z.array($.z.record($.z.string())).optional()}).optional(),Ac=$.z.object({id:$.z.string(),instruction:$.z.string(),generatedCode:$.z.string().default(""),order:$.z.number().int().default(0)}),Rf=$.z.object({before:$.z.array(Ac).default([]),after:$.z.array(Ac).default([])}).default({before:[],after:[]}),ea=$.z.object({id:$.z.string().min(1),name:$.z.string().min(1),description:$.z.string(),tags:$.z.array($.z.string()),priority:$.z.enum(["critical","high","medium","low"]),timeout:$.z.number().int().positive().optional(),dataSource:If,steps:$.z.array(Ds),caseHooks:Rf,lighthouseCategories:$.z.array($.z.enum(["performance","accessibility","seo"])).default(["performance","accessibility","seo"]),createdAt:$.z.string().datetime(),updatedAt:$.z.string().datetime()}),ta=$.z.object({id:$.z.string().min(1),name:$.z.string().min(1),description:$.z.string(),tags:$.z.array($.z.string()),type:$.z.enum(["ui","api","audit","performance"]).default("ui"),timeout:$.z.number().int().positive().optional(),createdAt:$.z.string().datetime(),updatedAt:$.z.string().datetime()}),$c=$.z.enum(["before_all","before_each","after_each","after_all"]),ra=$.z.object({before_all:$.z.array(Ds).default([]),before_each:$.z.array(Ds).default([]),after_each:$.z.array(Ds).default([]),after_all:$.z.array(Ds).default([])})});function zr(r){let e=/^```(?:typescript|javascript|ts|js)?\n?([\s\S]*?)```\s*$/m,t=r.match(e);return t?.[1]!==void 0?t[1].trim():r.trim()}function wn(r){let e=zr(r);try{return JSON.parse(e),e}catch{}let t=e.indexOf("{"),s=e.indexOf("["),n=t===-1?s:s===-1?t:Math.min(t,s);if(n===-1)return e;let i=e[n],a=i==="{"?"}":"]",o=0,c=!1,l=!1;for(let u=n;u<e.length;u++){let d=e[u];if(l){l=!1;continue}if(d==="\\"&&c){l=!0;continue}if(d==='"'){c=!c;continue}if(!c){if(d===i)o++;else if(d===a&&(o--,o===0))return e.slice(n,u+1)}}return e.slice(n)}function kf(r){for(let e of Tf)if(e.test(r))throw new X(`Generated code contains forbidden pattern: ${e.source}. This may be a prompt injection attempt. Please regenerate the step.`,"generatedCode","UNSAFE_CODE")}function qr(r,e){let t=/\bbutton\b/i.test(r)?"button":/\blink\b/i.test(r)?"link":null;return t===null?e:e.replace(/page\.getByText\((['"])(.*?)\1\)\.click\(\)/g,(s,n,i)=>`page.getByRole('${t}', { name: '${i}' }).click()`)}function _c(r){let e=r.replace(Af,"").trim();return e.length>0?e:r}function $f(r){let e=r;return e=e.replace(/(getBy(?:Label|Placeholder)\(\s*)(['"`])([\s\S]*?)\2/g,(t,s,n,i)=>`${s}${n}${_c(i)}${n}`),e=e.replace(/(name:\s*)(['"`])([\s\S]*?)\2/g,(t,s,n,i)=>`${s}${n}${_c(i)}${n}`),e}function Xr(r){let e=r;return e=e.replace(/\.or\((?:[^()]*|\([^()]*\))*\)(?:\.(?:first|last)\(\))?/g,""),e=e.replace(/\.(?:first|last)\(\)(?=\.\w)/g,""),e=$f(e),e}function Oe(r){let e=zr(r);if(!e)throw new X("AI returned an empty code response. Please try regenerating.","generatedCode","EMPTY_CODE");let t=Xr(e);return kf(t),t}function It(r){return r.toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}var Tf,Af,Rt=w(()=>{"use strict";p();re();Tf=[/\brequire\s*\(/,/\bimport\s*\(/,/\bprocess\b/,/\bchild_process\b/,/\bexec\s*\(/,/\bspawn\s*\(/,/\beval\s*\(/,/\bFunction\s*\(/,/\b__dirname\b/,/\b__filename\b/,/\bglobal\b/,/\bwindow\.location\.href\s*=/,/\bdocument\.cookie\b/,/\blocalStorage\b/,/\bsessionStorage\b/,/\bIndexedDB\b/,/\bXMLHttpRequest\b/,/\bfetch\s*\(/,/\bWebSocket\s*\(/];Af=/\s+(?:field|input|box|textbox|text\s?box|drop-?\s?down|dropdown|combo\s?box|combobox|menu|selector|element|checkbox|radio\s?button|radio)$/i});var oa={};Q(oa,{createSuite:()=>Ms,deleteSuite:()=>na,findSuiteDirById:()=>pe,listSuiteDirs:()=>Tt,listSuites:()=>Pr,listSuitesWithCounts:()=>aa,moveSuiteType:()=>ia,readSuite:()=>ve,updateSuite:()=>vn,writeSuite:()=>sa});async function ve(r){let e=Re.default.join(r,bn);if(!await Ge.default.pathExists(e))throw new ie(`Suite file not found at "${e}". Ensure the suite directory exists and contains a suite.json file.`,e,"SUITE_NOT_FOUND");let t=await de(e),s=ta.safeParse(t);if(!s.success){let i=s.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
91
+ </html>`)}return u==="GET"&&!l.startsWith("/api/")&&!l.startsWith("/trace/")&&l!=="/ws"?c.sendFile("index.html"):c.code(404).send({message:`Route ${u}:${l} not found`,error:"Not Found",statusCode:404})})):(Bs.warn({uiDist:i},'UI not built \u2014 serving placeholder. Run "npm run build:ui" first.'),r.get("/",(o,c)=>{c.type("application/json").send({message:"Assuremind Studio",status:"ui-not-built",note:'Run "npm run build:ui" to build the React UI, then restart the server.'})}))}var Us,Wr,Bs,jc=b(()=>{"use strict";m();Us=x(require("path")),Wr=x(require("fs-extra"));N();Bs=E("static")});function w(r,e,t,s){let n=s instanceof cr?s.code:"INTERNAL_ERROR",i=s instanceof Error?s.message:s!==void 0?String(s):void 0,a=s instanceof fe||Wf.has(n),o=a?422:e,c=i?.includes("JIRA_NOT_CONFIGURED")||i?.includes("Jira not configured"),l=i?.includes("XRAY_NOT_CONFIGURED")||i?.includes("Xray not configured"),u=c?"JIRA_NOT_CONFIGURED":l?"XRAY_NOT_CONFIGURED":a?"AI_NOT_CONFIGURED":void 0;return o>=500?Bc.error({err:s},t):Bc.debug({err:s},t),r.status(o).send({error:t,...i&&i!==t&&{detail:i},code:n,...u&&{featureHint:u}})}var Bc,Wf,re=b(()=>{"use strict";m();te();N();Bc=E("server"),Wf=new Set(["ENV_VALIDATION_FAILED","PROVIDER_ENV_MISSING","UNKNOWN_PROVIDER","CONFIG_ERROR"])});async function Uc(r){let e=r.rootDir;r.get("/config",async(t,s)=>{try{let n=await G(e);return s.send(n)}catch(n){return w(s,500,"Failed to read config",n)}}),r.put("/config",async(t,s)=>{let n=Jf.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid config",details:n.error.issues});try{let i=await G(e),a=Tr.parse({...i,...n.data});return await Sn(e,a),s.send(a)}catch(i){return w(s,500,"Failed to update config",i)}}),r.get("/ai-provider",async(t,s)=>{try{let n=Rt(),i=String(n.AI_PROVIDER??"unknown"),a={anthropic:String(n.ANTHROPIC_MODEL??"claude-sonnet-4-20250514"),bedrock:String(n.BEDROCK_MODEL??"us.anthropic.claude-sonnet-4-20250514-v1:0"),openai:String(n.OPENAI_MODEL??"gpt-4o"),google:String(n.GOOGLE_MODEL??"gemini-2.5-flash"),"azure-openai":String(n.AZURE_OPENAI_DEPLOYMENT??"gpt-4o"),ollama:String(n.OLLAMA_MODEL??"codellama")};return s.send({provider:i,model:a[i]??"unknown"})}catch{return s.send({provider:"unknown",model:"unknown"})}}),r.get("/config/status",async(t,s)=>{let n=Gt(),i=process.env.JIRA_BASE_URL,a=process.env.JIRA_EMAIL,o=process.env.JIRA_API_TOKEN,c=!!(i&&a&&o),l=process.env.XRAY_PROJECT_KEY,u=c&&!!l;return s.send({ai:{configured:!!n,provider:n?String(n.AI_PROVIDER):null},jira:{configured:c},xray:{configured:u}})}),r.get("/mcp/status",async(t,s)=>{try{let n=await G(e),i=n.mcp?.enabled??!1,a=!1;try{require.resolve("@playwright/mcp"),a=!0}catch{}return s.send({enabled:i,packageAvailable:a,headless:n.mcp?.headless??!0,actThenScript:n.mcp?.actThenScript??!1,proactiveHealing:n.mcp?.proactiveHealing??!1})}catch(n){return w(s,500,"Failed to check MCP status",n)}})}var Jf,Hc=b(()=>{"use strict";m();Te();wn();lr();re();Jf=Tr.partial()});var $,Hs,Yf,Vc,Qf,ca,la,Gc,ua,Vs=b(()=>{"use strict";m();$=require("zod"),Hs=$.z.object({id:$.z.string().min(1),order:$.z.number().int().positive(),instruction:$.z.string().min(1),generatedCode:$.z.string(),strategy:$.z.enum(["template","cache","rag","batch","fast","primary","recorder"]),stepType:$.z.enum(["ui","api","mock"]).default("ui"),lastHealed:$.z.string().nullable(),timeout:$.z.number().int().positive().optional(),retries:$.z.number().int().min(0).optional(),mockUrl:$.z.string().optional(),mockResponse:$.z.string().optional(),mockStatus:$.z.number().int().optional(),runAudit:$.z.boolean().optional(),soft:$.z.boolean().optional(),visualCheck:$.z.boolean().optional()}),Yf=$.z.object({type:$.z.enum(["inline","json-file","csv-file"]),path:$.z.string().optional(),data:$.z.array($.z.record($.z.string())).optional()}).optional(),Vc=$.z.object({id:$.z.string(),instruction:$.z.string(),generatedCode:$.z.string().default(""),order:$.z.number().int().default(0)}),Qf=$.z.object({before:$.z.array(Vc).default([]),after:$.z.array(Vc).default([])}).default({before:[],after:[]}),ca=$.z.object({id:$.z.string().min(1),name:$.z.string().min(1),description:$.z.string(),tags:$.z.array($.z.string()),priority:$.z.enum(["critical","high","medium","low"]),timeout:$.z.number().int().positive().optional(),dataSource:Yf,steps:$.z.array(Hs),caseHooks:Qf,lighthouseCategories:$.z.array($.z.enum(["performance","accessibility","seo"])).default(["performance","accessibility","seo"]),createdAt:$.z.string().datetime(),updatedAt:$.z.string().datetime()}),la=$.z.object({id:$.z.string().min(1),name:$.z.string().min(1),description:$.z.string(),tags:$.z.array($.z.string()),type:$.z.enum(["ui","api","audit","performance"]).default("ui"),timeout:$.z.number().int().positive().optional(),createdAt:$.z.string().datetime(),updatedAt:$.z.string().datetime()}),Gc=$.z.enum(["before_all","before_each","after_each","after_all"]),ua=$.z.object({before_all:$.z.array(Hs).default([]),before_each:$.z.array(Hs).default([]),after_each:$.z.array(Hs).default([]),after_all:$.z.array(Hs).default([])})});function Jr(r){let e=/^```(?:typescript|javascript|ts|js)?\n?([\s\S]*?)```\s*$/m,t=r.match(e);return t?.[1]!==void 0?t[1].trim():r.trim()}function En(r){let e=Jr(r);try{return JSON.parse(e),e}catch{}let t=e.indexOf("{"),s=e.indexOf("["),n=t===-1?s:s===-1?t:Math.min(t,s);if(n===-1)return e;let i=e[n],a=i==="{"?"}":"]",o=0,c=!1,l=!1;for(let u=n;u<e.length;u++){let d=e[u];if(l){l=!1;continue}if(d==="\\"&&c){l=!0;continue}if(d==='"'){c=!c;continue}if(!c){if(d===i)o++;else if(d===a&&(o--,o===0))return e.slice(n,u+1)}}return e.slice(n)}function eh(r){for(let e of Zf)if(e.test(r))throw new X(`Generated code contains forbidden pattern: ${e.source}. This may be a prompt injection attempt. Please regenerate the step.`,"generatedCode","UNSAFE_CODE")}function Yr(r,e){let t=/\bbutton\b/i.test(r)?"button":/\blink\b/i.test(r)?"link":null;return t===null?e:e.replace(/page\.getByText\((['"])(.*?)\1\)\.click\(\)/g,(s,n,i)=>`page.getByRole('${t}', { name: '${i}' }).click()`)}function zc(r){let e=r.replace(th,"").trim();return e.length>0?e:r}function rh(r){let e=r;return e=e.replace(/(getBy(?:Label|Placeholder)\(\s*)(['"`])([\s\S]*?)\2/g,(t,s,n,i)=>`${s}${n}${zc(i)}${n}`),e=e.replace(/(name:\s*)(['"`])([\s\S]*?)\2/g,(t,s,n,i)=>`${s}${n}${zc(i)}${n}`),e}function sh(r){return r.replace(/\blocator\((['"`])([\s\S]*?)\1\)/g,(e,t,s)=>{if(!s.includes(" >> "))return e;let n=s.split(" >> ").map(i=>i.trim()).filter(Boolean);return n.length<2?e:n.map(i=>`locator(${t}${i}${t})`).join(".")})}function Qr(r){let e=r;return e=sh(e),e=e.replace(/\.or\((?:[^()]*|\([^()]*\))*\)(?:\.(?:first|last)\(\))?/g,""),e=e.replace(/\.(?:first|last)\(\)(?=\.\w)/g,""),e=rh(e),e}function De(r){let e=Jr(r);if(!e)throw new X("AI returned an empty code response. Please try regenerating.","generatedCode","EMPTY_CODE");let t=Qr(e);return eh(t),t}function kt(r){return r.toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}var Zf,th,At=b(()=>{"use strict";m();te();Zf=[/\brequire\s*\(/,/\bimport\s*\(/,/\bprocess\b/,/\bchild_process\b/,/\bexec\s*\(/,/\bspawn\s*\(/,/\beval\s*\(/,/\bFunction\s*\(/,/\b__dirname\b/,/\b__filename\b/,/\bglobal\b/,/\bwindow\.location\.href\s*=/,/\bdocument\.cookie\b/,/\blocalStorage\b/,/\bsessionStorage\b/,/\bIndexedDB\b/,/\bXMLHttpRequest\b/,/\bfetch\s*\(/,/\bWebSocket\s*\(/];th=/\s+(?:field|input|box|textbox|text\s?box|drop-?\s?down|dropdown|combo\s?box|combobox|menu|selector|element|checkbox|radio\s?button|radio)$/i});var fa={};Q(fa,{createSuite:()=>Gs,deleteSuite:()=>pa,findSuiteDirById:()=>de,listSuiteDirs:()=>$t,listSuites:()=>kr,listSuitesWithCounts:()=>ga,moveSuiteType:()=>ma,readSuite:()=>ve,updateSuite:()=>Pn,writeSuite:()=>da});async function ve(r){let e=Re.default.join(r,In);if(!await qe.default.pathExists(e))throw new oe(`Suite file not found at "${e}". Ensure the suite directory exists and contains a suite.json file.`,e,"SUITE_NOT_FOUND");let t=await ue(e),s=la.safeParse(t);if(!s.success){let i=s.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
92
92
  `);throw new X(`Invalid suite.json at "${e}":
93
- ${i}`,"suite","INVALID_SUITE")}if(!t.type){let i=Re.default.basename(Re.default.dirname(r));i==="api"?s.data.type="api":i==="audit"||i==="performance"?s.data.type="audit":s.data.type="ui"}return s.data}async function sa(r,e){await Ge.default.ensureDir(r);let t=Re.default.join(r,bn),s=ta.safeParse(e);if(!s.success){let n=s.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
93
+ ${i}`,"suite","INVALID_SUITE")}if(!t.type){let i=Re.default.basename(Re.default.dirname(r));i==="api"?s.data.type="api":i==="audit"||i==="performance"?s.data.type="audit":s.data.type="ui"}return s.data}async function da(r,e){await qe.default.ensureDir(r);let t=Re.default.join(r,In),s=la.safeParse(e);if(!s.success){let n=s.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
94
94
  `);throw new X(`Cannot write invalid suite to "${t}":
95
- ${n}`,"suite","INVALID_SUITE")}await K(t,s.data),Kr.debug({suiteId:e.id,path:t},"Suite written")}async function Ms(r,e){let t=new Date().toISOString(),s=e.type??"ui",n={...e,type:s,id:(0,Oc.v4)(),createdAt:t,updatedAt:t},i=Re.default.join(r,s),a=Re.default.join(i,It(n.name));if(await Ge.default.pathExists(Re.default.join(a,bn)))throw new ie(`Suite directory already exists at "${a}". Choose a different name or delete the existing suite first.`,a,"SUITE_ALREADY_EXISTS");return await sa(a,n),Kr.info({suiteId:n.id,path:a},"Suite created"),{suiteDir:a,suiteId:n.id}}async function vn(r,e){let t=await ve(r),s={...t,...e,id:t.id,createdAt:t.createdAt,updatedAt:new Date().toISOString()};return await sa(r,s),s}async function na(r){if(!await Ge.default.pathExists(r))throw new ie(`Suite directory not found at "${r}".`,r,"SUITE_NOT_FOUND");await Ge.default.remove(r),Kr.info({path:r},"Suite deleted")}async function Tt(r){let e=[],t=[Re.default.join(r,"ui"),Re.default.join(r,"api"),Re.default.join(r,"audit"),Re.default.join(r,"performance"),r];for(let s of t){if(!await Ge.default.pathExists(s))continue;let n=await Ge.default.readdir(s,{withFileTypes:!0});for(let i of n){if(!i.isDirectory()||s===r&&(i.name==="ui"||i.name==="api"||i.name==="audit"||i.name==="performance"))continue;let a=Re.default.join(s,i.name,bn);await Ge.default.pathExists(a)&&e.push(Re.default.join(s,i.name))}}return e}async function ia(r,e,t){let s=await ve(e),n=Re.default.basename(e),i=Re.default.join(r,t),a=Re.default.join(i,n);if(e===a)return e;if(await Ge.default.ensureDir(i),await Ge.default.pathExists(a))throw new ie(`Cannot move suite \u2014 "${a}" already exists.`,a,"SUITE_ALREADY_EXISTS");return await Ge.default.move(e,a),await vn(a,{type:t}),Kr.info({suiteId:s.id,from:e,to:a},"Suite moved"),a}async function pe(r,e){let t=await Tt(r);for(let s of t)try{if((await ve(s)).id===e)return s}catch{}return null}async function Pr(r){let e=await Tt(r),t=[];for(let s of e)try{t.push(await ve(s))}catch(n){Kr.warn({path:s,err:n},"Failed to read suite \u2014 skipping")}return t}async function aa(r){let e=await Tt(r),t=[];for(let s of e)try{let n=await ve(s),a=(await Ge.default.readdir(s,{withFileTypes:!0})).filter(o=>o.isFile()&&o.name.endsWith(".test.json")).length;t.push({...n,caseCount:a})}catch(n){Kr.warn({path:s,err:n},"Failed to read suite \u2014 skipping")}return t}var Re,Ge,Oc,Kr,bn,ze=w(()=>{"use strict";p();Re=x(require("path")),Ge=x(require("fs-extra")),Oc=require("uuid");Ns();re();F();Rt();Ve();Kr=E("suite-store"),bn="suite.json"});async function Dc(r){let e=Lc.default.join(r.rootDir,"tests");r.get("/suites",async(t,s)=>{try{let n=await aa(e),i=t.query.type;return(i==="ui"||i==="api"||i==="performance")&&(n=n.filter(a=>a.type===i)),s.send(n)}catch(n){return b(s,500,"Failed to list suites",n)}}),r.post("/suites",async(t,s)=>{let n=_f.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid suite data",details:n.error.issues});try{let{suiteDir:i}=await Ms(e,n.data),a=await ve(i);return s.status(201).send(a)}catch(i){return b(s,500,"Failed to create suite",i)}}),r.get("/suites/:id",async(t,s)=>{try{let n=await pe(e,t.params.id);if(!n)return s.status(404).send({error:`Suite "${t.params.id}" not found`});let i=await ve(n);return s.send(i)}catch(n){return b(s,500,"Failed to get suite",n)}}),r.patch("/suites/:id",async(t,s)=>{let n=Of.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid suite data",details:n.error.issues});try{let i=await pe(e,t.params.id);if(!i)return s.status(404).send({error:`Suite "${t.params.id}" not found`});n.data.type&&(await ve(i)).type!==n.data.type&&(i=await ia(e,i,n.data.type));let a=await vn(i,n.data);return s.send(a)}catch(i){return b(s,500,"Failed to update suite",i)}}),r.delete("/suites/:id",async(t,s)=>{try{let n=await pe(e,t.params.id);return n?(await na(n),s.status(204).send()):s.status(404).send({error:`Suite "${t.params.id}" not found`})}catch(n){return b(s,500,"Failed to delete suite",n)}})}var Lc,Ne,_f,Of,Nc=w(()=>{"use strict";p();Lc=x(require("path")),Ne=require("zod");ze();ae();_f=Ne.z.object({name:Ne.z.string().min(1),description:Ne.z.string().default(""),tags:Ne.z.array(Ne.z.string()).default([]),type:Ne.z.enum(["ui","api","audit","performance"]).default("ui")}),Of=Ne.z.object({name:Ne.z.string().min(1).optional(),description:Ne.z.string().optional(),tags:Ne.z.array(Ne.z.string()).optional(),timeout:Ne.z.number().int().positive().optional(),type:Ne.z.enum(["ui","api","audit","performance"]).optional()})});function Ze(r){return Lf.some(e=>e.test(r))?"api":"ui"}var Lf,Ir=w(()=>{"use strict";p();Lf=[/\b(GET|POST|PUT|DELETE|PATCH)\s+\//i,/\bsend\s+(a\s+)?(GET|POST|PUT|DELETE|PATCH)\b/i,/\b(api|rest|http|graphql)\s+(call|request|endpoint)/i,/\bresponse\s+(status|body|code|header|time|structure|bodies|fields)/i,/\bstatus\s+code/i,/\brequest\s+(to|with|body|header)/i,/\bextract\s+.*\bfrom\s+response\b/i,/\bauthenticate\s+via\s+(api|token)\b/i,/\bfetch\s+.*\bfrom\s+api\b/i,/\bverify\s+(the\s+)?(response|api|endpoint|status)/i,/\b\/api\//i,/\brequest\s+body\b/i,/\b(response|request)\s+(body|code|header)/i,/\b(store|save|extract)\s+(the\s+)?(full\s+)?(response|request|body|token|header)/i,/\berror\s+(fields?|messages?)\s+.*\bresponse/i,/\bresponse\s+.*\b(error|fields?|messages?|bodies|keys|data\s+types?)/i,/\b(three|two|all|multiple)\s+(response|request)/i,/\bscoped.?token\b/i,/\boauth\b/i,/\baccess.?token\b/i,/\b(bearer|authorization)\s+token\b/i,/\bjson\s+(response|body|payload)\b/i,/\bhttp\s+\d{3}\b/i,/\bpayload\b/i]});var Fc={};Q(Fc,{createCase:()=>Jr,deleteCase:()=>js,findCasePathById:()=>ut,getCasePath:()=>Df,listCasePaths:()=>Ht,listCases:()=>qe,readCase:()=>se,updateCase:()=>Me,writeCase:()=>Fs});async function se(r){if(!await Wr.default.pathExists(r))throw new ie(`Test case file not found at "${r}".`,r,"CASE_NOT_FOUND");let e=await de(r),t=ea.safeParse(e);if(!t.success){let s=t.error.issues.map(n=>` \u2022 ${n.path.join(".")}: ${n.message}`).join(`
95
+ ${n}`,"suite","INVALID_SUITE")}await K(t,s.data),Zr.debug({suiteId:e.id,path:t},"Suite written")}async function Gs(r,e){let t=new Date().toISOString(),s=e.type??"ui",n={...e,type:s,id:(0,qc.v4)(),createdAt:t,updatedAt:t},i=Re.default.join(r,s),a=Re.default.join(i,kt(n.name));if(await qe.default.pathExists(Re.default.join(a,In)))throw new oe(`Suite directory already exists at "${a}". Choose a different name or delete the existing suite first.`,a,"SUITE_ALREADY_EXISTS");return await da(a,n),Zr.info({suiteId:n.id,path:a},"Suite created"),{suiteDir:a,suiteId:n.id}}async function Pn(r,e){let t=await ve(r),s={...t,...e,id:t.id,createdAt:t.createdAt,updatedAt:new Date().toISOString()};return await da(r,s),s}async function pa(r){if(!await qe.default.pathExists(r))throw new oe(`Suite directory not found at "${r}".`,r,"SUITE_NOT_FOUND");await qe.default.remove(r),Zr.info({path:r},"Suite deleted")}async function $t(r){let e=[],t=[Re.default.join(r,"ui"),Re.default.join(r,"api"),Re.default.join(r,"audit"),Re.default.join(r,"performance"),r];for(let s of t){if(!await qe.default.pathExists(s))continue;let n=await qe.default.readdir(s,{withFileTypes:!0});for(let i of n){if(!i.isDirectory()||s===r&&(i.name==="ui"||i.name==="api"||i.name==="audit"||i.name==="performance"))continue;let a=Re.default.join(s,i.name,In);await qe.default.pathExists(a)&&e.push(Re.default.join(s,i.name))}}return e}async function ma(r,e,t){let s=await ve(e),n=Re.default.basename(e),i=Re.default.join(r,t),a=Re.default.join(i,n);if(e===a)return e;if(await qe.default.ensureDir(i),await qe.default.pathExists(a))throw new oe(`Cannot move suite \u2014 "${a}" already exists.`,a,"SUITE_ALREADY_EXISTS");return await qe.default.move(e,a),await Pn(a,{type:t}),Zr.info({suiteId:s.id,from:e,to:a},"Suite moved"),a}async function de(r,e){let t=await $t(r);for(let s of t)try{if((await ve(s)).id===e)return s}catch{}return null}async function kr(r){let e=await $t(r),t=[];for(let s of e)try{t.push(await ve(s))}catch(n){Zr.warn({path:s,err:n},"Failed to read suite \u2014 skipping")}return t}async function ga(r){let e=await $t(r),t=[];for(let s of e)try{let n=await ve(s),a=(await qe.default.readdir(s,{withFileTypes:!0})).filter(o=>o.isFile()&&o.name.endsWith(".test.json")).length;t.push({...n,caseCount:a})}catch(n){Zr.warn({path:s,err:n},"Failed to read suite \u2014 skipping")}return t}var Re,qe,qc,Zr,In,Xe=b(()=>{"use strict";m();Re=x(require("path")),qe=x(require("fs-extra")),qc=require("uuid");Vs();te();N();At();ze();Zr=E("suite-store"),In="suite.json"});async function Kc(r){let e=Xc.default.join(r.rootDir,"tests");r.get("/suites",async(t,s)=>{try{let n=await ga(e),i=t.query.type;return(i==="ui"||i==="api"||i==="performance")&&(n=n.filter(a=>a.type===i)),s.send(n)}catch(n){return w(s,500,"Failed to list suites",n)}}),r.post("/suites",async(t,s)=>{let n=nh.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid suite data",details:n.error.issues});try{let{suiteDir:i}=await Gs(e,n.data),a=await ve(i);return s.status(201).send(a)}catch(i){return w(s,500,"Failed to create suite",i)}}),r.get("/suites/:id",async(t,s)=>{try{let n=await de(e,t.params.id);if(!n)return s.status(404).send({error:`Suite "${t.params.id}" not found`});let i=await ve(n);return s.send(i)}catch(n){return w(s,500,"Failed to get suite",n)}}),r.patch("/suites/:id",async(t,s)=>{let n=ih.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid suite data",details:n.error.issues});try{let i=await de(e,t.params.id);if(!i)return s.status(404).send({error:`Suite "${t.params.id}" not found`});n.data.type&&(await ve(i)).type!==n.data.type&&(i=await ma(e,i,n.data.type));let a=await Pn(i,n.data);return s.send(a)}catch(i){return w(s,500,"Failed to update suite",i)}}),r.delete("/suites/:id",async(t,s)=>{try{let n=await de(e,t.params.id);return n?(await pa(n),s.status(204).send()):s.status(404).send({error:`Suite "${t.params.id}" not found`})}catch(n){return w(s,500,"Failed to delete suite",n)}})}var Xc,je,nh,ih,Wc=b(()=>{"use strict";m();Xc=x(require("path")),je=require("zod");Xe();re();nh=je.z.object({name:je.z.string().min(1),description:je.z.string().default(""),tags:je.z.array(je.z.string()).default([]),type:je.z.enum(["ui","api","audit","performance"]).default("ui")}),ih=je.z.object({name:je.z.string().min(1).optional(),description:je.z.string().optional(),tags:je.z.array(je.z.string()).optional(),timeout:je.z.number().int().positive().optional(),type:je.z.enum(["ui","api","audit","performance"]).optional()})});function tt(r){return ah.some(e=>e.test(r))?"api":"ui"}var ah,Ar=b(()=>{"use strict";m();ah=[/\b(GET|POST|PUT|DELETE|PATCH)\s+\//i,/\bsend\s+(a\s+)?(GET|POST|PUT|DELETE|PATCH)\b/i,/\b(api|rest|http|graphql)\s+(call|request|endpoint)/i,/\bresponse\s+(status|body|code|header|time|structure|bodies|fields)/i,/\bstatus\s+code/i,/\brequest\s+(to|with|body|header)/i,/\bextract\s+.*\bfrom\s+response\b/i,/\bauthenticate\s+via\s+(api|token)\b/i,/\bfetch\s+.*\bfrom\s+api\b/i,/\bverify\s+(the\s+)?(response|api|endpoint|status)/i,/\b\/api\//i,/\brequest\s+body\b/i,/\b(response|request)\s+(body|code|header)/i,/\b(store|save|extract)\s+(the\s+)?(full\s+)?(response|request|body|token|header)/i,/\berror\s+(fields?|messages?)\s+.*\bresponse/i,/\bresponse\s+.*\b(error|fields?|messages?|bodies|keys|data\s+types?)/i,/\b(three|two|all|multiple)\s+(response|request)/i,/\bscoped.?token\b/i,/\boauth\b/i,/\baccess.?token\b/i,/\b(bearer|authorization)\s+token\b/i,/\bjson\s+(response|body|payload)\b/i,/\bhttp\s+\d{3}\b/i,/\bpayload\b/i]});var Yc={};Q(Yc,{createCase:()=>ts,deleteCase:()=>qs,findCasePathById:()=>mt,getCasePath:()=>oh,listCasePaths:()=>zt,listCases:()=>Ke,readCase:()=>se,updateCase:()=>Be,writeCase:()=>zs});async function se(r){if(!await es.default.pathExists(r))throw new oe(`Test case file not found at "${r}".`,r,"CASE_NOT_FOUND");let e=await ue(r),t=ca.safeParse(e);if(!t.success){let s=t.error.issues.map(n=>` \u2022 ${n.path.join(".")}: ${n.message}`).join(`
96
96
  `);throw new X(`Invalid test case file at "${r}":
97
- ${s}`,"case","INVALID_CASE")}return t.data}async function Fs(r,e){let t=ea.safeParse(e);if(!t.success){let s=t.error.issues.map(n=>` \u2022 ${n.path.join(".")}: ${n.message}`).join(`
97
+ ${s}`,"case","INVALID_CASE")}return t.data}async function zs(r,e){let t=ca.safeParse(e);if(!t.success){let s=t.error.issues.map(n=>` \u2022 ${n.path.join(".")}: ${n.message}`).join(`
98
98
  `);throw new X(`Cannot write invalid test case to "${r}":
99
- ${s}`,"case","INVALID_CASE")}await K(r,t.data),Sn.debug({caseId:e.id,path:r},"Test case written")}async function Jr(r,e){let t=new Date().toISOString(),s={...e,id:(0,Mc.v4)(),createdAt:t,updatedAt:t},n=xn.default.join(r,`${It(s.name)}${ca}`);return await Fs(n,s),Sn.info({caseId:s.id,path:n},"Test case created"),n}async function Me(r,e){let t=await se(r),s={...t,...e,id:t.id,createdAt:t.createdAt,updatedAt:new Date().toISOString()};return await Fs(r,s),s}async function js(r){if(!await Wr.default.pathExists(r))throw new ie(`Test case file not found at "${r}".`,r,"CASE_NOT_FOUND");await Wr.default.remove(r),Sn.info({path:r},"Test case deleted")}async function Ht(r){return await Wr.default.pathExists(r)?(await Wr.default.readdir(r,{withFileTypes:!0})).filter(t=>t.isFile()&&t.name.endsWith(ca)).map(t=>xn.default.join(r,t.name)):[]}async function qe(r){let e=await Ht(r),t=[];for(let s of e)try{t.push(await se(s))}catch(n){Sn.warn({path:s,err:n},"Failed to read test case \u2014 skipping")}return t.sort((s,n)=>s.name.localeCompare(n.name))}function Df(r,e){return xn.default.join(r,`${It(e)}${ca}`)}async function ut(r,e){let t=await Ht(r);for(let s of t)try{if((await se(s)).id===e)return s}catch{}return null}var xn,Wr,Mc,Sn,ca,dt=w(()=>{"use strict";p();xn=x(require("path")),Wr=x(require("fs-extra")),Mc=require("uuid");Ns();re();F();Rt();Ve();Sn=E("case-store"),ca=".test.json"});async function Bc(r){let e=jc.default.join(r.rootDir,"tests");async function t(s){return pe(e,s)}r.post("/suites/:suiteId/cases/bulk-delete",async(s,n)=>{let i=jf.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid request"});try{let a=await t(s.params.suiteId);if(!a)return n.status(404).send({error:`Suite "${s.params.suiteId}" not found`});let o=0;for(let c of i.data.ids){let l=await ut(a,c);l&&(await js(l),o++)}return n.send({deleted:o})}catch(a){return b(n,500,"Failed to bulk delete cases",a)}}),r.post("/suites/:suiteId/cases/bulk-move",async(s,n)=>{let i=Bf.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid request"});try{let a=await t(s.params.suiteId);if(!a)return n.status(404).send({error:`Suite "${s.params.suiteId}" not found`});let o=await pe(e,i.data.targetSuiteId);if(!o)return n.status(404).send({error:`Target suite "${i.data.targetSuiteId}" not found`});let c=0;for(let l of i.data.ids){let u=await ut(a,l);if(u){let d=await se(u);await Jr(o,d),await js(u),c++}}return n.send({moved:c})}catch(a){return b(n,500,"Failed to bulk move cases",a)}}),r.get("/suites/:suiteId/cases",async(s,n)=>{try{let i=await t(s.params.suiteId);if(!i)return n.status(404).send({error:`Suite "${s.params.suiteId}" not found`});let a=await qe(i);return n.send(a)}catch(i){return b(n,500,"Failed to list cases",i)}}),r.post("/suites/:suiteId/cases",async(s,n)=>{let i=Nf.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid case data",details:i.error.issues});try{let a=await t(s.params.suiteId);if(!a)return n.status(404).send({error:`Suite "${s.params.suiteId}" not found`});let{name:o,description:c,tags:l,priority:u,steps:d}=i.data,g=await Jr(a,{name:o,description:c,tags:l,priority:u,steps:d.map((f,h)=>({id:`step-${h+1}`,order:h+1,instruction:f.instruction,generatedCode:"",strategy:"primary",stepType:Ze(f.instruction),lastHealed:null}))}),m=await se(g);return n.status(201).send(m)}catch(a){return b(n,500,"Failed to create case",a)}}),r.get("/suites/:suiteId/cases/:caseId",async(s,n)=>{try{let i=await t(s.params.suiteId);if(!i)return n.status(404).send({error:`Suite "${s.params.suiteId}" not found`});let a=await ut(i,s.params.caseId);if(!a)return n.status(404).send({error:`Case "${s.params.caseId}" not found`});let o=await se(a);return n.send(o)}catch(i){return b(n,500,"Failed to get case",i)}}),r.patch("/suites/:suiteId/cases/:caseId",async(s,n)=>{let i=Ff.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid case data",details:i.error.issues});try{let a=await t(s.params.suiteId);if(!a)return n.status(404).send({error:`Suite "${s.params.suiteId}" not found`});let o=await ut(a,s.params.caseId);if(!o)return n.status(404).send({error:`Case "${s.params.caseId}" not found`});let c=await Me(o,i.data);return n.send(c)}catch(a){return b(n,500,"Failed to update case",a)}}),r.delete("/suites/:suiteId/cases/:caseId",async(s,n)=>{try{let i=await t(s.params.suiteId);if(!i)return n.status(404).send({error:`Suite "${s.params.suiteId}" not found`});let a=await ut(i,s.params.caseId);return a?(await js(a),n.status(204).send()):n.status(404).send({error:`Case "${s.params.caseId}" not found`})}catch(i){return b(n,500,"Failed to delete case",i)}})}var jc,z,Nf,Mf,Ff,jf,Bf,Uc=w(()=>{"use strict";p();jc=x(require("path")),z=require("zod");Ir();dt();ze();ae();Nf=z.z.object({name:z.z.string().min(1),description:z.z.string().default(""),tags:z.z.array(z.z.string()).default([]),priority:z.z.enum(["critical","high","medium","low"]).default("medium"),steps:z.z.array(z.z.object({instruction:z.z.string().min(1)})).default([])}),Mf=z.z.object({type:z.z.enum(["inline","json-file","csv-file"]),path:z.z.string().optional(),data:z.z.array(z.z.record(z.z.string())).optional()}).optional().nullable(),Ff=z.z.object({name:z.z.string().min(1).optional(),description:z.z.string().optional(),tags:z.z.array(z.z.string()).optional(),priority:z.z.enum(["critical","high","medium","low"]).optional(),timeout:z.z.number().int().positive().optional(),dataSource:Mf,lighthouseCategories:z.z.array(z.z.enum(["performance","accessibility","seo"])).optional()}),jf=z.z.object({ids:z.z.array(z.z.string().min(1)).min(1)}),Bf=z.z.object({ids:z.z.array(z.z.string().min(1)).min(1),targetSuiteId:z.z.string().min(1)})});function Vf(r){return typeof r=="object"&&r.secret===!0}function Hc(r){return Vf(r)?r.value:r}var or,Uf,Hf,la,Vc=w(()=>{"use strict";p();or=require("zod"),Uf=or.z.object({value:or.z.string(),secret:or.z.literal(!0)}),Hf=or.z.union([or.z.string(),Uf]),la=or.z.record(or.z.string(),Hf)});function zf(r){return`${r}.env.json`}async function Yr(r){if(!await Bs.default.pathExists(r))return{};let e=await de(r),t=la.safeParse(e);if(!t.success){let s=t.error.issues.map(n=>` \u2022 ${n.path.join(".")}: ${n.message}`).join(`
99
+ ${s}`,"case","INVALID_CASE")}await K(r,t.data),Tn.debug({caseId:e.id,path:r},"Test case written")}async function ts(r,e){let t=new Date().toISOString(),s={...e,id:(0,Jc.v4)(),createdAt:t,updatedAt:t},n=Rn.default.join(r,`${kt(s.name)}${ha}`);return await zs(n,s),Tn.info({caseId:s.id,path:n},"Test case created"),n}async function Be(r,e){let t=await se(r),s={...t,...e,id:t.id,createdAt:t.createdAt,updatedAt:new Date().toISOString()};return await zs(r,s),s}async function qs(r){if(!await es.default.pathExists(r))throw new oe(`Test case file not found at "${r}".`,r,"CASE_NOT_FOUND");await es.default.remove(r),Tn.info({path:r},"Test case deleted")}async function zt(r){return await es.default.pathExists(r)?(await es.default.readdir(r,{withFileTypes:!0})).filter(t=>t.isFile()&&t.name.endsWith(ha)).map(t=>Rn.default.join(r,t.name)):[]}async function Ke(r){let e=await zt(r),t=[];for(let s of e)try{t.push(await se(s))}catch(n){Tn.warn({path:s,err:n},"Failed to read test case \u2014 skipping")}return t.sort((s,n)=>s.name.localeCompare(n.name))}function oh(r,e){return Rn.default.join(r,`${kt(e)}${ha}`)}async function mt(r,e){let t=await zt(r);for(let s of t)try{if((await se(s)).id===e)return s}catch{}return null}var Rn,es,Jc,Tn,ha,gt=b(()=>{"use strict";m();Rn=x(require("path")),es=x(require("fs-extra")),Jc=require("uuid");Vs();te();N();At();ze();Tn=E("case-store"),ha=".test.json"});async function Zc(r){let e=Qc.default.join(r.rootDir,"tests");async function t(s){return de(e,s)}r.post("/suites/:suiteId/cases/bulk-delete",async(s,n)=>{let i=dh.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid request"});try{let a=await t(s.params.suiteId);if(!a)return n.status(404).send({error:`Suite "${s.params.suiteId}" not found`});let o=0;for(let c of i.data.ids){let l=await mt(a,c);l&&(await qs(l),o++)}return n.send({deleted:o})}catch(a){return w(n,500,"Failed to bulk delete cases",a)}}),r.post("/suites/:suiteId/cases/bulk-move",async(s,n)=>{let i=ph.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid request"});try{let a=await t(s.params.suiteId);if(!a)return n.status(404).send({error:`Suite "${s.params.suiteId}" not found`});let o=await de(e,i.data.targetSuiteId);if(!o)return n.status(404).send({error:`Target suite "${i.data.targetSuiteId}" not found`});let c=0;for(let l of i.data.ids){let u=await mt(a,l);if(u){let d=await se(u);await ts(o,d),await qs(u),c++}}return n.send({moved:c})}catch(a){return w(n,500,"Failed to bulk move cases",a)}}),r.get("/suites/:suiteId/cases",async(s,n)=>{try{let i=await t(s.params.suiteId);if(!i)return n.status(404).send({error:`Suite "${s.params.suiteId}" not found`});let a=await Ke(i);return n.send(a)}catch(i){return w(n,500,"Failed to list cases",i)}}),r.post("/suites/:suiteId/cases",async(s,n)=>{let i=ch.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid case data",details:i.error.issues});try{let a=await t(s.params.suiteId);if(!a)return n.status(404).send({error:`Suite "${s.params.suiteId}" not found`});let{name:o,description:c,tags:l,priority:u,steps:d}=i.data,p=await ts(a,{name:o,description:c,tags:l,priority:u,steps:d.map((f,h)=>({id:`step-${h+1}`,order:h+1,instruction:f.instruction,generatedCode:"",strategy:"primary",stepType:tt(f.instruction),lastHealed:null}))}),g=await se(p);return n.status(201).send(g)}catch(a){return w(n,500,"Failed to create case",a)}}),r.get("/suites/:suiteId/cases/:caseId",async(s,n)=>{try{let i=await t(s.params.suiteId);if(!i)return n.status(404).send({error:`Suite "${s.params.suiteId}" not found`});let a=await mt(i,s.params.caseId);if(!a)return n.status(404).send({error:`Case "${s.params.caseId}" not found`});let o=await se(a);return n.send(o)}catch(i){return w(n,500,"Failed to get case",i)}}),r.patch("/suites/:suiteId/cases/:caseId",async(s,n)=>{let i=uh.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid case data",details:i.error.issues});try{let a=await t(s.params.suiteId);if(!a)return n.status(404).send({error:`Suite "${s.params.suiteId}" not found`});let o=await mt(a,s.params.caseId);if(!o)return n.status(404).send({error:`Case "${s.params.caseId}" not found`});let c=await Be(o,i.data);return n.send(c)}catch(a){return w(n,500,"Failed to update case",a)}}),r.delete("/suites/:suiteId/cases/:caseId",async(s,n)=>{try{let i=await t(s.params.suiteId);if(!i)return n.status(404).send({error:`Suite "${s.params.suiteId}" not found`});let a=await mt(i,s.params.caseId);return a?(await qs(a),n.status(204).send()):n.status(404).send({error:`Case "${s.params.caseId}" not found`})}catch(i){return w(n,500,"Failed to delete case",i)}})}var Qc,z,ch,lh,uh,dh,ph,el=b(()=>{"use strict";m();Qc=x(require("path")),z=require("zod");Ar();gt();Xe();re();ch=z.z.object({name:z.z.string().min(1),description:z.z.string().default(""),tags:z.z.array(z.z.string()).default([]),priority:z.z.enum(["critical","high","medium","low"]).default("medium"),steps:z.z.array(z.z.object({instruction:z.z.string().min(1)})).default([])}),lh=z.z.object({type:z.z.enum(["inline","json-file","csv-file"]),path:z.z.string().optional(),data:z.z.array(z.z.record(z.z.string())).optional()}).optional().nullable(),uh=z.z.object({name:z.z.string().min(1).optional(),description:z.z.string().optional(),tags:z.z.array(z.z.string()).optional(),priority:z.z.enum(["critical","high","medium","low"]).optional(),timeout:z.z.number().int().positive().optional(),dataSource:lh,lighthouseCategories:z.z.array(z.z.enum(["performance","accessibility","seo"])).optional()}),dh=z.z.object({ids:z.z.array(z.z.string().min(1)).min(1)}),ph=z.z.object({ids:z.z.array(z.z.string().min(1)).min(1),targetSuiteId:z.z.string().min(1)})});function fh(r){return typeof r=="object"&&r.secret===!0}function tl(r){return fh(r)?r.value:r}var ur,mh,gh,ya,rl=b(()=>{"use strict";m();ur=require("zod"),mh=ur.z.object({value:ur.z.string(),secret:ur.z.literal(!0)}),gh=ur.z.union([ur.z.string(),mh]),ya=ur.z.record(ur.z.string(),gh)});function yh(r){return`${r}.env.json`}async function rs(r){if(!await Xs.default.pathExists(r))return{};let e=await ue(r),t=ya.safeParse(e);if(!t.success){let s=t.error.issues.map(n=>` \u2022 ${n.path.join(".")}: ${n.message}`).join(`
100
100
  `);throw new X(`Invalid variables file at "${r}":
101
- ${s}`,"variables","INVALID_VARIABLES")}return t.data}async function Gc(r,e){let t=la.safeParse(e);if(!t.success){let s=t.error.issues.map(n=>` \u2022 ${n.path.join(".")}: ${n.message}`).join(`
101
+ ${s}`,"variables","INVALID_VARIABLES")}return t.data}async function sl(r,e){let t=ya.safeParse(e);if(!t.success){let s=t.error.issues.map(n=>` \u2022 ${n.path.join(".")}: ${n.message}`).join(`
102
102
  `);throw new X(`Cannot write invalid variables to "${r}":
103
- ${s}`,"variables","INVALID_VARIABLES")}await K(r,t.data),Gf.debug({path:r},"Variables written")}async function da(r){let e=cr.default.join(r,Us,ua);return Yr(e)}async function pa(r,e){let t=cr.default.join(r,Us,zf(e));return Yr(t)}async function et(r,e){let t=await da(r),s=e?await pa(r,e):{},n={...t,...s},i={};for(let[a,o]of Object.entries(n))i[a]=Hc(o);return i}async function zc(r,e,t){let s=cr.default.join(r,Us,ua);await Bs.default.ensureDir(cr.default.dirname(s));let n=await Yr(s);n[e]=t,await Gc(s,n)}async function qc(r,e){let t=cr.default.join(r,Us,ua),s=await Yr(t);if(!(e in s))throw new ie(`Variable "${e}" not found in global variables.`,t,"VARIABLE_NOT_FOUND");delete s[e],await Gc(t,s)}async function Xc(r){let e=cr.default.join(r,Us);return await Bs.default.pathExists(e)?(await Bs.default.readdir(e,{withFileTypes:!0})).filter(s=>s.isFile()&&s.name.endsWith(".json")).map(s=>cr.default.join(e,s.name)):[]}var cr,Bs,Gf,Us,ua,lr=w(()=>{"use strict";p();cr=x(require("path")),Bs=x(require("fs-extra"));Vc();re();F();Ve();Gf=E("variable-store"),Us="variables",ua="global.json"});function qf(r){let e=r.trim();return/^https?:\/\//i.test(e)?e:e.startsWith("/")?`{{BASE_URL}}${e}`:/^[\w-]+\.[\w.-]+/.test(e)?`https://${e}`:e}function Hs(r){return(r??"").trim().replace(/^(?:the|a|an)\s+/i,"").replace(/\s+(?:field|input|box|textbox|dropdown|drop-down|menu|list|selector|element)$/i,"").trim()}function ma(r){let e=Hs(r);return/\b(?:pass(?:word|code|phrase)?|pwd)\b/i.test(e)?`page.getByLabel('${e}')`:/\b(?:number|amount|quantity|qty|age|count)\b/i.test(e)?`page.getByRole('spinbutton', { name: '${e}' })`:`page.getByRole('textbox', { name: '${e}' })`}var Kc,Cn,Wc=w(()=>{"use strict";p();Kc=[{regex:/^(?:go to|navigate to|open|visit)\s+(.+)$/i,gen:r=>`await page.goto('${qf(r[1]??"")}');`},{regex:/^(?:go|navigate)\s+back$/i,gen:()=>"await page.goBack();"},{regex:/^refresh\s+(?:the\s+)?page$/i,gen:()=>"await page.reload();"},{regex:/^(?:select|choose|click|tick|pick)\s+(?:the\s+)?(?:on\s+)?["']?(.+?)["']?\s+radio(?:\s+button)?$/i,gen:r=>`await page.getByRole('radio', { name: '${Hs(r[1]??"")}' }).check();`},{regex:/^click\s+(?:the\s+)?(?:on\s+)?["'](.+?)["'](\s+button|\s+link|\s+tab|\s+menu)?$/i,gen:r=>{let e=r[1]??"",t=(r[2]??"").trim().toLowerCase();return t==="button"?`await page.getByRole('button', { name: '${e}' }).click();`:t==="link"?`await page.getByRole('link', { name: '${e}' }).click();`:`await page.getByText('${e}').click();`}},{regex:/^click\s+(?:the\s+)?(?:on\s+)?(\w[\w\s]{0,30}?)(\s+button|\s+link|\s+tab)?$/i,gen:r=>{let e=(r[1]??"").trim(),t=(r[2]??"").trim().toLowerCase();return t==="button"?`await page.getByRole('button', { name: '${e}' }).click();`:t==="link"?`await page.getByRole('link', { name: '${e}' }).click();`:`await page.getByText('${e}').click();`}},{regex:/^double\s+click\s+(?:the\s+)?(?:on\s+)?["']?(.+?)["']?$/i,gen:r=>`await page.getByText('${r[1]}').dblclick();`},{regex:/^right\s+click\s+(?:the\s+)?(?:on\s+)?["']?(.+?)["']?$/i,gen:r=>`await page.getByText('${r[1]}').click({ button: 'right' });`},{regex:/^(?:type|enter|fill|input)\s+["']?(.+?)["']?\s+(?:in|into)\s+(?:the\s+)?(.+)$/i,gen:r=>`await ${ma(r[2]??"")}.fill('${r[1]}');`},{regex:/^clear\s+(?:the\s+)?(.+?)(?:\s+field)?$/i,gen:r=>`await ${ma(r[1]??"")}.clear();`},{regex:/^(?:verify|check|assert|ensure|confirm)\s+(?:that\s+)?["'](.+?)["']\s+(?:is\s+)?(?:visible|shown|displayed|present|appears)$/i,gen:r=>`await expect(page.getByText('${r[1]}')).toBeVisible();`},{regex:/^(?:verify|check|assert)\s+(?:that\s+)?["'](.+?)["']\s+(?:is\s+)?(?:not visible|hidden|not shown|gone|disappeared|not present)$/i,gen:r=>`await expect(page.getByText('${r[1]}')).not.toBeVisible();`},{regex:/^(?:verify|check)\s+(?:the\s+)?(?:page\s+)?title\s+(?:is|contains)\s+["'](.+?)["']$/i,gen:r=>`await expect(page).toHaveTitle(/${r[1]}/);`},{regex:/^(?:verify|check)\s+(?:the\s+)?url\s+(?:is|contains|matches)\s+["'](.+?)["']$/i,gen:r=>`await expect(page).toHaveURL(/${(r[1]??"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}/);`},{regex:/^(?:verify|check)\s+(?:the\s+)?["'](.+?)["']\s+(?:field|input)\s+(?:has value|contains|equals)\s+["'](.+?)["']$/i,gen:r=>`await expect(page.getByLabel('${r[1]}')).toHaveValue('${r[2]}');`},{regex:/^soft\s+(?:verify|check|assert|ensure|confirm)\s+(?:that\s+)?["'](.+?)["']\s+(?:is\s+)?(?:visible|shown|displayed|present|appears)$/i,gen:r=>`await expect.soft(page.getByText('${r[1]}')).toBeVisible();`},{regex:/^soft\s+(?:verify|check|assert)\s+(?:that\s+)?["'](.+?)["']\s+(?:is\s+)?(?:not visible|hidden|not shown|gone|disappeared|not present)$/i,gen:r=>`await expect.soft(page.getByText('${r[1]}')).not.toBeVisible();`},{regex:/^soft\s+(?:verify|check)\s+(?:the\s+)?(?:page\s+)?title\s+(?:is|contains)\s+["'](.+?)["']$/i,gen:r=>`await expect.soft(page).toHaveTitle(/${r[1]}/);`},{regex:/^soft\s+(?:verify|check)\s+(?:the\s+)?url\s+(?:is|contains|matches)\s+["'](.+?)["']$/i,gen:r=>`await expect.soft(page).toHaveURL(/${(r[1]??"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}/);`},{regex:/^soft\s+(?:verify|check)\s+(?:the\s+)?["'](.+?)["']\s+(?:field|input)\s+(?:has value|contains|equals)\s+["'](.+?)["']$/i,gen:r=>`await expect.soft(page.getByLabel('${r[1]}')).toHaveValue('${r[2]}');`},{regex:/^press\s+(.+)$/i,gen:r=>`await page.keyboard.press('${(r[1]??"").trim()}');`},{regex:/^(?:type|enter|fill)\s+["']?(.+?)["']?\s+(?:and\s+)?press\s+enter$/i,gen:r=>`await page.keyboard.type('${r[1]}');
104
- await page.keyboard.press('Enter');`},{regex:/^select\s+["'](.+?)["']\s+from\s+(?:the\s+)?(.+)$/i,gen:r=>`await page.getByRole('combobox', { name: '${Hs(r[2]??"")}' }).selectOption('${r[1]}');`},{regex:/^check\s+(?:the\s+)?["']?(.+?)["']?(?:\s+checkbox)?$/i,gen:r=>`await page.getByRole('checkbox', { name: '${Hs(r[1]??"")}' }).check();`},{regex:/^uncheck\s+(?:the\s+)?["']?(.+?)["']?(?:\s+checkbox)?$/i,gen:r=>`await page.getByRole('checkbox', { name: '${Hs(r[1]??"")}' }).uncheck();`},{regex:/^wait\s+(?:for\s+)?(\d+)\s+seconds?$/i,gen:r=>`await page.waitForTimeout(${parseInt(r[1]??"1",10)*1e3});`},{regex:/^wait\s+(?:for\s+)?(?:the\s+)?page\s+(?:to\s+)?load$/i,gen:()=>"await page.waitForLoadState('networkidle');"},{regex:/^scroll\s+(down|up)$/i,gen:r=>`await page.evaluate(() => window.scrollBy(0, ${(r[1]??"").toLowerCase()==="down"?500:-500}));`},{regex:/^scroll\s+to\s+(top|bottom)$/i,gen:r=>`await page.evaluate(() => window.scrollTo(0, ${(r[1]??"").toLowerCase()==="top"?0:"document.body.scrollHeight"}));`},{regex:/^hover\s+(?:over\s+)?(?:the\s+)?["']?(.+?)["']?$/i,gen:r=>`await page.getByText('${r[1]}').hover();`},{regex:/^take\s+(?:a\s+)?screenshot$/i,gen:()=>`await page.screenshot({ path: 'results/screenshots/step_${Date.now()}.png', fullPage: true });`},{regex:/^(?:focus|tab to)\s+(?:the\s+)?(.+?)(?:\s+field)?$/i,gen:r=>`await ${ma(r[1]??"")}.focus();`}],Cn=class{tryMatch(e){for(let t of Kc){let s=e.match(t.regex);if(s!==null)return t.gen(s)}return null}get patternCount(){return Kc.length}}});function Xf(r){return(0,Jc.createHash)("sha256").update(r,"utf8").digest("hex")}function Kf(r){try{return new URL(r).pathname.split("/").map(s=>/^\d+$/.test(s)||/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(s)||/^[a-z0-9-]{8,}$/i.test(s)&&/-/.test(s)?"*":s).join("/")}catch{return r}}function Yc(r,e){let t=r.toLowerCase().replace(/\s+/g," ").trim(),s=Kf(e);return Xf(`${t}|${s}`).slice(0,16)}var Jc,Qc=w(()=>{"use strict";p();Jc=require("crypto")});var Zc,ga,Qr,Wf,Jf,Zr,fa=w(()=>{"use strict";p();Zc=x(require("path")),ga=x(require("fs-extra"));Qc();F();Ve();Qr=E("code-cache"),Wf=Zc.default.join("results",".code-cache.json"),Jf=3e4,Zr=class{constructor(e=Wf){this.persistPath=e}cache=new Map;dirty=!1;persistTimer=null;generateKey(e,t){return Yc(e,t)}get(e){let t=this.cache.get(e);return t?t.failCount>=2?(this.cache.delete(e),this.dirty=!0,Qr.debug({key:e},"Cache entry invalidated after 2 failures"),null):(t.lastUsedAt=Date.now(),t):null}set(e,t,s){this.cache.set(e,{code:t,urlPattern:s,successCount:0,failCount:0,createdAt:Date.now(),lastUsedAt:Date.now()}),this.dirty=!0}recordPass(e){let t=this.cache.get(e);t&&(t.successCount++,t.failCount=0,this.dirty=!0)}recordFail(e){let t=this.cache.get(e);t&&(t.failCount++,t.failCount>=2&&(this.cache.delete(e),Qr.debug({key:e},"Cache entry removed after 2 failures")),this.dirty=!0)}get size(){return this.cache.size}async persist(){if(this.dirty)try{let e=Object.fromEntries(this.cache.entries());await K(this.persistPath,e),this.dirty=!1,Qr.debug({entries:this.cache.size,path:this.persistPath},"Cache persisted")}catch(e){Qr.warn({err:e},"Failed to persist code cache")}}async load(){if(await ga.default.pathExists(this.persistPath))try{let e=await ga.default.readJson(this.persistPath);this.cache.clear();for(let[t,s]of Object.entries(e))this.cache.set(t,s);Qr.debug({entries:this.cache.size,path:this.persistPath},"Cache loaded")}catch(e){Qr.warn({err:e},"Failed to load code cache \u2014 starting fresh")}}startAutoSave(){if(this.persistTimer)return;this.persistTimer=setInterval(()=>{this.persist()},Jf),this.persistTimer.unref&&this.persistTimer.unref();let e=()=>{this.persist()};process.once("exit",e),process.once("SIGINT",e),process.once("SIGTERM",e)}stopAutoSave(){this.persistTimer&&(clearInterval(this.persistTimer),this.persistTimer=null)}}});var Yf,En,el=w(()=>{"use strict";p();Yf=[/table|grid|chart|graph|calendar|datepicker/i,/drag|drop|resize|reorder|sortable/i,/verify.*(count|greater|less|between|exactly|more than|fewer)/i,/wait\s+until|disappears|loading\s+(?:is\s+)?(?:done|complete|finished)/i,/(?:first|second|third|last|nth|\d+(?:st|nd|rd|th))\s+(?:item|row|card|element|result)/i,/if\s+|conditional|depending|based on/i,/iframe|shadow\s*dom|popup|modal|dialog|alert/i,/upload|download|file|attachment/i,/hover\s+.*then|right.click|double.click/i,/api|network|request|response|intercept/i,/(?:store|save|capture|extract)\s+.*(?:variable|value|text)/i,/multi.?select|autocomplete|typeahead|combobox/i],En=class{classify(e){let t=Yf.filter(s=>s.test(e)).length;return t>=2?"complex":t===1?"medium":"simple"}}});var ha,Pn,tl=w(()=>{"use strict";p();Rt();F();ha=E("batch-processor"),Pn=class{constructor(e,t){this.templateEngine=e;this.cache=t}async batchGenerate(e,t){let s=new Map,n=[];for(let o=0;o<e.length;o++){let{instruction:c,context:l}=e[o],u=this.templateEngine.tryMatch(c);if(u!==null){s.set(o,u);continue}let d=this.cache.generateKey(c,l.url),g=this.cache.get(d);if(g!==null){s.set(o,g.code);continue}n.push({index:o,instruction:c,context:l})}if(ha.debug({total:e.length,local:s.size,needsAI:n.length},"Batch resolution"),n.length===0)return s;let i=n.map(o=>({instruction:o.instruction,context:o.context})),a=await t.batchGenerateCode(i);for(let o=0;o<n.length;o++){let c=n[o],l=a[o];if(!l){ha.warn({instruction:c.instruction},"AI returned empty code for step");continue}let u;try{u=Oe(l)}catch(g){ha.warn({instruction:c.instruction,err:g},"Skipping unsafe/invalid batch result");continue}s.set(c.index,u);let d=this.cache.generateKey(c.instruction,c.context.url);this.cache.set(d,u,c.context.url)}return s}}});function eh(r){return(r.match(/^(\s*)/)?.[1]??"").replace(/\t/g," ").length}function th(r,e){if(r)return`iframe[name='${r}']`;let t=e.match(/title=([^\s\]]+)/i);return t?`iframe[title='${t[1]}']`:"iframe"}function In(r){if(!r||!r.trim())return{title:"",interactiveElements:"",accessibilityTree:""};let e=r.split(`
105
- `),t="",s=[],n=[];for(let l of e){let u=l.trim();if(!u||u==="-")continue;let d=eh(l);for(;n.length>0&&d<=n[n.length-1].indent;)n.pop();let g=u.match(/^-?\s*Page\s+"([^"]*)"/i);if(g){t=g[1]??"";continue}let m=u.match(/^-?\s*([\w-]+)(?:\s+"([^"]*)")?(?:\s+\[([^\]]*)\])?/);if(!m)continue;let f=m[1].toLowerCase(),h=m[2]??"",C=m[3]??"";if(f==="iframe"||f==="frame"){let k=n.length>0?n[n.length-1].chain:"",R=th(h,C),I=k?`${k}||${R}`:R;n.push({indent:d,chain:I});continue}if(h.length>80&&(h=h.slice(0,79)+"\u2026"),!h&&!C)continue;let P=Qf.has(f),v=Zf.has(f);if(P||v){let k=n.length>0?n[n.length-1].chain:null;s.push({role:f,name:h,attrs:C,isInteractive:P,frame:k})}}let i=s.filter(l=>l.isInteractive),a=s.filter(l=>!l.isInteractive),c=[...i,...a].slice(0,120).map(l=>{let u=`${l.role} "${l.name}"`;return l.attrs&&(u+=` [${l.attrs}]`),l.frame&&(u+=` frame="${l.frame}"`),u});return{title:t,interactiveElements:c.join(`
106
- `),accessibilityTree:r.slice(0,8e3)}}var Qf,Zf,ya=w(()=>{"use strict";p();Qf=new Set(["button","link","textbox","checkbox","radio","combobox","listbox","menuitem","menuitemcheckbox","menuitemradio","option","searchbox","slider","spinbutton","switch","tab","treeitem"]),Zf=new Set(["heading","img","navigation","dialog","alert","alertdialog","status","progressbar","table","row","cell","columnheader","rowheader"])});function rl(r,e){let t=`Current page accessibility snapshot:
103
+ ${s}`,"variables","INVALID_VARIABLES")}await K(r,t.data),hh.debug({path:r},"Variables written")}async function ba(r){let e=dr.default.join(r,Ks,wa);return rs(e)}async function va(r,e){let t=dr.default.join(r,Ks,yh(e));return rs(t)}async function rt(r,e){let t=await ba(r),s=e?await va(r,e):{},n={...t,...s},i={};for(let[a,o]of Object.entries(n))i[a]=tl(o);return i}async function nl(r,e,t){let s=dr.default.join(r,Ks,wa);await Xs.default.ensureDir(dr.default.dirname(s));let n=await rs(s);n[e]=t,await sl(s,n)}async function il(r,e){let t=dr.default.join(r,Ks,wa),s=await rs(t);if(!(e in s))throw new oe(`Variable "${e}" not found in global variables.`,t,"VARIABLE_NOT_FOUND");delete s[e],await sl(t,s)}async function al(r){let e=dr.default.join(r,Ks);return await Xs.default.pathExists(e)?(await Xs.default.readdir(e,{withFileTypes:!0})).filter(s=>s.isFile()&&s.name.endsWith(".json")).map(s=>dr.default.join(e,s.name)):[]}var dr,Xs,hh,Ks,wa,pr=b(()=>{"use strict";m();dr=x(require("path")),Xs=x(require("fs-extra"));rl();te();N();ze();hh=E("variable-store"),Ks="variables",wa="global.json"});function wh(r){let e=r.trim();return/^https?:\/\//i.test(e)?e:e.startsWith("/")?`{{BASE_URL}}${e}`:/^[\w-]+\.[\w.-]+/.test(e)?`https://${e}`:e}function $r(r){return(r??"").trim().replace(/^(?:the|a|an)\s+/i,"").replace(/\s+(?:field|input|box|textbox|dropdown|drop-down|menu|list|selector|element)$/i,"").trim()}function xa(r){let e=$r(r);return/\b(?:pass(?:word|code|phrase)?|pwd)\b/i.test(e)?`page.getByLabel('${e}')`:/\b(?:number|amount|quantity|qty|age|count)\b/i.test(e)?`page.getByRole('spinbutton', { name: '${e}' })`:`page.getByRole('textbox', { name: '${e}' })`}function Sa(r,e,t){let s=$r(e),i=[`await ${s?`page.getByLabel('${s}')`:`page.locator('input[type="file"]')`}.setInputFiles('${r}');`];return t?i.push(`await expect(page.getByText('${t}')).toBeVisible();`):i.push("await page.waitForLoadState('networkidle');"),i.join(`
104
+ `)}function ol(r,e){let t=$r(r);return["const downloadPromise = page.waitForEvent('download');",`await ${e==="button"?`page.getByRole('button', { name: '${t}' })`:e==="link"?`page.getByRole('link', { name: '${t}' })`:`page.getByText('${t}')`}.click();`,"const download = await downloadPromise;","await download.path();"].join(`
105
+ `)}var cl,kn,ll=b(()=>{"use strict";m();cl=[{regex:/^(?:go to|navigate to|open|visit)\s+(.+)$/i,gen:r=>`await page.goto('${wh(r[1]??"")}');`},{regex:/^(?:go|navigate)\s+back$/i,gen:()=>"await page.goBack();"},{regex:/^refresh\s+(?:the\s+)?page$/i,gen:()=>"await page.reload();"},{regex:/^download\s+(?:the\s+)?(?:file\s+)?(?:by\s+clicking\s+)?["']?(.+?)["']?(\s+button|\s+link)?$/i,gen:r=>ol((r[1]??"").trim(),(r[2]??"").trim().toLowerCase())},{regex:/^click\s+(?:the\s+)?(?:on\s+)?["']?(.+?)["']?(\s+button|\s+link)?\s+(?:to\s+download|and\s+wait\s+for\s+(?:the\s+)?download)$/i,gen:r=>ol((r[1]??"").trim(),(r[2]??"").trim().toLowerCase())},{regex:/^(?:select|choose|click|tick|pick)\s+(?:the\s+)?(?:on\s+)?["']?(.+?)["']?\s+radio(?:\s+button)?$/i,gen:r=>`await page.getByRole('radio', { name: '${$r(r[1]??"")}' }).check();`},{regex:/^click\s+(?:the\s+)?(?:on\s+)?["'](.+?)["'](\s+button|\s+link|\s+tab|\s+menu)?$/i,gen:r=>{let e=r[1]??"",t=(r[2]??"").trim().toLowerCase();return t==="button"?`await page.getByRole('button', { name: '${e}' }).click();`:t==="link"?`await page.getByRole('link', { name: '${e}' }).click();`:`await page.getByText('${e}').click();`}},{regex:/^click\s+(?:the\s+)?(?:on\s+)?(\w[\w\s]{0,30}?)(\s+button|\s+link|\s+tab)?$/i,gen:r=>{let e=(r[1]??"").trim(),t=(r[2]??"").trim().toLowerCase();return t==="button"?`await page.getByRole('button', { name: '${e}' }).click();`:t==="link"?`await page.getByRole('link', { name: '${e}' }).click();`:`await page.getByText('${e}').click();`}},{regex:/^double\s+click\s+(?:the\s+)?(?:on\s+)?["']?(.+?)["']?$/i,gen:r=>`await page.getByText('${r[1]}').dblclick();`},{regex:/^right\s+click\s+(?:the\s+)?(?:on\s+)?["']?(.+?)["']?$/i,gen:r=>`await page.getByText('${r[1]}').click({ button: 'right' });`},{regex:/^(?:type|enter|fill|input)\s+["']?(.+?)["']?\s+(?:in|into)\s+(?:the\s+)?(.+)$/i,gen:r=>`await ${xa(r[2]??"")}.fill('${r[1]}');`},{regex:/^clear\s+(?:the\s+)?(.+?)(?:\s+field)?$/i,gen:r=>`await ${xa(r[1]??"")}.clear();`},{regex:/^upload\s+(?:the\s+)?(?:file\s+)?["']?(.+?)["']?\s+(?:to|into|in|on)\s+(?:the\s+)?(.+?)\s+and\s+wait\s+for\s+["'](.+?)["']$/i,gen:r=>Sa(r[1]??"",r[2]??"",r[3]??"")},{regex:/^upload\s+(?:the\s+)?(?:file\s+)?["']?(.+?)["']?\s+(?:to|into|in|on)\s+(?:the\s+)?(.+)$/i,gen:r=>Sa(r[1]??"",r[2]??"","")},{regex:/^upload\s+(?:the\s+)?(?:file\s+)?["']?(.+?)["']?$/i,gen:r=>Sa(r[1]??"","","")},{regex:/^(?:verify|check|assert|ensure|confirm)\s+(?:that\s+)?["'](.+?)["']\s+(?:is\s+)?(?:visible|shown|displayed|present|appears)$/i,gen:r=>`await expect(page.getByText('${r[1]}')).toBeVisible();`},{regex:/^(?:verify|check|assert)\s+(?:that\s+)?["'](.+?)["']\s+(?:is\s+)?(?:not visible|hidden|not shown|gone|disappeared|not present)$/i,gen:r=>`await expect(page.getByText('${r[1]}')).not.toBeVisible();`},{regex:/^(?:verify|check)\s+(?:the\s+)?(?:page\s+)?title\s+(?:is|contains)\s+["'](.+?)["']$/i,gen:r=>`await expect(page).toHaveTitle(/${r[1]}/);`},{regex:/^(?:verify|check)\s+(?:the\s+)?url\s+(?:is|contains|matches)\s+["'](.+?)["']$/i,gen:r=>`await expect(page).toHaveURL(/${(r[1]??"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}/);`},{regex:/^(?:verify|check)\s+(?:the\s+)?["'](.+?)["']\s+(?:field|input)\s+(?:has value|contains|equals)\s+["'](.+?)["']$/i,gen:r=>`await expect(page.getByLabel('${r[1]}')).toHaveValue('${r[2]}');`},{regex:/^soft\s+(?:verify|check|assert|ensure|confirm)\s+(?:that\s+)?["'](.+?)["']\s+(?:is\s+)?(?:visible|shown|displayed|present|appears)$/i,gen:r=>`await expect.soft(page.getByText('${r[1]}')).toBeVisible();`},{regex:/^soft\s+(?:verify|check|assert)\s+(?:that\s+)?["'](.+?)["']\s+(?:is\s+)?(?:not visible|hidden|not shown|gone|disappeared|not present)$/i,gen:r=>`await expect.soft(page.getByText('${r[1]}')).not.toBeVisible();`},{regex:/^soft\s+(?:verify|check)\s+(?:the\s+)?(?:page\s+)?title\s+(?:is|contains)\s+["'](.+?)["']$/i,gen:r=>`await expect.soft(page).toHaveTitle(/${r[1]}/);`},{regex:/^soft\s+(?:verify|check)\s+(?:the\s+)?url\s+(?:is|contains|matches)\s+["'](.+?)["']$/i,gen:r=>`await expect.soft(page).toHaveURL(/${(r[1]??"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}/);`},{regex:/^soft\s+(?:verify|check)\s+(?:the\s+)?["'](.+?)["']\s+(?:field|input)\s+(?:has value|contains|equals)\s+["'](.+?)["']$/i,gen:r=>`await expect.soft(page.getByLabel('${r[1]}')).toHaveValue('${r[2]}');`},{regex:/^press\s+(.+)$/i,gen:r=>`await page.keyboard.press('${(r[1]??"").trim()}');`},{regex:/^(?:type|enter|fill)\s+["']?(.+?)["']?\s+(?:and\s+)?press\s+enter$/i,gen:r=>`await page.keyboard.type('${r[1]}');
106
+ await page.keyboard.press('Enter');`},{regex:/^select\s+["'](.+?)["']\s+from\s+(?:the\s+)?(.+)$/i,gen:r=>`await page.getByRole('combobox', { name: '${$r(r[2]??"")}' }).selectOption('${r[1]}');`},{regex:/^check\s+(?:the\s+)?["']?(.+?)["']?(?:\s+checkbox)?$/i,gen:r=>`await page.getByRole('checkbox', { name: '${$r(r[1]??"")}' }).check();`},{regex:/^uncheck\s+(?:the\s+)?["']?(.+?)["']?(?:\s+checkbox)?$/i,gen:r=>`await page.getByRole('checkbox', { name: '${$r(r[1]??"")}' }).uncheck();`},{regex:/^wait\s+(?:for\s+)?(\d+)\s+seconds?$/i,gen:r=>`await page.waitForTimeout(${parseInt(r[1]??"1",10)*1e3});`},{regex:/^wait\s+(?:for\s+)?(?:the\s+)?page\s+(?:to\s+)?load$/i,gen:()=>"await page.waitForLoadState('networkidle');"},{regex:/^scroll\s+(down|up)$/i,gen:r=>`await page.evaluate(() => window.scrollBy(0, ${(r[1]??"").toLowerCase()==="down"?500:-500}));`},{regex:/^scroll\s+to\s+(top|bottom)$/i,gen:r=>`await page.evaluate(() => window.scrollTo(0, ${(r[1]??"").toLowerCase()==="top"?0:"document.body.scrollHeight"}));`},{regex:/^hover\s+(?:over\s+)?(?:the\s+)?["']?(.+?)["']?$/i,gen:r=>`await page.getByText('${r[1]}').hover();`},{regex:/^take\s+(?:a\s+)?screenshot$/i,gen:()=>`await page.screenshot({ path: 'results/screenshots/step_${Date.now()}.png', fullPage: true });`},{regex:/^(?:focus|tab to)\s+(?:the\s+)?(.+?)(?:\s+field)?$/i,gen:r=>`await ${xa(r[1]??"")}.focus();`}],kn=class{tryMatch(e){for(let t of cl){let s=e.match(t.regex);if(s!==null)return t.gen(s)}return null}get patternCount(){return cl.length}}});function bh(r){return(0,ul.createHash)("sha256").update(r,"utf8").digest("hex")}function vh(r){try{return new URL(r).pathname.split("/").map(s=>/^\d+$/.test(s)||/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(s)||/^[a-z0-9-]{8,}$/i.test(s)&&/-/.test(s)?"*":s).join("/")}catch{return r}}function dl(r,e){let t=r.toLowerCase().replace(/\s+/g," ").trim(),s=vh(e);return bh(`${t}|${s}`).slice(0,16)}var ul,pl=b(()=>{"use strict";m();ul=require("crypto")});var ml,Ca,ss,xh,Sh,ns,Ea=b(()=>{"use strict";m();ml=x(require("path")),Ca=x(require("fs-extra"));pl();N();ze();ss=E("code-cache"),xh=ml.default.join("results",".code-cache.json"),Sh=3e4,ns=class{constructor(e=xh){this.persistPath=e}cache=new Map;dirty=!1;persistTimer=null;generateKey(e,t){return dl(e,t)}get(e){let t=this.cache.get(e);return t?t.failCount>=2?(this.cache.delete(e),this.dirty=!0,ss.debug({key:e},"Cache entry invalidated after 2 failures"),null):(t.lastUsedAt=Date.now(),t):null}set(e,t,s){this.cache.set(e,{code:t,urlPattern:s,successCount:0,failCount:0,createdAt:Date.now(),lastUsedAt:Date.now()}),this.dirty=!0}recordPass(e){let t=this.cache.get(e);t&&(t.successCount++,t.failCount=0,this.dirty=!0)}recordFail(e){let t=this.cache.get(e);t&&(t.failCount++,t.failCount>=2&&(this.cache.delete(e),ss.debug({key:e},"Cache entry removed after 2 failures")),this.dirty=!0)}get size(){return this.cache.size}async persist(){if(this.dirty)try{let e=Object.fromEntries(this.cache.entries());await K(this.persistPath,e),this.dirty=!1,ss.debug({entries:this.cache.size,path:this.persistPath},"Cache persisted")}catch(e){ss.warn({err:e},"Failed to persist code cache")}}async load(){if(await Ca.default.pathExists(this.persistPath))try{let e=await Ca.default.readJson(this.persistPath);this.cache.clear();for(let[t,s]of Object.entries(e))this.cache.set(t,s);ss.debug({entries:this.cache.size,path:this.persistPath},"Cache loaded")}catch(e){ss.warn({err:e},"Failed to load code cache \u2014 starting fresh")}}startAutoSave(){if(this.persistTimer)return;this.persistTimer=setInterval(()=>{this.persist()},Sh),this.persistTimer.unref&&this.persistTimer.unref();let e=()=>{this.persist()};process.once("exit",e),process.once("SIGINT",e),process.once("SIGTERM",e)}stopAutoSave(){this.persistTimer&&(clearInterval(this.persistTimer),this.persistTimer=null)}}});var Ch,An,gl=b(()=>{"use strict";m();Ch=[/table|grid|chart|graph|calendar|datepicker/i,/drag|drop|resize|reorder|sortable/i,/verify.*(count|greater|less|between|exactly|more than|fewer)/i,/wait\s+until|disappears|loading\s+(?:is\s+)?(?:done|complete|finished)/i,/(?:first|second|third|last|nth|\d+(?:st|nd|rd|th))\s+(?:item|row|card|element|result)/i,/if\s+|conditional|depending|based on/i,/iframe|shadow\s*dom|popup|modal|dialog|alert/i,/upload|download|file|attachment/i,/hover\s+.*then|right.click|double.click/i,/api|network|request|response|intercept/i,/(?:store|save|capture|extract)\s+.*(?:variable|value|text)/i,/multi.?select|autocomplete|typeahead|combobox/i],An=class{classify(e){let t=Ch.filter(s=>s.test(e)).length;return t>=2?"complex":t===1?"medium":"simple"}}});var Ia,$n,fl=b(()=>{"use strict";m();At();N();Ia=E("batch-processor"),$n=class{constructor(e,t){this.templateEngine=e;this.cache=t}async batchGenerate(e,t){let s=new Map,n=[];for(let o=0;o<e.length;o++){let{instruction:c,context:l}=e[o],u=this.templateEngine.tryMatch(c);if(u!==null){s.set(o,u);continue}let d=this.cache.generateKey(c,l.url),p=this.cache.get(d);if(p!==null){s.set(o,p.code);continue}n.push({index:o,instruction:c,context:l})}if(Ia.debug({total:e.length,local:s.size,needsAI:n.length},"Batch resolution"),n.length===0)return s;let i=n.map(o=>({instruction:o.instruction,context:o.context})),a=await t.batchGenerateCode(i);for(let o=0;o<n.length;o++){let c=n[o],l=a[o];if(!l){Ia.warn({instruction:c.instruction},"AI returned empty code for step");continue}let u;try{u=De(l)}catch(p){Ia.warn({instruction:c.instruction,err:p},"Skipping unsafe/invalid batch result");continue}s.set(c.index,u);let d=this.cache.generateKey(c.instruction,c.context.url);this.cache.set(d,u,c.context.url)}return s}}});function Eh(r){return r.includes("'")?`"${r.replace(/"/g,'\\"')}"`:`'${r.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}'`}function hl(r){return r.split("||").map(e=>e.trim()).filter(Boolean).map(e=>`frameLocator(${Eh(e)})`).join(".")+"."}function Ih(r){let e=new Map;for(let t of r.split(`
107
+ `)){if(!t.trim())continue;let s=t.match(/frame="([^"]*)"/),n=s?s[1]:null,i=[],a=t.match(/^[\w-]+\s+"([^"]*)"/);a&&i.push(a[1]);for(let o of t.matchAll(/(?:text|label|aria-label|placeholder)="([^"]*)"/g))i.push(o[1]);for(let o of i){let c=o.trim().toLowerCase();if(!c)continue;let l=e.get(c);l?l.frame!==n&&(l.ambiguous=!0):e.set(c,{frame:n,ambiguous:!1})}}return e}function yl(r,e){if(!e)return null;let t=r.get(e.trim().toLowerCase());return!t||t.ambiguous||!t.frame?null:t.frame}function wl(r,e){if(!r||!e||!e.includes("frame=")||!r.includes("page.getBy"))return r;let t=Ih(e);if(t.size===0)return r;let s=r;return s=s.replace(/\bpage\.getByRole\((['"])[^'"]+\1\s*,\s*\{[^}]*\}/g,n=>{let i=n.match(/name:\s*(['"])([^'"]*)\1/),a=yl(t,i?.[2]);return a?n.replace(/^page\./,`page.${hl(a)}`):n}),s=s.replace(/\bpage\.getBy(?:Text|Label|Placeholder)\((['"])([^'"]+)\1/g,(n,i,a)=>{let o=yl(t,a);return o?n.replace(/^page\./,`page.${hl(o)}`):n}),s}var bl=b(()=>{"use strict";m()});function Th(r){return(r.match(/^(\s*)/)?.[1]??"").replace(/\t/g," ").length}function kh(r,e){if(r)return`iframe[name='${r}']`;let t=e.match(/title=([^\s\]]+)/i);return t?`iframe[title='${t[1]}']`:"iframe"}function _n(r){if(!r||!r.trim())return{title:"",interactiveElements:"",accessibilityTree:""};let e=r.split(`
108
+ `),t="",s=[],n=[];for(let l of e){let u=l.trim();if(!u||u==="-")continue;let d=Th(l);for(;n.length>0&&d<=n[n.length-1].indent;)n.pop();let p=u.match(/^-?\s*Page\s+"([^"]*)"/i);if(p){t=p[1]??"";continue}let g=u.match(/^-?\s*([\w-]+)(?:\s+"([^"]*)")?(?:\s+\[([^\]]*)\])?/);if(!g)continue;let f=g[1].toLowerCase(),h=g[2]??"",S=g[3]??"";if(f==="iframe"||f==="frame"){let k=n.length>0?n[n.length-1].chain:"",T=kh(h,S),P=k?`${k}||${T}`:T;n.push({indent:d,chain:P});continue}if(h.length>80&&(h=h.slice(0,79)+"\u2026"),!h&&!S)continue;let I=Ph.has(f),v=Rh.has(f);if(I||v){let k=n.length>0?n[n.length-1].chain:null;s.push({role:f,name:h,attrs:S,isInteractive:I,frame:k})}}let i=s.filter(l=>l.isInteractive),a=s.filter(l=>!l.isInteractive),c=[...i,...a].slice(0,120).map(l=>{let u=`${l.role} "${l.name}"`;return l.attrs&&(u+=` [${l.attrs}]`),l.frame&&(u+=` frame="${l.frame}"`),u});return{title:t,interactiveElements:c.join(`
109
+ `),accessibilityTree:r.slice(0,8e3)}}var Ph,Rh,Pa=b(()=>{"use strict";m();Ph=new Set(["button","link","textbox","checkbox","radio","combobox","listbox","menuitem","menuitemcheckbox","menuitemradio","option","searchbox","slider","spinbutton","switch","tab","treeitem"]),Rh=new Set(["heading","img","navigation","dialog","alert","alertdialog","status","progressbar","table","row","cell","columnheader","rowheader"])});function vl(r,e){let t=`Current page accessibility snapshot:
107
110
  ${e.slice(0,6e3)}
108
111
 
109
112
  Step to execute: "${r}"
110
113
 
111
- Plan the MCP browser actions needed. Return JSON with the "actions" array.`;return{system:rh,user:t}}var rh,sl=w(()=>{"use strict";p();rh=`You are a browser automation expert. Given a test step instruction and an accessibility snapshot of the current page, plan the exact browser actions needed to accomplish the step.
114
+ Plan the MCP browser actions needed. Return JSON with the "actions" array.`;return{system:Ah,user:t}}var Ah,xl=b(()=>{"use strict";m();Ah=`You are a browser automation expert. Given a test step instruction and an accessibility snapshot of the current page, plan the exact browser actions needed to accomplish the step.
112
115
 
113
116
  \u2501\u2501\u2501 OUTPUT FORMAT \u2501\u2501\u2501
114
117
  Return ONLY valid JSON \u2014 no markdown, no explanations.
@@ -147,12 +150,12 @@ Match elements from the snapshot by their role and name:
147
150
  - "Click Login button" \u2192 find button with name containing "Login"
148
151
  - "Select country" \u2192 find combobox/listbox with name containing "country"
149
152
 
150
- Always use the ref value from the snapshot (e.g., "s1e4") \u2014 this is the unique element identifier.`});async function nl(r,e,t){try{let{system:s,user:n}=rl(e,t),i={url:"",title:"",interactiveElements:"",htmlSnapshot:"",previousSteps:[{instruction:"SYSTEM",code:s}],variables:{}},o=(await r.generateCode(`[MCP_ACTION_PLAN] ${n}`,i)).replace(/```json?\s*/g,"").replace(/```/g,"").trim(),c=JSON.parse(o);if(!c.actions||!Array.isArray(c.actions))return wa.warn("AI returned invalid action plan \u2014 no actions array"),[];let l=c.actions.filter(u=>u.tool&&typeof u.tool=="string"&&u.args);return wa.info({instruction:e,actionCount:l.length},"MCP action plan created"),l}catch(s){let n=s instanceof Error?s.message:String(s);return wa.warn({err:n,instruction:e},"Failed to plan MCP actions"),[]}}var wa,il=w(()=>{"use strict";p();sl();F();wa=E("action-mapper")});function ol(r){let e=[];for(let t of r){let s=sh(t);s&&e.push(s)}return e.length===0?(al.warn("No actions could be converted to script"),""):e.join(`
151
- `)}function sh(r){let e=r.args??{};switch(r.tool){case"browser_navigate":{let t=String(e.url??"");return t?`await page.goto('${Vt(t)}', { waitUntil: 'networkidle' });`:null}case"browser_click":{let t=Rn(e);return t?`await ${t}.click();`:null}case"browser_type":{let t=Rn(e),s=String(e.text??"");return!t||!s?null:`await ${t}.fill('${Vt(s)}');`}case"browser_select_option":{let t=Rn(e),s=e.values;if(!t||!s?.length)return null;let n=s.map(i=>`'${Vt(i)}'`).join(", ");return`await ${t}.selectOption([${n}]);`}case"browser_hover":{let t=Rn(e);return t?`await ${t}.hover();`:null}case"browser_press_key":{let t=String(e.key??"");return t?`await page.keyboard.press('${Vt(t)}');`:null}case"browser_wait":return`await page.waitForTimeout(${Number(e.time??1e3)});`;default:return al.debug({tool:r.tool},"Unknown MCP action \u2014 skipping"),null}}function Rn(r){let e=String(r.element??"");if(!e)return null;let t=typeof r.frame=="string"?r.frame.trim():"",s=`page.${nh(t)}`,n=e.match(/^(\w+)\s+['"]([^'"]*)['"]/);if(n){let a=n[1].toLowerCase(),o=n[2],c={button:"button",link:"link",textbox:"textbox",checkbox:"checkbox",radio:"radio",combobox:"combobox",listbox:"listbox",menuitem:"menuitem",option:"option",searchbox:"searchbox",slider:"slider",spinbutton:"spinbutton",switch:"switch",tab:"tab",heading:"heading"};if((a==="textbox"||a==="searchbox")&&o&&/\b(?:pass(?:word|code|phrase)?|pwd)\b/i.test(o))return`${s}getByLabel('${Vt(o)}')`;let l=c[a];if(l&&o)return`${s}getByRole('${l}', { name: '${Vt(o)}' })`;if((a==="textbox"||a==="searchbox")&&o)return`${s}getByLabel('${Vt(o)}')`}let i=e.match(/['"]([^'"]+)['"]/);return i?`${s}getByText('${Vt(i[1])}')`:null}function nh(r){return r?r.split("||").map(e=>e.trim()).filter(Boolean).map(e=>`frameLocator(${ih(e)})`).join(".")+".":""}function ih(r){return r.includes("'")?`"${r.replace(/"/g,'\\"')}"`:`'${Vt(r)}'`}function Vt(r){return r.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}var al,cl=w(()=>{"use strict";p();F();al=E("action-to-script")});var Te,Tn,ll=w(()=>{"use strict";p();Wc();fa();el();tl();Rt();F();Ir();ya();il();cl();Te=E("smart-router"),Tn=class{templateEngine;cache;classifier;batchProcessor;primaryProvider;fastProvider;mcpSession;actThenScript;ragManager;stats={template:0,cache:0,rag:0,batch:0,fast:0,primary:0,total:0};constructor(e){this.primaryProvider=e.primaryProvider,this.fastProvider=e.fastProvider??null,this.mcpSession=e.mcpSession??null,this.actThenScript=e.actThenScript??!1,this.ragManager=e.ragManager??null,this.cache=e.cache??new Zr,this.templateEngine=new Cn,this.classifier=new En,this.batchProcessor=new Pn(this.templateEngine,this.cache)}async generate(e,t){if(this.stats.total++,!(Ze(e)==="api")){let h=this.templateEngine.tryMatch(e);if(h!==null)return this.stats.template++,Te.debug({instruction:e},"Template match"),{code:Xr(h),strategy:"template",cost:0,model:"local"}}let n=this.cache.generateKey(e,t.url),i=this.cache.get(n);if(i!==null)return this.stats.cache++,Te.debug({instruction:e},"Cache hit"),{code:qr(e,Xr(i.code)),strategy:"cache",cost:0,model:"local"};let a=[],o=[];if(this.ragManager)try{let h=this.ragManager.codeCorpus.retrieve(e,t.url);if(h.length>0&&h[0].score>=.9){let C=h[0];this.stats.rag++,Te.info({instruction:e,score:C.score,matchedInstruction:C.instruction},"RAG direct hit");let P=qr(e,Xr(C.code));return this.cache.set(n,P,t.url),{code:P,strategy:"rag",cost:0,model:"local"}}a=h.filter(C=>C.score>=.65),a.length>0&&Te.debug({instruction:e,examples:a.length,topScore:a[0].score},"RAG examples found"),o=this.ragManager.errorCatalog.getWarnings(t.url),o.length>0&&Te.debug({url:t.url,warnings:o.length},"RAG error warnings")}catch(h){Te.debug({err:h},"RAG retrieval failed \u2014 continuing without memory")}let c=this.mcpSession?await this.enrichWithMcp(e,t):t,l=a.length>0||o.length>0?{...c,_ragExamples:a,_errorWarnings:o}:c;if(this.actThenScript&&this.mcpSession&&c.accessibilityTree){let h=await this.tryActThenScript(e,c);if(h!==null)return this.stats.primary++,this.cache.set(n,h,t.url),{code:h,strategy:"primary",cost:.003,model:"mcp-act"};Te.debug({instruction:e},"Act-then-script failed \u2014 falling back to AI generation")}let u=this.classifier.classify(e),d=this.fastProvider!==null&&u!=="complex",g=d?this.fastProvider:this.primaryProvider,m=d?"fast":"primary";Te.debug({instruction:e,complexity:u,strategy:m,ragExamples:a.length,errorWarnings:o.length},"AI call");let f=await g.generateCode(e,l);return this.cache.set(n,f,t.url),d?this.stats.fast++:this.stats.primary++,{code:f,strategy:m,cost:d?3e-4:.005,model:g.model}}async batchGenerate(e){let t=await this.batchProcessor.batchGenerate(e,this.primaryProvider);return this.stats.batch+=e.length,e.map((s,n)=>({code:t.get(n)??"",strategy:"batch",cost:.001,model:this.primaryProvider.model}))}recordPass(e,t){let s=this.cache.generateKey(e,t);this.cache.recordPass(s)}recordFail(e,t){let s=this.cache.generateKey(e,t);this.cache.recordFail(s)}getStats(){let e=this.stats.template+this.stats.cache+this.stats.rag;return{...this.stats,freeCalls:e,freePercent:(e/Math.max(this.stats.total,1)*100).toFixed(1),cacheEntries:this.cache.size}}getCache(){return this.cache}getPrimaryProvider(){return this.primaryProvider}getMcpSession(){return this.mcpSession}getRagManager(){return this.ragManager}async enrichWithMcp(e,t){try{let s=this.mcpSession;t.url&&(!s.currentUrl||!this.isSameOriginPath(s.currentUrl,t.url))&&(Te.debug({url:t.url},"MCP: navigating to target URL"),await s.navigate(t.url));let n=await s.snapshot();if(!n)return Te.debug("MCP: snapshot returned null \u2014 using blind context"),t;let i=In(n);return Te.info({elements:i.interactiveElements.split(`
152
- `).length,title:i.title},"MCP: enriched context with live page elements"),{...t,title:i.title||t.title,interactiveElements:i.interactiveElements||t.interactiveElements,accessibilityTree:i.accessibilityTree}}catch(s){let n=s instanceof Error?s.message:String(s);return Te.warn({err:n},"MCP enrichment failed \u2014 using blind context"),t}}async tryActThenScript(e,t){try{let s=this.mcpSession,n=t.accessibilityTree??"";if(!n)return null;let i=await nl(this.primaryProvider,e,n);if(i.length===0)return null;for(let c of i){let l=c.args??{},u=null;switch(c.tool){case"browser_click":u=await s.click(String(l.element??""),String(l.ref??""));break;case"browser_type":u=await s.fill(String(l.element??""),String(l.ref??""),String(l.text??""));break;case"browser_select_option":u=await s.selectOption(String(l.element??""),String(l.ref??""),l.values??[]);break;case"browser_hover":u=await s.hover(String(l.element??""),String(l.ref??""));break;case"browser_press_key":u=await s.pressKey(String(l.key??""));break;case"browser_navigate":u=await s.navigate(String(l.url??""));break;default:Te.debug({tool:c.tool},"Unknown MCP action in act-then-script");continue}if(u===null)return Te.debug({tool:c.tool,instruction:e},"MCP action failed during act-then-script"),null}let a=ol(i);if(!a)return null;let o=Xr(a);return Te.info({instruction:e,actions:i.length},"Act-then-script succeeded"),o}catch(s){let n=s instanceof Error?s.message:String(s);return Te.warn({err:n,instruction:e},"Act-then-script failed"),null}}isSameOriginPath(e,t){try{let s=new URL(e),n=new URL(t);return s.origin===n.origin&&s.pathname===n.pathname}catch{return e===t}}}});var ul,dl,kn,An,pl=w(()=>{"use strict";p();ul=require("@modelcontextprotocol/sdk/client/index.js"),dl=require("@modelcontextprotocol/sdk/client/stdio.js");F();kn=E("mcp-client"),An=class{client=null;transport=null;_connected=!1;headless;actionTimeout;constructor(e={}){this.headless=e.headless??!0,this.actionTimeout=e.actionTimeout??15e3}get connected(){return this._connected}async connect(){if(this._connected)return;let e=["@playwright/mcp@latest"];this.headless&&e.push("--headless"),this.transport=new dl.StdioClientTransport({command:"npx",args:e}),this.client=new ul.Client({name:"assuremind-studio",version:"1.0.0"},{capabilities:{}}),await this.client.connect(this.transport),this._connected=!0,kn.info({headless:this.headless},"MCP client connected")}async disconnect(){if(!(!this._connected||!this.client)){try{await this.client.close()}catch{}this.client=null,this.transport=null,this._connected=!1,kn.info("MCP client disconnected")}}async navigate(e){return this.callTool("browser_navigate",{url:e})}async snapshot(){return this.callTool("browser_snapshot",{})}async click(e,t){return this.callTool("browser_click",{element:e,ref:t})}async fill(e,t,s){return this.callTool("browser_type",{element:e,ref:t,text:s})}async selectOption(e,t,s){return this.callTool("browser_select_option",{element:e,ref:t,values:s})}async hover(e,t){return this.callTool("browser_hover",{element:e,ref:t})}async pressKey(e){return this.callTool("browser_press_key",{key:e})}async screenshot(){return this.callTool("browser_take_screenshot",{})}async consoleLogs(){return this.callTool("browser_console_messages",{})}async networkRequests(){return this.callTool("browser_network_requests",{})}async waitAndSnapshot(e){return e?this.callTool("browser_wait",{time:e}):this.callTool("browser_wait",{time:1e3})}async callTool(e,t){if(!this._connected||!this.client)return kn.warn({tool:e},"MCP callTool called but client not connected"),null;try{let s=await Promise.race([this.client.callTool({name:e,arguments:t}),new Promise((n,i)=>setTimeout(()=>i(new Error(`MCP tool "${e}" timed out after ${this.actionTimeout}ms`)),this.actionTimeout))]);return s&&Array.isArray(s.content)&&s.content.filter(i=>i.type==="text").map(i=>i.text).join(`
153
- `)||null}catch(s){let n=s instanceof Error?s.message:String(s);return kn.warn({tool:e,error:n},"MCP tool call failed"),null}}}});var ml,pt,Vs=w(()=>{"use strict";p();pl();F();ml=E("mcp-session"),pt=class{client;idleTimeout;idleTimer=null;mutex=Promise.resolve();_currentUrl=null;constructor(e={}){this.client=new An(e),this.idleTimeout=e.idleTimeout??3e4}get currentUrl(){return this._currentUrl}get connected(){return this.client.connected}async ensureConnected(){this.resetIdleTimer(),this.client.connected||await this.client.connect()}release(){this.startIdleTimer()}async disconnect(){this.clearIdleTimer(),this._currentUrl=null,await this.client.disconnect()}async navigate(e){return this.withMutex(async()=>{if(await this.ensureConnected(),this._currentUrl&&this.isSameUrl(this._currentUrl,e))return ml.debug({url:e},"Already on URL \u2014 skipping navigation"),this.client.snapshot();let t=await this.client.navigate(e);return t!==null&&(this._currentUrl=e),t})}async snapshot(){return this.withMutex(async()=>(await this.ensureConnected(),this.client.snapshot()))}async click(e,t){return this.withMutex(async()=>(await this.ensureConnected(),this.client.click(e,t)))}async fill(e,t,s){return this.withMutex(async()=>(await this.ensureConnected(),this.client.fill(e,t,s)))}async selectOption(e,t,s){return this.withMutex(async()=>(await this.ensureConnected(),this.client.selectOption(e,t,s)))}async hover(e,t){return this.withMutex(async()=>(await this.ensureConnected(),this.client.hover(e,t)))}async pressKey(e){return this.withMutex(async()=>(await this.ensureConnected(),this.client.pressKey(e)))}async screenshot(){return this.withMutex(async()=>(await this.ensureConnected(),this.client.screenshot()))}async consoleLogs(){return this.withMutex(async()=>(await this.ensureConnected(),this.client.consoleLogs()))}async networkRequests(){return this.withMutex(async()=>(await this.ensureConnected(),this.client.networkRequests()))}async waitAndSnapshot(e){return this.withMutex(async()=>(await this.ensureConnected(),this.client.waitAndSnapshot(e)))}async withMutex(e){let t,s=new Promise(i=>{t=i}),n=this.mutex;this.mutex=s,await n,this.resetIdleTimer();try{return await e()}finally{t()}}isSameUrl(e,t){try{let s=new URL(e),n=new URL(t);return s.origin===n.origin&&s.pathname===n.pathname}catch{return e===t}}startIdleTimer(){this.clearIdleTimer(),this.idleTimer=setTimeout(async()=>{ml.info("MCP session idle \u2014 disconnecting"),await this.disconnect()},this.idleTimeout)}resetIdleTimer(){this.clearIdleTimer()}clearIdleTimer(){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=null)}}});var H,gl,ah,fl,oh,hl,ch,yl,wl,bl,ba=w(()=>{"use strict";p();H=require("zod"),gl=H.z.object({instruction:H.z.string().min(1)}),ah=H.z.object({name:H.z.string().min(1),description:H.z.string().default(""),tags:H.z.array(H.z.string()).default([]),steps:H.z.array(gl)}),fl=H.z.object({name:H.z.string().min(1),description:H.z.string().default(""),tags:H.z.array(H.z.string()).default([]),cases:H.z.array(ah)}),oh=H.z.object({index:H.z.number().int().min(0),code:H.z.string()}),hl=H.z.object({results:H.z.array(oh)}),ch=H.z.object({name:H.z.string().min(1),description:H.z.string().default(""),tags:H.z.array(H.z.string()).default([])}),yl=H.z.object({name:H.z.string().min(1),description:H.z.string().default(""),tags:H.z.array(H.z.string()).default([]),cases:H.z.array(ch)}),wl=H.z.object({steps:H.z.array(gl)}),bl=H.z.object({x:H.z.number(),y:H.z.number(),action:H.z.string()})});function vl(r,e){let t=e.previousSteps.length>0?e.previousSteps.slice(-5).map((m,f)=>` ${f+1}. "${m.instruction}"
154
- ${m.code}`).join(`
155
- `):" None",s=Object.keys(e.variables).length>0?Object.entries(e.variables).map(([m,f])=>` {{${m}}} = ${f}`).join(`
153
+ Always use the ref value from the snapshot (e.g., "s1e4") \u2014 this is the unique element identifier.`});async function Sl(r,e,t){try{let{system:s,user:n}=vl(e,t),i={url:"",title:"",interactiveElements:"",htmlSnapshot:"",previousSteps:[{instruction:"SYSTEM",code:s}],variables:{}},o=(await r.generateCode(`[MCP_ACTION_PLAN] ${n}`,i)).replace(/```json?\s*/g,"").replace(/```/g,"").trim(),c=JSON.parse(o);if(!c.actions||!Array.isArray(c.actions))return Ra.warn("AI returned invalid action plan \u2014 no actions array"),[];let l=c.actions.filter(u=>u.tool&&typeof u.tool=="string"&&u.args);return Ra.info({instruction:e,actionCount:l.length},"MCP action plan created"),l}catch(s){let n=s instanceof Error?s.message:String(s);return Ra.warn({err:n,instruction:e},"Failed to plan MCP actions"),[]}}var Ra,Cl=b(()=>{"use strict";m();xl();N();Ra=E("action-mapper")});function Il(r){let e=[];for(let t of r){let s=$h(t);s&&e.push(s)}return e.length===0?(El.warn("No actions could be converted to script"),""):e.join(`
154
+ `)}function $h(r){let e=r.args??{};switch(r.tool){case"browser_navigate":{let t=String(e.url??"");return t?`await page.goto('${qt(t)}', { waitUntil: 'networkidle' });`:null}case"browser_click":{let t=Ln(e);return t?`await ${t}.click();`:null}case"browser_type":{let t=Ln(e),s=String(e.text??"");return!t||!s?null:`await ${t}.fill('${qt(s)}');`}case"browser_select_option":{let t=Ln(e),s=e.values;if(!t||!s?.length)return null;let n=s.map(i=>`'${qt(i)}'`).join(", ");return`await ${t}.selectOption([${n}]);`}case"browser_hover":{let t=Ln(e);return t?`await ${t}.hover();`:null}case"browser_press_key":{let t=String(e.key??"");return t?`await page.keyboard.press('${qt(t)}');`:null}case"browser_wait":return`await page.waitForTimeout(${Number(e.time??1e3)});`;default:return El.debug({tool:r.tool},"Unknown MCP action \u2014 skipping"),null}}function Ln(r){let e=String(r.element??"");if(!e)return null;let t=typeof r.frame=="string"?r.frame.trim():"",s=`page.${_h(t)}`,n=e.match(/^(\w+)\s+['"]([^'"]*)['"]/);if(n){let a=n[1].toLowerCase(),o=n[2],c={button:"button",link:"link",textbox:"textbox",checkbox:"checkbox",radio:"radio",combobox:"combobox",listbox:"listbox",menuitem:"menuitem",option:"option",searchbox:"searchbox",slider:"slider",spinbutton:"spinbutton",switch:"switch",tab:"tab",heading:"heading"};if((a==="textbox"||a==="searchbox")&&o&&/\b(?:pass(?:word|code|phrase)?|pwd)\b/i.test(o))return`${s}getByLabel('${qt(o)}')`;let l=c[a];if(l&&o)return`${s}getByRole('${l}', { name: '${qt(o)}' })`;if((a==="textbox"||a==="searchbox")&&o)return`${s}getByLabel('${qt(o)}')`}let i=e.match(/['"]([^'"]+)['"]/);return i?`${s}getByText('${qt(i[1])}')`:null}function _h(r){return r?r.split("||").map(e=>e.trim()).filter(Boolean).map(e=>`frameLocator(${Lh(e)})`).join(".")+".":""}function Lh(r){return r.includes("'")?`"${r.replace(/"/g,'\\"')}"`:`'${qt(r)}'`}function qt(r){return r.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}var El,Pl=b(()=>{"use strict";m();N();El=E("action-to-script")});var ke,On,Rl=b(()=>{"use strict";m();ll();Ea();gl();fl();At();bl();N();Ar();Pa();Cl();Pl();ke=E("smart-router"),On=class{templateEngine;cache;classifier;batchProcessor;primaryProvider;fastProvider;mcpSession;actThenScript;ragManager;stats={template:0,cache:0,rag:0,batch:0,fast:0,primary:0,total:0};constructor(e){this.primaryProvider=e.primaryProvider,this.fastProvider=e.fastProvider??null,this.mcpSession=e.mcpSession??null,this.actThenScript=e.actThenScript??!1,this.ragManager=e.ragManager??null,this.cache=e.cache??new ns,this.templateEngine=new kn,this.classifier=new An,this.batchProcessor=new $n(this.templateEngine,this.cache)}async generate(e,t){if(this.stats.total++,!(tt(e)==="api")){let S=this.templateEngine.tryMatch(e);if(S!==null)return this.stats.template++,ke.debug({instruction:e},"Template match"),{code:Qr(S),strategy:"template",cost:0,model:"local"}}let n=this.cache.generateKey(e,t.url),i=this.cache.get(n);if(i!==null)return this.stats.cache++,ke.debug({instruction:e},"Cache hit"),{code:Yr(e,Qr(i.code)),strategy:"cache",cost:0,model:"local"};let a=[],o=[];if(this.ragManager)try{let S=this.ragManager.codeCorpus.retrieve(e,t.url);if(S.length>0&&S[0].score>=.9){let I=S[0];this.stats.rag++,ke.info({instruction:e,score:I.score,matchedInstruction:I.instruction},"RAG direct hit");let v=Yr(e,Qr(I.code));return this.cache.set(n,v,t.url),{code:v,strategy:"rag",cost:0,model:"local"}}a=S.filter(I=>I.score>=.65),a.length>0&&ke.debug({instruction:e,examples:a.length,topScore:a[0].score},"RAG examples found"),o=this.ragManager.errorCatalog.getWarnings(t.url),o.length>0&&ke.debug({url:t.url,warnings:o.length},"RAG error warnings")}catch(S){ke.debug({err:S},"RAG retrieval failed \u2014 continuing without memory")}let c=this.mcpSession?await this.enrichWithMcp(e,t):t,l=a.length>0||o.length>0?{...c,_ragExamples:a,_errorWarnings:o}:c;if(this.actThenScript&&this.mcpSession&&c.accessibilityTree){let S=await this.tryActThenScript(e,c);if(S!==null)return this.stats.primary++,this.cache.set(n,S,t.url),{code:S,strategy:"primary",cost:.003,model:"mcp-act"};ke.debug({instruction:e},"Act-then-script failed \u2014 falling back to AI generation")}let u=this.classifier.classify(e),d=this.fastProvider!==null&&u!=="complex",p=d?this.fastProvider:this.primaryProvider,g=d?"fast":"primary";ke.debug({instruction:e,complexity:u,strategy:g,ragExamples:a.length,errorWarnings:o.length},"AI call");let f=await p.generateCode(e,l),h=wl(f,c.interactiveElements);return this.cache.set(n,h,t.url),d?this.stats.fast++:this.stats.primary++,{code:h,strategy:g,cost:d?3e-4:.005,model:p.model}}async batchGenerate(e){let t=await this.batchProcessor.batchGenerate(e,this.primaryProvider);return this.stats.batch+=e.length,e.map((s,n)=>({code:t.get(n)??"",strategy:"batch",cost:.001,model:this.primaryProvider.model}))}recordPass(e,t){let s=this.cache.generateKey(e,t);this.cache.recordPass(s)}recordFail(e,t){let s=this.cache.generateKey(e,t);this.cache.recordFail(s)}getStats(){let e=this.stats.template+this.stats.cache+this.stats.rag;return{...this.stats,freeCalls:e,freePercent:(e/Math.max(this.stats.total,1)*100).toFixed(1),cacheEntries:this.cache.size}}getCache(){return this.cache}getPrimaryProvider(){return this.primaryProvider}getMcpSession(){return this.mcpSession}getRagManager(){return this.ragManager}async enrichWithMcp(e,t){try{let s=this.mcpSession;t.url&&(!s.currentUrl||!this.isSameOriginPath(s.currentUrl,t.url))&&(ke.debug({url:t.url},"MCP: navigating to target URL"),await s.navigate(t.url));let n=await s.snapshot();if(!n)return ke.debug("MCP: snapshot returned null \u2014 using blind context"),t;let i=_n(n);return ke.info({elements:i.interactiveElements.split(`
155
+ `).length,title:i.title},"MCP: enriched context with live page elements"),{...t,title:i.title||t.title,interactiveElements:i.interactiveElements||t.interactiveElements,accessibilityTree:i.accessibilityTree}}catch(s){let n=s instanceof Error?s.message:String(s);return ke.warn({err:n},"MCP enrichment failed \u2014 using blind context"),t}}async tryActThenScript(e,t){try{let s=this.mcpSession,n=t.accessibilityTree??"";if(!n)return null;let i=await Sl(this.primaryProvider,e,n);if(i.length===0)return null;for(let c of i){let l=c.args??{},u=null;switch(c.tool){case"browser_click":u=await s.click(String(l.element??""),String(l.ref??""));break;case"browser_type":u=await s.fill(String(l.element??""),String(l.ref??""),String(l.text??""));break;case"browser_select_option":u=await s.selectOption(String(l.element??""),String(l.ref??""),l.values??[]);break;case"browser_hover":u=await s.hover(String(l.element??""),String(l.ref??""));break;case"browser_press_key":u=await s.pressKey(String(l.key??""));break;case"browser_navigate":u=await s.navigate(String(l.url??""));break;default:ke.debug({tool:c.tool},"Unknown MCP action in act-then-script");continue}if(u===null)return ke.debug({tool:c.tool,instruction:e},"MCP action failed during act-then-script"),null}let a=Il(i);if(!a)return null;let o=Qr(a);return ke.info({instruction:e,actions:i.length},"Act-then-script succeeded"),o}catch(s){let n=s instanceof Error?s.message:String(s);return ke.warn({err:n,instruction:e},"Act-then-script failed"),null}}isSameOriginPath(e,t){try{let s=new URL(e),n=new URL(t);return s.origin===n.origin&&s.pathname===n.pathname}catch{return e===t}}}});var Tl,kl,Dn,Fn,Al=b(()=>{"use strict";m();Tl=require("@modelcontextprotocol/sdk/client/index.js"),kl=require("@modelcontextprotocol/sdk/client/stdio.js");N();Dn=E("mcp-client"),Fn=class{client=null;transport=null;_connected=!1;headless;actionTimeout;constructor(e={}){this.headless=e.headless??!0,this.actionTimeout=e.actionTimeout??15e3}get connected(){return this._connected}async connect(){if(this._connected)return;let e=["@playwright/mcp@latest"];this.headless&&e.push("--headless"),this.transport=new kl.StdioClientTransport({command:"npx",args:e}),this.client=new Tl.Client({name:"assuremind-studio",version:"1.0.0"},{capabilities:{}}),await this.client.connect(this.transport),this._connected=!0,Dn.info({headless:this.headless},"MCP client connected")}async disconnect(){if(!(!this._connected||!this.client)){try{await this.client.close()}catch{}this.client=null,this.transport=null,this._connected=!1,Dn.info("MCP client disconnected")}}async navigate(e){return this.callTool("browser_navigate",{url:e})}async snapshot(){return this.callTool("browser_snapshot",{})}async click(e,t){return this.callTool("browser_click",{element:e,ref:t})}async fill(e,t,s){return this.callTool("browser_type",{element:e,ref:t,text:s})}async selectOption(e,t,s){return this.callTool("browser_select_option",{element:e,ref:t,values:s})}async hover(e,t){return this.callTool("browser_hover",{element:e,ref:t})}async pressKey(e){return this.callTool("browser_press_key",{key:e})}async screenshot(){return this.callTool("browser_take_screenshot",{})}async consoleLogs(){return this.callTool("browser_console_messages",{})}async networkRequests(){return this.callTool("browser_network_requests",{})}async waitAndSnapshot(e){return e?this.callTool("browser_wait",{time:e}):this.callTool("browser_wait",{time:1e3})}async callTool(e,t){if(!this._connected||!this.client)return Dn.warn({tool:e},"MCP callTool called but client not connected"),null;try{let s=await Promise.race([this.client.callTool({name:e,arguments:t}),new Promise((n,i)=>setTimeout(()=>i(new Error(`MCP tool "${e}" timed out after ${this.actionTimeout}ms`)),this.actionTimeout))]);return s&&Array.isArray(s.content)&&s.content.filter(i=>i.type==="text").map(i=>i.text).join(`
156
+ `)||null}catch(s){let n=s instanceof Error?s.message:String(s);return Dn.warn({tool:e,error:n},"MCP tool call failed"),null}}}});var $l,ft,Ws=b(()=>{"use strict";m();Al();N();$l=E("mcp-session"),ft=class{client;idleTimeout;idleTimer=null;mutex=Promise.resolve();_currentUrl=null;constructor(e={}){this.client=new Fn(e),this.idleTimeout=e.idleTimeout??3e4}get currentUrl(){return this._currentUrl}get connected(){return this.client.connected}async ensureConnected(){this.resetIdleTimer(),this.client.connected||await this.client.connect()}release(){this.startIdleTimer()}async disconnect(){this.clearIdleTimer(),this._currentUrl=null,await this.client.disconnect()}async navigate(e){return this.withMutex(async()=>{if(await this.ensureConnected(),this._currentUrl&&this.isSameUrl(this._currentUrl,e))return $l.debug({url:e},"Already on URL \u2014 skipping navigation"),this.client.snapshot();let t=await this.client.navigate(e);return t!==null&&(this._currentUrl=e),t})}async snapshot(){return this.withMutex(async()=>(await this.ensureConnected(),this.client.snapshot()))}async click(e,t){return this.withMutex(async()=>(await this.ensureConnected(),this.client.click(e,t)))}async fill(e,t,s){return this.withMutex(async()=>(await this.ensureConnected(),this.client.fill(e,t,s)))}async selectOption(e,t,s){return this.withMutex(async()=>(await this.ensureConnected(),this.client.selectOption(e,t,s)))}async hover(e,t){return this.withMutex(async()=>(await this.ensureConnected(),this.client.hover(e,t)))}async pressKey(e){return this.withMutex(async()=>(await this.ensureConnected(),this.client.pressKey(e)))}async screenshot(){return this.withMutex(async()=>(await this.ensureConnected(),this.client.screenshot()))}async consoleLogs(){return this.withMutex(async()=>(await this.ensureConnected(),this.client.consoleLogs()))}async networkRequests(){return this.withMutex(async()=>(await this.ensureConnected(),this.client.networkRequests()))}async waitAndSnapshot(e){return this.withMutex(async()=>(await this.ensureConnected(),this.client.waitAndSnapshot(e)))}async withMutex(e){let t,s=new Promise(i=>{t=i}),n=this.mutex;this.mutex=s,await n,this.resetIdleTimer();try{return await e()}finally{t()}}isSameUrl(e,t){try{let s=new URL(e),n=new URL(t);return s.origin===n.origin&&s.pathname===n.pathname}catch{return e===t}}startIdleTimer(){this.clearIdleTimer(),this.idleTimer=setTimeout(async()=>{$l.info("MCP session idle \u2014 disconnecting"),await this.disconnect()},this.idleTimeout)}resetIdleTimer(){this.clearIdleTimer()}clearIdleTimer(){this.idleTimer&&(clearTimeout(this.idleTimer),this.idleTimer=null)}}});var H,_l,Oh,Ll,Dh,Ol,Fh,Dl,Fl,Nl,Ta=b(()=>{"use strict";m();H=require("zod"),_l=H.z.object({instruction:H.z.string().min(1)}),Oh=H.z.object({name:H.z.string().min(1),description:H.z.string().default(""),tags:H.z.array(H.z.string()).default([]),steps:H.z.array(_l)}),Ll=H.z.object({name:H.z.string().min(1),description:H.z.string().default(""),tags:H.z.array(H.z.string()).default([]),cases:H.z.array(Oh)}),Dh=H.z.object({index:H.z.number().int().min(0),code:H.z.string()}),Ol=H.z.object({results:H.z.array(Dh)}),Fh=H.z.object({name:H.z.string().min(1),description:H.z.string().default(""),tags:H.z.array(H.z.string()).default([])}),Dl=H.z.object({name:H.z.string().min(1),description:H.z.string().default(""),tags:H.z.array(H.z.string()).default([]),cases:H.z.array(Fh)}),Fl=H.z.object({steps:H.z.array(_l)}),Nl=H.z.object({x:H.z.number(),y:H.z.number(),action:H.z.string()})});function Ml(r,e){let t=e.previousSteps.length>0?e.previousSteps.slice(-5).map((g,f)=>` ${f+1}. "${g.instruction}"
157
+ ${g.code}`).join(`
158
+ `):" None",s=Object.keys(e.variables).length>0?Object.entries(e.variables).map(([g,f])=>` {{${g}}} = ${f}`).join(`
156
159
  `):" None",i=!!(e.interactiveElements&&e.accessibilityTree)?`Interactive elements on page (LIVE from actual page \u2014 use exact roles/names):
157
160
  ${e.interactiveElements}
158
161
 
@@ -162,13 +165,13 @@ ${e.interactiveElements||" None captured"}`,a=e.accessibilityTree?`
162
165
  Full accessibility tree (for additional context):
163
166
  ${e.accessibilityTree.slice(0,4e3)}`:"",o=e,c=o._ragExamples??[],l=o._errorWarnings??[],u=c.length>0?`
164
167
  Similar past steps that worked (use as reference \u2014 adapt, don't copy blindly):
165
- ${c.slice(0,3).map((m,f)=>` ${f+1}. "${m.instruction}" (similarity: ${(m.score*100).toFixed(0)}%)
166
- ${m.code}`).join(`
168
+ ${c.slice(0,3).map((g,f)=>` ${f+1}. "${g.instruction}" (similarity: ${(g.score*100).toFixed(0)}%)
169
+ ${g.code}`).join(`
167
170
  `)}`:"",d=l.length>0?`
168
171
  Known issues on this page (avoid these patterns):
169
- ${l.slice(0,3).map((m,f)=>` ${f+1}. ${m.errorPattern} (occurred ${m.frequency}x)${m.suggestedFix?`
170
- Suggested fix: ${m.suggestedFix}`:""}`).join(`
171
- `)}`:"",g=`Current page:
172
+ ${l.slice(0,3).map((g,f)=>` ${f+1}. ${g.errorPattern} (occurred ${g.frequency}x)${g.suggestedFix?`
173
+ Suggested fix: ${g.suggestedFix}`:""}`).join(`
174
+ `)}`:"",p=`Current page:
172
175
  URL: ${e.url}
173
176
  Title: ${e.title}
174
177
 
@@ -180,7 +183,7 @@ ${t}
180
183
  Runtime variables:
181
184
  ${s}
182
185
 
183
- Step to implement: "${r}"${u}${d}`;return{system:lh,user:g}}var lh,xl=w(()=>{"use strict";p();lh=`You are a Playwright test automation expert. Convert plain English test steps into executable Playwright TypeScript code.
186
+ Step to implement: "${r}"${u}${d}`;return{system:Nh,user:p}}var Nh,jl=b(()=>{"use strict";m();Nh=`You are a Playwright test automation expert. Convert plain English test steps into executable Playwright TypeScript code.
184
187
 
185
188
  \u2501\u2501\u2501 OUTPUT RULES \u2501\u2501\u2501
186
189
  1. Return ONLY raw executable code \u2014 no markdown, no \`\`\`, no explanations
@@ -276,6 +279,33 @@ DROP trailing type words like "field", "input", "box", "dropdown", "checkbox", "
276
279
  - Number / quantity inputs \u2192 getByRole('spinbutton', { name: '...' }).fill('value')
277
280
  - NEVER use getByText() to click a button/link \u2014 always use getByRole
278
281
 
282
+ \u2501\u2501\u2501 FILE UPLOAD \u2501\u2501\u2501
283
+ Uploaded fixture files are referenced with the {{FILE:name}} token (resolved to a path at runtime).
284
+ // Direct <input type="file"> (most reliable)
285
+ await page.locator('input[type="file"]').setInputFiles('{{FILE:resume.pdf}}');
286
+ // When the input has an associated label
287
+ await page.getByLabel('Resume').setInputFiles('{{FILE:resume.pdf}}');
288
+ // Button that opens a file chooser \u2014 register the listener BEFORE the click
289
+ const fileChooserPromise = page.waitForEvent('filechooser');
290
+ await page.getByRole('button', { name: 'Choose File' }).click();
291
+ (await fileChooserPromise).setFiles('{{FILE:resume.pdf}}');
292
+ Keep the {{FILE:...}} token EXACTLY as given \u2014 do not rewrite the path.
293
+ WAIT for the upload to complete after setInputFiles (there is no upload event \u2014 wait for a signal):
294
+ // Preferred: wait for the app's success indicator if the step names one
295
+ await expect(page.getByText('Upload complete')).toBeVisible();
296
+ // Otherwise let the upload request settle
297
+ await page.waitForLoadState('networkidle');
298
+
299
+ \u2501\u2501\u2501 FILE DOWNLOAD \u2501\u2501\u2501
300
+ The framework auto-saves downloads (results/downloads/<runId>/) \u2014 do NOT call download.saveAs() or use fs/path.
301
+ WAIT for the download so the step finishes only after the file finishes downloading:
302
+ const downloadPromise = page.waitForEvent('download');
303
+ await page.getByRole('link', { name: 'Download' }).click();
304
+ const download = await downloadPromise;
305
+ await download.path(); // resolves once the download is complete
306
+ Register waitForEvent BEFORE the click, and keep all of it in the SAME step. The captured file appears
307
+ in Reports \u2192 Downloads.
308
+
279
309
  \u2501\u2501\u2501 NAVIGATION \u2501\u2501\u2501
280
310
  Always use { waitUntil: 'networkidle' } with page.goto() so the page fully loads before the next step:
281
311
  await page.goto('https://example.com', { waitUntil: 'networkidle' });
@@ -327,21 +357,22 @@ When the step mentions "accept alert", "dismiss alert", "handle popup", "click O
327
357
  IMPORTANT: Register the dialog handler with page.once() BEFORE the action that triggers it.
328
358
 
329
359
  \u2501\u2501\u2501 SHADOW DOM \u2501\u2501\u2501
330
- For elements inside a Shadow Root, use Playwright's CSS pierce combinator (>>):
331
- // Click a button inside shadow root
332
- await page.locator('my-component >> button').click();
333
- await page.locator('my-component >> [data-testid="submit"]').click();
360
+ Playwright pierces OPEN shadow roots automatically with normal CSS. Use locator CHAINING
361
+ (host then inner) \u2014 NEVER the deprecated '>>' combinator.
362
+ // Click a button inside a shadow root
363
+ await page.locator('my-component').locator('button').click();
364
+ await page.locator('my-component').locator('[data-testid="submit"]').click();
334
365
 
335
- // Fill an input inside shadow root
336
- await page.locator('custom-input >> input').fill('value');
366
+ // Fill an input inside a shadow root
367
+ await page.locator('custom-input').locator('input').fill('value');
337
368
 
338
- // Deep shadow DOM (multiple levels)
339
- await page.locator('outer-element >> inner-element >> button').click();
369
+ // Deep / nested shadow DOM \u2014 chain one locator per host level
370
+ await page.locator('outer-element').locator('inner-element').locator('button').click();
340
371
 
341
- // Using :host selector
342
- await page.locator(':shadow(my-component) >> input').fill('text');
372
+ // Often the inner CSS alone is enough, since open shadow roots are pierced automatically:
373
+ await page.locator('#shadow_content > span').click();
343
374
 
344
- When elements are inside a shadow root, use locator() with >> combinator instead of getBy methods.
375
+ NEVER emit '>>' (e.g. 'host >> inner') \u2014 it is deprecated. Chain .locator() calls instead.
345
376
 
346
377
  \u2501\u2501\u2501 IFRAMES (CRITICAL) \u2501\u2501\u2501
347
378
  Any element in the "Interactive elements" list tagged with frame="<selector>" lives INSIDE an iframe.
@@ -386,13 +417,13 @@ For keyboard-specific steps (press key, keyboard shortcut, type text):
386
417
  await page.getByLabel('Search').press('Enter');
387
418
  await page.getByRole('textbox').press('Control+A');
388
419
 
389
- Use page.keyboard.press() for single keys or shortcuts, page.keyboard.type() when the step says "type using keyboard".`});function Sl(r){return{system:uh,user:`User story:
420
+ Use page.keyboard.press() for single keys or shortcuts, page.keyboard.type() when the step says "type using keyboard".`});function Bl(r){return{system:Mh,user:`User story:
390
421
  ${r}
391
422
 
392
423
  Generate the suite outline (no steps) following this schema:
393
- ${dh}
424
+ ${jh}
394
425
 
395
- Return only the JSON object.`}}function Cl(r,e,t,s){return{system:ph,user:`Suite: "${r}"
426
+ Return only the JSON object.`}}function Ul(r,e,t,s){return{system:Bh,user:`Suite: "${r}"
396
427
  Test case: "${e}"
397
428
  Description: "${t}"
398
429
 
@@ -400,17 +431,17 @@ Context (original user story):
400
431
  ${s}
401
432
 
402
433
  Generate the steps for this test case following this schema:
403
- ${mh}
434
+ ${Uh}
404
435
 
405
- Return only the JSON object.`}}function El(r){let e=`User story:
436
+ Return only the JSON object.`}}function Hl(r){let e=`User story:
406
437
  ${r}
407
438
 
408
439
  Generate a JSON test suite following this exact schema:
409
- ${fh}
440
+ ${Vh}
410
441
 
411
- Important: return only the JSON object, nothing else.`;return{system:gh,user:e}}var uh,dh,ph,mh,gh,fh,Pl=w(()=>{"use strict";p();uh=`You are a QA test planning expert.
442
+ Important: return only the JSON object, nothing else.`;return{system:Hh,user:e}}var Mh,jh,Bh,Uh,Hh,Vh,Vl=b(()=>{"use strict";m();Mh=`You are a QA test planning expert.
412
443
  Given a user story, produce a test suite outline \u2014 the suite metadata and a list of test cases.
413
- Do NOT include steps yet. Return ONLY valid JSON, no markdown, no code fences.`,dh=`{
444
+ Do NOT include steps yet. Return ONLY valid JSON, no markdown, no code fences.`,jh=`{
414
445
  "name": "Suite name (e.g. Authentication)",
415
446
  "description": "What this suite covers",
416
447
  "tags": ["smoke", "regression"],
@@ -421,13 +452,13 @@ Do NOT include steps yet. Return ONLY valid JSON, no markdown, no code fences.`,
421
452
  "tags": ["smoke"]
422
453
  }
423
454
  ]
424
- }`;ph=`You are a QA test automation expert.
455
+ }`;Bh=`You are a QA test automation expert.
425
456
  Given a test case name and description, write the detailed plain-English steps needed to execute it.
426
457
  Rules:
427
458
  1. Return ONLY valid JSON \u2014 no markdown, no code fences
428
459
  2. Each step must be a single atomic action or assertion
429
460
  3. Be concrete \u2014 reference actual UI elements by their visible labels or text
430
- 4. Use {{VARIABLE}} tokens for sensitive values (e.g. {{PASSWORD}}, {{USERNAME}})`,mh=`{
461
+ 4. Use {{VARIABLE}} tokens for sensitive values (e.g. {{PASSWORD}}, {{USERNAME}})`,Uh=`{
431
462
  "steps": [
432
463
  { "instruction": "Navigate to the login page" },
433
464
  { "instruction": "Enter 'admin' in the Username field" },
@@ -435,7 +466,7 @@ Rules:
435
466
  { "instruction": "Click the 'Login' button" },
436
467
  { "instruction": "Verify the Dashboard heading is visible" }
437
468
  ]
438
- }`;gh=`You are a QA test planning expert. Convert user stories into structured test suites.
469
+ }`;Hh=`You are a QA test planning expert. Convert user stories into structured test suites.
439
470
 
440
471
  RULES:
441
472
  1. Return ONLY valid JSON \u2014 no markdown, no explanations, no code fences
@@ -443,7 +474,7 @@ RULES:
443
474
  3. Steps must be atomic \u2014 one action or assertion per step
444
475
  4. Cover the happy path, then common edge cases and negative scenarios
445
476
  5. Test case names must be descriptive and start with a verb (e.g. "Login with valid credentials")
446
- 6. Steps should be concrete \u2014 reference actual UI elements by their labels or text`,fh=`{
477
+ 6. Steps should be concrete \u2014 reference actual UI elements by their labels or text`,Vh=`{
447
478
  "name": "Suite name (e.g. Authentication)",
448
479
  "description": "What this suite covers",
449
480
  "tags": ["smoke", "regression"],
@@ -461,7 +492,7 @@ RULES:
461
492
  ]
462
493
  }
463
494
  ]
464
- }`});function Il(r,e,t,s,n){let a=!!(s.interactiveElements&&s.accessibilityTree)?`Current interactive elements (LIVE from page snapshot \u2014 use exact names):
495
+ }`});function Gl(r,e,t,s,n){let a=!!(s.interactiveElements&&s.accessibilityTree)?`Current interactive elements (LIVE from page snapshot \u2014 use exact names):
465
496
  ${s.interactiveElements}`:`Current interactive elements:
466
497
  ${s.interactiveElements||" None captured"}`,o=s.accessibilityTree?`
467
498
  Accessibility tree:
@@ -488,7 +519,7 @@ ${a}
488
519
  HTML snapshot (partial):
489
520
  ${s.htmlSnapshot.slice(0,3e3)}${o}${c}
490
521
 
491
- Generate new Playwright code that achieves: "${r}"`;return{system:hh,user:l}}var hh,Rl=w(()=>{"use strict";p();hh=`You are a Playwright test self-healing expert. A test step has failed due to an infrastructure issue (broken selector, element moved, DOM changed) and you must generate new code that will work with the current page state.
522
+ Generate new Playwright code that achieves: "${r}"`;return{system:Gh,user:l}}var Gh,zl=b(()=>{"use strict";m();Gh=`You are a Playwright test self-healing expert. A test step has failed due to an infrastructure issue (broken selector, element moved, DOM changed) and you must generate new code that will work with the current page state.
492
523
 
493
524
  RULES:
494
525
  1. Return ONLY raw executable code \u2014 no markdown, no explanations, no code fences
@@ -501,7 +532,12 @@ RULES:
501
532
  If the original code has expect(status).toBe(200), keep it as toBe(200).
502
533
  If the original code has expect(text).toContain('Welcome'), keep it as toContain('Welcome').
503
534
  Assertions represent the TEST INTENT \u2014 changing them would hide real bugs.
504
- 8. Only fix HOW the test interacts with the page (selectors, actions) \u2014 never WHAT it verifies`});function Tl(r,e){let t=r.map(c=>` ${c.index}. "${c.instruction}"`).join(`
535
+ 8. Only fix HOW the test interacts with the page (selectors, actions) \u2014 never WHAT it verifies
536
+ 9. If the failing code is an assertion whose locator could not be found (e.g.
537
+ expect(page.frameLocator('#wrong').getByText('Docs')).toBeVisible()), fix ONLY the
538
+ structural/locator path \u2014 the frame selector or container. PRESERVE the matcher
539
+ (toBeVisible/toHaveText/...) AND the content being matched (e.g. keep getByText('Docs')
540
+ verbatim). Never swap 'Docs' for another element to force a pass.`});function ql(r,e){let t=r.map(c=>` ${c.index}. "${c.instruction}"`).join(`
505
541
  `),s=Object.keys(e.variables).length>0?Object.entries(e.variables).map(([c,l])=>` {{${c}}} = ${l}`).join(`
506
542
  `):" None",i=!!(e.interactiveElements&&e.accessibilityTree)?`Interactive elements on page (LIVE from actual page \u2014 use exact roles/names):
507
543
  ${e.interactiveElements}
@@ -532,7 +568,7 @@ Return JSON:
532
568
  ]
533
569
  }
534
570
 
535
- Return one result per step. Include ALL ${r.length} steps.`;return{system:yh,user:o}}var yh,kl=w(()=>{"use strict";p();yh=`You are a Playwright test automation expert. Generate executable Playwright code for multiple test steps in a single JSON response.
571
+ Return one result per step. Include ALL ${r.length} steps.`;return{system:zh,user:o}}var zh,Xl=b(()=>{"use strict";m();zh=`You are a Playwright test automation expert. Generate executable Playwright code for multiple test steps in a single JSON response.
536
572
 
537
573
  \u2501\u2501\u2501 OUTPUT FORMAT \u2501\u2501\u2501
538
574
  1. Return ONLY valid JSON \u2014 no markdown, no \`\`\`, no explanations
@@ -617,8 +653,8 @@ Not visible: await expect(page.getByText('Error')).not.toBeVisible()
617
653
  \u2501\u2501\u2501 SOFT ASSERTIONS (test continues on failure) \u2501\u2501\u2501
618
654
  When instruction starts with "Soft verify/assert/check", use expect.soft():
619
655
  await expect.soft(page.getByText('Welcome')).toBeVisible()
620
- await expect.soft(page).toHaveURL(/dashboard/)`});async function wh(r,e){let t=new Array(r.length),s=0;async function n(){for(;s<r.length;){let a=s++;t[a]=await r[a]()}}let i=Array.from({length:Math.min(e,r.length)},n);return await Promise.all(i),t}function Gs(r){let e=zr(r).trim();try{return JSON.parse(e),null}catch{}let t=[],s=!1,n=!1;for(let a of e){if(n){n=!1;continue}if(a==="\\"&&s){n=!0;continue}if(a==='"'){s=!s;continue}s||(a==="{"||a==="["?t.push(a==="{"?"}":"]"):(a==="}"||a==="]")&&t.pop())}if(t.length===0)return null;let i=e;s&&(i+='"'),i+=t.reverse().join("");try{return JSON.parse(i),i}catch{return null}}var ke,ur=w(()=>{"use strict";p();ba();xl();Pl();Rl();kl();Rt();re();ba();Rt();ke=class{timeoutMs;maxRetries;temperature;constructor(e){this.timeoutMs=e.timeoutMs??3e4,this.maxRetries=e.maxRetries??2,this.temperature=e.temperature??.1}async generateCode(e,t){let{system:s,user:n}=vl(e,t),i=await this.chatWithRetry([{role:"system",content:s},{role:"user",content:n}]),a=Oe(i);return qr(e,a)}async generateTestSuite(e){try{return await this.generateTestSuiteTwoPass(e)}catch{return await this.generateTestSuiteSinglePass(e)}}async generateTestSuiteTwoPass(e){let t=Sl(e),s=await this.chatWithRetry([{role:"system",content:t.system},{role:"user",content:t.user}]),n=wn(s),i=Gs(n)??n,a=yl.safeParse(JSON.parse(i));if(!a.success)throw new X("Outline parse failed","outline","INVALID_OUTLINE");let o=a.data,c=await wh(o.cases.map(l=>async()=>{let u=Cl(o.name,l.name,l.description,e),d=await this.chatWithRetry([{role:"system",content:u.system},{role:"user",content:u.user}]),g=wn(d),m=Gs(g)??g,f=wl.safeParse(JSON.parse(m));return f.success?f.data.steps:[]}),5);return{name:o.name,description:o.description,tags:o.tags,cases:o.cases.map((l,u)=>({name:l.name,description:l.description,tags:l.tags,steps:(c[u]??[]).map(d=>({instruction:d.instruction,generatedCode:"",strategy:"primary"}))}))}}async generateTestSuiteSinglePass(e){let{system:t,user:s}=El(e),n=[{role:"system",content:t},{role:"user",content:s}],i=await this.chatWithRetry(n);for(let a=0;a<2;a++){let o=Gs(i);try{return this.parseGeneratedSuite(o??i)}catch(c){let l=i.trimEnd();if(!(!l.endsWith("}")&&!l.endsWith("]}")))throw c;n.push({role:"assistant",content:i}),n.push({role:"user",content:"Your JSON was cut off. Continue the JSON exactly from where you stopped \u2014 output only the continuation, no preamble."}),i+=await this.chatWithRetry(n)}}return this.parseGeneratedSuite(Gs(i)??i)}async healSelector(e,t,s,n){let{system:i,user:a}=Il(e,t,s,n),o=await this.chatWithRetry([{role:"system",content:i},{role:"user",content:a}]);return Oe(o)}async batchGenerateCode(e){if(e.length===0)return[];let t=e.map((o,c)=>({index:c,instruction:o.instruction})),{system:s,user:n}=Tl(t,e[0].context),i=await this.chatWithRetry([{role:"system",content:s},{role:"user",content:n}]);return(await this.parseBatchResponse(i,e.length)).map((o,c)=>qr(e[c]?.instruction??"",o))}async analyzeScreenshot(e,t){if(!this.supportsVision||!this.chatWithVision)throw new U(`Provider "${this.name}" does not support vision. Use Claude, GPT-4o, or Gemini for visual/coordinate-based healing.`,this.name,"VISION_NOT_SUPPORTED");let s=`Identify the UI element to interact with for this step: "${t}"
621
- Return JSON: { "x": <pixels from left>, "y": <pixels from top>, "action": "click|fill|hover" }`,n=await this.chatWithVision(s,e);return this.parseScreenshotAnalysis(n)}async analyzeWithSoM(e,t,s){if(!this.supportsVision||!this.chatWithVision)throw new U(`Provider "${this.name}" does not support vision.`,this.name,"VISION_NOT_SUPPORTED");let n=`You are a Playwright test automation expert analyzing an annotated browser screenshot.
656
+ await expect.soft(page).toHaveURL(/dashboard/)`});async function qh(r,e){let t=new Array(r.length),s=0;async function n(){for(;s<r.length;){let a=s++;t[a]=await r[a]()}}let i=Array.from({length:Math.min(e,r.length)},n);return await Promise.all(i),t}function Js(r){let e=Jr(r).trim();try{return JSON.parse(e),null}catch{}let t=[],s=!1,n=!1;for(let a of e){if(n){n=!1;continue}if(a==="\\"&&s){n=!0;continue}if(a==='"'){s=!s;continue}s||(a==="{"||a==="["?t.push(a==="{"?"}":"]"):(a==="}"||a==="]")&&t.pop())}if(t.length===0)return null;let i=e;s&&(i+='"'),i+=t.reverse().join("");try{return JSON.parse(i),i}catch{return null}}var Ae,mr=b(()=>{"use strict";m();Ta();jl();Vl();zl();Xl();At();te();Ta();At();Ae=class{timeoutMs;maxRetries;temperature;constructor(e){this.timeoutMs=e.timeoutMs??3e4,this.maxRetries=e.maxRetries??2,this.temperature=e.temperature??.1}async generateCode(e,t){let{system:s,user:n}=Ml(e,t),i=await this.chatWithRetry([{role:"system",content:s},{role:"user",content:n}]),a=De(i);return Yr(e,a)}async generateTestSuite(e){try{return await this.generateTestSuiteTwoPass(e)}catch{return await this.generateTestSuiteSinglePass(e)}}async generateTestSuiteTwoPass(e){let t=Bl(e),s=await this.chatWithRetry([{role:"system",content:t.system},{role:"user",content:t.user}]),n=En(s),i=Js(n)??n,a=Dl.safeParse(JSON.parse(i));if(!a.success)throw new X("Outline parse failed","outline","INVALID_OUTLINE");let o=a.data,c=await qh(o.cases.map(l=>async()=>{let u=Ul(o.name,l.name,l.description,e),d=await this.chatWithRetry([{role:"system",content:u.system},{role:"user",content:u.user}]),p=En(d),g=Js(p)??p,f=Fl.safeParse(JSON.parse(g));return f.success?f.data.steps:[]}),5);return{name:o.name,description:o.description,tags:o.tags,cases:o.cases.map((l,u)=>({name:l.name,description:l.description,tags:l.tags,steps:(c[u]??[]).map(d=>({instruction:d.instruction,generatedCode:"",strategy:"primary"}))}))}}async generateTestSuiteSinglePass(e){let{system:t,user:s}=Hl(e),n=[{role:"system",content:t},{role:"user",content:s}],i=await this.chatWithRetry(n);for(let a=0;a<2;a++){let o=Js(i);try{return this.parseGeneratedSuite(o??i)}catch(c){let l=i.trimEnd();if(!(!l.endsWith("}")&&!l.endsWith("]}")))throw c;n.push({role:"assistant",content:i}),n.push({role:"user",content:"Your JSON was cut off. Continue the JSON exactly from where you stopped \u2014 output only the continuation, no preamble."}),i+=await this.chatWithRetry(n)}}return this.parseGeneratedSuite(Js(i)??i)}async healSelector(e,t,s,n){let{system:i,user:a}=Gl(e,t,s,n),o=await this.chatWithRetry([{role:"system",content:i},{role:"user",content:a}]);return De(o)}async batchGenerateCode(e){if(e.length===0)return[];let t=e.map((o,c)=>({index:c,instruction:o.instruction})),{system:s,user:n}=ql(t,e[0].context),i=await this.chatWithRetry([{role:"system",content:s},{role:"user",content:n}]);return(await this.parseBatchResponse(i,e.length)).map((o,c)=>Yr(e[c]?.instruction??"",o))}async analyzeScreenshot(e,t){if(!this.supportsVision||!this.chatWithVision)throw new B(`Provider "${this.name}" does not support vision. Use Claude, GPT-4o, or Gemini for visual/coordinate-based healing.`,this.name,"VISION_NOT_SUPPORTED");let s=`Identify the UI element to interact with for this step: "${t}"
657
+ Return JSON: { "x": <pixels from left>, "y": <pixels from top>, "action": "click|fill|hover" }`,n=await this.chatWithVision(s,e);return this.parseScreenshotAnalysis(n)}async analyzeWithSoM(e,t,s){if(!this.supportsVision||!this.chatWithVision)throw new B(`Provider "${this.name}" does not support vision.`,this.name,"VISION_NOT_SUPPORTED");let n=`You are a Playwright test automation expert analyzing an annotated browser screenshot.
622
658
 
623
659
  Each interactive element on the page has been highlighted with a colored numbered box.
624
660
 
@@ -641,63 +677,63 @@ Rules:
641
677
  Examples:
642
678
  await page.getByRole('link', { name: 'Admin' }).click()
643
679
  await page.getByPlaceholder('Username').fill('Admin')
644
- await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible()`,i=await this.chatWithVision(n,e);return Oe(i)}async validate(){try{return await this.chat([{role:"user",content:"Reply with the single word: ready"}]),{valid:!0}}catch(e){return{valid:!1,error:e instanceof Error?e.message:String(e)}}}async chatWithRetry(e,t=this.maxRetries){let s;for(let n=0;n<=t;n++)try{return await this.chat(e)}catch(i){s=i instanceof Error?i:new Error(String(i)),n<t&&await new Promise(a=>setTimeout(a,1e3*(n+1)))}throw new U(`Provider "${this.name}" failed after ${t+1} attempt(s): ${s?.message??"Unknown error"}`,this.name,"PROVIDER_EXHAUSTED")}parseGeneratedSuite(e){let t=wn(e),s=Gs(t)??t,n;try{n=JSON.parse(s)}catch{throw new X(`Provider "${this.name}" returned invalid JSON for test suite generation. Raw response: ${t.slice(0,200)}`,"generatedSuite","INVALID_SUITE_JSON")}let i=fl.safeParse(n);if(!i.success){let a=i.error.issues.map(o=>` \u2022 ${o.path.join(".")}: ${o.message}`).join(`
680
+ await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible()`,i=await this.chatWithVision(n,e);return De(i)}async validate(){try{return await this.chat([{role:"user",content:"Reply with the single word: ready"}]),{valid:!0}}catch(e){return{valid:!1,error:e instanceof Error?e.message:String(e)}}}async chatWithRetry(e,t=this.maxRetries){let s;for(let n=0;n<=t;n++)try{return await this.chat(e)}catch(i){s=i instanceof Error?i:new Error(String(i)),n<t&&await new Promise(a=>setTimeout(a,1e3*(n+1)))}throw new B(`Provider "${this.name}" failed after ${t+1} attempt(s): ${s?.message??"Unknown error"}`,this.name,"PROVIDER_EXHAUSTED")}parseGeneratedSuite(e){let t=En(e),s=Js(t)??t,n;try{n=JSON.parse(s)}catch{throw new X(`Provider "${this.name}" returned invalid JSON for test suite generation. Raw response: ${t.slice(0,200)}`,"generatedSuite","INVALID_SUITE_JSON")}let i=Ll.safeParse(n);if(!i.success){let a=i.error.issues.map(o=>` \u2022 ${o.path.join(".")}: ${o.message}`).join(`
645
681
  `);throw new X(`AI-generated suite has invalid structure:
646
- ${a}`,"generatedSuite","INVALID_SUITE_SCHEMA")}return{name:i.data.name,description:i.data.description,tags:i.data.tags,cases:i.data.cases.map(a=>({name:a.name,description:a.description,tags:a.tags,steps:a.steps.map(o=>({instruction:o.instruction,generatedCode:"",strategy:"primary"}))}))}}parseBatchResponse(e,t){let s=zr(e),n=s.match(/\{[\s\S]*\}/);n&&(s=n[0]);let i=new Array(t).fill(""),a=!1;try{let l=JSON.parse(s),u=hl.safeParse(l);if(u.success){a=!0;for(let d of u.data.results)if(d.index<t)try{i[d.index]=Oe(d.code)}catch{}return i}}catch{}if(a)return i;let o=/\/\/\s*STEP[_\s]?(\d+)\s*\n([\s\S]*?)(?=\/\/\s*STEP[_\s]?\d+|$)/g,c;for(;(c=o.exec(s))!==null;){let l=parseInt(c[1],10);if(l<t)try{i[l]=Oe(c[2].trim())}catch{}}return i}parseScreenshotAnalysis(e){let t=zr(e);try{let s=JSON.parse(t),n=bl.safeParse(s);if(n.success)return n.data}catch{}throw new X(`Could not parse screenshot analysis response: ${t.slice(0,200)}`,"screenshotAnalysis","INVALID_SCREENSHOT_ANALYSIS")}}});var $l={};Q($l,{AnthropicProvider:()=>va});var Al,va,_l=w(()=>{"use strict";p();Al=x(require("@anthropic-ai/sdk"));ur();re();va=class extends ke{name="anthropic";model;supportsVision=!0;client;constructor(e){super(e),this.model=e.model,this.client=new Al.default({apiKey:e.apiKey,timeout:this.timeoutMs,maxRetries:0})}async chat(e){let t=e.find(n=>n.role==="system")?.content,s=e.filter(n=>n.role!=="system");try{let i=(await this.client.messages.create({model:this.model,max_tokens:8192,temperature:this.temperature,system:t,messages:s.map(a=>({role:a.role,content:a.content}))})).content[0];if(!i||i.type!=="text")throw new U("Anthropic returned an empty or non-text response.",this.name,"EMPTY_RESPONSE");return i.text}catch(n){if(n instanceof U)throw n;let i=n instanceof Error?n.message:String(n);throw new U(`Anthropic API error: ${i}`,this.name,"API_ERROR")}}async chatWithVision(e,t){try{let n=(await this.client.messages.create({model:this.model,max_tokens:512,messages:[{role:"user",content:[{type:"image",source:{type:"base64",media_type:"image/png",data:t.toString("base64")}},{type:"text",text:e}]}]})).content[0];if(!n||n.type!=="text")throw new U("Anthropic vision returned empty response.",this.name);return n.text}catch(s){throw s instanceof U?s:new U(`Anthropic vision error: ${s instanceof Error?s.message:String(s)}`,this.name,"VISION_ERROR")}}async validate(){return this.client.apiKey?super.validate():{valid:!1,error:"ANTHROPIC_API_KEY is not set"}}}});var Ll={};Q(Ll,{OpenAIProvider:()=>xa});var Ol,xa,Dl=w(()=>{"use strict";p();Ol=x(require("openai"));ur();re();xa=class extends ke{name="openai";model;supportsVision=!0;client;constructor(e){super(e),this.model=e.model,this.client=new Ol.default({apiKey:e.apiKey,timeout:this.timeoutMs,maxRetries:0})}async chat(e){try{let s=(await this.client.chat.completions.create({model:this.model,messages:e.map(n=>({role:n.role,content:n.content})),temperature:this.temperature,max_tokens:8192})).choices[0]?.message?.content;if(!s)throw new U("OpenAI returned an empty response.",this.name,"EMPTY_RESPONSE");return s}catch(t){throw t instanceof U?t:new U(`OpenAI API error: ${t instanceof Error?t.message:String(t)}`,this.name,"API_ERROR")}}async chatWithVision(e,t){try{let n=(await this.client.chat.completions.create({model:this.model,max_tokens:512,messages:[{role:"user",content:[{type:"image_url",image_url:{url:`data:image/png;base64,${t.toString("base64")}`}},{type:"text",text:e}]}]})).choices[0]?.message?.content;if(!n)throw new U("OpenAI vision returned empty response.",this.name);return n}catch(s){throw s instanceof U?s:new U(`OpenAI vision error: ${s instanceof Error?s.message:String(s)}`,this.name,"VISION_ERROR")}}async validate(){return this.client.apiKey?super.validate():{valid:!1,error:"OPENAI_API_KEY is not set"}}}});var Ml={};Q(Ml,{GoogleProvider:()=>Sa});var Nl,Sa,Fl=w(()=>{"use strict";p();Nl=require("@google/generative-ai");ur();re();Sa=class extends ke{name="google";model;supportsVision=!0;genAI;constructor(e){super(e),this.model=e.model,this.genAI=new Nl.GoogleGenerativeAI(e.apiKey)}async chat(e){try{let t=e.find(g=>g.role==="system"),s=e.filter(g=>g.role!=="system"),n=s.at(-1)?.content??"",i=n.includes("Return only the JSON")||n.includes("Return ONLY valid JSON")||n.includes("return only the JSON")||n.includes("Return only a single line")||(t?.content?.includes("Return ONLY valid JSON")??!1),a=this.genAI.getGenerativeModel({model:this.model,systemInstruction:t?.content,generationConfig:{temperature:this.temperature,maxOutputTokens:8192,...i?{responseMimeType:"application/json"}:{}}}),o=s.slice(0,-1).map(g=>({role:g.role==="assistant"?"model":"user",parts:[{text:g.content}]})),c=s.at(-1);if(!c)throw new U("No user message provided.",this.name);let d=(await a.startChat({history:o}).sendMessage(c.content)).response.text();if(!d)throw new U("Google Gemini returned empty response.",this.name,"EMPTY_RESPONSE");return d}catch(t){throw t instanceof U?t:new U(`Google Gemini error: ${t instanceof Error?t.message:String(t)}`,this.name,"API_ERROR")}}async chatWithVision(e,t){try{return(await this.genAI.getGenerativeModel({model:this.model}).generateContent([e,{inlineData:{data:t.toString("base64"),mimeType:"image/png"}}])).response.text()}catch(s){throw new U(`Google vision error: ${s instanceof Error?s.message:String(s)}`,this.name,"VISION_ERROR")}}async validate(){return this.genAI?super.validate():{valid:!1,error:"GOOGLE_API_KEY is not set"}}}});var Bl={};Q(Bl,{AzureOpenAIProvider:()=>Ca});var jl,Ca,Ul=w(()=>{"use strict";p();jl=x(require("openai"));ur();re();Ca=class extends ke{name="azure-openai";model;supportsVision=!0;client;constructor(e){super(e),this.model=e.deployment,this.client=new jl.default({apiKey:e.apiKey,baseURL:`${e.endpoint}/openai/deployments/${e.deployment}`,defaultQuery:{"api-version":e.apiVersion??"2024-10-21"},defaultHeaders:{"api-key":e.apiKey},timeout:this.timeoutMs,maxRetries:0})}async chat(e){try{let s=(await this.client.chat.completions.create({model:this.model,messages:e.map(n=>({role:n.role,content:n.content})),temperature:this.temperature,max_tokens:8192})).choices[0]?.message?.content;if(!s)throw new U("Azure OpenAI returned empty response.",this.name,"EMPTY_RESPONSE");return s}catch(t){throw t instanceof U?t:new U(`Azure OpenAI error: ${t instanceof Error?t.message:String(t)}`,this.name,"API_ERROR")}}async validate(){return this.client.apiKey?super.validate():{valid:!1,error:"AZURE_OPENAI_API_KEY is not set"}}}});var Hl={};Q(Hl,{BedrockProvider:()=>Ea});var $n,Ea,Vl=w(()=>{"use strict";p();$n=require("@aws-sdk/client-bedrock-runtime");ur();re();Ea=class extends ke{name="bedrock";model;supportsVision=!1;client;constructor(e){super(e),this.model=e.model,this.client=new $n.BedrockRuntimeClient({region:e.region,credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey,...e.sessionToken?{sessionToken:e.sessionToken}:{}}})}async chat(e){try{return this.model.includes("claude")?await this.chatClaude(e):await this.chatClaude(e)}catch(t){throw t instanceof U?t:new U(`Bedrock error: ${t instanceof Error?t.message:String(t)}`,this.name,"API_ERROR")}}async chatClaude(e){let t=e.find(u=>u.role==="system")?.content,s=e.filter(u=>u.role!=="system"),n={anthropic_version:"bedrock-2023-05-31",max_tokens:8192,temperature:this.temperature,messages:s.map(u=>({role:u.role,content:u.content}))};t&&(n.system=t);let i=new $n.InvokeModelCommand({modelId:this.model,body:JSON.stringify(n),contentType:"application/json",accept:"application/json"}),a=await this.client.send(i),o=new TextDecoder().decode(a.body),l=JSON.parse(o).content[0]?.text;if(!l)throw new U("Bedrock returned empty response.",this.name,"EMPTY_RESPONSE");return l}async validate(){return this.client.config.credentials?super.validate():{valid:!1,error:"AWS credentials are not configured"}}}});var Gl,Fe,Rr=w(()=>{"use strict";p();Gl=x(require("openai"));ur();re();Fe=class extends ke{name;model;supportsVision=!1;client;constructor(e,t){super(t),this.name=e,this.model=t.model,this.client=new Gl.default({apiKey:t.apiKey,baseURL:t.baseUrl,timeout:this.timeoutMs,maxRetries:0})}async chat(e){try{let s=(await this.client.chat.completions.create({model:this.model,messages:e.map(n=>({role:n.role,content:n.content})),temperature:this.temperature,max_tokens:8192})).choices[0]?.message?.content;if(!s)throw new U(`Provider "${this.name}" returned an empty response.`,this.name,"EMPTY_RESPONSE");return s}catch(t){if(t instanceof U)throw t;let s=t instanceof Error?t.message:String(t);throw new U(`Provider "${this.name}" API error: ${s}`,this.name,"API_ERROR")}}async validate(){return!this.client.apiKey||this.client.apiKey==="none"?{valid:!1,error:`API key is not configured for provider "${this.name}"`}:super.validate()}}});var zl={};Q(zl,{DeepSeekProvider:()=>Pa});var Pa,ql=w(()=>{"use strict";p();Rr();Pa=class extends Fe{name="deepseek";constructor(e){let t={apiKey:e.apiKey,baseUrl:"https://api.deepseek.com/v1",model:e.model??"deepseek-chat",timeoutMs:e.timeoutMs,maxRetries:e.maxRetries};super("deepseek",t)}}});var Xl={};Q(Xl,{GroqProvider:()=>Ia});var Ia,Kl=w(()=>{"use strict";p();Rr();Ia=class extends Fe{name="groq";constructor(e){let t={apiKey:e.apiKey,baseUrl:"https://api.groq.com/openai/v1",model:e.model??"llama-3.3-70b-versatile",timeoutMs:e.timeoutMs,maxRetries:e.maxRetries};super("groq",t)}}});var Wl={};Q(Wl,{TogetherProvider:()=>Ra});var Ra,Jl=w(()=>{"use strict";p();Rr();Ra=class extends Fe{name="together";constructor(e){let t={apiKey:e.apiKey,baseUrl:"https://api.together.xyz/v1",model:e.model??"meta-llama/Llama-3.3-70B-Instruct-Turbo",timeoutMs:e.timeoutMs,maxRetries:e.maxRetries};super("together",t)}}});var Yl={};Q(Yl,{QwenProvider:()=>Ta});var Ta,Ql=w(()=>{"use strict";p();Rr();Ta=class extends Fe{name="qwen";constructor(e){let t={apiKey:e.apiKey,baseUrl:e.baseUrl??"https://dashscope-intl.aliyuncs.com/compatible-mode/v1",model:e.model??"qwen-max",timeoutMs:e.timeoutMs,maxRetries:e.maxRetries};super("qwen",t)}}});var Zl={};Q(Zl,{PerplexityProvider:()=>ka});var ka,eu=w(()=>{"use strict";p();Rr();ka=class extends Fe{name="perplexity";constructor(e){let t={apiKey:e.apiKey,baseUrl:"https://api.perplexity.ai",model:e.model??"sonar-pro",timeoutMs:e.timeoutMs,maxRetries:e.maxRetries};super("perplexity",t)}}});var ru={};Q(ru,{OllamaProvider:()=>Aa});var tu,Aa,su=w(()=>{"use strict";p();tu=x(require("openai"));ur();re();Aa=class extends ke{name="ollama";model;supportsVision=!1;baseUrl;client;constructor(e={}){super({model:e.model??"llama3.3",timeoutMs:e.timeoutMs??12e4,maxRetries:e.maxRetries??1}),this.model=e.model??"llama3.3",this.baseUrl=`${e.baseUrl??"http://localhost:11434"}/v1`,this.client=new tu.default({apiKey:"ollama",baseURL:this.baseUrl,timeout:this.timeoutMs,maxRetries:0})}async chat(e){try{let s=(await this.client.chat.completions.create({model:this.model,messages:e.map(n=>({role:n.role,content:n.content})),temperature:this.temperature})).choices[0]?.message?.content;if(!s)throw new U("Ollama returned an empty response.",this.name,"EMPTY_RESPONSE");return s}catch(t){if(t instanceof U)throw t;let s=t instanceof Error?t.message:String(t);throw s.includes("ECONNREFUSED")||s.includes("fetch failed")?new U(`Cannot connect to Ollama at ${this.baseUrl}. Make sure Ollama is running: start it with "ollama serve" and confirm it's on port 11434.`,this.name,"CONNECTION_REFUSED"):s.includes("model")&&(s.includes("not found")||s.includes("pull"))?new U(`Ollama model "${this.model}" is not available locally. Pull it first: ollama pull ${this.model}`,this.name,"MODEL_NOT_FOUND"):new U(`Ollama error: ${s}`,this.name,"API_ERROR")}}async validate(){try{return await this.chat([{role:"user",content:"Reply with the single word: ready"}]),{valid:!0}}catch(e){return{valid:!1,error:e instanceof Error?e.message:String(e)}}}}});var nu={};Q(nu,{CustomProvider:()=>$a});var $a,iu=w(()=>{"use strict";p();Rr();$a=class extends Fe{name="custom";constructor(e){let t={apiKey:e.apiKey,baseUrl:e.baseUrl,model:e.model,timeoutMs:e.timeoutMs,maxRetries:e.maxRetries};super("custom",t)}}});var au={};Q(au,{createProvider:()=>Tr,createSmartRouter:()=>tt,generateSuiteFromStory:()=>zs,generateSuitesFromStories:()=>Oa});function Tr(r,e){let t=Et(),s=r??String(t.AI_PROVIDER),n=t.AI_TIMEOUT*1e3,i=t.AI_MAX_RETRIES,a=e?.temperature;switch(s){case"anthropic":{let{AnthropicProvider:o}=(_l(),Qe($l));return new o({apiKey:String(t.ANTHROPIC_API_KEY??""),model:String(t.ANTHROPIC_MODEL??"claude-sonnet-4-20250514"),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"openai":{let{OpenAIProvider:o}=(Dl(),Qe(Ll));return new o({apiKey:String(t.OPENAI_API_KEY??""),model:String(t.OPENAI_MODEL??"gpt-4o"),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"google":{let{GoogleProvider:o}=(Fl(),Qe(Ml));return new o({apiKey:String(t.GOOGLE_API_KEY??""),model:String(t.GOOGLE_MODEL??"gemini-2.5-flash"),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"azure-openai":{let{AzureOpenAIProvider:o}=(Ul(),Qe(Bl));return new o({apiKey:String(t.AZURE_OPENAI_API_KEY??""),endpoint:String(t.AZURE_OPENAI_ENDPOINT??""),deployment:String(t.AZURE_OPENAI_DEPLOYMENT??""),apiVersion:String(t.AZURE_OPENAI_API_VERSION??"2024-10-21"),model:String(t.AZURE_OPENAI_DEPLOYMENT??""),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"bedrock":{let{BedrockProvider:o}=(Vl(),Qe(Hl));return new o({accessKeyId:String(t.AWS_ACCESS_KEY_ID??""),secretAccessKey:String(t.AWS_SECRET_ACCESS_KEY??""),...t.AWS_SESSION_TOKEN?{sessionToken:String(t.AWS_SESSION_TOKEN)}:{},region:String(t.AWS_REGION??"us-east-1"),model:String(t.BEDROCK_MODEL??"anthropic.claude-sonnet-4-20250514-v1:0"),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"deepseek":{let{DeepSeekProvider:o}=(ql(),Qe(zl));return new o({apiKey:String(t.DEEPSEEK_API_KEY??""),model:String(t.DEEPSEEK_MODEL??"deepseek-chat"),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"groq":{let{GroqProvider:o}=(Kl(),Qe(Xl));return new o({apiKey:String(t.GROQ_API_KEY??""),model:String(t.GROQ_MODEL??"llama-3.3-70b-versatile"),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"together":{let{TogetherProvider:o}=(Jl(),Qe(Wl));return new o({apiKey:String(t.TOGETHER_API_KEY??""),model:String(t.TOGETHER_MODEL??"meta-llama/Llama-3.3-70B-Instruct-Turbo"),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"qwen":{let{QwenProvider:o}=(Ql(),Qe(Yl));return new o({apiKey:String(t.QWEN_API_KEY??""),model:String(t.QWEN_MODEL??"qwen-max"),baseUrl:t.QWEN_BASE_URL,timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"perplexity":{let{PerplexityProvider:o}=(eu(),Qe(Zl));return new o({apiKey:String(t.PERPLEXITY_API_KEY??""),model:String(t.PERPLEXITY_MODEL??"sonar-pro"),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"ollama":{let{OllamaProvider:o}=(su(),Qe(ru));return new o({model:String(t.OLLAMA_MODEL??"llama3.3"),baseUrl:t.OLLAMA_BASE_URL,timeoutMs:Math.max(n,12e4),maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"custom":{let{CustomProvider:o}=(iu(),Qe(nu));return new o({apiKey:String(t.CUSTOM_API_KEY??""),baseUrl:String(t.CUSTOM_BASE_URL??""),model:String(t.CUSTOM_MODEL??""),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}default:throw new ye(`Unknown AI provider: "${s}". Supported: anthropic, openai, google, azure-openai, bedrock, deepseek, groq, together, qwen, perplexity, ollama, custom`,"UNKNOWN_PROVIDER")}}function tt(r,e,t,s){let n=Et(),i=Tr(),a;if(n.AI_TIERED_ENABLED){let l=n.AI_TIERED_FAST_PROVIDER;if(l)try{a=Tr(l),Le.info({fast:l,primary:String(n.AI_PROVIDER)},"Tiered mode active")}catch(u){Le.warn({err:u},"Failed to create fast provider \u2014 tiered mode disabled")}}let o=r?_n.default.join(r,"results",".code-cache.json"):void 0,c=new Zr(o);return new Tn({primaryProvider:i,fastProvider:a,cache:c,mcpSession:e,actThenScript:t,ragManager:s})}async function zs(r,e){let t=Tr();Le.info({provider:t.name,model:t.model},"Generating suite from story");let s=await t.generateTestSuite(r),n=e.suiteName??s.name,{suiteDir:i,suiteId:a}=await Ms(e.outputDir,{name:n,description:s.description,tags:s.tags,type:e.type??"ui"});Le.info({suiteDir:i,suiteId:a,cases:s.cases.length},"Suite directory created");for(let l of s.cases)await Jr(i,{name:l.name,description:l.description,tags:l.tags,priority:"medium",steps:l.steps.map((u,d)=>({id:`step-${d+1}`,order:d+1,instruction:u.instruction,generatedCode:u.generatedCode||"",strategy:u.strategy??"primary",stepType:Ze(u.instruction),lastHealed:null}))});Le.info({suiteId:a,cases:s.cases.length},"Auto-generating code for all steps");let o;try{let l=await J(e.rootDir),u=await et(e.rootDir).catch(()=>({}));l.mcp?.enabled&&(o=new pt({headless:l.mcp.headless,actionTimeout:l.mcp.actionTimeout,idleTimeout:l.mcp.idleTimeout}),Le.info({headless:l.mcp.headless},"MCP session created for suite generation"));let d=tt(e.rootDir,o,l.mcp?.actThenScript),g=await Ht(i);for(let m of g){let f=await se(m),h=f.steps.filter(I=>!I.generatedCode.trim());if(h.length===0)continue;let C=h.map(I=>({instruction:I.instruction,context:{url:l.baseUrl,title:"",interactiveElements:"",htmlSnapshot:"",previousSteps:f.steps.filter(B=>B.order<I.order&&B.generatedCode).map(B=>({instruction:B.instruction,code:B.generatedCode})),variables:u}})),P=await d.batchGenerate(C),v=new Map(h.map((I,B)=>[I.id,P[B]])),k=0,R=f.steps.map(I=>{let B=v.get(I.id);return B&&B.code.trim()?(k++,{...I,generatedCode:B.code,strategy:B.strategy}):I});k>0&&(await Me(m,{steps:R}),Le.info({caseName:f.name,generated:k,total:f.steps.length},"Code generated for case"))}await d.getCache().persist(),Le.info({suiteId:a},"Auto code generation complete")}catch(l){Le.warn({err:l,suiteId:a},"Auto code generation failed \u2014 steps saved without code")}finally{o&&(o.release(),Le.debug("MCP session released after suite generation"))}let c=_n.default.join(e.rootDir,"results",`generated-suite-${It(n)}.json`);return await _a.default.ensureDir(_n.default.dirname(c)),await _a.default.writeJson(c,{story:r,generated:s,suiteDir:i,suiteId:a},{spaces:2}),Le.info({reportPath:c,suiteId:a},"Generation complete"),{suiteId:a,suiteName:n}}async function Oa(r,e,t,s=3){let{randomUUID:n}=await import("crypto"),i=n(),a=r.length,o=0,c=0,l=[];t?.broadcast("story:bulk-start",{jobId:i,total:a}),Le.info({jobId:i,total:a,concurrency:s},"Bulk story generation started");let u=0,d=[...r.entries()],g=[];async function m(){for(;d.length>0;){let h=d.shift();if(!h)break;let[C,P]=h;t?.broadcast("story:bulk-progress",{jobId:i,total:a,completed:o,failed:c,currentIndex:C,currentStory:P.story.slice(0,80)});try{await zs(P.story,{rootDir:e.rootDir,outputDir:e.outputDir,suiteName:P.suiteName}),o++,Le.info({jobId:i,index:C,completed:o,total:a},"Story processed")}catch(v){c++;let k=v instanceof Error?v.message:String(v);l.push({index:C,story:P.story.slice(0,120),error:k}),Le.warn({jobId:i,index:C,error:k},"Story generation failed \u2014 continuing batch")}t?.broadcast("story:bulk-progress",{jobId:i,total:a,completed:o,failed:c,currentIndex:C,currentStory:P.story.slice(0,80)}),d.length>0&&await new Promise(v=>setTimeout(v,350))}}for(let h=0;h<Math.min(s,a);h++)g.push(m());await Promise.all(g);let f={jobId:i,total:a,completed:o,failed:c,failedItems:l};return t?.broadcast("story:bulk-done",f),Le.info({jobId:i,completed:o,failed:c,total:a},"Bulk story generation finished"),f}var _n,_a,Le,dr=w(()=>{"use strict";p();_n=x(require("path")),_a=x(require("fs-extra"));ar();re();F();ll();fa();Vs();dt();ze();_e();lr();Rt();Ir();Le=E("router")});async function lu(r){let e=r.rootDir,t=ou.default.join(e,"tests");async function s(n,i){let a=await pe(t,n);return a?ut(a,i):null}r.post("/suites/:suiteId/cases/:caseId/steps",async(n,i)=>{let a=bh.safeParse(n.body);if(!a.success)return i.status(400).send({error:"Invalid step data",details:a.error.issues});try{let o=await s(n.params.suiteId,n.params.caseId);if(!o)return i.status(404).send({error:`Case "${n.params.caseId}" not found`});let c=await se(o),l=a.data.order??c.steps.length+1,u={id:`step-${(0,cu.randomUUID)().slice(0,8)}`,order:l,instruction:a.data.instruction,generatedCode:a.data.generatedCode??"",strategy:a.data.generatedCode?a.data.strategy??"recorder":"primary",lastHealed:null,...a.data.soft?{soft:!0}:{}},d=[...c.steps.map(m=>m.order>=l?{...m,order:m.order+1}:m),u].sort((m,f)=>m.order-f.order),g=await Me(o,{steps:d});return i.status(201).send(g)}catch(o){return b(i,500,"Failed to add step",o)}}),r.delete("/suites/:suiteId/cases/:caseId/steps/:stepId",async(n,i)=>{try{let a=await s(n.params.suiteId,n.params.caseId);if(!a)return i.status(404).send({error:`Case "${n.params.caseId}" not found`});let c=(await se(a)).steps.filter(u=>u.id!==n.params.stepId).map((u,d)=>({...u,order:d+1})),l=await Me(a,{steps:c});return i.send(l)}catch(a){return b(i,500,"Failed to delete step",a)}}),r.post("/suites/:suiteId/cases/:caseId/steps/:stepId/generate",async(n,i)=>{let a;try{let o=await s(n.params.suiteId,n.params.caseId);if(!o)return i.status(404).send({error:`Case "${n.params.caseId}" not found`});let c=await se(o),l=c.steps.find(v=>v.id===n.params.stepId);if(!l)return i.status(404).send({error:`Step "${n.params.stepId}" not found`});let u=await et(e).catch(()=>({})),d=await J(e),g=n.body?.useMcp??d.mcp?.enabled;g&&(a=new pt({headless:d.mcp?.headless??!0,actionTimeout:d.mcp?.actionTimeout??15e3,idleTimeout:d.mcp?.idleTimeout??3e4}));let m=tt(e,a,g?d.mcp?.actThenScript:!1),f=await m.generate(l.instruction,{url:d.baseUrl,title:"",interactiveElements:"",htmlSnapshot:"",previousSteps:c.steps.filter(v=>v.order<l.order&&v.generatedCode).map(v=>({instruction:v.instruction,code:v.generatedCode})),variables:u}),h=f.code;l.soft&&h&&(h=h.replace(/\bexpect\(/g,"expect.soft("));let C=c.steps.map(v=>v.id===l.id?{...v,generatedCode:h,strategy:f.strategy}:v);await m.getCache().persist();let P=await Me(o,{steps:C});return i.send({step:P.steps.find(v=>v.id===l.id),strategy:f.strategy,cost:f.cost,mcpUsed:!!a})}catch(o){return b(i,500,"Failed to generate code for step",o)}finally{a?.release()}}),r.post("/suites/:suiteId/cases/:caseId/steps/generate-all",async(n,i)=>{let a;try{let o=await s(n.params.suiteId,n.params.caseId);if(!o)return i.status(404).send({error:`Case "${n.params.caseId}" not found`});let c=await se(o),l=c.steps.filter(R=>!R.generatedCode.trim());if(l.length===0)return i.send({message:"All steps already have code",generated:0});let u=await et(e).catch(()=>({})),d=await J(e),g=n.body?.useMcp??d.mcp?.enabled;g&&(a=new pt({headless:d.mcp?.headless??!0,actionTimeout:d.mcp?.actionTimeout??15e3,idleTimeout:d.mcp?.idleTimeout??3e4}));let m=tt(e,a,g?d.mcp?.actThenScript:!1),f=l.map(R=>({instruction:R.instruction,context:{url:d.baseUrl,title:"",interactiveElements:"",htmlSnapshot:"",previousSteps:c.steps.filter(I=>I.order<R.order&&I.generatedCode).map(I=>({instruction:I.instruction,code:I.generatedCode})),variables:u}})),h=await m.batchGenerate(f);await m.getCache().persist();let C=new Map(l.map((R,I)=>[R.id,h[I]])),P=0,v=c.steps.map(R=>{let I=C.get(R.id);if(I&&I.code.trim()){P++;let B=R.soft?I.code.replace(/\bexpect\(/g,"expect.soft("):I.code;return{...R,generatedCode:B,strategy:I.strategy}}return R});if(P===0)return i.status(500).send({error:"AI code generation produced no results",detail:"The AI provider responded but returned empty code for all steps. Check your API key, model name, and server terminal logs for details.",code:"GENERATION_EMPTY"});let k=await Me(o,{steps:v});return i.send({generated:P,case:k,mcpUsed:!!a})}catch(o){return b(i,500,"Failed to generate code for steps",o)}finally{a?.release()}}),r.patch("/suites/:suiteId/cases/:caseId/steps/reorder",async(n,i)=>{let a=vh.safeParse(n.body);if(!a.success)return i.status(400).send({error:"Invalid reorder data",details:a.error.issues});try{let o=await s(n.params.suiteId,n.params.caseId);if(!o)return i.status(404).send({error:`Case "${n.params.caseId}" not found`});let c=await se(o),l=new Map(c.steps.map(g=>[g.id,g])),u=a.data.stepIds.map((g,m)=>{let f=l.get(g);return f?{...f,order:m+1}:null}).filter(g=>g!==null),d=await Me(o,{steps:u});return i.send(d)}catch(o){return b(i,500,"Failed to reorder steps",o)}}),r.patch("/suites/:suiteId/cases/:caseId/steps/:stepId",async(n,i)=>{let a=xh.safeParse(n.body);if(!a.success)return i.status(400).send({error:"Invalid step data",details:a.error.issues});try{let o=await s(n.params.suiteId,n.params.caseId);if(!o)return i.status(404).send({error:`Case "${n.params.caseId}" not found`});let c=await se(o);if(!c.steps.find(g=>g.id===n.params.stepId))return i.status(404).send({error:`Step "${n.params.stepId}" not found`});let u=c.steps.map(g=>{if(g.id!==n.params.stepId)return g;let m={};return a.data.instruction!==void 0&&(m.instruction=a.data.instruction),a.data.timeout!==void 0&&(m.timeout=a.data.timeout??void 0),a.data.stepType!==void 0&&(m.stepType=a.data.stepType),a.data.retries!==void 0&&(m.retries=a.data.retries),a.data.mockUrl!==void 0&&(m.mockUrl=a.data.mockUrl),a.data.mockResponse!==void 0&&(m.mockResponse=a.data.mockResponse),a.data.mockStatus!==void 0&&(m.mockStatus=a.data.mockStatus),a.data.auditUrl!==void 0&&(m.auditUrl=a.data.auditUrl),a.data.lighthouseCategories!==void 0&&(m.lighthouseCategories=a.data.lighthouseCategories),a.data.runAudit!==void 0&&(m.runAudit=a.data.runAudit),a.data.soft!==void 0&&(m.soft=a.data.soft,g.generatedCode&&(a.data.soft?m.generatedCode=g.generatedCode.replace(/\bexpect\(/g,"expect.soft("):m.generatedCode=g.generatedCode.replace(/\bexpect\.soft\(/g,"expect("))),a.data.visualCheck!==void 0&&(m.visualCheck=a.data.visualCheck),{...g,...m}}),d=await Me(o,{steps:u});return i.send(d)}catch(o){return b(i,500,"Failed to update step",o)}})}var ou,cu,ne,bh,vh,xh,uu=w(()=>{"use strict";p();ou=x(require("path")),cu=require("crypto"),ne=require("zod");dt();ze();lr();_e();dr();Vs();ae();bh=ne.z.object({instruction:ne.z.string().min(1),order:ne.z.number().int().positive().optional(),generatedCode:ne.z.string().optional(),strategy:ne.z.enum(["template","cache","rag","batch","fast","primary","recorder"]).optional(),soft:ne.z.boolean().optional()}),vh=ne.z.object({stepIds:ne.z.array(ne.z.string().min(1))}),xh=ne.z.object({instruction:ne.z.string().min(1).optional(),timeout:ne.z.number().int().positive().optional().nullable(),stepType:ne.z.enum(["ui","api","mock"]).optional(),retries:ne.z.number().int().min(0).optional(),mockUrl:ne.z.string().optional(),mockResponse:ne.z.string().optional(),mockStatus:ne.z.number().int().optional(),auditUrl:ne.z.string().optional(),lighthouseCategories:ne.z.array(ne.z.enum(["performance","accessibility","seo"])).optional(),runAudit:ne.z.boolean().optional(),soft:ne.z.boolean().optional(),visualCheck:ne.z.boolean().optional()})});async function pr(r){let e=La.default.join(r,gu);if(!await Da.default.pathExists(e))return{...du};let t=await de(e),s=ra.safeParse(t);return s.success?s.data:(mu.warn({path:e,errors:s.error.issues},"Invalid hooks.json \u2014 returning defaults"),{...du})}async function kr(r,e){await Da.default.ensureDir(r);let t=La.default.join(r,gu),s=ra.safeParse(e);if(!s.success){let n=s.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
682
+ ${a}`,"generatedSuite","INVALID_SUITE_SCHEMA")}return{name:i.data.name,description:i.data.description,tags:i.data.tags,cases:i.data.cases.map(a=>({name:a.name,description:a.description,tags:a.tags,steps:a.steps.map(o=>({instruction:o.instruction,generatedCode:"",strategy:"primary"}))}))}}parseBatchResponse(e,t){let s=Jr(e),n=s.match(/\{[\s\S]*\}/);n&&(s=n[0]);let i=new Array(t).fill(""),a=!1;try{let l=JSON.parse(s),u=Ol.safeParse(l);if(u.success){a=!0;for(let d of u.data.results)if(d.index<t)try{i[d.index]=De(d.code)}catch{}return i}}catch{}if(a)return i;let o=/\/\/\s*STEP[_\s]?(\d+)\s*\n([\s\S]*?)(?=\/\/\s*STEP[_\s]?\d+|$)/g,c;for(;(c=o.exec(s))!==null;){let l=parseInt(c[1],10);if(l<t)try{i[l]=De(c[2].trim())}catch{}}return i}parseScreenshotAnalysis(e){let t=Jr(e);try{let s=JSON.parse(t),n=Nl.safeParse(s);if(n.success)return n.data}catch{}throw new X(`Could not parse screenshot analysis response: ${t.slice(0,200)}`,"screenshotAnalysis","INVALID_SCREENSHOT_ANALYSIS")}}});var Wl={};Q(Wl,{AnthropicProvider:()=>ka});var Kl,ka,Jl=b(()=>{"use strict";m();Kl=x(require("@anthropic-ai/sdk"));mr();te();ka=class extends Ae{name="anthropic";model;supportsVision=!0;client;constructor(e){super(e),this.model=e.model,this.client=new Kl.default({apiKey:e.apiKey,timeout:this.timeoutMs,maxRetries:0})}async chat(e){let t=e.find(n=>n.role==="system")?.content,s=e.filter(n=>n.role!=="system");try{let i=(await this.client.messages.create({model:this.model,max_tokens:8192,temperature:this.temperature,system:t,messages:s.map(a=>({role:a.role,content:a.content}))})).content[0];if(!i||i.type!=="text")throw new B("Anthropic returned an empty or non-text response.",this.name,"EMPTY_RESPONSE");return i.text}catch(n){if(n instanceof B)throw n;let i=n instanceof Error?n.message:String(n);throw new B(`Anthropic API error: ${i}`,this.name,"API_ERROR")}}async chatWithVision(e,t){try{let n=(await this.client.messages.create({model:this.model,max_tokens:512,messages:[{role:"user",content:[{type:"image",source:{type:"base64",media_type:"image/png",data:t.toString("base64")}},{type:"text",text:e}]}]})).content[0];if(!n||n.type!=="text")throw new B("Anthropic vision returned empty response.",this.name);return n.text}catch(s){throw s instanceof B?s:new B(`Anthropic vision error: ${s instanceof Error?s.message:String(s)}`,this.name,"VISION_ERROR")}}async validate(){return this.client.apiKey?super.validate():{valid:!1,error:"ANTHROPIC_API_KEY is not set"}}}});var Ql={};Q(Ql,{OpenAIProvider:()=>Aa});var Yl,Aa,Zl=b(()=>{"use strict";m();Yl=x(require("openai"));mr();te();Aa=class extends Ae{name="openai";model;supportsVision=!0;client;constructor(e){super(e),this.model=e.model,this.client=new Yl.default({apiKey:e.apiKey,timeout:this.timeoutMs,maxRetries:0})}async chat(e){try{let s=(await this.client.chat.completions.create({model:this.model,messages:e.map(n=>({role:n.role,content:n.content})),temperature:this.temperature,max_tokens:8192})).choices[0]?.message?.content;if(!s)throw new B("OpenAI returned an empty response.",this.name,"EMPTY_RESPONSE");return s}catch(t){throw t instanceof B?t:new B(`OpenAI API error: ${t instanceof Error?t.message:String(t)}`,this.name,"API_ERROR")}}async chatWithVision(e,t){try{let n=(await this.client.chat.completions.create({model:this.model,max_tokens:512,messages:[{role:"user",content:[{type:"image_url",image_url:{url:`data:image/png;base64,${t.toString("base64")}`}},{type:"text",text:e}]}]})).choices[0]?.message?.content;if(!n)throw new B("OpenAI vision returned empty response.",this.name);return n}catch(s){throw s instanceof B?s:new B(`OpenAI vision error: ${s instanceof Error?s.message:String(s)}`,this.name,"VISION_ERROR")}}async validate(){return this.client.apiKey?super.validate():{valid:!1,error:"OPENAI_API_KEY is not set"}}}});var tu={};Q(tu,{GoogleProvider:()=>$a});var eu,$a,ru=b(()=>{"use strict";m();eu=require("@google/generative-ai");mr();te();$a=class extends Ae{name="google";model;supportsVision=!0;genAI;constructor(e){super(e),this.model=e.model,this.genAI=new eu.GoogleGenerativeAI(e.apiKey)}async chat(e){try{let t=e.find(p=>p.role==="system"),s=e.filter(p=>p.role!=="system"),n=s.at(-1)?.content??"",i=n.includes("Return only the JSON")||n.includes("Return ONLY valid JSON")||n.includes("return only the JSON")||n.includes("Return only a single line")||(t?.content?.includes("Return ONLY valid JSON")??!1),a=this.genAI.getGenerativeModel({model:this.model,systemInstruction:t?.content,generationConfig:{temperature:this.temperature,maxOutputTokens:8192,...i?{responseMimeType:"application/json"}:{}}}),o=s.slice(0,-1).map(p=>({role:p.role==="assistant"?"model":"user",parts:[{text:p.content}]})),c=s.at(-1);if(!c)throw new B("No user message provided.",this.name);let d=(await a.startChat({history:o}).sendMessage(c.content)).response.text();if(!d)throw new B("Google Gemini returned empty response.",this.name,"EMPTY_RESPONSE");return d}catch(t){throw t instanceof B?t:new B(`Google Gemini error: ${t instanceof Error?t.message:String(t)}`,this.name,"API_ERROR")}}async chatWithVision(e,t){try{return(await this.genAI.getGenerativeModel({model:this.model}).generateContent([e,{inlineData:{data:t.toString("base64"),mimeType:"image/png"}}])).response.text()}catch(s){throw new B(`Google vision error: ${s instanceof Error?s.message:String(s)}`,this.name,"VISION_ERROR")}}async validate(){return this.genAI?super.validate():{valid:!1,error:"GOOGLE_API_KEY is not set"}}}});var nu={};Q(nu,{AzureOpenAIProvider:()=>_a});var su,_a,iu=b(()=>{"use strict";m();su=x(require("openai"));mr();te();_a=class extends Ae{name="azure-openai";model;supportsVision=!0;client;constructor(e){super(e),this.model=e.deployment,this.client=new su.default({apiKey:e.apiKey,baseURL:`${e.endpoint}/openai/deployments/${e.deployment}`,defaultQuery:{"api-version":e.apiVersion??"2024-10-21"},defaultHeaders:{"api-key":e.apiKey},timeout:this.timeoutMs,maxRetries:0})}async chat(e){try{let s=(await this.client.chat.completions.create({model:this.model,messages:e.map(n=>({role:n.role,content:n.content})),temperature:this.temperature,max_tokens:8192})).choices[0]?.message?.content;if(!s)throw new B("Azure OpenAI returned empty response.",this.name,"EMPTY_RESPONSE");return s}catch(t){throw t instanceof B?t:new B(`Azure OpenAI error: ${t instanceof Error?t.message:String(t)}`,this.name,"API_ERROR")}}async validate(){return this.client.apiKey?super.validate():{valid:!1,error:"AZURE_OPENAI_API_KEY is not set"}}}});var au={};Q(au,{BedrockProvider:()=>La});var Nn,La,ou=b(()=>{"use strict";m();Nn=require("@aws-sdk/client-bedrock-runtime");mr();te();La=class extends Ae{name="bedrock";model;supportsVision=!1;client;constructor(e){super(e),this.model=e.model,this.client=new Nn.BedrockRuntimeClient({region:e.region,credentials:{accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey,...e.sessionToken?{sessionToken:e.sessionToken}:{}}})}async chat(e){try{return this.model.includes("claude")?await this.chatClaude(e):await this.chatClaude(e)}catch(t){throw t instanceof B?t:new B(`Bedrock error: ${t instanceof Error?t.message:String(t)}`,this.name,"API_ERROR")}}async chatClaude(e){let t=e.find(u=>u.role==="system")?.content,s=e.filter(u=>u.role!=="system"),n={anthropic_version:"bedrock-2023-05-31",max_tokens:8192,temperature:this.temperature,messages:s.map(u=>({role:u.role,content:u.content}))};t&&(n.system=t);let i=new Nn.InvokeModelCommand({modelId:this.model,body:JSON.stringify(n),contentType:"application/json",accept:"application/json"}),a=await this.client.send(i),o=new TextDecoder().decode(a.body),l=JSON.parse(o).content[0]?.text;if(!l)throw new B("Bedrock returned empty response.",this.name,"EMPTY_RESPONSE");return l}async validate(){return this.client.config.credentials?super.validate():{valid:!1,error:"AWS credentials are not configured"}}}});var cu,Ue,_r=b(()=>{"use strict";m();cu=x(require("openai"));mr();te();Ue=class extends Ae{name;model;supportsVision=!1;client;constructor(e,t){super(t),this.name=e,this.model=t.model,this.client=new cu.default({apiKey:t.apiKey,baseURL:t.baseUrl,timeout:this.timeoutMs,maxRetries:0})}async chat(e){try{let s=(await this.client.chat.completions.create({model:this.model,messages:e.map(n=>({role:n.role,content:n.content})),temperature:this.temperature,max_tokens:8192})).choices[0]?.message?.content;if(!s)throw new B(`Provider "${this.name}" returned an empty response.`,this.name,"EMPTY_RESPONSE");return s}catch(t){if(t instanceof B)throw t;let s=t instanceof Error?t.message:String(t);throw new B(`Provider "${this.name}" API error: ${s}`,this.name,"API_ERROR")}}async validate(){return!this.client.apiKey||this.client.apiKey==="none"?{valid:!1,error:`API key is not configured for provider "${this.name}"`}:super.validate()}}});var lu={};Q(lu,{DeepSeekProvider:()=>Oa});var Oa,uu=b(()=>{"use strict";m();_r();Oa=class extends Ue{name="deepseek";constructor(e){let t={apiKey:e.apiKey,baseUrl:"https://api.deepseek.com/v1",model:e.model??"deepseek-chat",timeoutMs:e.timeoutMs,maxRetries:e.maxRetries};super("deepseek",t)}}});var du={};Q(du,{GroqProvider:()=>Da});var Da,pu=b(()=>{"use strict";m();_r();Da=class extends Ue{name="groq";constructor(e){let t={apiKey:e.apiKey,baseUrl:"https://api.groq.com/openai/v1",model:e.model??"llama-3.3-70b-versatile",timeoutMs:e.timeoutMs,maxRetries:e.maxRetries};super("groq",t)}}});var mu={};Q(mu,{TogetherProvider:()=>Fa});var Fa,gu=b(()=>{"use strict";m();_r();Fa=class extends Ue{name="together";constructor(e){let t={apiKey:e.apiKey,baseUrl:"https://api.together.xyz/v1",model:e.model??"meta-llama/Llama-3.3-70B-Instruct-Turbo",timeoutMs:e.timeoutMs,maxRetries:e.maxRetries};super("together",t)}}});var fu={};Q(fu,{QwenProvider:()=>Na});var Na,hu=b(()=>{"use strict";m();_r();Na=class extends Ue{name="qwen";constructor(e){let t={apiKey:e.apiKey,baseUrl:e.baseUrl??"https://dashscope-intl.aliyuncs.com/compatible-mode/v1",model:e.model??"qwen-max",timeoutMs:e.timeoutMs,maxRetries:e.maxRetries};super("qwen",t)}}});var yu={};Q(yu,{PerplexityProvider:()=>Ma});var Ma,wu=b(()=>{"use strict";m();_r();Ma=class extends Ue{name="perplexity";constructor(e){let t={apiKey:e.apiKey,baseUrl:"https://api.perplexity.ai",model:e.model??"sonar-pro",timeoutMs:e.timeoutMs,maxRetries:e.maxRetries};super("perplexity",t)}}});var vu={};Q(vu,{OllamaProvider:()=>ja});var bu,ja,xu=b(()=>{"use strict";m();bu=x(require("openai"));mr();te();ja=class extends Ae{name="ollama";model;supportsVision=!1;baseUrl;client;constructor(e={}){super({model:e.model??"llama3.3",timeoutMs:e.timeoutMs??12e4,maxRetries:e.maxRetries??1}),this.model=e.model??"llama3.3",this.baseUrl=`${e.baseUrl??"http://localhost:11434"}/v1`,this.client=new bu.default({apiKey:"ollama",baseURL:this.baseUrl,timeout:this.timeoutMs,maxRetries:0})}async chat(e){try{let s=(await this.client.chat.completions.create({model:this.model,messages:e.map(n=>({role:n.role,content:n.content})),temperature:this.temperature})).choices[0]?.message?.content;if(!s)throw new B("Ollama returned an empty response.",this.name,"EMPTY_RESPONSE");return s}catch(t){if(t instanceof B)throw t;let s=t instanceof Error?t.message:String(t);throw s.includes("ECONNREFUSED")||s.includes("fetch failed")?new B(`Cannot connect to Ollama at ${this.baseUrl}. Make sure Ollama is running: start it with "ollama serve" and confirm it's on port 11434.`,this.name,"CONNECTION_REFUSED"):s.includes("model")&&(s.includes("not found")||s.includes("pull"))?new B(`Ollama model "${this.model}" is not available locally. Pull it first: ollama pull ${this.model}`,this.name,"MODEL_NOT_FOUND"):new B(`Ollama error: ${s}`,this.name,"API_ERROR")}}async validate(){try{return await this.chat([{role:"user",content:"Reply with the single word: ready"}]),{valid:!0}}catch(e){return{valid:!1,error:e instanceof Error?e.message:String(e)}}}}});var Su={};Q(Su,{CustomProvider:()=>Ba});var Ba,Cu=b(()=>{"use strict";m();_r();Ba=class extends Ue{name="custom";constructor(e){let t={apiKey:e.apiKey,baseUrl:e.baseUrl,model:e.model,timeoutMs:e.timeoutMs,maxRetries:e.maxRetries};super("custom",t)}}});var Eu={};Q(Eu,{createProvider:()=>Lr,createSmartRouter:()=>st,generateSuiteFromStory:()=>Ys,generateSuitesFromStories:()=>Ha});function Lr(r,e){let t=Rt(),s=r??String(t.AI_PROVIDER),n=t.AI_TIMEOUT*1e3,i=t.AI_MAX_RETRIES,a=e?.temperature;switch(s){case"anthropic":{let{AnthropicProvider:o}=(Jl(),et(Wl));return new o({apiKey:String(t.ANTHROPIC_API_KEY??""),model:String(t.ANTHROPIC_MODEL??"claude-sonnet-4-20250514"),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"openai":{let{OpenAIProvider:o}=(Zl(),et(Ql));return new o({apiKey:String(t.OPENAI_API_KEY??""),model:String(t.OPENAI_MODEL??"gpt-4o"),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"google":{let{GoogleProvider:o}=(ru(),et(tu));return new o({apiKey:String(t.GOOGLE_API_KEY??""),model:String(t.GOOGLE_MODEL??"gemini-2.5-flash"),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"azure-openai":{let{AzureOpenAIProvider:o}=(iu(),et(nu));return new o({apiKey:String(t.AZURE_OPENAI_API_KEY??""),endpoint:String(t.AZURE_OPENAI_ENDPOINT??""),deployment:String(t.AZURE_OPENAI_DEPLOYMENT??""),apiVersion:String(t.AZURE_OPENAI_API_VERSION??"2024-10-21"),model:String(t.AZURE_OPENAI_DEPLOYMENT??""),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"bedrock":{let{BedrockProvider:o}=(ou(),et(au));return new o({accessKeyId:String(t.AWS_ACCESS_KEY_ID??""),secretAccessKey:String(t.AWS_SECRET_ACCESS_KEY??""),...t.AWS_SESSION_TOKEN?{sessionToken:String(t.AWS_SESSION_TOKEN)}:{},region:String(t.AWS_REGION??"us-east-1"),model:String(t.BEDROCK_MODEL??"anthropic.claude-sonnet-4-20250514-v1:0"),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"deepseek":{let{DeepSeekProvider:o}=(uu(),et(lu));return new o({apiKey:String(t.DEEPSEEK_API_KEY??""),model:String(t.DEEPSEEK_MODEL??"deepseek-chat"),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"groq":{let{GroqProvider:o}=(pu(),et(du));return new o({apiKey:String(t.GROQ_API_KEY??""),model:String(t.GROQ_MODEL??"llama-3.3-70b-versatile"),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"together":{let{TogetherProvider:o}=(gu(),et(mu));return new o({apiKey:String(t.TOGETHER_API_KEY??""),model:String(t.TOGETHER_MODEL??"meta-llama/Llama-3.3-70B-Instruct-Turbo"),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"qwen":{let{QwenProvider:o}=(hu(),et(fu));return new o({apiKey:String(t.QWEN_API_KEY??""),model:String(t.QWEN_MODEL??"qwen-max"),baseUrl:t.QWEN_BASE_URL,timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"perplexity":{let{PerplexityProvider:o}=(wu(),et(yu));return new o({apiKey:String(t.PERPLEXITY_API_KEY??""),model:String(t.PERPLEXITY_MODEL??"sonar-pro"),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"ollama":{let{OllamaProvider:o}=(xu(),et(vu));return new o({model:String(t.OLLAMA_MODEL??"llama3.3"),baseUrl:t.OLLAMA_BASE_URL,timeoutMs:Math.max(n,12e4),maxRetries:i,...a!==void 0?{temperature:a}:{}})}case"custom":{let{CustomProvider:o}=(Cu(),et(Su));return new o({apiKey:String(t.CUSTOM_API_KEY??""),baseUrl:String(t.CUSTOM_BASE_URL??""),model:String(t.CUSTOM_MODEL??""),timeoutMs:n,maxRetries:i,...a!==void 0?{temperature:a}:{}})}default:throw new fe(`Unknown AI provider: "${s}". Supported: anthropic, openai, google, azure-openai, bedrock, deepseek, groq, together, qwen, perplexity, ollama, custom`,"UNKNOWN_PROVIDER")}}function st(r,e,t,s){let n=Rt(),i=Lr(),a;if(n.AI_TIERED_ENABLED){let l=n.AI_TIERED_FAST_PROVIDER;if(l)try{a=Lr(l),Fe.info({fast:l,primary:String(n.AI_PROVIDER)},"Tiered mode active")}catch(u){Fe.warn({err:u},"Failed to create fast provider \u2014 tiered mode disabled")}}let o=r?Mn.default.join(r,"results",".code-cache.json"):void 0,c=new ns(o);return new On({primaryProvider:i,fastProvider:a,cache:c,mcpSession:e,actThenScript:t,ragManager:s})}async function Ys(r,e){let t=Lr();Fe.info({provider:t.name,model:t.model},"Generating suite from story");let s=await t.generateTestSuite(r),n=e.suiteName??s.name,{suiteDir:i,suiteId:a}=await Gs(e.outputDir,{name:n,description:s.description,tags:s.tags,type:e.type??"ui"});Fe.info({suiteDir:i,suiteId:a,cases:s.cases.length},"Suite directory created");for(let l of s.cases)await ts(i,{name:l.name,description:l.description,tags:l.tags,priority:"medium",steps:l.steps.map((u,d)=>({id:`step-${d+1}`,order:d+1,instruction:u.instruction,generatedCode:u.generatedCode||"",strategy:u.strategy??"primary",stepType:tt(u.instruction),lastHealed:null}))});Fe.info({suiteId:a,cases:s.cases.length},"Auto-generating code for all steps");let o;try{let l=await G(e.rootDir),u=await rt(e.rootDir).catch(()=>({}));l.mcp?.enabled&&(o=new ft({headless:l.mcp.headless,actionTimeout:l.mcp.actionTimeout,idleTimeout:l.mcp.idleTimeout}),Fe.info({headless:l.mcp.headless},"MCP session created for suite generation"));let d=st(e.rootDir,o,l.mcp?.actThenScript),p=await zt(i);for(let g of p){let f=await se(g),h=f.steps.filter(P=>!P.generatedCode.trim());if(h.length===0)continue;let S=h.map(P=>({instruction:P.instruction,context:{url:l.baseUrl,title:"",interactiveElements:"",htmlSnapshot:"",previousSteps:f.steps.filter(j=>j.order<P.order&&j.generatedCode).map(j=>({instruction:j.instruction,code:j.generatedCode})),variables:u}})),I=await d.batchGenerate(S),v=new Map(h.map((P,j)=>[P.id,I[j]])),k=0,T=f.steps.map(P=>{let j=v.get(P.id);return j&&j.code.trim()?(k++,{...P,generatedCode:j.code,strategy:j.strategy}):P});k>0&&(await Be(g,{steps:T}),Fe.info({caseName:f.name,generated:k,total:f.steps.length},"Code generated for case"))}await d.getCache().persist(),Fe.info({suiteId:a},"Auto code generation complete")}catch(l){Fe.warn({err:l,suiteId:a},"Auto code generation failed \u2014 steps saved without code")}finally{o&&(o.release(),Fe.debug("MCP session released after suite generation"))}let c=Mn.default.join(e.rootDir,"results",`generated-suite-${kt(n)}.json`);return await Ua.default.ensureDir(Mn.default.dirname(c)),await Ua.default.writeJson(c,{story:r,generated:s,suiteDir:i,suiteId:a},{spaces:2}),Fe.info({reportPath:c,suiteId:a},"Generation complete"),{suiteId:a,suiteName:n}}async function Ha(r,e,t,s=3){let{randomUUID:n}=await import("crypto"),i=n(),a=r.length,o=0,c=0,l=[];t?.broadcast("story:bulk-start",{jobId:i,total:a}),Fe.info({jobId:i,total:a,concurrency:s},"Bulk story generation started");let u=0,d=[...r.entries()],p=[];async function g(){for(;d.length>0;){let h=d.shift();if(!h)break;let[S,I]=h;t?.broadcast("story:bulk-progress",{jobId:i,total:a,completed:o,failed:c,currentIndex:S,currentStory:I.story.slice(0,80)});try{await Ys(I.story,{rootDir:e.rootDir,outputDir:e.outputDir,suiteName:I.suiteName}),o++,Fe.info({jobId:i,index:S,completed:o,total:a},"Story processed")}catch(v){c++;let k=v instanceof Error?v.message:String(v);l.push({index:S,story:I.story.slice(0,120),error:k}),Fe.warn({jobId:i,index:S,error:k},"Story generation failed \u2014 continuing batch")}t?.broadcast("story:bulk-progress",{jobId:i,total:a,completed:o,failed:c,currentIndex:S,currentStory:I.story.slice(0,80)}),d.length>0&&await new Promise(v=>setTimeout(v,350))}}for(let h=0;h<Math.min(s,a);h++)p.push(g());await Promise.all(p);let f={jobId:i,total:a,completed:o,failed:c,failedItems:l};return t?.broadcast("story:bulk-done",f),Fe.info({jobId:i,completed:o,failed:c,total:a},"Bulk story generation finished"),f}var Mn,Ua,Fe,gr=b(()=>{"use strict";m();Mn=x(require("path")),Ua=x(require("fs-extra"));lr();te();N();Rl();Ea();Ws();gt();Xe();Te();pr();At();Ar();Fe=E("router")});async function Ru(r){let e=r.rootDir,t=Iu.default.join(e,"tests");async function s(n,i){let a=await de(t,n);return a?mt(a,i):null}r.post("/suites/:suiteId/cases/:caseId/steps",async(n,i)=>{let a=Xh.safeParse(n.body);if(!a.success)return i.status(400).send({error:"Invalid step data",details:a.error.issues});try{let o=await s(n.params.suiteId,n.params.caseId);if(!o)return i.status(404).send({error:`Case "${n.params.caseId}" not found`});let c=await se(o),l=a.data.order??c.steps.length+1,u={id:`step-${(0,Pu.randomUUID)().slice(0,8)}`,order:l,instruction:a.data.instruction,generatedCode:a.data.generatedCode??"",strategy:a.data.generatedCode?a.data.strategy??"recorder":"primary",lastHealed:null,...a.data.soft?{soft:!0}:{}},d=[...c.steps.map(g=>g.order>=l?{...g,order:g.order+1}:g),u].sort((g,f)=>g.order-f.order),p=await Be(o,{steps:d});return i.status(201).send(p)}catch(o){return w(i,500,"Failed to add step",o)}}),r.delete("/suites/:suiteId/cases/:caseId/steps/:stepId",async(n,i)=>{try{let a=await s(n.params.suiteId,n.params.caseId);if(!a)return i.status(404).send({error:`Case "${n.params.caseId}" not found`});let c=(await se(a)).steps.filter(u=>u.id!==n.params.stepId).map((u,d)=>({...u,order:d+1})),l=await Be(a,{steps:c});return i.send(l)}catch(a){return w(i,500,"Failed to delete step",a)}}),r.post("/suites/:suiteId/cases/:caseId/steps/:stepId/generate",async(n,i)=>{let a;try{let o=await s(n.params.suiteId,n.params.caseId);if(!o)return i.status(404).send({error:`Case "${n.params.caseId}" not found`});let c=await se(o),l=c.steps.find(v=>v.id===n.params.stepId);if(!l)return i.status(404).send({error:`Step "${n.params.stepId}" not found`});let u=await rt(e).catch(()=>({})),d=await G(e),p=n.body?.useMcp??d.mcp?.enabled;p&&(a=new ft({headless:d.mcp?.headless??!0,actionTimeout:d.mcp?.actionTimeout??15e3,idleTimeout:d.mcp?.idleTimeout??3e4}));let g=st(e,a,p?d.mcp?.actThenScript:!1),f=await g.generate(l.instruction,{url:d.baseUrl,title:"",interactiveElements:"",htmlSnapshot:"",previousSteps:c.steps.filter(v=>v.order<l.order&&v.generatedCode).map(v=>({instruction:v.instruction,code:v.generatedCode})),variables:u}),h=f.code;l.soft&&h&&(h=h.replace(/\bexpect\(/g,"expect.soft("));let S=c.steps.map(v=>v.id===l.id?{...v,generatedCode:h,strategy:f.strategy}:v);await g.getCache().persist();let I=await Be(o,{steps:S});return i.send({step:I.steps.find(v=>v.id===l.id),strategy:f.strategy,cost:f.cost,mcpUsed:!!a})}catch(o){return w(i,500,"Failed to generate code for step",o)}finally{a?.release()}}),r.post("/suites/:suiteId/cases/:caseId/steps/generate-all",async(n,i)=>{let a;try{let o=await s(n.params.suiteId,n.params.caseId);if(!o)return i.status(404).send({error:`Case "${n.params.caseId}" not found`});let c=await se(o),l=c.steps.filter(T=>!T.generatedCode.trim());if(l.length===0)return i.send({message:"All steps already have code",generated:0});let u=await rt(e).catch(()=>({})),d=await G(e),p=n.body?.useMcp??d.mcp?.enabled;p&&(a=new ft({headless:d.mcp?.headless??!0,actionTimeout:d.mcp?.actionTimeout??15e3,idleTimeout:d.mcp?.idleTimeout??3e4}));let g=st(e,a,p?d.mcp?.actThenScript:!1),f=l.map(T=>({instruction:T.instruction,context:{url:d.baseUrl,title:"",interactiveElements:"",htmlSnapshot:"",previousSteps:c.steps.filter(P=>P.order<T.order&&P.generatedCode).map(P=>({instruction:P.instruction,code:P.generatedCode})),variables:u}})),h=await g.batchGenerate(f);await g.getCache().persist();let S=new Map(l.map((T,P)=>[T.id,h[P]])),I=0,v=c.steps.map(T=>{let P=S.get(T.id);if(P&&P.code.trim()){I++;let j=T.soft?P.code.replace(/\bexpect\(/g,"expect.soft("):P.code;return{...T,generatedCode:j,strategy:P.strategy}}return T});if(I===0)return i.status(500).send({error:"AI code generation produced no results",detail:"The AI provider responded but returned empty code for all steps. Check your API key, model name, and server terminal logs for details.",code:"GENERATION_EMPTY"});let k=await Be(o,{steps:v});return i.send({generated:I,case:k,mcpUsed:!!a})}catch(o){return w(i,500,"Failed to generate code for steps",o)}finally{a?.release()}}),r.patch("/suites/:suiteId/cases/:caseId/steps/reorder",async(n,i)=>{let a=Kh.safeParse(n.body);if(!a.success)return i.status(400).send({error:"Invalid reorder data",details:a.error.issues});try{let o=await s(n.params.suiteId,n.params.caseId);if(!o)return i.status(404).send({error:`Case "${n.params.caseId}" not found`});let c=await se(o),l=new Map(c.steps.map(p=>[p.id,p])),u=a.data.stepIds.map((p,g)=>{let f=l.get(p);return f?{...f,order:g+1}:null}).filter(p=>p!==null),d=await Be(o,{steps:u});return i.send(d)}catch(o){return w(i,500,"Failed to reorder steps",o)}}),r.patch("/suites/:suiteId/cases/:caseId/steps/:stepId",async(n,i)=>{let a=Wh.safeParse(n.body);if(!a.success)return i.status(400).send({error:"Invalid step data",details:a.error.issues});try{let o=await s(n.params.suiteId,n.params.caseId);if(!o)return i.status(404).send({error:`Case "${n.params.caseId}" not found`});let c=await se(o);if(!c.steps.find(p=>p.id===n.params.stepId))return i.status(404).send({error:`Step "${n.params.stepId}" not found`});let u=c.steps.map(p=>{if(p.id!==n.params.stepId)return p;let g={};return a.data.instruction!==void 0&&(g.instruction=a.data.instruction),a.data.timeout!==void 0&&(g.timeout=a.data.timeout??void 0),a.data.stepType!==void 0&&(g.stepType=a.data.stepType),a.data.retries!==void 0&&(g.retries=a.data.retries),a.data.mockUrl!==void 0&&(g.mockUrl=a.data.mockUrl),a.data.mockResponse!==void 0&&(g.mockResponse=a.data.mockResponse),a.data.mockStatus!==void 0&&(g.mockStatus=a.data.mockStatus),a.data.auditUrl!==void 0&&(g.auditUrl=a.data.auditUrl),a.data.lighthouseCategories!==void 0&&(g.lighthouseCategories=a.data.lighthouseCategories),a.data.runAudit!==void 0&&(g.runAudit=a.data.runAudit),a.data.soft!==void 0&&(g.soft=a.data.soft,p.generatedCode&&(a.data.soft?g.generatedCode=p.generatedCode.replace(/\bexpect\(/g,"expect.soft("):g.generatedCode=p.generatedCode.replace(/\bexpect\.soft\(/g,"expect("))),a.data.visualCheck!==void 0&&(g.visualCheck=a.data.visualCheck),{...p,...g}}),d=await Be(o,{steps:u});return i.send(d)}catch(o){return w(i,500,"Failed to update step",o)}})}var Iu,Pu,ne,Xh,Kh,Wh,Tu=b(()=>{"use strict";m();Iu=x(require("path")),Pu=require("crypto"),ne=require("zod");gt();Xe();pr();Te();gr();Ws();re();Xh=ne.z.object({instruction:ne.z.string().min(1),order:ne.z.number().int().positive().optional(),generatedCode:ne.z.string().optional(),strategy:ne.z.enum(["template","cache","rag","batch","fast","primary","recorder"]).optional(),soft:ne.z.boolean().optional()}),Kh=ne.z.object({stepIds:ne.z.array(ne.z.string().min(1))}),Wh=ne.z.object({instruction:ne.z.string().min(1).optional(),timeout:ne.z.number().int().positive().optional().nullable(),stepType:ne.z.enum(["ui","api","mock"]).optional(),retries:ne.z.number().int().min(0).optional(),mockUrl:ne.z.string().optional(),mockResponse:ne.z.string().optional(),mockStatus:ne.z.number().int().optional(),auditUrl:ne.z.string().optional(),lighthouseCategories:ne.z.array(ne.z.enum(["performance","accessibility","seo"])).optional(),runAudit:ne.z.boolean().optional(),soft:ne.z.boolean().optional(),visualCheck:ne.z.boolean().optional()})});async function fr(r){let e=Va.default.join(r,_u);if(!await Ga.default.pathExists(e))return{...ku};let t=await ue(e),s=ua.safeParse(t);return s.success?s.data:($u.warn({path:e,errors:s.error.issues},"Invalid hooks.json \u2014 returning defaults"),{...ku})}async function Or(r,e){await Ga.default.ensureDir(r);let t=Va.default.join(r,_u),s=ua.safeParse(e);if(!s.success){let n=s.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
647
683
  `);throw new X(`Cannot write invalid hooks to "${t}":
648
- ${n}`,"hooks","INVALID_HOOKS")}await K(t,s.data),mu.debug({path:t},"Hooks written")}async function fu(r,e,t,s){let n=await pr(r),i=n[e],a=s??i.length+1,o={id:`step-${(0,pu.randomUUID)().slice(0,8)}`,order:a,instruction:t,generatedCode:"",strategy:"primary",lastHealed:null},c=[...i.map(l=>l.order>=a?{...l,order:l.order+1}:l),o].sort((l,u)=>l.order-u.order);return n[e]=c,await kr(r,n),n}async function hu(r,e,t){let s=await pr(r);return s[e]=s[e].filter(n=>n.id!==t).map((n,i)=>({...n,order:i+1})),await kr(r,s),s}async function yu(r,e,t){let s=await pr(r),n=new Map(s[e].map(i=>[i.id,i]));return s[e]=t.map((i,a)=>{let o=n.get(i);return o?{...o,order:a+1}:null}).filter(i=>i!==null),await kr(r,s),s}async function wu(r,e,t,s){let n=await pr(r);return n[e]=n[e].map(i=>{if(i.id!==t)return i;let a={};return s.instruction!==void 0&&(a.instruction=s.instruction),s.timeout!==void 0&&(a.timeout=s.timeout??void 0),{...i,...a}}),await kr(r,n),n}var La,Da,pu,mu,gu,du,bu=w(()=>{"use strict";p();La=x(require("path")),Da=x(require("fs-extra")),pu=require("crypto");Ns();re();F();Ve();mu=E("hooks-store"),gu="hooks.json",du={before_all:[],before_each:[],after_each:[],after_all:[]}});function es(r){let e=$c.safeParse(r);return e.success?e.data:null}async function xu(r){let e=r.rootDir,t=vu.default.join(e,"tests");async function s(n){return pe(t,n)}r.get("/suites/:suiteId/hooks",async(n,i)=>{try{let a=await s(n.params.suiteId);if(!a)return i.status(404).send({error:"Suite not found"});let o=await pr(a);return i.send(o)}catch(a){return b(i,500,"Failed to read hooks",a)}}),r.post("/suites/:suiteId/hooks/:hookType/steps",async(n,i)=>{let a=es(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});let o=Sh.safeParse(n.body);if(!o.success)return i.status(400).send({error:"Invalid step data",details:o.error.issues});try{let c=await s(n.params.suiteId);if(!c)return i.status(404).send({error:"Suite not found"});let l=await fu(c,a,o.data.instruction,o.data.order);return i.status(201).send(l)}catch(c){return b(i,500,"Failed to add hook step",c)}}),r.post("/suites/:suiteId/hooks/:hookType/steps/generate-all",async(n,i)=>{let a=es(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});try{let o=await s(n.params.suiteId);if(!o)return i.status(404).send({error:"Suite not found"});let c=await pr(o),l=c[a],u=l.filter(v=>!v.generatedCode.trim());if(u.length===0)return i.send({message:"All steps already have code",generated:0,hooks:c});let d=await et(e).catch(()=>({})),g=await Promise.resolve().then(()=>(_e(),Qi)).then(v=>v.readConfig(e)),m=tt(e),f=u.map(v=>({instruction:v.instruction,context:{url:g.baseUrl,title:"",interactiveElements:"",htmlSnapshot:"",previousSteps:l.filter(k=>k.order<v.order&&k.generatedCode).map(k=>({instruction:k.instruction,code:k.generatedCode})),variables:d}})),h=await m.batchGenerate(f);await m.getCache().persist();let C=new Map(u.map((v,k)=>[v.id,h[k]])),P=0;return c[a]=l.map(v=>{let k=C.get(v.id);return k&&k.code.trim()?(P++,{...v,generatedCode:k.code,strategy:k.strategy}):v}),P===0?i.status(500).send({error:"AI code generation produced no results",code:"GENERATION_EMPTY"}):(await kr(o,c),i.send({generated:P,hooks:c}))}catch(o){return b(i,500,"Failed to generate code for hook steps",o)}}),r.patch("/suites/:suiteId/hooks/:hookType/steps/reorder",async(n,i)=>{let a=es(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});let o=Ch.safeParse(n.body);if(!o.success)return i.status(400).send({error:"Invalid reorder data",details:o.error.issues});try{let c=await s(n.params.suiteId);if(!c)return i.status(404).send({error:"Suite not found"});let l=await yu(c,a,o.data.stepIds);return i.send(l)}catch(c){return b(i,500,"Failed to reorder hook steps",c)}}),r.delete("/suites/:suiteId/hooks/:hookType/steps/:stepId",async(n,i)=>{let a=es(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});try{let o=await s(n.params.suiteId);if(!o)return i.status(404).send({error:"Suite not found"});let c=await hu(o,a,n.params.stepId);return i.send(c)}catch(o){return b(i,500,"Failed to delete hook step",o)}}),r.patch("/suites/:suiteId/hooks/:hookType/steps/:stepId",async(n,i)=>{let a=es(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});let o=Eh.safeParse(n.body);if(!o.success)return i.status(400).send({error:"Invalid step data",details:o.error.issues});try{let c=await s(n.params.suiteId);if(!c)return i.status(404).send({error:"Suite not found"});let l=await wu(c,a,n.params.stepId,o.data);return i.send(l)}catch(c){return b(i,500,"Failed to update hook step",c)}}),r.post("/suites/:suiteId/hooks/:hookType/steps/:stepId/generate",async(n,i)=>{let a=es(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});try{let o=await s(n.params.suiteId);if(!o)return i.status(404).send({error:"Suite not found"});let c=await pr(o),l=c[a],u=l.find(h=>h.id===n.params.stepId);if(!u)return i.status(404).send({error:`Step "${n.params.stepId}" not found`});let d=await et(e).catch(()=>({})),g=tt(e),m=await Promise.resolve().then(()=>(_e(),Qi)).then(h=>h.readConfig(e)),f=await g.generate(u.instruction,{url:m.baseUrl,title:"",interactiveElements:"",htmlSnapshot:"",previousSteps:l.filter(h=>h.order<u.order&&h.generatedCode).map(h=>({instruction:h.instruction,code:h.generatedCode})),variables:d});return c[a]=l.map(h=>h.id===u.id?{...h,generatedCode:f.code,strategy:f.strategy}:h),await g.getCache().persist(),await kr(o,c),i.send({step:c[a].find(h=>h.id===u.id),strategy:f.strategy,cost:f.cost})}catch(o){return b(i,500,"Failed to generate code for hook step",o)}})}var vu,kt,Sh,Ch,Eh,Su=w(()=>{"use strict";p();vu=x(require("path")),kt=require("zod");ze();bu();lr();dr();ae();Ns();Sh=kt.z.object({instruction:kt.z.string().min(1),order:kt.z.number().int().positive().optional()}),Ch=kt.z.object({stepIds:kt.z.array(kt.z.string().min(1))}),Eh=kt.z.object({instruction:kt.z.string().min(1).optional(),timeout:kt.z.number().int().positive().optional().nullable()})});async function Cu(r){let e=r.rootDir;r.get("/variables",async(t,s)=>{try{let n=await da(e);try{let i=await J(e),a=i.environment??"stage",c=i.environmentUrls?.[a]||i.baseUrl;return delete n.BASE_URL,s.send({BASE_URL:c,...n,_system:{BASE_URL:{source:"settings",environment:a,readOnly:!0}}})}catch{return s.send(n)}}catch(n){return b(s,500,"Failed to read variables",n)}}),r.get("/variables/env/:env",async(t,s)=>{try{let n=await pa(e,t.params.env);return s.send(n)}catch(n){return b(s,500,`Failed to read variables for env "${t.params.env}"`,n)}}),r.put("/variables/:key",async(t,s)=>{if(t.params.key==="BASE_URL")return s.status(400).send({error:"BASE_URL is managed in Settings \u2192 Environment. Update it there."});let n=Ph.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid variable value",details:n.error.issues});try{return await zc(e,t.params.key,n.data.value),s.send({key:t.params.key,value:n.data.value})}catch(i){return b(s,500,"Failed to set variable",i)}}),r.delete("/variables/:key",async(t,s)=>{if(t.params.key==="BASE_URL")return s.status(400).send({error:"BASE_URL is managed in Settings \u2192 Environment. It cannot be deleted."});try{return await qc(e,t.params.key),s.status(204).send()}catch(n){return b(s,500,"Failed to delete variable",n)}})}var Ar,Ph,Eu=w(()=>{"use strict";p();Ar=require("zod");lr();_e();ae();Ph=Ar.z.object({value:Ar.z.union([Ar.z.string(),Ar.z.object({value:Ar.z.string(),secret:Ar.z.literal(!0)})])})});var ee,Ih,Rh,On,Na,Pu=w(()=>{"use strict";p();ee=require("zod"),Ih=ee.z.enum(["pending","accepted","rejected"]),Rh=ee.z.enum(["retry","regenerate","multi-selector","visual","decompose","manual"]),On=ee.z.object({id:ee.z.string(),runId:ee.z.string(),suiteId:ee.z.string(),caseId:ee.z.string(),stepId:ee.z.string(),stepInstruction:ee.z.string(),failedCode:ee.z.string(),healedCode:ee.z.string(),error:ee.z.string(),strategy:Rh,level:ee.z.number().int().min(1).max(6),status:Ih,pageUrl:ee.z.string(),timestamp:ee.z.string().datetime(),acceptedAt:ee.z.string().datetime().optional(),rejectedAt:ee.z.string().datetime().optional()}),Na=ee.z.object({runId:ee.z.string(),generatedAt:ee.z.string().datetime(),totalHeals:ee.z.number().int(),accepted:ee.z.number().int(),rejected:ee.z.number().int(),pending:ee.z.number().int(),events:ee.z.array(On)})});function Tu(r,e){return De.default.join(r,`${Ln}${e}.json`)}function _r(r){return De.default.join(r,Th)}async function ku(r,e){let t=Na.safeParse(e);if(!t.success){let i=t.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
684
+ ${n}`,"hooks","INVALID_HOOKS")}await K(t,s.data),$u.debug({path:t},"Hooks written")}async function Lu(r,e,t,s){let n=await fr(r),i=n[e],a=s??i.length+1,o={id:`step-${(0,Au.randomUUID)().slice(0,8)}`,order:a,instruction:t,generatedCode:"",strategy:"primary",lastHealed:null},c=[...i.map(l=>l.order>=a?{...l,order:l.order+1}:l),o].sort((l,u)=>l.order-u.order);return n[e]=c,await Or(r,n),n}async function Ou(r,e,t){let s=await fr(r);return s[e]=s[e].filter(n=>n.id!==t).map((n,i)=>({...n,order:i+1})),await Or(r,s),s}async function Du(r,e,t){let s=await fr(r),n=new Map(s[e].map(i=>[i.id,i]));return s[e]=t.map((i,a)=>{let o=n.get(i);return o?{...o,order:a+1}:null}).filter(i=>i!==null),await Or(r,s),s}async function Fu(r,e,t,s){let n=await fr(r);return n[e]=n[e].map(i=>{if(i.id!==t)return i;let a={};return s.instruction!==void 0&&(a.instruction=s.instruction),s.timeout!==void 0&&(a.timeout=s.timeout??void 0),{...i,...a}}),await Or(r,n),n}var Va,Ga,Au,$u,_u,ku,Nu=b(()=>{"use strict";m();Va=x(require("path")),Ga=x(require("fs-extra")),Au=require("crypto");Vs();te();N();ze();$u=E("hooks-store"),_u="hooks.json",ku={before_all:[],before_each:[],after_each:[],after_all:[]}});function is(r){let e=Gc.safeParse(r);return e.success?e.data:null}async function ju(r){let e=r.rootDir,t=Mu.default.join(e,"tests");async function s(n){return de(t,n)}r.get("/suites/:suiteId/hooks",async(n,i)=>{try{let a=await s(n.params.suiteId);if(!a)return i.status(404).send({error:"Suite not found"});let o=await fr(a);return i.send(o)}catch(a){return w(i,500,"Failed to read hooks",a)}}),r.post("/suites/:suiteId/hooks/:hookType/steps",async(n,i)=>{let a=is(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});let o=Jh.safeParse(n.body);if(!o.success)return i.status(400).send({error:"Invalid step data",details:o.error.issues});try{let c=await s(n.params.suiteId);if(!c)return i.status(404).send({error:"Suite not found"});let l=await Lu(c,a,o.data.instruction,o.data.order);return i.status(201).send(l)}catch(c){return w(i,500,"Failed to add hook step",c)}}),r.post("/suites/:suiteId/hooks/:hookType/steps/generate-all",async(n,i)=>{let a=is(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});try{let o=await s(n.params.suiteId);if(!o)return i.status(404).send({error:"Suite not found"});let c=await fr(o),l=c[a],u=l.filter(v=>!v.generatedCode.trim());if(u.length===0)return i.send({message:"All steps already have code",generated:0,hooks:c});let d=await rt(e).catch(()=>({})),p=await Promise.resolve().then(()=>(Te(),aa)).then(v=>v.readConfig(e)),g=st(e),f=u.map(v=>({instruction:v.instruction,context:{url:p.baseUrl,title:"",interactiveElements:"",htmlSnapshot:"",previousSteps:l.filter(k=>k.order<v.order&&k.generatedCode).map(k=>({instruction:k.instruction,code:k.generatedCode})),variables:d}})),h=await g.batchGenerate(f);await g.getCache().persist();let S=new Map(u.map((v,k)=>[v.id,h[k]])),I=0;return c[a]=l.map(v=>{let k=S.get(v.id);return k&&k.code.trim()?(I++,{...v,generatedCode:k.code,strategy:k.strategy}):v}),I===0?i.status(500).send({error:"AI code generation produced no results",code:"GENERATION_EMPTY"}):(await Or(o,c),i.send({generated:I,hooks:c}))}catch(o){return w(i,500,"Failed to generate code for hook steps",o)}}),r.patch("/suites/:suiteId/hooks/:hookType/steps/reorder",async(n,i)=>{let a=is(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});let o=Yh.safeParse(n.body);if(!o.success)return i.status(400).send({error:"Invalid reorder data",details:o.error.issues});try{let c=await s(n.params.suiteId);if(!c)return i.status(404).send({error:"Suite not found"});let l=await Du(c,a,o.data.stepIds);return i.send(l)}catch(c){return w(i,500,"Failed to reorder hook steps",c)}}),r.delete("/suites/:suiteId/hooks/:hookType/steps/:stepId",async(n,i)=>{let a=is(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});try{let o=await s(n.params.suiteId);if(!o)return i.status(404).send({error:"Suite not found"});let c=await Ou(o,a,n.params.stepId);return i.send(c)}catch(o){return w(i,500,"Failed to delete hook step",o)}}),r.patch("/suites/:suiteId/hooks/:hookType/steps/:stepId",async(n,i)=>{let a=is(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});let o=Qh.safeParse(n.body);if(!o.success)return i.status(400).send({error:"Invalid step data",details:o.error.issues});try{let c=await s(n.params.suiteId);if(!c)return i.status(404).send({error:"Suite not found"});let l=await Fu(c,a,n.params.stepId,o.data);return i.send(l)}catch(c){return w(i,500,"Failed to update hook step",c)}}),r.post("/suites/:suiteId/hooks/:hookType/steps/:stepId/generate",async(n,i)=>{let a=is(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});try{let o=await s(n.params.suiteId);if(!o)return i.status(404).send({error:"Suite not found"});let c=await fr(o),l=c[a],u=l.find(h=>h.id===n.params.stepId);if(!u)return i.status(404).send({error:`Step "${n.params.stepId}" not found`});let d=await rt(e).catch(()=>({})),p=st(e),g=await Promise.resolve().then(()=>(Te(),aa)).then(h=>h.readConfig(e)),f=await p.generate(u.instruction,{url:g.baseUrl,title:"",interactiveElements:"",htmlSnapshot:"",previousSteps:l.filter(h=>h.order<u.order&&h.generatedCode).map(h=>({instruction:h.instruction,code:h.generatedCode})),variables:d});return c[a]=l.map(h=>h.id===u.id?{...h,generatedCode:f.code,strategy:f.strategy}:h),await p.getCache().persist(),await Or(o,c),i.send({step:c[a].find(h=>h.id===u.id),strategy:f.strategy,cost:f.cost})}catch(o){return w(i,500,"Failed to generate code for hook step",o)}})}var Mu,_t,Jh,Yh,Qh,Bu=b(()=>{"use strict";m();Mu=x(require("path")),_t=require("zod");Xe();Nu();pr();gr();re();Vs();Jh=_t.z.object({instruction:_t.z.string().min(1),order:_t.z.number().int().positive().optional()}),Yh=_t.z.object({stepIds:_t.z.array(_t.z.string().min(1))}),Qh=_t.z.object({instruction:_t.z.string().min(1).optional(),timeout:_t.z.number().int().positive().optional().nullable()})});async function Uu(r){let e=r.rootDir;r.get("/variables",async(t,s)=>{try{let n=await ba(e);try{let i=await G(e),a=i.environment??"stage",c=i.environmentUrls?.[a]||i.baseUrl;return delete n.BASE_URL,s.send({BASE_URL:c,...n,_system:{BASE_URL:{source:"settings",environment:a,readOnly:!0}}})}catch{return s.send(n)}}catch(n){return w(s,500,"Failed to read variables",n)}}),r.get("/variables/env/:env",async(t,s)=>{try{let n=await va(e,t.params.env);return s.send(n)}catch(n){return w(s,500,`Failed to read variables for env "${t.params.env}"`,n)}}),r.put("/variables/:key",async(t,s)=>{if(t.params.key==="BASE_URL")return s.status(400).send({error:"BASE_URL is managed in Settings \u2192 Environment. Update it there."});let n=Zh.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid variable value",details:n.error.issues});try{return await nl(e,t.params.key,n.data.value),s.send({key:t.params.key,value:n.data.value})}catch(i){return w(s,500,"Failed to set variable",i)}}),r.delete("/variables/:key",async(t,s)=>{if(t.params.key==="BASE_URL")return s.status(400).send({error:"BASE_URL is managed in Settings \u2192 Environment. It cannot be deleted."});try{return await il(e,t.params.key),s.status(204).send()}catch(n){return w(s,500,"Failed to delete variable",n)}})}var Dr,Zh,Hu=b(()=>{"use strict";m();Dr=require("zod");pr();Te();re();Zh=Dr.z.object({value:Dr.z.union([Dr.z.string(),Dr.z.object({value:Dr.z.string(),secret:Dr.z.literal(!0)})])})});var ee,ey,ty,jn,za,Vu=b(()=>{"use strict";m();ee=require("zod"),ey=ee.z.enum(["pending","accepted","rejected"]),ty=ee.z.enum(["retry","regenerate","multi-selector","visual","decompose","manual"]),jn=ee.z.object({id:ee.z.string(),runId:ee.z.string(),suiteId:ee.z.string(),caseId:ee.z.string(),stepId:ee.z.string(),stepInstruction:ee.z.string(),failedCode:ee.z.string(),healedCode:ee.z.string(),error:ee.z.string(),strategy:ty,level:ee.z.number().int().min(1).max(6),status:ey,pageUrl:ee.z.string(),timestamp:ee.z.string().datetime(),acceptedAt:ee.z.string().datetime().optional(),rejectedAt:ee.z.string().datetime().optional()}),za=ee.z.object({runId:ee.z.string(),generatedAt:ee.z.string().datetime(),totalHeals:ee.z.number().int(),accepted:ee.z.number().int(),rejected:ee.z.number().int(),pending:ee.z.number().int(),events:ee.z.array(jn)})});function qu(r,e){return Ne.default.join(r,`${Bn}${e}.json`)}function Nr(r){return Ne.default.join(r,ry)}async function Xu(r,e){let t=za.safeParse(e);if(!t.success){let i=t.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
649
685
  `);throw new X(`Cannot write invalid healing report:
650
- ${i}`,"healingReport","INVALID_HEALING_REPORT")}let s=De.default.join(r,At),n=Tu(s,e.runId);await K(n,t.data),mr.info({runId:e.runId,totalHeals:e.totalHeals},"Healing report saved")}async function Dn(r,e){let t=De.default.join(r,At),s=Tu(t,e);if(!await $r.default.pathExists(s))throw new ie(`Healing report not found for runId "${e}".`,s,"HEALING_REPORT_NOT_FOUND");let n=await de(s),i=Na.safeParse(n);if(!i.success){let a=i.error.issues.map(o=>` \u2022 ${o.path.join(".")}: ${o.message}`).join(`
686
+ ${i}`,"healingReport","INVALID_HEALING_REPORT")}let s=Ne.default.join(r,Lt),n=qu(s,e.runId);await K(n,t.data),hr.info({runId:e.runId,totalHeals:e.totalHeals},"Healing report saved")}async function Un(r,e){let t=Ne.default.join(r,Lt),s=qu(t,e);if(!await Fr.default.pathExists(s))throw new oe(`Healing report not found for runId "${e}".`,s,"HEALING_REPORT_NOT_FOUND");let n=await ue(s),i=za.safeParse(n);if(!i.success){let a=i.error.issues.map(o=>` \u2022 ${o.path.join(".")}: ${o.message}`).join(`
651
687
  `);throw new X(`Invalid healing report at "${s}":
652
- ${a}`,"healingReport","INVALID_HEALING_REPORT")}return i.data}async function rt(r){let e=De.default.join(r,At),t=_r(e);if(!await $r.default.pathExists(t))return[];let s=await de(t),n=On.array().safeParse(s);return n.success?n.data:(mr.warn({path:t},"Pending healing file is malformed \u2014 resetting"),[])}function kh(r){if(r.length<=Iu)return r;let e=[...r].sort((n,i)=>{let a=Ru.indexOf(n.status),o=Ru.indexOf(i.status);return a!==o?a-o:n.timestamp<i.timestamp?-1:1}),t=r.length-Iu,s=new Set(e.slice(0,t).map(n=>n.id));return mr.info({excess:t,deleted:s.size},"Auto-pruning healing events to enforce cap"),r.filter(n=>!s.has(n.id))}async function Au(r,e){let t=On.safeParse(e);if(!t.success)throw new X(`Invalid healing event: ${t.error.message}`,"healingEvent","INVALID_HEALING_EVENT");let s=De.default.join(r,At);await $r.default.ensureDir(s);let n=await rt(r);n.push(t.data),await K(_r(s),kh(n))}async function qs(r,e){let t=await rt(r),s=t.findIndex(i=>i.id===e);if(s===-1)throw new ie(`Healing event "${e}" not found in pending list.`,e,"HEALING_EVENT_NOT_FOUND");t[s]={...t[s],status:"accepted",acceptedAt:new Date().toISOString()};let n=De.default.join(r,At);return await K(_r(n),t),mr.info({eventId:e},"Healing event accepted"),t[s]}async function Nn(r,e){let t=await rt(r),s=t.findIndex(i=>i.id===e);if(s===-1)throw new ie(`Healing event "${e}" not found in pending list.`,e,"HEALING_EVENT_NOT_FOUND");t[s]={...t[s],status:"rejected",rejectedAt:new Date().toISOString()};let n=De.default.join(r,At);return await K(_r(n),t),mr.info({eventId:e},"Healing event rejected"),t[s]}async function $u(r,e){let s=(await rt(r)).filter(i=>i.id!==e),n=De.default.join(r,At);await K(_r(n),s),mr.info({eventId:e},"Healing event deleted")}async function _u(r,e){let t=await rt(r),s=new Set(e),n=t.filter(o=>!s.has(o.id)),i=t.length-n.length,a=De.default.join(r,At);return await K(_r(a),n),mr.info({count:i},"Healing events bulk-deleted"),i}async function Ou(r){let t=(await rt(r)).length,s=De.default.join(r,At);return await K(_r(s),[]),mr.info({count:t},"All healing events cleared"),t}async function Lu(r){let e=await rt(r),t=e.filter(i=>i.status==="pending").length,s=e.filter(i=>i.status==="accepted").length,n=e.filter(i=>i.status==="rejected").length;return{pending:t,accepted:s,rejected:n,total:e.length}}async function Du(r){let e=De.default.join(r,At);if(!await $r.default.pathExists(e))return[];let s=(await $r.default.readdir(e,{withFileTypes:!0})).filter(i=>i.isFile()&&i.name.startsWith(Ln)&&i.name.endsWith(".json")).map(i=>i.name.slice(Ln.length,-5));return(await Promise.all(s.map(async i=>{let a=await $r.default.stat(De.default.join(e,`${Ln}${i}.json`));return{id:i,mtime:a.mtimeMs}}))).sort((i,a)=>a.mtime-i.mtime).map(i=>i.id)}var De,$r,mr,At,Th,Ln,Iu,Ru,Mn=w(()=>{"use strict";p();De=x(require("path")),$r=x(require("fs-extra"));Pu();re();F();Ve();mr=E("healing-store"),At=De.default.join("results","healing"),Th="pending.json",Ln="healing-report-";Iu=50,Ru=["pending","rejected","accepted"]});async function Fu(r){let e=r.rootDir,t=Mu.default.join(e,"tests");r.get("/healing",async(s,n)=>{try{let i=await Du(e),a=[];for(let o of i){let c=await Dn(e,o);a.push(...c.events)}return n.send(a)}catch(i){return b(n,500,"Failed to list healing events",i)}}),r.get("/healing/pending",async(s,n)=>{try{let i=await rt(e);return n.send(i)}catch(i){return b(n,500,"Failed to read pending healing events",i)}}),r.get("/healing/stats",async(s,n)=>{try{let i=await Lu(e);return n.send(i)}catch(i){return b(n,500,"Failed to get healing stats",i)}}),r.patch("/healing/:id/accept",async(s,n)=>{try{let i=await qs(e,s.params.id);return await Ma(t,i.caseId,i.stepId,i.healedCode),Nu.info({id:s.params.id,caseId:i.caseId,stepId:i.stepId},"Healing accepted and applied"),n.send(i)}catch(i){return b(n,500,"Failed to accept healing event",i)}}),r.patch("/healing/:id/reject",async(s,n)=>{try{let i=await Nn(e,s.params.id);return n.send(i)}catch(i){return b(n,500,"Failed to reject healing event",i)}}),r.post("/healing/accept-all",async(s,n)=>{try{let i=await rt(e),a=[];for(let o of i)try{await qs(e,o.id),await Ma(t,o.caseId,o.stepId,o.healedCode),a.push({id:o.id,status:"accepted"}),Nu.info({id:o.id},"Bulk healing accepted")}catch(c){a.push({id:o.id,status:"failed",error:c instanceof Error?c.message:String(c)})}return n.send({accepted:a.filter(o=>o.status==="accepted").length,results:a})}catch(i){return b(n,500,"Failed to accept all healing events",i)}}),r.post("/healing/clear-all",async(s,n)=>{try{let i=await Ou(e);return n.send({deleted:i})}catch(i){return b(n,500,"Failed to clear healing events",i)}}),r.post("/healing/delete-bulk",async(s,n)=>{let i=$h.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid request",details:i.error.issues});try{let a=await _u(e,i.data.ids);return n.send({deleted:a})}catch(a){return b(n,500,"Failed to delete healing events",a)}}),r.delete("/healing/:id",async(s,n)=>{try{return await $u(e,s.params.id),n.status(204).send()}catch(i){return b(n,500,"Failed to delete healing event",i)}}),r.post("/healing/apply-from-report",async(s,n)=>{let i=Ah.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid request",details:i.error.issues});try{let{default:a}=await import("fs-extra"),o=await a.readJson(i.data.reportPath);if(!Array.isArray(o.events))return n.status(400).send({error:"Invalid healing report format"});let c=[];for(let l of o.events)try{await Ma(t,l.caseId,l.stepId,l.healedCode),c.push({id:l.id,status:"applied"})}catch(u){c.push({id:l.id,status:"failed",error:u instanceof Error?u.message:String(u)})}return n.send({applied:c.filter(l=>l.status==="applied").length,results:c})}catch(a){return b(n,500,"Failed to apply healing report",a)}})}async function Ma(r,e,t,s){let n=await _h(r,e);if(!n)throw new Error(`Case "${e}" not found in tests directory`);let i=await se(n);if(!i.steps.find(c=>c.id===t))throw new Error(`Step "${t}" not found in case "${e}"`);let o=i.steps.map(c=>c.id===t?{...c,generatedCode:s,lastHealed:new Date().toISOString()}:c);await Me(n,{steps:o})}async function _h(r,e){let{default:t}=await import("fs-extra"),{listSuiteDirs:s}=await Promise.resolve().then(()=>(ze(),oa)),n=await s(r);for(let i of n){let a=await ut(i,e);if(a)return a}return null}var Mu,ts,Nu,Ah,$h,ju=w(()=>{"use strict";p();Mu=x(require("path")),ts=require("zod");Mn();dt();ae();F();Nu=E("routes/healing"),Ah=ts.z.object({reportPath:ts.z.string().min(1)}),$h=ts.z.object({ids:ts.z.array(ts.z.string().min(1)).min(1)})});var T,Fn,Oh,Lh,mt,Bu,Dh,Nh,Mh,Fh,Fa,Uu=w(()=>{"use strict";p();T=require("zod"),Fn=T.z.enum(["pending","running","passed","failed","skipped"]),Oh=T.z.object({method:T.z.string(),url:T.z.string(),headers:T.z.record(T.z.string()).optional(),body:T.z.string().optional()}).optional(),Lh=T.z.object({status:T.z.number(),statusText:T.z.string(),headers:T.z.record(T.z.string()).optional(),body:T.z.string().optional(),duration:T.z.number()}).optional(),mt=T.z.number().nullish().transform(r=>r??void 0),Bu=T.z.object({id:T.z.string(),title:T.z.string(),passed:T.z.boolean(),partial:T.z.boolean().optional(),na:T.z.boolean().optional()}),Dh=T.z.object({url:T.z.string(),stepIndex:T.z.number().int(),stepInstruction:T.z.string(),score:mt,a11yScore:mt,seoScore:mt,fcp:mt,lcp:mt,cls:mt,ttfb:mt,tbt:mt,si:mt,tti:mt,inp:mt,a11yAudits:T.z.array(Bu).optional(),seoAudits:T.z.array(Bu).optional(),lighthouseError:T.z.string().optional()}),Nh=T.z.object({stepId:T.z.string(),instruction:T.z.string(),status:Fn,code:T.z.string(),error:T.z.string().optional(),duration:T.z.number(),screenshotPath:T.z.string().optional(),healed:T.z.boolean().optional(),healedCode:T.z.string().optional(),stepType:T.z.enum(["ui","api","mock"]).optional(),apiRequest:Oh,apiResponse:Lh,navigatedToUrl:T.z.string().optional(),auditUrl:T.z.string().optional()}),Mh=T.z.object({caseId:T.z.string(),caseName:T.z.string(),status:Fn,steps:T.z.array(Nh),duration:T.z.number(),browser:T.z.string(),device:T.z.string().optional(),startedAt:T.z.string().datetime(),finishedAt:T.z.string().datetime(),videoPath:T.z.string().optional(),tracePath:T.z.string().optional(),dataRowIndex:T.z.number().int().optional(),dataRow:T.z.record(T.z.string()).optional(),pageLoads:T.z.array(Dh).default([])}),Fh=T.z.object({suiteId:T.z.string(),suiteName:T.z.string(),suiteType:T.z.enum(["ui","api","audit","performance"]).optional(),status:Fn,cases:T.z.array(Mh),duration:T.z.number(),browser:T.z.string(),startedAt:T.z.string().datetime(),finishedAt:T.z.string().datetime()}),Fa=T.z.object({runId:T.z.string(),status:Fn,environment:T.z.string().optional(),suites:T.z.array(Fh),duration:T.z.number(),startedAt:T.z.string().datetime(),finishedAt:T.z.string().datetime(),totalTests:T.z.number().int(),passed:T.z.number().int(),failed:T.z.number().int(),skipped:T.z.number().int(),logFilePath:T.z.string().optional()})});function Ba(r,e){return Lr.default.join(r,Hu,`${e}.json`)}async function Vu(r,e){let t=Fa.safeParse(e);if(!t.success){let n=t.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
688
+ ${a}`,"healingReport","INVALID_HEALING_REPORT")}return i.data}async function nt(r){let e=Ne.default.join(r,Lt),t=Nr(e);if(!await Fr.default.pathExists(t))return[];let s=await ue(t),n=jn.array().safeParse(s);return n.success?n.data:(hr.warn({path:t},"Pending healing file is malformed \u2014 resetting"),[])}function sy(r){if(r.length<=Gu)return r;let e=[...r].sort((n,i)=>{let a=zu.indexOf(n.status),o=zu.indexOf(i.status);return a!==o?a-o:n.timestamp<i.timestamp?-1:1}),t=r.length-Gu,s=new Set(e.slice(0,t).map(n=>n.id));return hr.info({excess:t,deleted:s.size},"Auto-pruning healing events to enforce cap"),r.filter(n=>!s.has(n.id))}async function Ku(r,e){let t=jn.safeParse(e);if(!t.success)throw new X(`Invalid healing event: ${t.error.message}`,"healingEvent","INVALID_HEALING_EVENT");let s=Ne.default.join(r,Lt);await Fr.default.ensureDir(s);let n=await nt(r);n.push(t.data),await K(Nr(s),sy(n))}async function Qs(r,e){let t=await nt(r),s=t.findIndex(i=>i.id===e);if(s===-1)throw new oe(`Healing event "${e}" not found in pending list.`,e,"HEALING_EVENT_NOT_FOUND");t[s]={...t[s],status:"accepted",acceptedAt:new Date().toISOString()};let n=Ne.default.join(r,Lt);return await K(Nr(n),t),hr.info({eventId:e},"Healing event accepted"),t[s]}async function Hn(r,e){let t=await nt(r),s=t.findIndex(i=>i.id===e);if(s===-1)throw new oe(`Healing event "${e}" not found in pending list.`,e,"HEALING_EVENT_NOT_FOUND");t[s]={...t[s],status:"rejected",rejectedAt:new Date().toISOString()};let n=Ne.default.join(r,Lt);return await K(Nr(n),t),hr.info({eventId:e},"Healing event rejected"),t[s]}async function Wu(r,e){let s=(await nt(r)).filter(i=>i.id!==e),n=Ne.default.join(r,Lt);await K(Nr(n),s),hr.info({eventId:e},"Healing event deleted")}async function Ju(r,e){let t=await nt(r),s=new Set(e),n=t.filter(o=>!s.has(o.id)),i=t.length-n.length,a=Ne.default.join(r,Lt);return await K(Nr(a),n),hr.info({count:i},"Healing events bulk-deleted"),i}async function Yu(r){let t=(await nt(r)).length,s=Ne.default.join(r,Lt);return await K(Nr(s),[]),hr.info({count:t},"All healing events cleared"),t}async function Qu(r){let e=await nt(r),t=e.filter(i=>i.status==="pending").length,s=e.filter(i=>i.status==="accepted").length,n=e.filter(i=>i.status==="rejected").length;return{pending:t,accepted:s,rejected:n,total:e.length}}async function Zu(r){let e=Ne.default.join(r,Lt);if(!await Fr.default.pathExists(e))return[];let s=(await Fr.default.readdir(e,{withFileTypes:!0})).filter(i=>i.isFile()&&i.name.startsWith(Bn)&&i.name.endsWith(".json")).map(i=>i.name.slice(Bn.length,-5));return(await Promise.all(s.map(async i=>{let a=await Fr.default.stat(Ne.default.join(e,`${Bn}${i}.json`));return{id:i,mtime:a.mtimeMs}}))).sort((i,a)=>a.mtime-i.mtime).map(i=>i.id)}var Ne,Fr,hr,Lt,ry,Bn,Gu,zu,Vn=b(()=>{"use strict";m();Ne=x(require("path")),Fr=x(require("fs-extra"));Vu();te();N();ze();hr=E("healing-store"),Lt=Ne.default.join("results","healing"),ry="pending.json",Bn="healing-report-";Gu=50,zu=["pending","rejected","accepted"]});async function rd(r){let e=r.rootDir,t=td.default.join(e,"tests");r.get("/healing",async(s,n)=>{try{let i=await Zu(e),a=[];for(let o of i){let c=await Un(e,o);a.push(...c.events)}return n.send(a)}catch(i){return w(n,500,"Failed to list healing events",i)}}),r.get("/healing/pending",async(s,n)=>{try{let i=await nt(e);return n.send(i)}catch(i){return w(n,500,"Failed to read pending healing events",i)}}),r.get("/healing/stats",async(s,n)=>{try{let i=await Qu(e);return n.send(i)}catch(i){return w(n,500,"Failed to get healing stats",i)}}),r.patch("/healing/:id/accept",async(s,n)=>{try{let i=await Qs(e,s.params.id);return await qa(t,i.caseId,i.stepId,i.healedCode),ed.info({id:s.params.id,caseId:i.caseId,stepId:i.stepId},"Healing accepted and applied"),n.send(i)}catch(i){return w(n,500,"Failed to accept healing event",i)}}),r.patch("/healing/:id/reject",async(s,n)=>{try{let i=await Hn(e,s.params.id);return n.send(i)}catch(i){return w(n,500,"Failed to reject healing event",i)}}),r.post("/healing/accept-all",async(s,n)=>{try{let i=await nt(e),a=[];for(let o of i)try{await Qs(e,o.id),await qa(t,o.caseId,o.stepId,o.healedCode),a.push({id:o.id,status:"accepted"}),ed.info({id:o.id},"Bulk healing accepted")}catch(c){a.push({id:o.id,status:"failed",error:c instanceof Error?c.message:String(c)})}return n.send({accepted:a.filter(o=>o.status==="accepted").length,results:a})}catch(i){return w(n,500,"Failed to accept all healing events",i)}}),r.post("/healing/clear-all",async(s,n)=>{try{let i=await Yu(e);return n.send({deleted:i})}catch(i){return w(n,500,"Failed to clear healing events",i)}}),r.post("/healing/delete-bulk",async(s,n)=>{let i=iy.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid request",details:i.error.issues});try{let a=await Ju(e,i.data.ids);return n.send({deleted:a})}catch(a){return w(n,500,"Failed to delete healing events",a)}}),r.delete("/healing/:id",async(s,n)=>{try{return await Wu(e,s.params.id),n.status(204).send()}catch(i){return w(n,500,"Failed to delete healing event",i)}}),r.post("/healing/apply-from-report",async(s,n)=>{let i=ny.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid request",details:i.error.issues});try{let{default:a}=await import("fs-extra"),o=await a.readJson(i.data.reportPath);if(!Array.isArray(o.events))return n.status(400).send({error:"Invalid healing report format"});let c=[];for(let l of o.events)try{await qa(t,l.caseId,l.stepId,l.healedCode),c.push({id:l.id,status:"applied"})}catch(u){c.push({id:l.id,status:"failed",error:u instanceof Error?u.message:String(u)})}return n.send({applied:c.filter(l=>l.status==="applied").length,results:c})}catch(a){return w(n,500,"Failed to apply healing report",a)}})}async function qa(r,e,t,s){let n=await ay(r,e);if(!n)throw new Error(`Case "${e}" not found in tests directory`);let i=await se(n);if(!i.steps.find(c=>c.id===t))throw new Error(`Step "${t}" not found in case "${e}"`);let o=i.steps.map(c=>c.id===t?{...c,generatedCode:s,lastHealed:new Date().toISOString()}:c);await Be(n,{steps:o})}async function ay(r,e){let{default:t}=await import("fs-extra"),{listSuiteDirs:s}=await Promise.resolve().then(()=>(Xe(),fa)),n=await s(r);for(let i of n){let a=await mt(i,e);if(a)return a}return null}var td,as,ed,ny,iy,sd=b(()=>{"use strict";m();td=x(require("path")),as=require("zod");Vn();gt();re();N();ed=E("routes/healing"),ny=as.z.object({reportPath:as.z.string().min(1)}),iy=as.z.object({ids:as.z.array(as.z.string().min(1)).min(1)})});var R,Gn,oy,cy,ht,nd,ly,uy,dy,py,Xa,id=b(()=>{"use strict";m();R=require("zod"),Gn=R.z.enum(["pending","running","passed","failed","skipped"]),oy=R.z.object({method:R.z.string(),url:R.z.string(),headers:R.z.record(R.z.string()).optional(),body:R.z.string().optional()}).optional(),cy=R.z.object({status:R.z.number(),statusText:R.z.string(),headers:R.z.record(R.z.string()).optional(),body:R.z.string().optional(),duration:R.z.number()}).optional(),ht=R.z.number().nullish().transform(r=>r??void 0),nd=R.z.object({id:R.z.string(),title:R.z.string(),passed:R.z.boolean(),partial:R.z.boolean().optional(),na:R.z.boolean().optional()}),ly=R.z.object({url:R.z.string(),stepIndex:R.z.number().int(),stepInstruction:R.z.string(),score:ht,a11yScore:ht,seoScore:ht,fcp:ht,lcp:ht,cls:ht,ttfb:ht,tbt:ht,si:ht,tti:ht,inp:ht,a11yAudits:R.z.array(nd).optional(),seoAudits:R.z.array(nd).optional(),lighthouseError:R.z.string().optional()}),uy=R.z.object({stepId:R.z.string(),instruction:R.z.string(),status:Gn,code:R.z.string(),error:R.z.string().optional(),duration:R.z.number(),screenshotPath:R.z.string().optional(),healed:R.z.boolean().optional(),healedCode:R.z.string().optional(),stepType:R.z.enum(["ui","api","mock"]).optional(),apiRequest:oy,apiResponse:cy,navigatedToUrl:R.z.string().optional(),auditUrl:R.z.string().optional()}),dy=R.z.object({caseId:R.z.string(),caseName:R.z.string(),status:Gn,steps:R.z.array(uy),duration:R.z.number(),browser:R.z.string(),device:R.z.string().optional(),startedAt:R.z.string().datetime(),finishedAt:R.z.string().datetime(),videoPath:R.z.string().optional(),tracePath:R.z.string().optional(),downloadPaths:R.z.array(R.z.string()).default([]),dataRowIndex:R.z.number().int().optional(),dataRow:R.z.record(R.z.string()).optional(),pageLoads:R.z.array(ly).default([])}),py=R.z.object({suiteId:R.z.string(),suiteName:R.z.string(),suiteType:R.z.enum(["ui","api","audit","performance"]).optional(),status:Gn,cases:R.z.array(dy),duration:R.z.number(),browser:R.z.string(),startedAt:R.z.string().datetime(),finishedAt:R.z.string().datetime()}),Xa=R.z.object({runId:R.z.string(),status:Gn,environment:R.z.string().optional(),suites:R.z.array(py),duration:R.z.number(),startedAt:R.z.string().datetime(),finishedAt:R.z.string().datetime(),totalTests:R.z.number().int(),passed:R.z.number().int(),failed:R.z.number().int(),skipped:R.z.number().int(),logFilePath:R.z.string().optional()})});function Wa(r,e){return jr.default.join(r,ad,`${e}.json`)}async function od(r,e){let t=Xa.safeParse(e);if(!t.success){let n=t.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
653
689
  `);throw new X(`Cannot write invalid run result:
654
- ${n}`,"result","INVALID_RESULT")}let s=Ba(Lr.default.join(r,jn),e.runId);await K(s,t.data),ja.info({runId:e.runId,status:e.status},"Run result saved")}async function Dr(r,e){let t=Ba(Lr.default.join(r,jn),e);if(!await Or.default.pathExists(t))throw new ie(`Run result not found for runId "${e}".`,t,"RESULT_NOT_FOUND");let s=await de(t),n=Fa.safeParse(s);if(!n.success){let i=n.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
690
+ ${n}`,"result","INVALID_RESULT")}let s=Wa(jr.default.join(r,zn),e.runId);await K(s,t.data),Ka.info({runId:e.runId,status:e.status},"Run result saved")}async function Br(r,e){let t=Wa(jr.default.join(r,zn),e);if(!await Mr.default.pathExists(t))throw new oe(`Run result not found for runId "${e}".`,t,"RESULT_NOT_FOUND");let s=await ue(t),n=Xa.safeParse(s);if(!n.success){let i=n.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
655
691
  `);throw new X(`Invalid run result at "${t}":
656
- ${i}`,"result","INVALID_RESULT")}return n.data}async function Ua(r){let e=Lr.default.join(r,jn,Hu);if(!await Or.default.pathExists(e))return[];let s=(await Or.default.readdir(e,{withFileTypes:!0})).filter(i=>i.isFile()&&i.name.endsWith(".json")).map(i=>i.name.replace(".json",""));return(await Promise.all(s.map(async i=>{let a=await Or.default.stat(Lr.default.join(e,`${i}.json`));return{id:i,mtime:a.mtimeMs}}))).sort((i,a)=>a.mtime-i.mtime).map(i=>i.id)}async function Bn(r,e=20){let t=await Ua(r),s=[];for(let n of t.slice(0,e))try{let i=await Dr(r,n);s.push({runId:i.runId,status:i.status,environment:i.environment,startedAt:i.startedAt,finishedAt:i.finishedAt,totalTests:i.totalTests,passed:i.passed,failed:i.failed,skipped:i.skipped,duration:i.duration,suiteIds:i.suites.map(a=>a.suiteId)})}catch(i){ja.warn({runId:n,err:i},"Failed to read run result \u2014 skipping")}return s}async function Gu(r,e){let t=Ba(Lr.default.join(r,jn),e);if(!await Or.default.pathExists(t))throw new ie(`Run result not found for runId "${e}".`,t,"RESULT_NOT_FOUND");await Or.default.remove(t),ja.info({runId:e},"Run result deleted")}var Lr,Or,ja,jn,Hu,Xs=w(()=>{"use strict";p();Lr=x(require("path")),Or=x(require("fs-extra"));Uu();re();F();Ve();ja=E("result-store"),jn="results",Hu="runs"});function zu(r){let t=r.toLowerCase().replace(/\{\{[^}]+\}\}/g," __var__ ").replace(/"([^"]+)"/g,(n,i)=>` ${i} `).replace(/'([^']+)'/g,(n,i)=>` ${i} `).replace(/[^a-z0-9\s-]/g," ").trim().split(/\s+/).filter(n=>n.length>1&&!jh.has(n)),s=[...t];for(let n=0;n<t.length-1;n++)s.push(`${t[n]}_${t[n+1]}`);return s}function Bh(r){return(0,qu.createHash)("md5").update(r).digest().readUInt32LE(0)%Ha}var qu,Hn,Ha,jh,Un,Xu=w(()=>{"use strict";p();qu=require("crypto"),Hn=require("fs-extra"),Ha=256,jh=new Set(["the","a","an","is","are","was","were","be","been","being","have","has","had","do","does","did","will","would","could","should","may","might","shall","can","need","dare","ought","to","of","in","for","on","with","at","by","from","as","into","through","during","before","after","above","below","between","out","off","over","under","again","further","then","once","that","this","these","those","and","but","or","nor","not","so","very","just","than","too","also","it","its"]);Un=class{constructor(e){this.vocabPath=e}vocab={docCount:0,termDocFreq:{}};dirty=!1;async load(){try{this.vocab=await(0,Hn.readJson)(this.vocabPath)}catch{this.vocab={docCount:0,termDocFreq:{}}}}async save(){this.dirty&&(await(0,Hn.outputJson)(this.vocabPath,this.vocab,{spaces:0}),this.dirty=!1)}addDocument(e){let t=new Set(zu(e));this.vocab.docCount++;for(let s of t)this.vocab.termDocFreq[s]=(this.vocab.termDocFreq[s]??0)+1;this.dirty=!0}addDocuments(e){for(let t of e)this.addDocument(t)}embed(e){let t=zu(e);if(t.length===0)return new Array(Ha).fill(0);let s={};for(let o of t)s[o]=(s[o]??0)+1;let n=new Array(Ha).fill(0),i=Math.max(this.vocab.docCount,1);for(let[o,c]of Object.entries(s)){let l=c/t.length,u=this.vocab.termDocFreq[o]??0,d=Math.log(1+i/(1+u)),g=l*d,m=Bh(o);n[m]+=g}let a=Math.sqrt(n.reduce((o,c)=>o+c*c,0));if(a>0)for(let o=0;o<n.length;o++)n[o]/=a;return n}get documentCount(){return this.vocab.docCount}}});function Ku(r,e){if(r.length!==e.length||r.length===0)return 0;let t=0,s=0,n=0;for(let a=0;a<r.length;a++)t+=r[a]*e[a],s+=r[a]*r[a],n+=e[a]*e[a];let i=Math.sqrt(s)*Math.sqrt(n);return i===0?0:t/i}var Wu=w(()=>{"use strict";p()});var ss,rs,Ju=w(()=>{"use strict";p();ss=require("fs-extra");Wu();rs=class{constructor(e,t=500){this.filePath=e;this.maxEntries=t}documents=[];dirty=!1;async load(){if(await(0,ss.pathExists)(this.filePath))try{let e=await(0,ss.readJson)(this.filePath);this.documents=e.documents??[]}catch{this.documents=[]}}async persist(){if(!this.dirty)return;let e={version:1,documents:this.documents};await(0,ss.outputJson)(this.filePath,e,{spaces:0}),this.dirty=!1}add(e,t,s,n){this.documents=this.documents.filter(a=>a.id!==e);let i=Date.now();this.documents.push({id:e,text:t,vector:s,metadata:n,createdAt:i,updatedAt:i}),this.dirty=!0,this.documents.length>this.maxEntries&&this.prune()}update(e,t){let s=this.documents.find(n=>n.id===e);return s?(s.metadata={...s.metadata,...t},s.updatedAt=Date.now(),this.dirty=!0,!0):!1}remove(e){let t=this.documents.length;return this.documents=this.documents.filter(s=>s.id!==e),this.documents.length!==t?(this.dirty=!0,!0):!1}get(e){return this.documents.find(t=>t.id===e)}has(e){return this.documents.some(t=>t.id===e)}get size(){return this.documents.length}search(e,t=5,s=.5){let n=[];for(let i of this.documents){let a=Ku(e,i.vector);a>=s&&n.push({id:i.id,text:i.text,metadata:i.metadata,score:a})}return n.sort((i,a)=>{if(Math.abs(i.score-a.score)>.001)return a.score-i.score;let o=this.documents.find(l=>l.id===i.id);return this.documents.find(l=>l.id===a.id).updatedAt-o.updatedAt}),n.slice(0,t)}prune(){let e=[...this.documents].sort((s,n)=>s.updatedAt-n.updatedAt),t=e.length-this.maxEntries;if(t>0){let s=new Set(e.slice(0,t).map(n=>n.id));this.documents=this.documents.filter(n=>!s.has(n.id))}}}});function Hh(r,e){let t=`${r.toLowerCase().trim()}|${Va(e)}`;return(0,Yu.createHash)("sha256").update(t).digest("hex").slice(0,16)}function Va(r){if(!r)return"";try{let e=new URL(r),t=e.pathname.replace(/\/\d+/g,"/*");return`${e.hostname}${t}`}catch{return r}}function Vh(r,e,t){let s=e+t;if(s===0)return r;let n=e/s;return r*(1+.05*n)}function Gh(r){return{id:r.id,instruction:r.metadata.instruction,code:r.metadata.code,urlPattern:r.metadata.urlPattern,score:r.score,successCount:r.metadata.successCount,failCount:r.metadata.failCount}}var Yu,Uh,Vn,Qu=w(()=>{"use strict";p();Yu=require("crypto"),Uh=2,Vn=class{constructor(e,t){this.store=e;this.embedder=t}ingest(e,t,s){let n=Hh(e,s),i=Va(s),a=`${e} ${i}`,o=this.store.get(n);if(o){this.store.update(n,{...o.metadata,code:t,successCount:o.metadata.successCount+1,consecutiveFails:0});return}this.embedder.addDocument(a);let c=this.embedder.embed(a);this.store.add(n,a,c,{instruction:e,code:t,urlPattern:i,successCount:1,failCount:0,consecutiveFails:0})}retrieve(e,t="",s=3,n=.65){if(this.store.size===0)return[];let i=Va(t),a=`${e} ${i}`,o=this.embedder.embed(a),l=this.store.search(o,s*2,n).map(u=>({...u,score:Vh(u.score,u.metadata.successCount,u.metadata.failCount)}));return l.sort((u,d)=>d.score-u.score),l.slice(0,s).map(Gh)}recordOutcome(e,t){let s=this.store.get(e);if(s)if(t)this.store.update(e,{...s.metadata,successCount:s.metadata.successCount+1,consecutiveFails:0});else{let n=s.metadata.consecutiveFails+1;if(n>=Uh){this.store.remove(e);return}this.store.update(e,{...s.metadata,failCount:s.metadata.failCount+1,consecutiveFails:n})}}get size(){return this.store.size}}});function zh(r,e){let t=`${r.toLowerCase().trim()}|${Gn(e)}`;return(0,Zu.createHash)("sha256").update(t).digest("hex").slice(0,16)}function Gn(r){return r.replace(/\d+ms/g,"Nms").replace(/\d+/g,"N").replace(/["'][^"']*["']/g,"'...'").replace(/\s+/g," ").trim().slice(0,200)}function qh(r){if(!r)return"";try{let e=new URL(r);return`${e.hostname}${e.pathname.replace(/\/\d+/g,"/*")}`}catch{return r}}function Xh(r){return{id:r.id,instruction:r.metadata.instruction,error:r.metadata.error,failedCode:r.metadata.failedCode,healedCode:r.metadata.healedCode,strategy:r.metadata.strategy,level:r.metadata.level,score:r.score,successCount:r.metadata.successCount}}var Zu,zn,ed=w(()=>{"use strict";p();Zu=require("crypto"),zn=class{constructor(e,t){this.store=e;this.embedder=t}ingest(e){let t=zh(e.instruction,e.error),s=qh(e.url),n=`${e.instruction} ${Gn(e.error)}`,i=this.store.get(t);if(i){this.store.update(t,{...i.metadata,healedCode:e.healedCode,strategy:e.strategy,level:e.level,successCount:i.metadata.successCount+1});return}this.embedder.addDocument(n);let a=this.embedder.embed(n);this.store.add(t,n,a,{instruction:e.instruction,error:Gn(e.error),failedCode:e.failedCode,healedCode:e.healedCode,strategy:e.strategy,level:e.level,urlPattern:s,successCount:1})}retrieve(e,t,s=3,n=.6){if(this.store.size===0)return[];let i=`${e} ${Gn(t)}`,a=this.embedder.embed(i);return this.store.search(a,s,n).map(Xh)}get size(){return this.store.size}}});function Kh(r,e){let t=`${r}|${e}`;return(0,rd.createHash)("sha256").update(t).digest("hex").slice(0,16)}function Wh(r){return r.replace(/\d+ms/g,"Nms").replace(/\d+/g,"N").replace(/["'][^"']*["']/g,"'...'").replace(/\s+/g," ").trim().slice(0,200)}function td(r){if(!r)return"";try{let e=new URL(r);return`${e.hostname}${e.pathname.replace(/\/\d+/g,"/*")}`}catch{return r}}function Jh(r){let e=r.metadata.commonFixes;return{errorPattern:r.metadata.errorPattern,urlPattern:r.metadata.urlPattern,frequency:r.metadata.frequency,suggestedFix:e.length>0?e[e.length-1]:null,score:r.score}}var rd,qn,sd=w(()=>{"use strict";p();rd=require("crypto"),qn=class{constructor(e,t){this.store=e;this.embedder=t}record(e,t,s){let n=Wh(e),i=td(t),a=Kh(n,i),o=`${n} ${i}`,c=this.store.get(a);if(c){let u=[...c.metadata.commonFixes];s&&!u.includes(s)&&(u.push(s),u.length>5&&u.shift()),this.store.update(a,{...c.metadata,frequency:c.metadata.frequency+1,lastSeen:Date.now(),commonFixes:u});return}this.embedder.addDocument(o);let l=this.embedder.embed(o);this.store.add(a,o,l,{errorPattern:n,urlPattern:i,frequency:1,lastSeen:Date.now(),commonFixes:s?[s]:[]})}getWarnings(e,t=5){if(this.store.size===0)return[];let s=td(e),n=this.embedder.embed(s),a=this.store.search(n,t*2,.3).filter(o=>o.metadata.frequency>=2);return a.sort((o,c)=>c.metadata.frequency-o.metadata.frequency),a.slice(0,t).map(Jh)}get size(){return this.store.size}}});var ns,nd,Ga,Xn,id=w(()=>{"use strict";p();ns=require("path"),nd=require("fs-extra");Xu();Ju();Qu();ed();sd();F();Ga=E("rag"),Xn=class r{codeCorpus;healingCorpus;errorCatalog;embedder;codeStore;healingStore;errorStore;constructor(e,t,s,n){this.embedder=e,this.codeStore=t,this.healingStore=s,this.errorStore=n,this.codeCorpus=new Vn(t,e),this.healingCorpus=new zn(s,e),this.errorCatalog=new qn(n,e)}static async create(e,t){let s=(0,ns.join)(e,"results",".rag");await(0,nd.ensureDir)(s),Ga.info({ragDir:s},"Initializing RAG manager");let n=new Un((0,ns.join)(s,"idf-vocab.json"));await n.load();let i=new rs((0,ns.join)(s,"code-corpus.json"),t.codeCorpus.maxEntries),a=new rs((0,ns.join)(s,"healing-corpus.json"),t.healingCorpus.maxEntries),o=new rs((0,ns.join)(s,"error-catalog.json"),t.errorCatalog.maxEntries);return await Promise.all([i.load(),a.load(),o.load()]),Ga.info({codeCorpus:i.size,healingCorpus:a.size,errorCatalog:o.size,idfDocuments:n.documentCount},"RAG corpora loaded"),new r(n,i,a,o)}async persist(){await Promise.all([this.embedder.save(),this.codeStore.persist(),this.healingStore.persist(),this.errorStore.persist()]),Ga.debug("RAG corpora persisted")}getStats(){return{codeCorpus:this.codeStore.size,healingCorpus:this.healingStore.size,errorCatalog:this.errorStore.size,idfVocab:this.embedder.documentCount}}}});function Qh(r){let e=[];for(let t of Yh){t.regex.lastIndex=0;let s;for(;(s=t.regex.exec(r))!==null;)t.type==="getByRole"?e.push({selector:s[0],type:t.type,role:s[1],name:s[2]}):e.push({selector:s[0],type:t.type,name:s[1]})}return e}function Zh(r,e,t){let s=r.toLowerCase();for(let n of e){let i=n.match(/"([^"]+)"/);if(i&&i[1].toLowerCase()===s&&(!t||n.toLowerCase().startsWith(t.toLowerCase())))return n}for(let n of e){let i=n.match(/"([^"]+)"/);if(i){let a=i[1].toLowerCase();if((a.includes(s)||s.includes(a))&&(!t||n.toLowerCase().startsWith(t.toLowerCase())))return n}}if(t){let n=e.filter(i=>i.toLowerCase().startsWith(t.toLowerCase()));if(n.length>0){let i=0,a;for(let o of n){let c=o.match(/"([^"]+)"/);if(c){let l=ey(s,c[1].toLowerCase());l>i&&(i=l,a=o)}}if(i>.3)return a}}}function ey(r,e){if(r===e)return 1;let t=r.length>e.length?r:e,s=r.length>e.length?e:r;if(t.length===0)return 1;let n=0;for(let i=0;i<s.length;i++)t.includes(s[i])&&n++;return n/t.length}async function od(r,e,t){let s=Qh(t);if(s.length===0)return{url:e,ok:!0,total:0,matched:0,missing:0,checks:[]};await r.navigate(e);let n=await r.snapshot();if(!n)return ad.warn({url:e},"Proactive check: snapshot returned null \u2014 skipping validation"),{url:e,ok:!0,total:s.length,matched:0,missing:0,checks:[]};let a=In(n).interactiveElements.split(`
657
- `).filter(Boolean),o=[];for(let u of s){let d=u.name??"",g=!1;for(let f of a){let h=f.match(/"([^"]+)"/);if(h&&h[1].toLowerCase()===d.toLowerCase())if(u.role){if(f.toLowerCase().startsWith(u.role.toLowerCase())){g=!0;break}}else{g=!0;break}}let m={selector:u.selector,type:u.type,found:g};if(!g){let f=Zh(d,a,u.role);f&&(m.suggestion=f)}o.push(m)}let c=o.filter(u=>u.found).length,l=o.filter(u=>!u.found).length;return ad.info({url:e,total:o.length,matched:c,missing:l},"Proactive selector check complete"),{url:e,ok:l===0,total:o.length,matched:c,missing:l,checks:o}}var ad,Yh,cd=w(()=>{"use strict";p();ya();F();ad=E("proactive-checker"),Yh=[{regex:/getByRole\(\s*['"](\w+)['"]\s*,\s*\{[^}]*name:\s*['"]([^'"]+)['"]/g,type:"getByRole"},{regex:/getByLabel\(\s*['"]([^'"]+)['"]/g,type:"getByLabel"},{regex:/getByPlaceholder\(\s*['"]([^'"]+)['"]/g,type:"getByPlaceholder"},{regex:/getByText\(\s*['"]([^'"]+)['"]/g,type:"getByText"},{regex:/getByTestId\(\s*['"]([^'"]+)['"]/g,type:"getByTestId"}]});var gt,Nr,Kn,ld=w(()=>{"use strict";p();gt=require("playwright");F();Nr=E("browser-manager"),Kn=class{browsers=new Map;async launchBrowser(e,t){let s=this.browsers.get(e);if(s)return s;let i=await(e==="firefox"?gt.firefox:e==="webkit"?gt.webkit:gt.chromium).launch({headless:t.headless});return this.browsers.set(e,i),Nr.info({browser:e,headless:t.headless},"Browser launched"),i}async newContext(e,t,s){let n=t.device&&gt.devices[t.device]?gt.devices[t.device]:null;t.device&&!n&&Nr.warn({device:t.device},"Unknown Playwright device \u2014 falling back to configured viewport");let i={...n??{},viewport:n?.viewport??t.viewport??{width:1280,height:720},storageState:void 0};t.video!=="off"&&s&&(i.recordVideo={dir:s});let a=await e.newContext(i);return await a.addInitScript(()=>{let o=`
692
+ ${i}`,"result","INVALID_RESULT")}return n.data}async function Ja(r){let e=jr.default.join(r,zn,ad);if(!await Mr.default.pathExists(e))return[];let s=(await Mr.default.readdir(e,{withFileTypes:!0})).filter(i=>i.isFile()&&i.name.endsWith(".json")).map(i=>i.name.replace(".json",""));return(await Promise.all(s.map(async i=>{let a=await Mr.default.stat(jr.default.join(e,`${i}.json`));return{id:i,mtime:a.mtimeMs}}))).sort((i,a)=>a.mtime-i.mtime).map(i=>i.id)}async function qn(r,e=20){let t=await Ja(r),s=[];for(let n of t.slice(0,e))try{let i=await Br(r,n);s.push({runId:i.runId,status:i.status,environment:i.environment,startedAt:i.startedAt,finishedAt:i.finishedAt,totalTests:i.totalTests,passed:i.passed,failed:i.failed,skipped:i.skipped,duration:i.duration,suiteIds:i.suites.map(a=>a.suiteId)})}catch(i){Ka.warn({runId:n,err:i},"Failed to read run result \u2014 skipping")}return s}async function cd(r,e){let t=Wa(jr.default.join(r,zn),e);if(!await Mr.default.pathExists(t))throw new oe(`Run result not found for runId "${e}".`,t,"RESULT_NOT_FOUND");await Mr.default.remove(t),Ka.info({runId:e},"Run result deleted")}var jr,Mr,Ka,zn,ad,Zs=b(()=>{"use strict";m();jr=x(require("path")),Mr=x(require("fs-extra"));id();te();N();ze();Ka=E("result-store"),zn="results",ad="runs"});function ld(r){let t=r.toLowerCase().replace(/\{\{[^}]+\}\}/g," __var__ ").replace(/"([^"]+)"/g,(n,i)=>` ${i} `).replace(/'([^']+)'/g,(n,i)=>` ${i} `).replace(/[^a-z0-9\s-]/g," ").trim().split(/\s+/).filter(n=>n.length>1&&!my.has(n)),s=[...t];for(let n=0;n<t.length-1;n++)s.push(`${t[n]}_${t[n+1]}`);return s}function gy(r){return(0,ud.createHash)("md5").update(r).digest().readUInt32LE(0)%Ya}var ud,Kn,Ya,my,Xn,dd=b(()=>{"use strict";m();ud=require("crypto"),Kn=require("fs-extra"),Ya=256,my=new Set(["the","a","an","is","are","was","were","be","been","being","have","has","had","do","does","did","will","would","could","should","may","might","shall","can","need","dare","ought","to","of","in","for","on","with","at","by","from","as","into","through","during","before","after","above","below","between","out","off","over","under","again","further","then","once","that","this","these","those","and","but","or","nor","not","so","very","just","than","too","also","it","its"]);Xn=class{constructor(e){this.vocabPath=e}vocab={docCount:0,termDocFreq:{}};dirty=!1;async load(){try{this.vocab=await(0,Kn.readJson)(this.vocabPath)}catch{this.vocab={docCount:0,termDocFreq:{}}}}async save(){this.dirty&&(await(0,Kn.outputJson)(this.vocabPath,this.vocab,{spaces:0}),this.dirty=!1)}addDocument(e){let t=new Set(ld(e));this.vocab.docCount++;for(let s of t)this.vocab.termDocFreq[s]=(this.vocab.termDocFreq[s]??0)+1;this.dirty=!0}addDocuments(e){for(let t of e)this.addDocument(t)}embed(e){let t=ld(e);if(t.length===0)return new Array(Ya).fill(0);let s={};for(let o of t)s[o]=(s[o]??0)+1;let n=new Array(Ya).fill(0),i=Math.max(this.vocab.docCount,1);for(let[o,c]of Object.entries(s)){let l=c/t.length,u=this.vocab.termDocFreq[o]??0,d=Math.log(1+i/(1+u)),p=l*d,g=gy(o);n[g]+=p}let a=Math.sqrt(n.reduce((o,c)=>o+c*c,0));if(a>0)for(let o=0;o<n.length;o++)n[o]/=a;return n}get documentCount(){return this.vocab.docCount}}});function pd(r,e){if(r.length!==e.length||r.length===0)return 0;let t=0,s=0,n=0;for(let a=0;a<r.length;a++)t+=r[a]*e[a],s+=r[a]*r[a],n+=e[a]*e[a];let i=Math.sqrt(s)*Math.sqrt(n);return i===0?0:t/i}var md=b(()=>{"use strict";m()});var cs,os,gd=b(()=>{"use strict";m();cs=require("fs-extra");md();os=class{constructor(e,t=500){this.filePath=e;this.maxEntries=t}documents=[];dirty=!1;async load(){if(await(0,cs.pathExists)(this.filePath))try{let e=await(0,cs.readJson)(this.filePath);this.documents=e.documents??[]}catch{this.documents=[]}}async persist(){if(!this.dirty)return;let e={version:1,documents:this.documents};await(0,cs.outputJson)(this.filePath,e,{spaces:0}),this.dirty=!1}add(e,t,s,n){this.documents=this.documents.filter(a=>a.id!==e);let i=Date.now();this.documents.push({id:e,text:t,vector:s,metadata:n,createdAt:i,updatedAt:i}),this.dirty=!0,this.documents.length>this.maxEntries&&this.prune()}update(e,t){let s=this.documents.find(n=>n.id===e);return s?(s.metadata={...s.metadata,...t},s.updatedAt=Date.now(),this.dirty=!0,!0):!1}remove(e){let t=this.documents.length;return this.documents=this.documents.filter(s=>s.id!==e),this.documents.length!==t?(this.dirty=!0,!0):!1}get(e){return this.documents.find(t=>t.id===e)}has(e){return this.documents.some(t=>t.id===e)}get size(){return this.documents.length}search(e,t=5,s=.5){let n=[];for(let i of this.documents){let a=pd(e,i.vector);a>=s&&n.push({id:i.id,text:i.text,metadata:i.metadata,score:a})}return n.sort((i,a)=>{if(Math.abs(i.score-a.score)>.001)return a.score-i.score;let o=this.documents.find(l=>l.id===i.id);return this.documents.find(l=>l.id===a.id).updatedAt-o.updatedAt}),n.slice(0,t)}prune(){let e=[...this.documents].sort((s,n)=>s.updatedAt-n.updatedAt),t=e.length-this.maxEntries;if(t>0){let s=new Set(e.slice(0,t).map(n=>n.id));this.documents=this.documents.filter(n=>!s.has(n.id))}}}});function hy(r,e){let t=`${r.toLowerCase().trim()}|${Qa(e)}`;return(0,fd.createHash)("sha256").update(t).digest("hex").slice(0,16)}function Qa(r){if(!r)return"";try{let e=new URL(r),t=e.pathname.replace(/\/\d+/g,"/*");return`${e.hostname}${t}`}catch{return r}}function yy(r,e,t){let s=e+t;if(s===0)return r;let n=e/s;return r*(1+.05*n)}function wy(r){return{id:r.id,instruction:r.metadata.instruction,code:r.metadata.code,urlPattern:r.metadata.urlPattern,score:r.score,successCount:r.metadata.successCount,failCount:r.metadata.failCount}}var fd,fy,Wn,hd=b(()=>{"use strict";m();fd=require("crypto"),fy=2,Wn=class{constructor(e,t){this.store=e;this.embedder=t}ingest(e,t,s){let n=hy(e,s),i=Qa(s),a=`${e} ${i}`,o=this.store.get(n);if(o){this.store.update(n,{...o.metadata,code:t,successCount:o.metadata.successCount+1,consecutiveFails:0});return}this.embedder.addDocument(a);let c=this.embedder.embed(a);this.store.add(n,a,c,{instruction:e,code:t,urlPattern:i,successCount:1,failCount:0,consecutiveFails:0})}retrieve(e,t="",s=3,n=.65){if(this.store.size===0)return[];let i=Qa(t),a=`${e} ${i}`,o=this.embedder.embed(a),l=this.store.search(o,s*2,n).map(u=>({...u,score:yy(u.score,u.metadata.successCount,u.metadata.failCount)}));return l.sort((u,d)=>d.score-u.score),l.slice(0,s).map(wy)}recordOutcome(e,t){let s=this.store.get(e);if(s)if(t)this.store.update(e,{...s.metadata,successCount:s.metadata.successCount+1,consecutiveFails:0});else{let n=s.metadata.consecutiveFails+1;if(n>=fy){this.store.remove(e);return}this.store.update(e,{...s.metadata,failCount:s.metadata.failCount+1,consecutiveFails:n})}}get size(){return this.store.size}}});function by(r,e){let t=`${r.toLowerCase().trim()}|${Jn(e)}`;return(0,yd.createHash)("sha256").update(t).digest("hex").slice(0,16)}function Jn(r){return r.replace(/\d+ms/g,"Nms").replace(/\d+/g,"N").replace(/["'][^"']*["']/g,"'...'").replace(/\s+/g," ").trim().slice(0,200)}function vy(r){if(!r)return"";try{let e=new URL(r);return`${e.hostname}${e.pathname.replace(/\/\d+/g,"/*")}`}catch{return r}}function xy(r){return{id:r.id,instruction:r.metadata.instruction,error:r.metadata.error,failedCode:r.metadata.failedCode,healedCode:r.metadata.healedCode,strategy:r.metadata.strategy,level:r.metadata.level,score:r.score,successCount:r.metadata.successCount}}var yd,Yn,wd=b(()=>{"use strict";m();yd=require("crypto"),Yn=class{constructor(e,t){this.store=e;this.embedder=t}ingest(e){let t=by(e.instruction,e.error),s=vy(e.url),n=`${e.instruction} ${Jn(e.error)}`,i=this.store.get(t);if(i){this.store.update(t,{...i.metadata,healedCode:e.healedCode,strategy:e.strategy,level:e.level,successCount:i.metadata.successCount+1});return}this.embedder.addDocument(n);let a=this.embedder.embed(n);this.store.add(t,n,a,{instruction:e.instruction,error:Jn(e.error),failedCode:e.failedCode,healedCode:e.healedCode,strategy:e.strategy,level:e.level,urlPattern:s,successCount:1})}retrieve(e,t,s=3,n=.6){if(this.store.size===0)return[];let i=`${e} ${Jn(t)}`,a=this.embedder.embed(i);return this.store.search(a,s,n).map(xy)}get size(){return this.store.size}}});function Sy(r,e){let t=`${r}|${e}`;return(0,vd.createHash)("sha256").update(t).digest("hex").slice(0,16)}function Cy(r){return r.replace(/\d+ms/g,"Nms").replace(/\d+/g,"N").replace(/["'][^"']*["']/g,"'...'").replace(/\s+/g," ").trim().slice(0,200)}function bd(r){if(!r)return"";try{let e=new URL(r);return`${e.hostname}${e.pathname.replace(/\/\d+/g,"/*")}`}catch{return r}}function Ey(r){let e=r.metadata.commonFixes;return{errorPattern:r.metadata.errorPattern,urlPattern:r.metadata.urlPattern,frequency:r.metadata.frequency,suggestedFix:e.length>0?e[e.length-1]:null,score:r.score}}var vd,Qn,xd=b(()=>{"use strict";m();vd=require("crypto"),Qn=class{constructor(e,t){this.store=e;this.embedder=t}record(e,t,s){let n=Cy(e),i=bd(t),a=Sy(n,i),o=`${n} ${i}`,c=this.store.get(a);if(c){let u=[...c.metadata.commonFixes];s&&!u.includes(s)&&(u.push(s),u.length>5&&u.shift()),this.store.update(a,{...c.metadata,frequency:c.metadata.frequency+1,lastSeen:Date.now(),commonFixes:u});return}this.embedder.addDocument(o);let l=this.embedder.embed(o);this.store.add(a,o,l,{errorPattern:n,urlPattern:i,frequency:1,lastSeen:Date.now(),commonFixes:s?[s]:[]})}getWarnings(e,t=5){if(this.store.size===0)return[];let s=bd(e),n=this.embedder.embed(s),a=this.store.search(n,t*2,.3).filter(o=>o.metadata.frequency>=2);return a.sort((o,c)=>c.metadata.frequency-o.metadata.frequency),a.slice(0,t).map(Ey)}get size(){return this.store.size}}});var ls,Sd,Za,Zn,Cd=b(()=>{"use strict";m();ls=require("path"),Sd=require("fs-extra");dd();gd();hd();wd();xd();N();Za=E("rag"),Zn=class r{codeCorpus;healingCorpus;errorCatalog;embedder;codeStore;healingStore;errorStore;constructor(e,t,s,n){this.embedder=e,this.codeStore=t,this.healingStore=s,this.errorStore=n,this.codeCorpus=new Wn(t,e),this.healingCorpus=new Yn(s,e),this.errorCatalog=new Qn(n,e)}static async create(e,t){let s=(0,ls.join)(e,"results",".rag");await(0,Sd.ensureDir)(s),Za.info({ragDir:s},"Initializing RAG manager");let n=new Xn((0,ls.join)(s,"idf-vocab.json"));await n.load();let i=new os((0,ls.join)(s,"code-corpus.json"),t.codeCorpus.maxEntries),a=new os((0,ls.join)(s,"healing-corpus.json"),t.healingCorpus.maxEntries),o=new os((0,ls.join)(s,"error-catalog.json"),t.errorCatalog.maxEntries);return await Promise.all([i.load(),a.load(),o.load()]),Za.info({codeCorpus:i.size,healingCorpus:a.size,errorCatalog:o.size,idfDocuments:n.documentCount},"RAG corpora loaded"),new r(n,i,a,o)}async persist(){await Promise.all([this.embedder.save(),this.codeStore.persist(),this.healingStore.persist(),this.errorStore.persist()]),Za.debug("RAG corpora persisted")}getStats(){return{codeCorpus:this.codeStore.size,healingCorpus:this.healingStore.size,errorCatalog:this.errorStore.size,idfVocab:this.embedder.documentCount}}}});function Py(r){let e=[];for(let t of Iy){t.regex.lastIndex=0;let s;for(;(s=t.regex.exec(r))!==null;)t.type==="getByRole"?e.push({selector:s[0],type:t.type,role:s[1],name:s[2]}):e.push({selector:s[0],type:t.type,name:s[1]})}return e}function Ry(r,e,t){let s=r.toLowerCase();for(let n of e){let i=n.match(/"([^"]+)"/);if(i&&i[1].toLowerCase()===s&&(!t||n.toLowerCase().startsWith(t.toLowerCase())))return n}for(let n of e){let i=n.match(/"([^"]+)"/);if(i){let a=i[1].toLowerCase();if((a.includes(s)||s.includes(a))&&(!t||n.toLowerCase().startsWith(t.toLowerCase())))return n}}if(t){let n=e.filter(i=>i.toLowerCase().startsWith(t.toLowerCase()));if(n.length>0){let i=0,a;for(let o of n){let c=o.match(/"([^"]+)"/);if(c){let l=Ty(s,c[1].toLowerCase());l>i&&(i=l,a=o)}}if(i>.3)return a}}}function Ty(r,e){if(r===e)return 1;let t=r.length>e.length?r:e,s=r.length>e.length?e:r;if(t.length===0)return 1;let n=0;for(let i=0;i<s.length;i++)t.includes(s[i])&&n++;return n/t.length}async function Id(r,e,t){let s=Py(t);if(s.length===0)return{url:e,ok:!0,total:0,matched:0,missing:0,checks:[]};await r.navigate(e);let n=await r.snapshot();if(!n)return Ed.warn({url:e},"Proactive check: snapshot returned null \u2014 skipping validation"),{url:e,ok:!0,total:s.length,matched:0,missing:0,checks:[]};let a=_n(n).interactiveElements.split(`
693
+ `).filter(Boolean),o=[];for(let u of s){let d=u.name??"",p=!1;for(let f of a){let h=f.match(/"([^"]+)"/);if(h&&h[1].toLowerCase()===d.toLowerCase())if(u.role){if(f.toLowerCase().startsWith(u.role.toLowerCase())){p=!0;break}}else{p=!0;break}}let g={selector:u.selector,type:u.type,found:p};if(!p){let f=Ry(d,a,u.role);f&&(g.suggestion=f)}o.push(g)}let c=o.filter(u=>u.found).length,l=o.filter(u=>!u.found).length;return Ed.info({url:e,total:o.length,matched:c,missing:l},"Proactive selector check complete"),{url:e,ok:l===0,total:o.length,matched:c,missing:l,checks:o}}var Ed,Iy,Pd=b(()=>{"use strict";m();Pa();N();Ed=E("proactive-checker"),Iy=[{regex:/getByRole\(\s*['"](\w+)['"]\s*,\s*\{[^}]*name:\s*['"]([^'"]+)['"]/g,type:"getByRole"},{regex:/getByLabel\(\s*['"]([^'"]+)['"]/g,type:"getByLabel"},{regex:/getByPlaceholder\(\s*['"]([^'"]+)['"]/g,type:"getByPlaceholder"},{regex:/getByText\(\s*['"]([^'"]+)['"]/g,type:"getByText"},{regex:/getByTestId\(\s*['"]([^'"]+)['"]/g,type:"getByTestId"}]});async function ky(r){if(!await ei.default.pathExists(r))return r;let e=yr.default.dirname(r),t=yr.default.extname(r),s=yr.default.basename(r,t);for(let n=1;n<1e3;n++){let i=yr.default.join(e,`${s} (${n})${t}`);if(!await ei.default.pathExists(i))return i}return r}var yr,ei,yt,Xt,ti,Rd=b(()=>{"use strict";m();yr=x(require("path")),ei=x(require("fs-extra")),yt=require("playwright");N();Xt=E("browser-manager");ti=class{browsers=new Map;pendingDownloads=new WeakMap;capturedDownloads=new WeakMap;async launchBrowser(e,t){let s=this.browsers.get(e);if(s)return s;let i=await(e==="firefox"?yt.firefox:e==="webkit"?yt.webkit:yt.chromium).launch({headless:t.headless});return this.browsers.set(e,i),Xt.info({browser:e,headless:t.headless},"Browser launched"),i}async newContext(e,t,s,n){let i=t.device&&yt.devices[t.device]?yt.devices[t.device]:null;t.device&&!i&&Xt.warn({device:t.device},"Unknown Playwright device \u2014 falling back to configured viewport");let a={...i??{},viewport:i?.viewport??t.viewport??{width:1280,height:720},storageState:void 0,acceptDownloads:!0};t.video!=="off"&&s&&(a.recordVideo={dir:s});let o=await e.newContext(a);return n&&(this.pendingDownloads.set(o,[]),this.capturedDownloads.set(o,[]),o.on("download",c=>{let l=(async()=>{try{await ei.default.ensureDir(n);let u=c.suggestedFilename()||"download",d=yr.default.basename(u).replace(/[^a-zA-Z0-9._-]+/g,"_")||"download",p=await ky(yr.default.join(n,d));await c.saveAs(p),this.capturedDownloads.get(o)?.push(p),Xt.info({file:yr.default.basename(p)},"Download captured")}catch(u){Xt.debug({err:u},"Failed to capture download")}})();this.pendingDownloads.get(o)?.push(l)})),await o.addInitScript(()=>{let c=`
658
694
  outline: 3px solid #3b82f6 !important;
659
695
  outline-offset: 3px !important;
660
696
  box-shadow: 0 0 0 6px rgba(59,130,246,0.20) !important;
661
697
  transition: outline 0.08s ease, box-shadow 0.08s ease !important;
662
- `,c=null;function l(){c&&(c.style.cssText=c.style.cssText.replace(/outline[^;]*;?/g,"").replace(/box-shadow[^;]*;?/g,"").replace(/transition[^;]*;?/g,""),c=null)}function u(d){!d||!(d instanceof HTMLElement)||(l(),c=d,c.style.cssText+=o,setTimeout(l,1800))}document.addEventListener("focus",d=>u(d.target),!0),document.addEventListener("mousedown",d=>u(d.target),!0)}),t.trace!=="off"&&await a.tracing.start({screenshots:!0,snapshots:!0,sources:!1}),a}async newPage(e){let t=await e.newPage(),s=[/Failed to load resource/i,/net::ERR_/i,/the server responded with a status of/i,/Access to .* has been blocked by CORS/i,/Mixed Content:/i,/favicon\.ico/i],n=[];return t.on("console",i=>{let a=i.text();s.some(o=>o.test(a))||n.push({type:i.type(),text:a,timestamp:Date.now()})}),t.on("pageerror",i=>{i.message?.includes("appendChild")&&i.message?.includes("null")||n.push({type:"error",text:`[PageError] ${i.message}`,timestamp:Date.now()})}),t.__consoleLogs=n,t}drainConsoleLogs(e){let t=e.__consoleLogs;if(!t)return[];let s=[...t];return t.length=0,s}apiContexts=[];async createApiOnlyPage(e){let t=await gt.request.newContext({baseURL:e||void 0});this.apiContexts.push(t);let s={request:t,url:()=>e??"",title:async()=>"",goto:async()=>null,waitForLoadState:async()=>{},setDefaultTimeout:()=>{},setDefaultNavigationTimeout:()=>{},screenshot:async()=>Buffer.alloc(0),video:()=>null,close:async()=>{}};return Nr.info("Created API-only request context (zero browser)"),s}async closeApiContexts(){for(let e of this.apiContexts)await e.dispose().catch(()=>{});this.apiContexts=[]}async closeContext(e,t,s){if(t.trace!=="off")try{s?await e.tracing.stop({path:s}):await e.tracing.stop()}catch(n){Nr.debug({err:n},"Tracing stop failed \u2014 ignoring")}await e.close().catch(n=>{Nr.debug({err:n},"Context close failed \u2014 ignoring")})}async closeAll(){await this.closeApiContexts();for(let[e,t]of this.browsers)try{await t.close(),Nr.debug({browser:e},"Browser closed")}catch(s){Nr.warn({err:s,browser:e},"Error closing browser")}this.browsers.clear()}get openBrowserCount(){return this.browsers.size}}});var ud,ty,Wn,dd=w(()=>{"use strict";p();F();ud=E("healing-budget"),ty=[/timeout/i,/ECONNREFUSED/i,/ENOTFOUND/i,/ETIMEDOUT/i,/net::ERR/i,/ERR_NAME_NOT_RESOLVED/i,/DNS/i,/socket hang up/i],Wn=class{constructor(e){this.dailyBudget=e}spent=0;healFailures=new Map;pageFailures=new Map;shouldHeal(e){if(this.spent>=this.dailyBudget)return ud.warn({spent:this.spent,budget:this.dailyBudget},"Daily healing budget exhausted"),{heal:!1,reason:"Daily budget exhausted"};let t=this.healFailures.get(e.stepId)??0;if(t>=3)return{heal:!1,reason:`Persistent failure \u2014 step "${e.stepId}" has failed healing ${t} times. Needs manual fix.`};if(this.isEnvironmental(e.error))return{heal:!1,reason:"Environmental error \u2014 retry instead"};let s=this.pageFailures.get(e.pageUrl)??[];return s.some(n=>n.stepId===e.stepId)||(s.push(e),this.pageFailures.set(e.pageUrl,s)),s.length>=3?{heal:!0,strategy:"batch",reason:`Batch heal \u2014 ${s.length} failures on ${e.pageUrl}, fix once for all`}:{heal:!0,strategy:"individual",reason:"Standard heal"}}recordSpend(e){this.spent+=e,ud.debug({spend:e,total:this.spent},"Healing budget spend recorded")}recordHealFailure(e){this.healFailures.set(e,(this.healFailures.get(e)??0)+1)}get totalSpent(){return this.spent}get remainingBudget(){return Math.max(0,this.dailyBudget-this.spent)}isEnvironmental(e){return ty.some(t=>t.test(e))}}});var pd,Jn,Yn,md=w(()=>{"use strict";p();pd=require("crypto");Mn();F();Jn=E("healing-report"),Yn=class{events=[];record(e){let t={id:(0,pd.randomUUID)(),runId:e.runId,suiteId:e.suiteId,caseId:e.caseId,stepId:e.stepId,stepInstruction:e.stepInstruction,failedCode:e.failedCode,healedCode:e.healedCode,error:e.error,strategy:e.strategy,level:e.level,status:"pending",pageUrl:e.pageUrl,timestamp:new Date().toISOString()};this.events.push(t),Jn.info({stepId:e.stepId,strategy:e.strategy,level:e.level},"Healing event recorded")}get eventCount(){return this.events.length}async flush(e,t){if(this.events.length===0)return;let s={runId:t,generatedAt:new Date().toISOString(),totalHeals:this.events.length,accepted:0,rejected:0,pending:this.events.length,events:[...this.events]};try{await ku(e,s),Jn.info({runId:t,count:this.events.length},"Healing report written")}catch(n){Jn.error({err:n,runId:t},"Failed to write healing report")}for(let n of this.events)try{await Au(e,n)}catch(i){Jn.warn({err:i,eventId:n.id},"Failed to append pending healing event")}}}});function gd(r){switch(r){case"passed":return"passed";case"failed":return"failed";case"skipped":return"skipped";default:return"broken"}}function ry(r){return r==null?"\u2014":r<1e3?`${Math.round(r)}ms`:`${(r/1e3).toFixed(2)}s`}function fd(r,e){if(e==null)return"na";let t={fcp:[1800,3e3],lcp:[2500,4e3],cls:[.1,.25],ttfb:[800,1800],tbt:[200,600],si:[3400,5800],tti:[3800,7300],inp:[200,500]},[s,n]=t[r];return e<s?"good":e<n?"average":"poor"}function sy(r){return r==null?"#94a3b8":r>=90?"#10b981":r>=50?"#f59e0b":"#ef4444"}function qa(r,e,t){let s={good:"#10b981",average:"#f59e0b",poor:"#ef4444",na:"#94a3b8"},n=[{key:"fcp",abbr:"FCP",label:"First Contentful Paint"},{key:"lcp",abbr:"LCP",label:"Largest Contentful Paint"},{key:"cls",abbr:"CLS",label:"Cumulative Layout Shift"},{key:"ttfb",abbr:"TTFB",label:"Time to First Byte"},{key:"tbt",abbr:"TBT",label:"Total Blocking Time"},{key:"si",abbr:"SI",label:"Speed Index"},{key:"tti",abbr:"TTI",label:"Time to Interactive"},{key:"inp",abbr:"INP",label:"Interaction to Next Paint"}],i=(u,d)=>u==="cls"&&d!=null?d.toFixed(3):ry(d),a=(u,d)=>{let g=sy(u),m=2*Math.PI*24,f=u!=null?u/100*m:0,h=u==null?"\u2014":u>=90?"Good":u>=50?"Needs Work":"Poor";return`
663
- <div style="flex:1;display:flex;flex-direction:column;align-items:center;padding:10px 8px;border-radius:10px;background:${g}12;border:2px solid ${g}44;">
698
+ `,l=null;function u(){l&&(l.style.cssText=l.style.cssText.replace(/outline[^;]*;?/g,"").replace(/box-shadow[^;]*;?/g,"").replace(/transition[^;]*;?/g,""),l=null)}function d(p){!p||!(p instanceof HTMLElement)||(u(),l=p,l.style.cssText+=c,setTimeout(u,1800))}document.addEventListener("focus",p=>d(p.target),!0),document.addEventListener("mousedown",p=>d(p.target),!0)}),t.trace!=="off"&&await o.tracing.start({screenshots:!0,snapshots:!0,sources:!1}),o}async newPage(e){let t=await e.newPage(),s=[/Failed to load resource/i,/net::ERR_/i,/the server responded with a status of/i,/Access to .* has been blocked by CORS/i,/Mixed Content:/i,/favicon\.ico/i],n=[];return t.on("console",i=>{let a=i.text();s.some(o=>o.test(a))||n.push({type:i.type(),text:a,timestamp:Date.now()})}),t.on("pageerror",i=>{i.message?.includes("appendChild")&&i.message?.includes("null")||n.push({type:"error",text:`[PageError] ${i.message}`,timestamp:Date.now()})}),t.__consoleLogs=n,t}drainConsoleLogs(e){let t=e.__consoleLogs;if(!t)return[];let s=[...t];return t.length=0,s}apiContexts=[];async createApiOnlyPage(e){let t=await yt.request.newContext({baseURL:e||void 0});this.apiContexts.push(t);let s={request:t,url:()=>e??"",title:async()=>"",goto:async()=>null,waitForLoadState:async()=>{},setDefaultTimeout:()=>{},setDefaultNavigationTimeout:()=>{},screenshot:async()=>Buffer.alloc(0),video:()=>null,close:async()=>{}};return Xt.info("Created API-only request context (zero browser)"),s}async closeApiContexts(){for(let e of this.apiContexts)await e.dispose().catch(()=>{});this.apiContexts=[]}async closeContext(e,t,s){let n=this.pendingDownloads.get(e);if(n&&n.length>0){let i=new Promise(a=>setTimeout(a,15e3));await Promise.race([Promise.allSettled(n),i]),this.pendingDownloads.delete(e)}if(t.trace!=="off")try{s?await e.tracing.stop({path:s}):await e.tracing.stop()}catch(i){Xt.debug({err:i},"Tracing stop failed \u2014 ignoring")}await e.close().catch(i=>{Xt.debug({err:i},"Context close failed \u2014 ignoring")})}takeDownloads(e){let t=this.capturedDownloads.get(e)??[];return this.capturedDownloads.delete(e),[...t]}async closeAll(){await this.closeApiContexts();for(let[e,t]of this.browsers)try{await t.close(),Xt.debug({browser:e},"Browser closed")}catch(s){Xt.warn({err:s,browser:e},"Error closing browser")}this.browsers.clear()}get openBrowserCount(){return this.browsers.size}}});var Td,Ay,ri,kd=b(()=>{"use strict";m();N();Td=E("healing-budget"),Ay=[/timeout/i,/ECONNREFUSED/i,/ENOTFOUND/i,/ETIMEDOUT/i,/net::ERR/i,/ERR_NAME_NOT_RESOLVED/i,/DNS/i,/socket hang up/i],ri=class{constructor(e){this.dailyBudget=e}spent=0;healFailures=new Map;pageFailures=new Map;shouldHeal(e){if(this.spent>=this.dailyBudget)return Td.warn({spent:this.spent,budget:this.dailyBudget},"Daily healing budget exhausted"),{heal:!1,reason:"Daily budget exhausted"};let t=this.healFailures.get(e.stepId)??0;if(t>=3)return{heal:!1,reason:`Persistent failure \u2014 step "${e.stepId}" has failed healing ${t} times. Needs manual fix.`};if(this.isEnvironmental(e.error))return{heal:!1,reason:"Environmental error \u2014 retry instead"};let s=this.pageFailures.get(e.pageUrl)??[];return s.some(n=>n.stepId===e.stepId)||(s.push(e),this.pageFailures.set(e.pageUrl,s)),s.length>=3?{heal:!0,strategy:"batch",reason:`Batch heal \u2014 ${s.length} failures on ${e.pageUrl}, fix once for all`}:{heal:!0,strategy:"individual",reason:"Standard heal"}}recordSpend(e){this.spent+=e,Td.debug({spend:e,total:this.spent},"Healing budget spend recorded")}recordHealFailure(e){this.healFailures.set(e,(this.healFailures.get(e)??0)+1)}get totalSpent(){return this.spent}get remainingBudget(){return Math.max(0,this.dailyBudget-this.spent)}isEnvironmental(e){return Ay.some(t=>t.test(e))}}});var Ad,si,ni,$d=b(()=>{"use strict";m();Ad=require("crypto");Vn();N();si=E("healing-report"),ni=class{events=[];record(e){let t={id:(0,Ad.randomUUID)(),runId:e.runId,suiteId:e.suiteId,caseId:e.caseId,stepId:e.stepId,stepInstruction:e.stepInstruction,failedCode:e.failedCode,healedCode:e.healedCode,error:e.error,strategy:e.strategy,level:e.level,status:"pending",pageUrl:e.pageUrl,timestamp:new Date().toISOString()};this.events.push(t),si.info({stepId:e.stepId,strategy:e.strategy,level:e.level},"Healing event recorded")}get eventCount(){return this.events.length}async flush(e,t){if(this.events.length===0)return;let s={runId:t,generatedAt:new Date().toISOString(),totalHeals:this.events.length,accepted:0,rejected:0,pending:this.events.length,events:[...this.events]};try{await Xu(e,s),si.info({runId:t,count:this.events.length},"Healing report written")}catch(n){si.error({err:n,runId:t},"Failed to write healing report")}for(let n of this.events)try{await Ku(e,n)}catch(i){si.warn({err:i,eventId:n.id},"Failed to append pending healing event")}}}});function $y(r){let e=r.slice(r.lastIndexOf(".")).toLowerCase();return{".pdf":"application/pdf",".csv":"text/csv",".txt":"text/plain",".json":"application/json",".xml":"application/xml",".html":"text/html",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".zip":"application/zip",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".xls":"application/vnd.ms-excel",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document"}[e]??"application/octet-stream"}function _d(r){switch(r){case"passed":return"passed";case"failed":return"failed";case"skipped":return"skipped";default:return"broken"}}function _y(r){return r==null?"\u2014":r<1e3?`${Math.round(r)}ms`:`${(r/1e3).toFixed(2)}s`}function Ld(r,e){if(e==null)return"na";let t={fcp:[1800,3e3],lcp:[2500,4e3],cls:[.1,.25],ttfb:[800,1800],tbt:[200,600],si:[3400,5800],tti:[3800,7300],inp:[200,500]},[s,n]=t[r];return e<s?"good":e<n?"average":"poor"}function Ly(r){return r==null?"#94a3b8":r>=90?"#10b981":r>=50?"#f59e0b":"#ef4444"}function to(r,e,t){let s={good:"#10b981",average:"#f59e0b",poor:"#ef4444",na:"#94a3b8"},n=[{key:"fcp",abbr:"FCP",label:"First Contentful Paint"},{key:"lcp",abbr:"LCP",label:"Largest Contentful Paint"},{key:"cls",abbr:"CLS",label:"Cumulative Layout Shift"},{key:"ttfb",abbr:"TTFB",label:"Time to First Byte"},{key:"tbt",abbr:"TBT",label:"Total Blocking Time"},{key:"si",abbr:"SI",label:"Speed Index"},{key:"tti",abbr:"TTI",label:"Time to Interactive"},{key:"inp",abbr:"INP",label:"Interaction to Next Paint"}],i=(u,d)=>u==="cls"&&d!=null?d.toFixed(3):_y(d),a=(u,d)=>{let p=Ly(u),g=2*Math.PI*24,f=u!=null?u/100*g:0,h=u==null?"\u2014":u>=90?"Good":u>=50?"Needs Work":"Poor";return`
699
+ <div style="flex:1;display:flex;flex-direction:column;align-items:center;padding:10px 8px;border-radius:10px;background:${p}12;border:2px solid ${p}44;">
664
700
  <div style="position:relative;width:58px;height:58px;">
665
701
  <svg width="58" height="58" viewBox="0 0 60 60" style="transform:rotate(-90deg)">
666
- <circle cx="30" cy="30" r="24" fill="none" stroke="${g}" stroke-width="5" stroke-opacity=".15"/>
667
- <circle cx="30" cy="30" r="24" fill="none" stroke="${g}" stroke-width="5"
668
- stroke-dasharray="${m.toFixed(2)}" stroke-dashoffset="${(m-f).toFixed(2)}" stroke-linecap="round"/>
702
+ <circle cx="30" cy="30" r="24" fill="none" stroke="${p}" stroke-width="5" stroke-opacity=".15"/>
703
+ <circle cx="30" cy="30" r="24" fill="none" stroke="${p}" stroke-width="5"
704
+ stroke-dasharray="${g.toFixed(2)}" stroke-dashoffset="${(g-f).toFixed(2)}" stroke-linecap="round"/>
669
705
  </svg>
670
- <div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:15px;font-weight:900;color:${g};">${u??"\u2014"}</div>
706
+ <div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:15px;font-weight:900;color:${p};">${u??"\u2014"}</div>
671
707
  </div>
672
- <div style="font-size:9px;font-weight:700;color:${g};margin-top:4px;">${h}</div>
708
+ <div style="font-size:9px;font-weight:700;color:${p};margin-top:4px;">${h}</div>
673
709
  <div style="font-size:9px;color:#64748b;margin-top:1px;text-align:center;">${d}</div>
674
- </div>`},o=e.map(u=>{let d=u.lighthouseError?`<div style="padding:12px 16px;background:#fef3c7;color:#92400e;font-size:12px;">\u26A0 ${u.lighthouseError}</div>`:"",g=u.lighthouseError?"":n.map(({key:v,abbr:k})=>{let R=fd(v,u[v]),I=R==="good"?"#ecfdf5":R==="average"?"#fffbeb":R==="poor"?"#fef2f2":"#f8fafc",B=s[R];return`<div style="flex:1;min-width:90px;background:${I};border:1px solid ${B}33;border-radius:8px;padding:8px 10px;text-align:center;">
675
- <div style="font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:${B};opacity:.8;margin-bottom:3px;">${k}</div>
676
- <div style="font-size:14px;font-weight:800;color:${B};font-variant-numeric:tabular-nums;">${i(v,u[v])}</div>
677
- </div>`}).join(""),m=u.lighthouseError?"":`
710
+ </div>`},o=e.map(u=>{let d=u.lighthouseError?`<div style="padding:12px 16px;background:#fef3c7;color:#92400e;font-size:12px;">\u26A0 ${u.lighthouseError}</div>`:"",p=u.lighthouseError?"":n.map(({key:v,abbr:k})=>{let T=Ld(v,u[v]),P=T==="good"?"#ecfdf5":T==="average"?"#fffbeb":T==="poor"?"#fef2f2":"#f8fafc",j=s[T];return`<div style="flex:1;min-width:90px;background:${P};border:1px solid ${j}33;border-radius:8px;padding:8px 10px;text-align:center;">
711
+ <div style="font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:${j};opacity:.8;margin-bottom:3px;">${k}</div>
712
+ <div style="font-size:14px;font-weight:800;color:${j};font-variant-numeric:tabular-nums;">${i(v,u[v])}</div>
713
+ </div>`}).join(""),g=u.lighthouseError?"":`
678
714
  <div style="border-top:1px solid #f1f5f9;padding:10px 16px;display:grid;grid-template-columns:1fr 1fr;gap:3px 24px;">
679
- ${n.map(({key:v,abbr:k,label:R})=>{let I=fd(v,u[v]);return`<div style="display:flex;align-items:center;gap:5px;font-size:9px;color:#64748b;padding:1px 0;">
680
- <span style="color:${I==="good"?"#10b981":I==="average"?"#f59e0b":I==="poor"?"#ef4444":"#94a3b8"};font-size:11px;line-height:1;flex-shrink:0;">\u25CF</span>
715
+ ${n.map(({key:v,abbr:k,label:T})=>{let P=Ld(v,u[v]);return`<div style="display:flex;align-items:center;gap:5px;font-size:9px;color:#64748b;padding:1px 0;">
716
+ <span style="color:${P==="good"?"#10b981":P==="average"?"#f59e0b":P==="poor"?"#ef4444":"#94a3b8"};font-size:11px;line-height:1;flex-shrink:0;">\u25CF</span>
681
717
  <span style="font-weight:700;color:#475569;">${k}</span>
682
- <span style="opacity:.7;">${R}</span>
718
+ <span style="opacity:.7;">${T}</span>
683
719
  </div>`}).join("")}
684
- </div>`,f=(v,k)=>{if(!v||v.length===0)return"";let R=v.map(I=>{let B=I.na?"#94a3b8":I.passed?"#10b981":"#ef4444",Y=I.na?"\u2013":I.passed?"\u2713":"\u2717";return`<div style="display:flex;align-items:center;gap:5px;font-size:9px;color:${B};padding:1px 0;">
685
- <span style="font-weight:700;flex-shrink:0;">${Y}</span>
686
- <span style="color:#475569;">${I.title}</span>
720
+ </div>`,f=(v,k)=>{if(!v||v.length===0)return"";let T=v.map(P=>{let j=P.na?"#94a3b8":P.passed?"#10b981":"#ef4444",J=P.na?"\u2013":P.passed?"\u2713":"\u2717";return`<div style="display:flex;align-items:center;gap:5px;font-size:9px;color:${j};padding:1px 0;">
721
+ <span style="font-weight:700;flex-shrink:0;">${J}</span>
722
+ <span style="color:#475569;">${P.title}</span>
687
723
  </div>`}).join("");return`<div>
688
724
  <div style="font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:#94a3b8;margin-bottom:4px;">${k}</div>
689
- ${R}
725
+ ${T}
690
726
  </div>`},h=t==="performance"&&!u.lighthouseError?`
691
727
  <div style="padding:16px;">
692
728
  <div style="display:flex;gap:10px;margin-bottom:14px;">${a(u.score,"Performance")}</div>
693
729
  <div style="font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#94a3b8;margin-bottom:8px;">Core Web Vitals</div>
694
- <div style="display:flex;flex-wrap:wrap;gap:6px;">${g}</div>
730
+ <div style="display:flex;flex-wrap:wrap;gap:6px;">${p}</div>
695
731
  </div>
696
- ${m}`:"",C=t==="accessibility"&&!u.lighthouseError?`
732
+ ${g}`:"",S=t==="accessibility"&&!u.lighthouseError?`
697
733
  <div style="padding:16px;">
698
734
  <div style="display:flex;gap:10px;margin-bottom:14px;">${a(u.a11yScore,"Accessibility")}</div>
699
735
  ${f(u.a11yAudits,"Accessibility Audits")}
700
- </div>`:"",P=t==="seo"&&!u.lighthouseError?`
736
+ </div>`:"",I=t==="seo"&&!u.lighthouseError?`
701
737
  <div style="padding:16px;">
702
738
  <div style="display:flex;gap:10px;margin-bottom:14px;">${a(u.seoScore,"SEO")}</div>
703
739
  ${f(u.seoAudits,"SEO Audits")}
@@ -709,7 +745,7 @@ ${i}`,"result","INVALID_RESULT")}return n.data}async function Ua(r){let e=Lr.def
709
745
  <div style="font-size:11px;font-family:monospace;color:#6366f1;font-weight:600;">${u.url}</div>
710
746
  </div>
711
747
  ${d}
712
- ${h}${C}${P}
748
+ ${h}${S}${I}
713
749
  </div>`}).join(""),c=new Date().toLocaleString(),l={performance:{icon:"\u26A1",color:"#7c3aed",title:"Performance Report",subtitle:"Core Web Vitals \xB7 Speed Metrics"},accessibility:{icon:"\u267F",color:"#2563eb",title:"Accessibility Report",subtitle:"WCAG Audit Checks"},seo:{icon:"\u{1F50D}",color:"#059669",title:"SEO Report",subtitle:"Search Engine Optimisation Checks"}}[t];return`<!DOCTYPE html>
714
750
  <html lang="en">
715
751
  <head>
@@ -749,17 +785,17 @@ ${i}`,"result","INVALID_RESULT")}return n.data}async function Ua(r){let e=Lr.def
749
785
  <p style="font-size:9px;color:#cbd5e1;text-align:center;margin-top:16px;">Powered by Google Lighthouse \xB7 Desktop preset \xB7 Assuremind Studio</p>
750
786
  </div>
751
787
  </body>
752
- </html>`}var je,hd,gr,za,Qn,yd=w(()=>{"use strict";p();je=x(require("path")),hd=require("crypto"),gr=x(require("fs-extra"));F();za=E("allure-reporter"),Qn=class{resultsDir;environment;constructor(e,t,s="dev"){this.resultsDir=je.default.join(e,"results","allure-results",t),this.environment=s}async writeResults(e){await gr.default.ensureDir(this.resultsDir);let t=[`Environment=${this.environment.toUpperCase()}`,"Framework=Assuremind"].join(`
753
- `);await gr.default.writeFile(je.default.join(this.resultsDir,"environment.properties"),t,"utf-8");let s;if(e.logFilePath)try{s=je.default.basename(e.logFilePath),await this.copyAttachment(e.logFilePath).catch(()=>{}),za.debug({logFile:s},"Log file copied to Allure results")}catch{za.debug("Failed to copy log file to Allure results")}let n=0;for(let i of e.suites)for(let a of i.cases)await this.writeTestResult(i,a,s),n++;za.info({dir:this.resultsDir,written:n},"Allure results written")}async writeTestResult(e,t,s){let n=(0,hd.randomUUID)(),i=new Date(t.startedAt).getTime(),a=new Date(t.finishedAt).getTime(),o=t.steps.find(g=>g.status==="failed"),c=[];if(t.videoPath){let g=je.default.basename(t.videoPath),f=je.default.extname(g).toLowerCase()===".mp4"?"video/mp4":"video/webm";c.push({name:"Video Recording",source:g,type:f})}if(t.tracePath){let g=je.default.basename(t.tracePath);c.push({name:"Playwright Trace",source:g,type:"application/zip"})}s&&c.push({name:"Run Log",source:s,type:"text/plain"});let l=t.pageLoads??[];if(l.length>0){let g=l.some(h=>!h.lighthouseError&&h.score!=null),m=l.some(h=>!h.lighthouseError&&(h.a11yScore!=null||(h.a11yAudits?.length??0)>0)),f=l.some(h=>!h.lighthouseError&&(h.seoScore!=null||(h.seoAudits?.length??0)>0));if(g){let h=qa(t.caseName,l,"performance"),C=`${n}-perf.html`;await gr.default.writeFile(je.default.join(this.resultsDir,C),h,"utf-8"),c.push({name:"\u26A1 Performance Report",source:C,type:"text/html"})}if(m){let h=qa(t.caseName,l,"accessibility"),C=`${n}-a11y.html`;await gr.default.writeFile(je.default.join(this.resultsDir,C),h,"utf-8"),c.push({name:"\u267F Accessibility Report",source:C,type:"text/html"})}if(f){let h=qa(t.caseName,l,"seo"),C=`${n}-seo.html`;await gr.default.writeFile(je.default.join(this.resultsDir,C),h,"utf-8"),c.push({name:"\u{1F50D} SEO Report",source:C,type:"text/html"})}}let u={uuid:n,historyId:`${e.suiteId}::${t.caseId}::${e.browser}`,testCaseId:`${e.suiteId}::${t.caseId}`,fullName:`${e.suiteName} > ${t.caseName}`,name:t.caseName,status:gd(t.status),stage:"finished",start:i,stop:a,labels:[{name:"suite",value:e.suiteName},{name:"browser",value:e.browser},{name:"framework",value:"assuremind"},{name:"tag",value:`ENV: ${this.environment.toUpperCase()}`}],links:[],parameters:[],attachments:c,steps:t.steps.map(g=>this.buildStepResult(g,i)),...o?.error&&{statusDetails:{message:o.error}}},d=je.default.join(this.resultsDir,`${n}-result.json`);await gr.default.writeJson(d,u,{spaces:2});for(let g of t.steps)g.screenshotPath&&await this.copyAttachment(g.screenshotPath).catch(()=>{});t.videoPath&&await this.copyAttachment(t.videoPath).catch(()=>{}),t.tracePath&&await this.copyAttachment(t.tracePath).catch(()=>{})}buildStepResult(e,t){let s=t,n=t+e.duration,i=[];if(e.screenshotPath){let a=je.default.basename(e.screenshotPath);i.push({name:"Screenshot",source:a,type:"image/png"})}return{name:e.instruction,status:gd(e.status),stage:"finished",start:s,stop:n,attachments:i,parameters:[],steps:[]}}async copyAttachment(e){let t=je.default.join(this.resultsDir,je.default.basename(e));await gr.default.copy(e,t,{overwrite:!0})}}});function iy(){try{let e=(0,vd.createRequire)(y??__filename).resolve("allure-commandline/package.json"),t=is.default.dirname(e);return is.default.join(t,"dist","bin",Ka?"allure.bat":"allure")}catch{return is.default.resolve(__dirname,Ka?"../node_modules/allure-commandline/dist/bin/allure.bat":"../node_modules/.bin/allure")}}async function xd(r,e){let t=is.default.join(r,"results","allure-results",e),s=is.default.join(r,"results","allure-report",e);if(!await Xa.default.pathExists(t))return Ks.debug({resultsDir:t},"No allure-results dir for run \u2014 skipping report generation"),!1;if((await Xa.default.readdir(t)).length===0)return Ks.debug({runId:e},"allure-results is empty \u2014 skipping report generation"),!1;try{return await ny(ay,["generate",t,"--output",s,"--clean","--single-file"],Ka?{shell:!0}:{}),Ks.info({reportDir:s,runId:e},"Allure HTML report generated"),!0}catch(i){let a=i instanceof Error?i.message:String(i);return a.includes("java")||a.includes("Java")||a.includes("JAVA")?Ks.warn("Allure report generation skipped \u2014 Java is not installed. Install Java (https://adoptium.net) to enable Allure HTML reports."):Ks.warn({err:a,runId:e},"Allure report generation failed"),!1}}var is,Xa,wd,bd,vd,ny,Ks,Ka,ay,Sd=w(()=>{"use strict";p();is=x(require("path")),Xa=x(require("fs-extra")),wd=require("child_process"),bd=require("util"),vd=require("module");F();ny=(0,bd.promisify)(wd.execFile),Ks=E("allure-generator"),Ka=process.platform==="win32";ay=iy()});function Zn(){return[{category:"person",methods:[{name:"fullName",example:S.faker.person.fullName()},{name:"firstName",example:S.faker.person.firstName()},{name:"lastName",example:S.faker.person.lastName()},{name:"middleName",example:S.faker.person.middleName()},{name:"sex",example:S.faker.person.sex()},{name:"prefix",example:S.faker.person.prefix()},{name:"suffix",example:S.faker.person.suffix()},{name:"jobTitle",example:S.faker.person.jobTitle()},{name:"jobArea",example:S.faker.person.jobArea()},{name:"jobType",example:S.faker.person.jobType()},{name:"bio",example:S.faker.person.bio()}]},{category:"internet",methods:[{name:"email",example:S.faker.internet.email()},{name:"userName",example:S.faker.internet.username()},{name:"password",example:S.faker.internet.password()},{name:"url",example:S.faker.internet.url()},{name:"domainName",example:S.faker.internet.domainName()},{name:"domainWord",example:S.faker.internet.domainWord()},{name:"ip",example:S.faker.internet.ip()},{name:"ipv6",example:S.faker.internet.ipv6()},{name:"mac",example:S.faker.internet.mac()},{name:"userAgent",example:S.faker.internet.userAgent()},{name:"emoji",example:S.faker.internet.emoji()}]},{category:"phone",methods:[{name:"number",example:S.faker.phone.number()},{name:"imei",example:S.faker.phone.imei()}]},{category:"location",methods:[{name:"streetAddress",example:S.faker.location.streetAddress()},{name:"street",example:S.faker.location.street()},{name:"city",example:S.faker.location.city()},{name:"state",example:S.faker.location.state()},{name:"zipCode",example:S.faker.location.zipCode()},{name:"country",example:S.faker.location.country()},{name:"countryCode",example:S.faker.location.countryCode()},{name:"county",example:S.faker.location.county()},{name:"latitude",example:String(S.faker.location.latitude())},{name:"longitude",example:String(S.faker.location.longitude())},{name:"timeZone",example:S.faker.location.timeZone()},{name:"buildingNumber",example:S.faker.location.buildingNumber()}]},{category:"company",methods:[{name:"name",example:S.faker.company.name()},{name:"catchPhrase",example:S.faker.company.catchPhrase()},{name:"buzzPhrase",example:S.faker.company.buzzPhrase()},{name:"buzzNoun",example:S.faker.company.buzzNoun()},{name:"buzzVerb",example:S.faker.company.buzzVerb()},{name:"buzzAdjective",example:S.faker.company.buzzAdjective()}]},{category:"finance",methods:[{name:"accountNumber",example:S.faker.finance.accountNumber()},{name:"accountName",example:S.faker.finance.accountName()},{name:"creditCardNumber",example:S.faker.finance.creditCardNumber()},{name:"creditCardCVV",example:S.faker.finance.creditCardCVV()},{name:"currencyCode",example:S.faker.finance.currencyCode()},{name:"currencyName",example:S.faker.finance.currencyName()},{name:"amount",example:S.faker.finance.amount()},{name:"iban",example:S.faker.finance.iban()},{name:"bic",example:S.faker.finance.bic()},{name:"bitcoinAddress",example:S.faker.finance.bitcoinAddress()},{name:"transactionType",example:S.faker.finance.transactionType()}]},{category:"date",methods:[{name:"past",example:S.faker.date.past().toISOString()},{name:"future",example:S.faker.date.future().toISOString()},{name:"recent",example:S.faker.date.recent().toISOString()},{name:"soon",example:S.faker.date.soon().toISOString()},{name:"birthdate",example:S.faker.date.birthdate().toISOString()},{name:"month",example:S.faker.date.month()},{name:"weekday",example:S.faker.date.weekday()}]},{category:"lorem",methods:[{name:"word",example:S.faker.lorem.word()},{name:"words",example:S.faker.lorem.words()},{name:"sentence",example:S.faker.lorem.sentence()},{name:"sentences",example:S.faker.lorem.sentences()},{name:"paragraph",example:S.faker.lorem.paragraph()},{name:"slug",example:S.faker.lorem.slug()},{name:"lines",example:S.faker.lorem.lines(1)}]},{category:"string",methods:[{name:"uuid",example:S.faker.string.uuid()},{name:"alphanumeric",example:S.faker.string.alphanumeric(10)},{name:"numeric",example:S.faker.string.numeric(6)},{name:"alpha",example:S.faker.string.alpha(8)},{name:"nanoid",example:S.faker.string.nanoid()},{name:"hexadecimal",example:S.faker.string.hexadecimal({length:8})},{name:"sample",example:S.faker.string.sample(12)}]},{category:"number",methods:[{name:"int",example:String(S.faker.number.int({max:9999}))},{name:"float",example:String(S.faker.number.float({max:100,fractionDigits:2}))}]},{category:"datatype",methods:[{name:"boolean",example:String(S.faker.datatype.boolean())}]},{category:"image",methods:[{name:"avatar",example:S.faker.image.avatar()},{name:"url",example:S.faker.image.url()}]},{category:"color",methods:[{name:"human",example:S.faker.color.human()},{name:"rgb",example:S.faker.color.rgb()},{name:"hex",example:S.faker.color.rgb({format:"hex"})}]},{category:"commerce",methods:[{name:"productName",example:S.faker.commerce.productName()},{name:"price",example:S.faker.commerce.price()},{name:"department",example:S.faker.commerce.department()},{name:"productDescription",example:S.faker.commerce.productDescription().slice(0,60)+"..."},{name:"isbn",example:S.faker.commerce.isbn()}]},{category:"vehicle",methods:[{name:"vehicle",example:S.faker.vehicle.vehicle()},{name:"manufacturer",example:S.faker.vehicle.manufacturer()},{name:"model",example:S.faker.vehicle.model()},{name:"vin",example:S.faker.vehicle.vin()},{name:"vrm",example:S.faker.vehicle.vrm()}]},{category:"system",methods:[{name:"fileName",example:S.faker.system.fileName()},{name:"mimeType",example:S.faker.system.mimeType()},{name:"fileExt",example:S.faker.system.fileExt()},{name:"filePath",example:S.faker.system.filePath()},{name:"semver",example:S.faker.system.semver()}]}]}function Mr(r,e){let t=S.faker[r],s=oy[`${r}.${e}`]??e;if(!t||typeof t[s]!="function")return`[unknown: ${r}.${e}]`;let n=t[s]();return n instanceof Date?n.toISOString():String(n)}var S,oy,Wa=w(()=>{"use strict";p();S=require("@faker-js/faker");oy={"internet.userName":"username"}});function Ed(r){switch(r){case"FAKE_FIRST_NAME":return Mr("person","firstName");case"FAKE_LAST_NAME":return Mr("person","lastName");case"FAKE_AGE":return String(Math.floor(Math.random()*63)+18);case"FAKE_EMAIL":return Mr("internet","email");case"FAKE_PHONE":return Mr("phone","number");case"FAKE_PASSWORD":return Mr("internet","password")}let e=r.match(/^FAKE_NUMBER_(\d+)$/);if(e&&e[1]){let t=Math.max(1,parseInt(e[1],10)),s=t===1?0:Math.pow(10,t-1),n=Math.pow(10,t)-1;return String(Math.floor(Math.random()*(n-s+1))+s)}if(r.startsWith("FAKE_")){let t=r.slice(5),s=Cd[t];if(s)return Mr(s[0],s[1])}return null}var Cd,Pd=w(()=>{"use strict";p();Wa();Cd={};for(let r of Zn())for(let e of r.methods){let t=`${r.category}_${e.name}`.toUpperCase();Cd[t]=[r.category,e.name]}});function Gt(r,e,t){return r.replace(new RegExp(cy,"g"),(s,n)=>{if(n==="BASE_URL")return t;let i=Ed(n);return i!==null?i:e[n]??`{{${n}}}`})}var cy,Ja=w(()=>{"use strict";p();Pd();cy="\\{\\{([A-Z0-9_]+)\\}\\}"});async function ft(r,e,t,s="domcontentloaded",n){t&&(e.setDefaultTimeout(t),e.setDefaultNavigationTimeout(t));let i=t?Ya.expect.configure({timeout:t}):Ya.expect,a=n??{setVariable:()=>{},getVariable:()=>{}},c=new ly("page","expect","context",r)(e,i,a);c.catch(()=>{}),await c;let l=t?Math.min(t/2,1e4):1e4;try{await e.waitForLoadState(s,{timeout:l})}catch{}}var Ya,ly,ei=w(()=>{"use strict";p();Ya=require("@playwright/test"),ly=Object.getPrototypeOf(async function(){}).constructor});async function uy(r,e){if(r===e)return null;let t=[],s=r;for(;s&&s!==e;){let n="iframe";try{let i=await s.frameElement();if(i){let a=await i.getAttribute("id").catch(()=>null),o=await i.getAttribute("name").catch(()=>null),c=await i.getAttribute("title").catch(()=>null);a?n=`#${a}`:o?n=`iframe[name='${o}']`:c&&(n=`iframe[title='${c}']`),await i.dispose().catch(()=>{})}}catch{}t.push(n),s=s.parentFrame()}return t.reverse().join("||")}async function Ws(r,e,t){let s=r.url(),n=await r.title().catch(()=>""),i={maxElements:120,maxTextLen:80},a=await r.evaluate(Id,i).catch(()=>[])??[],o=[],c=r.mainFrame();for(let d of r.frames())if(d!==c){if(o.length+a.length>=120)break;try{let g=await uy(d,c);if(g===null)continue;let m=await d.evaluate(Id,i).catch(()=>[])??[];for(let f of m)o.push(`${f} frame="${g}"`)}catch{}}let l=[...a,...o].slice(0,120).join(`
754
- `),u=await r.evaluate(({maxLen:d})=>document.body?.innerHTML?.slice(0,d)??"",{maxLen:8e3}).catch(()=>"");return{url:s,title:n,interactiveElements:l,htmlSnapshot:u,previousSteps:e,variables:t}}var Id,Rd=w(()=>{"use strict";p();Id=({maxElements:r,maxTextLen:e})=>{let t=["button",'[role="button"]',"a[href]",'input:not([type="hidden"])',"textarea","select",'[role="link"]','[role="tab"]','[role="checkbox"]','[role="radio"]','[role="menuitem"]','[role="option"]','[role="combobox"]','[role="listbox"]','[role="switch"]'];function s(l){let u=l.getAttribute("aria-labelledby");return u?u.split(/\s+/).map(d=>document.getElementById(d)?.textContent?.trim()??"").filter(Boolean).join(" "):""}function n(l){let u=l.getAttribute("id");if(u){let g=document.querySelector(`label[for="${u}"]`);if(g)return(g.textContent??"").trim().slice(0,60)}let d=l.closest("label");if(d){let g=d.cloneNode(!0);return g.querySelectorAll("input,textarea,select").forEach(m=>m.remove()),(g.textContent??"").trim().slice(0,60)}return""}function i(l){let u=window.getComputedStyle(l);if(u.display==="none"||u.visibility==="hidden"||u.opacity==="0")return!1;let d=l.getBoundingClientRect();return d.width>0&&d.height>0}function a(l){return l.getAttribute("data-testid")??l.getAttribute("data-cy")??l.getAttribute("data-qa")??l.getAttribute("data-test")??""}let o=new Set,c=[];for(let l of t){if(c.length>=r)break;for(let u of Array.from(document.querySelectorAll(l))){if(c.length>=r)break;if(o.has(u)||!i(u))continue;o.add(u);let d=u.tagName.toLowerCase(),g=u.getAttribute("role")??d,m=(u.textContent??"").trim().replace(/\s+/g," ").slice(0,e),f=u.getAttribute("aria-label")??"",h=s(u),C=n(u),P=a(u),v=u.getAttribute("name")??"",k=u.getAttribute("id")??"",R=u.getAttribute("placeholder")??"",I=u.getAttribute("type")??"",B=d==="a"?(u.getAttribute("href")??"").slice(0,60):"",Y=d==="select"||d==="input"?u.value?.slice(0,40):"",j=[`<${d}>`];P&&j.push(`data-testid="${P}"`),f&&j.push(`aria-label="${f}"`),h&&j.push(`aria-labelledby="${h}"`),C&&j.push(`label="${C}"`),R&&j.push(`placeholder="${R}"`),m&&j.push(`text="${m}"`),I&&j.push(`type="${I}"`),v&&j.push(`name="${v}"`),k&&j.push(`id="${k}"`),B&&j.push(`href="${B}"`),Y&&j.push(`value="${Y}"`),g!==d&&j.push(`role="${g}"`),c.push(j.join(" "))}}return c}});function dy(r){return r.testId?`page.getByTestId('${r.testId}')`:r.ariaLabel?`page.getByRole('${r.role||r.tag}', { name: '${r.ariaLabel}' })`:r.labelText&&(r.tag==="input"||r.tag==="textarea"||r.tag==="select")?`page.getByLabel('${r.labelText}')`:r.placeholder?`page.getByPlaceholder('${r.placeholder}')`:r.tag==="a"&&r.text?`page.getByRole('link', { name: '${r.text}' })`:(r.tag==="button"||r.role==="button")&&r.text?`page.getByRole('button', { name: '${r.text}' })`:r.role&&r.text?`page.getByRole('${r.role}', { name: '${r.text}' })`:r.text?`page.getByText('${r.text}')`:r.id?`page.locator('#${r.id}')`:r.name?`page.locator('[name="${r.name}"]')`:r.inputType?`page.locator('${r.tag}[type="${r.inputType}"]')`:`page.locator('${r.tag}')`}async function Za(r){let t=(await r.evaluate(()=>{let i=["button",'[role="button"]',"a[href]",'input:not([type="hidden"])',"textarea","select",'[role="link"]','[role="tab"]','[role="checkbox"]','[role="radio"]','[role="menuitem"]','[role="option"]','[role="combobox"]','[role="switch"]'];function a(g){let m=g.getAttribute("aria-labelledby");return m?m.split(/\s+/).map(f=>document.getElementById(f)?.textContent?.trim()??"").filter(Boolean).join(" "):""}function o(g){let m=g.getAttribute("id");if(m){let h=document.querySelector(`label[for="${m}"]`);if(h)return(h.textContent??"").trim().slice(0,60)}let f=g.closest("label");if(f){let h=f.cloneNode(!0);return h.querySelectorAll("input,textarea,select").forEach(C=>C.remove()),(h.textContent??"").trim().slice(0,60)}return""}let c=new Set,l=[],u=window.innerWidth,d=window.innerHeight;for(let g of i){for(let m of Array.from(document.querySelectorAll(g))){if(c.has(m))continue;let f=window.getComputedStyle(m);if(f.display==="none"||f.visibility==="hidden"||f.opacity==="0")continue;let h=m.getBoundingClientRect();if(h.width<=0||h.height<=0||h.right<0||h.bottom<0||h.left>u||h.top>d)continue;c.add(m);let C=m.tagName.toLowerCase(),P=m.getAttribute("role")??"",v=(m.textContent??"").trim().replace(/\s+/g," ").slice(0,60),k=m.getAttribute("aria-label")??"",R=a(m),I=o(m),B=m.getAttribute("data-testid")??m.getAttribute("data-cy")??m.getAttribute("data-qa")??m.getAttribute("data-test")??"",Y=m.getAttribute("placeholder")??"",j=C==="a"?m.getAttribute("href")??"":"",Ee=m.getAttribute("id")??"",vt=m.getAttribute("name")??"",Ue=m.getAttribute("type")??"";if(l.push({tag:C,role:P,text:v,ariaLabel:k,ariaLabelledBy:R,labelText:I,testId:B,placeholder:Y,href:j,id:Ee,name:vt,inputType:Ue,x:Math.round(h.left),y:Math.round(h.top),width:Math.round(h.width),height:Math.round(h.height)}),l.length>=80)break}if(l.length>=80)break}return l})).map((i,a)=>{let o=dy(i),c=i.ariaLabel||i.labelText||i.text||i.placeholder||i.testId||i.href||`${i.tag}[${a}]`,l=`[${a+1}] ${i.tag}${i.role?`(${i.role})`:""} "${c.slice(0,50)}" \u2192 ${o}`;return{index:a+1,tag:i.tag,role:i.role||i.tag,selector:o,description:l,x:i.x,y:i.y,width:i.width,height:i.height}});await r.evaluate(({els:i,overlayId:a})=>{let o=document.getElementById(a);o&&o.remove();let c="http://www.w3.org/2000/svg",l=document.createElementNS(c,"svg");l.id=a,l.setAttribute("xmlns",c),l.style.cssText=["position:fixed","top:0","left:0","width:100%","height:100%","pointer-events:none","z-index:2147483647"].join(";");let u=(d,g)=>{let m=d.toLowerCase(),f=g.toLowerCase();return m==="button"||f==="button"?"#FF6B6B":m==="a"||f==="link"?"#96CEB4":m==="input"||m==="textarea"?"#4ECDC4":m==="select"||f==="combobox"?"#45B7D1":f==="menuitem"||f==="tab"?"#DDA0DD":"#FFE66D"};for(let d of i){let g=u(d.tag,d.role),m=document.createElementNS(c,"rect");m.setAttribute("x",String(d.x+1)),m.setAttribute("y",String(d.y+1)),m.setAttribute("width",String(Math.max(d.width-2,4))),m.setAttribute("height",String(Math.max(d.height-2,4))),m.setAttribute("fill","none"),m.setAttribute("stroke",g),m.setAttribute("stroke-width","2"),m.setAttribute("stroke-dasharray","4,3"),l.appendChild(m);let f=d.index>=10?22:16,h=16,C=d.index<d.x-f?d.x-f:d.x,P=d.y<h?d.y:d.y-h+2,v=document.createElementNS(c,"rect");v.setAttribute("x",String(C)),v.setAttribute("y",String(P)),v.setAttribute("width",String(f)),v.setAttribute("height",String(h)),v.setAttribute("fill",g),v.setAttribute("rx","3"),l.appendChild(v);let k=document.createElementNS(c,"text");k.setAttribute("x",String(C+f/2)),k.setAttribute("y",String(P+12)),k.setAttribute("fill","#000"),k.setAttribute("font-size","11"),k.setAttribute("font-family","monospace"),k.setAttribute("font-weight","bold"),k.setAttribute("text-anchor","middle"),k.textContent=String(d.index),l.appendChild(k)}document.documentElement.appendChild(l)},{els:t.map(i=>({index:i.index,x:i.x,y:i.y,width:i.width,height:i.height,tag:i.tag,role:i.role})),overlayId:Qa});let s=await r.screenshot({type:"png",fullPage:!1});await r.evaluate(i=>document.getElementById(i)?.remove(),Qa);let n=t.map(i=>i.description).join(`
755
- `);return{screenshot:s,elements:t,elementMap:n}}async function eo(r){await r.evaluate(e=>document.getElementById(e)?.remove(),Qa).catch(()=>{})}var Qa,Td=w(()=>{"use strict";p();Qa="__testassuremind_som__"});function kd(r){let e=r.replace(/^```[\w]*\n?/gm,"").replace(/^```\s*$/gm,"").trim();return e.includes("---")?e.split("---").map(t=>t.trim()).filter(t=>t.length>0):e.split(`
756
- `).map(t=>t.trim()).filter(t=>t.length>0&&t.startsWith("await"))}var Xe,ti,Ad=w(()=>{"use strict";p();Rd();Td();Rt();Ja();F();ei();Ir();Xe=E("self-healing"),ti=class{constructor(e,t,s){this.provider=e;this.maxLevel=t;this.ragManager=s}async heal(e,t,s,n,i,a){if(t.failureKind==="assertion")return Xe.info({stepId:e.id},"Assertion failure \u2014 skipping all healing levels (possible application bug)"),null;let o=e.stepType==="api"||Ze(e.instruction)==="api";for(let c=1;c<=this.maxLevel;c++){if(o&&(c===3||c===4)){Xe.debug({stepId:e.id,level:c},`Skipping DOM-specific level ${c} for API step`);continue}Xe.debug({stepId:e.id,level:c,isApi:o},`Attempting heal level ${c}`);try{let l=await this.tryLevel(c,e,t,s,n,i,a,o);if(l!==null)return Xe.info({stepId:e.id,level:c,strategy:l.strategy},"Healing succeeded"),l}catch(l){Xe.debug({err:l,level:c,stepId:e.id},`Level ${c} healing attempt threw`)}}return Xe.warn({stepId:e.id,maxLevel:this.maxLevel},"All healing levels exhausted"),null}async tryLevel(e,t,s,n,i,a,o,c=!1){switch(e){case 1:return this.level1Retry(s,i);case 2:return c?this.level2ApiRegenerate(t,s,i,a,o):this.level2Regenerate(t,s,n,i,a,o);case 3:return this.level3MultiSelector(t,s,n,i,a,o);case 4:return this.level4Visual(t,i,a,o);case 5:return this.level5Decompose(t,s,n,i,a,o);case 6:return this.level6Manual(t,s);default:return null}}async level1Retry(e,t){return await t.waitForLoadState("networkidle",{timeout:5e3}).catch(()=>{}),await t.waitForTimeout(1e3),await ft(e.failedCode,t),{code:e.failedCode,level:1,strategy:"retry"}}async level2Regenerate(e,t,s,n,i,a){if(this.provider.supportsVision)try{let d=await Za(n);Xe.debug({stepId:e.id},"Level 2: using SoM vision healing");let g=await this.provider.analyzeWithSoM(d.screenshot,d.elementMap,e.instruction),m=Gt(Oe(g),i,a);return await ft(m,n),{code:m,level:2,strategy:"regenerate"}}catch(d){Xe.debug({stepId:e.id,err:d},"SoM vision failed, falling back to text regeneration"),await eo(n)}let o=await Ws(n,s,i),c="";if(this.ragManager)try{let d=this.ragManager.healingCorpus.retrieve(e.instruction,t.error,2);d.length>0&&(c=`
788
+ </html>`}var Me,Od,wr,eo,ii,Dd=b(()=>{"use strict";m();Me=x(require("path")),Od=require("crypto"),wr=x(require("fs-extra"));N();eo=E("allure-reporter"),ii=class{resultsDir;environment;constructor(e,t,s="dev"){this.resultsDir=Me.default.join(e,"results","allure-results",t),this.environment=s}async writeResults(e){await wr.default.ensureDir(this.resultsDir);let t=[`Environment=${this.environment.toUpperCase()}`,"Framework=Assuremind"].join(`
789
+ `);await wr.default.writeFile(Me.default.join(this.resultsDir,"environment.properties"),t,"utf-8");let s;if(e.logFilePath)try{s=Me.default.basename(e.logFilePath),await this.copyAttachment(e.logFilePath).catch(()=>{}),eo.debug({logFile:s},"Log file copied to Allure results")}catch{eo.debug("Failed to copy log file to Allure results")}let n=0;for(let i of e.suites)for(let a of i.cases)await this.writeTestResult(i,a,s),n++;eo.info({dir:this.resultsDir,written:n},"Allure results written")}async writeTestResult(e,t,s){let n=(0,Od.randomUUID)(),i=new Date(t.startedAt).getTime(),a=new Date(t.finishedAt).getTime(),o=t.steps.find(p=>p.status==="failed"),c=[];if(t.videoPath){let p=Me.default.basename(t.videoPath),f=Me.default.extname(p).toLowerCase()===".mp4"?"video/mp4":"video/webm";c.push({name:"Video Recording",source:p,type:f})}if(t.tracePath){let p=Me.default.basename(t.tracePath);c.push({name:"Playwright Trace",source:p,type:"application/zip"})}s&&c.push({name:"Run Log",source:s,type:"text/plain"});for(let p of t.downloadPaths??[]){let g=Me.default.basename(p);c.push({name:`Downloaded: ${g}`,source:g,type:$y(g)})}let l=t.pageLoads??[];if(l.length>0){let p=l.some(h=>!h.lighthouseError&&h.score!=null),g=l.some(h=>!h.lighthouseError&&(h.a11yScore!=null||(h.a11yAudits?.length??0)>0)),f=l.some(h=>!h.lighthouseError&&(h.seoScore!=null||(h.seoAudits?.length??0)>0));if(p){let h=to(t.caseName,l,"performance"),S=`${n}-perf.html`;await wr.default.writeFile(Me.default.join(this.resultsDir,S),h,"utf-8"),c.push({name:"\u26A1 Performance Report",source:S,type:"text/html"})}if(g){let h=to(t.caseName,l,"accessibility"),S=`${n}-a11y.html`;await wr.default.writeFile(Me.default.join(this.resultsDir,S),h,"utf-8"),c.push({name:"\u267F Accessibility Report",source:S,type:"text/html"})}if(f){let h=to(t.caseName,l,"seo"),S=`${n}-seo.html`;await wr.default.writeFile(Me.default.join(this.resultsDir,S),h,"utf-8"),c.push({name:"\u{1F50D} SEO Report",source:S,type:"text/html"})}}let u={uuid:n,historyId:`${e.suiteId}::${t.caseId}::${e.browser}`,testCaseId:`${e.suiteId}::${t.caseId}`,fullName:`${e.suiteName} > ${t.caseName}`,name:t.caseName,status:_d(t.status),stage:"finished",start:i,stop:a,labels:[{name:"suite",value:e.suiteName},{name:"browser",value:e.browser},{name:"framework",value:"assuremind"},{name:"tag",value:`ENV: ${this.environment.toUpperCase()}`}],links:[],parameters:[],attachments:c,steps:t.steps.map(p=>this.buildStepResult(p,i)),...o?.error&&{statusDetails:{message:o.error}}},d=Me.default.join(this.resultsDir,`${n}-result.json`);await wr.default.writeJson(d,u,{spaces:2});for(let p of t.steps)p.screenshotPath&&await this.copyAttachment(p.screenshotPath).catch(()=>{});t.videoPath&&await this.copyAttachment(t.videoPath).catch(()=>{}),t.tracePath&&await this.copyAttachment(t.tracePath).catch(()=>{});for(let p of t.downloadPaths??[])await this.copyAttachment(p).catch(()=>{})}buildStepResult(e,t){let s=t,n=t+e.duration,i=[];if(e.screenshotPath){let a=Me.default.basename(e.screenshotPath);i.push({name:"Screenshot",source:a,type:"image/png"})}return{name:e.instruction,status:_d(e.status),stage:"finished",start:s,stop:n,attachments:i,parameters:[],steps:[]}}async copyAttachment(e){let t=Me.default.join(this.resultsDir,Me.default.basename(e));await wr.default.copy(e,t,{overwrite:!0})}}});function Dy(){try{let e=(0,Md.createRequire)(y??__filename).resolve("allure-commandline/package.json"),t=us.default.dirname(e);return us.default.join(t,"dist","bin",so?"allure.bat":"allure")}catch{return us.default.resolve(__dirname,so?"../node_modules/allure-commandline/dist/bin/allure.bat":"../node_modules/.bin/allure")}}async function jd(r,e){let t=us.default.join(r,"results","allure-results",e),s=us.default.join(r,"results","allure-report",e);if(!await ro.default.pathExists(t))return en.debug({resultsDir:t},"No allure-results dir for run \u2014 skipping report generation"),!1;if((await ro.default.readdir(t)).length===0)return en.debug({runId:e},"allure-results is empty \u2014 skipping report generation"),!1;try{return await Oy(Fy,["generate",t,"--output",s,"--clean","--single-file"],so?{shell:!0}:{}),en.info({reportDir:s,runId:e},"Allure HTML report generated"),!0}catch(i){let a=i instanceof Error?i.message:String(i);return a.includes("java")||a.includes("Java")||a.includes("JAVA")?en.warn("Allure report generation skipped \u2014 Java is not installed. Install Java (https://adoptium.net) to enable Allure HTML reports."):en.warn({err:a,runId:e},"Allure report generation failed"),!1}}var us,ro,Fd,Nd,Md,Oy,en,so,Fy,Bd=b(()=>{"use strict";m();us=x(require("path")),ro=x(require("fs-extra")),Fd=require("child_process"),Nd=require("util"),Md=require("module");N();Oy=(0,Nd.promisify)(Fd.execFile),en=E("allure-generator"),so=process.platform==="win32";Fy=Dy()});function ai(){return[{category:"person",methods:[{name:"fullName",example:C.faker.person.fullName()},{name:"firstName",example:C.faker.person.firstName()},{name:"lastName",example:C.faker.person.lastName()},{name:"middleName",example:C.faker.person.middleName()},{name:"sex",example:C.faker.person.sex()},{name:"prefix",example:C.faker.person.prefix()},{name:"suffix",example:C.faker.person.suffix()},{name:"jobTitle",example:C.faker.person.jobTitle()},{name:"jobArea",example:C.faker.person.jobArea()},{name:"jobType",example:C.faker.person.jobType()},{name:"bio",example:C.faker.person.bio()}]},{category:"internet",methods:[{name:"email",example:C.faker.internet.email()},{name:"userName",example:C.faker.internet.username()},{name:"password",example:C.faker.internet.password()},{name:"url",example:C.faker.internet.url()},{name:"domainName",example:C.faker.internet.domainName()},{name:"domainWord",example:C.faker.internet.domainWord()},{name:"ip",example:C.faker.internet.ip()},{name:"ipv6",example:C.faker.internet.ipv6()},{name:"mac",example:C.faker.internet.mac()},{name:"userAgent",example:C.faker.internet.userAgent()},{name:"emoji",example:C.faker.internet.emoji()}]},{category:"phone",methods:[{name:"number",example:C.faker.phone.number()},{name:"imei",example:C.faker.phone.imei()}]},{category:"location",methods:[{name:"streetAddress",example:C.faker.location.streetAddress()},{name:"street",example:C.faker.location.street()},{name:"city",example:C.faker.location.city()},{name:"state",example:C.faker.location.state()},{name:"zipCode",example:C.faker.location.zipCode()},{name:"country",example:C.faker.location.country()},{name:"countryCode",example:C.faker.location.countryCode()},{name:"county",example:C.faker.location.county()},{name:"latitude",example:String(C.faker.location.latitude())},{name:"longitude",example:String(C.faker.location.longitude())},{name:"timeZone",example:C.faker.location.timeZone()},{name:"buildingNumber",example:C.faker.location.buildingNumber()}]},{category:"company",methods:[{name:"name",example:C.faker.company.name()},{name:"catchPhrase",example:C.faker.company.catchPhrase()},{name:"buzzPhrase",example:C.faker.company.buzzPhrase()},{name:"buzzNoun",example:C.faker.company.buzzNoun()},{name:"buzzVerb",example:C.faker.company.buzzVerb()},{name:"buzzAdjective",example:C.faker.company.buzzAdjective()}]},{category:"finance",methods:[{name:"accountNumber",example:C.faker.finance.accountNumber()},{name:"accountName",example:C.faker.finance.accountName()},{name:"creditCardNumber",example:C.faker.finance.creditCardNumber()},{name:"creditCardCVV",example:C.faker.finance.creditCardCVV()},{name:"currencyCode",example:C.faker.finance.currencyCode()},{name:"currencyName",example:C.faker.finance.currencyName()},{name:"amount",example:C.faker.finance.amount()},{name:"iban",example:C.faker.finance.iban()},{name:"bic",example:C.faker.finance.bic()},{name:"bitcoinAddress",example:C.faker.finance.bitcoinAddress()},{name:"transactionType",example:C.faker.finance.transactionType()}]},{category:"date",methods:[{name:"past",example:C.faker.date.past().toISOString()},{name:"future",example:C.faker.date.future().toISOString()},{name:"recent",example:C.faker.date.recent().toISOString()},{name:"soon",example:C.faker.date.soon().toISOString()},{name:"birthdate",example:C.faker.date.birthdate().toISOString()},{name:"month",example:C.faker.date.month()},{name:"weekday",example:C.faker.date.weekday()}]},{category:"lorem",methods:[{name:"word",example:C.faker.lorem.word()},{name:"words",example:C.faker.lorem.words()},{name:"sentence",example:C.faker.lorem.sentence()},{name:"sentences",example:C.faker.lorem.sentences()},{name:"paragraph",example:C.faker.lorem.paragraph()},{name:"slug",example:C.faker.lorem.slug()},{name:"lines",example:C.faker.lorem.lines(1)}]},{category:"string",methods:[{name:"uuid",example:C.faker.string.uuid()},{name:"alphanumeric",example:C.faker.string.alphanumeric(10)},{name:"numeric",example:C.faker.string.numeric(6)},{name:"alpha",example:C.faker.string.alpha(8)},{name:"nanoid",example:C.faker.string.nanoid()},{name:"hexadecimal",example:C.faker.string.hexadecimal({length:8})},{name:"sample",example:C.faker.string.sample(12)}]},{category:"number",methods:[{name:"int",example:String(C.faker.number.int({max:9999}))},{name:"float",example:String(C.faker.number.float({max:100,fractionDigits:2}))}]},{category:"datatype",methods:[{name:"boolean",example:String(C.faker.datatype.boolean())}]},{category:"image",methods:[{name:"avatar",example:C.faker.image.avatar()},{name:"url",example:C.faker.image.url()}]},{category:"color",methods:[{name:"human",example:C.faker.color.human()},{name:"rgb",example:C.faker.color.rgb()},{name:"hex",example:C.faker.color.rgb({format:"hex"})}]},{category:"commerce",methods:[{name:"productName",example:C.faker.commerce.productName()},{name:"price",example:C.faker.commerce.price()},{name:"department",example:C.faker.commerce.department()},{name:"productDescription",example:C.faker.commerce.productDescription().slice(0,60)+"..."},{name:"isbn",example:C.faker.commerce.isbn()}]},{category:"vehicle",methods:[{name:"vehicle",example:C.faker.vehicle.vehicle()},{name:"manufacturer",example:C.faker.vehicle.manufacturer()},{name:"model",example:C.faker.vehicle.model()},{name:"vin",example:C.faker.vehicle.vin()},{name:"vrm",example:C.faker.vehicle.vrm()}]},{category:"system",methods:[{name:"fileName",example:C.faker.system.fileName()},{name:"mimeType",example:C.faker.system.mimeType()},{name:"fileExt",example:C.faker.system.fileExt()},{name:"filePath",example:C.faker.system.filePath()},{name:"semver",example:C.faker.system.semver()}]}]}function Ur(r,e){let t=C.faker[r],s=Ny[`${r}.${e}`]??e;if(!t||typeof t[s]!="function")return`[unknown: ${r}.${e}]`;let n=t[s]();return n instanceof Date?n.toISOString():String(n)}var C,Ny,no=b(()=>{"use strict";m();C=require("@faker-js/faker");Ny={"internet.userName":"username"}});function Hd(r){switch(r){case"FAKE_FIRST_NAME":return Ur("person","firstName");case"FAKE_LAST_NAME":return Ur("person","lastName");case"FAKE_AGE":return String(Math.floor(Math.random()*63)+18);case"FAKE_EMAIL":return Ur("internet","email");case"FAKE_PHONE":return Ur("phone","number");case"FAKE_PASSWORD":return Ur("internet","password")}let e=r.match(/^FAKE_NUMBER_(\d+)$/);if(e&&e[1]){let t=Math.max(1,parseInt(e[1],10)),s=t===1?0:Math.pow(10,t-1),n=Math.pow(10,t)-1;return String(Math.floor(Math.random()*(n-s+1))+s)}if(r.startsWith("FAKE_")){let t=r.slice(5),s=Ud[t];if(s)return Ur(s[0],s[1])}return null}var Ud,Vd=b(()=>{"use strict";m();no();Ud={};for(let r of ai())for(let e of r.methods){let t=`${r.category}_${e.name}`.toUpperCase();Ud[t]=[r.category,e.name]}});function Kt(r,e,t){let s=r.replace(/\{\{FILE:([^}]+)\}\}/g,(n,i)=>`fixtures/uploads/${i.trim().replace(/[^a-zA-Z0-9._-]+/g,"_")}`);return s=s.replace(new RegExp(My,"g"),(n,i)=>{if(i==="BASE_URL")return t;let a=Hd(i);return a!==null?a:e[i]??`{{${i}}}`}),s}var My,io=b(()=>{"use strict";m();Vd();My="\\{\\{([A-Z0-9_]+)\\}\\}"});async function wt(r,e,t,s="domcontentloaded",n){t&&(e.setDefaultTimeout(t),e.setDefaultNavigationTimeout(t));let i=t?ao.expect.configure({timeout:t}):ao.expect,a=n??{setVariable:()=>{},getVariable:()=>{}},c=new jy("page","expect","context",r)(e,i,a);c.catch(()=>{}),await c;let l=t?Math.min(t/2,1e4):1e4;try{await e.waitForLoadState(s,{timeout:l})}catch{}}var ao,jy,oi=b(()=>{"use strict";m();ao=require("@playwright/test"),jy=Object.getPrototypeOf(async function(){}).constructor});async function By(r,e){if(r===e)return null;let t=[],s=r;for(;s&&s!==e;){let n="iframe";try{let i=await s.frameElement();if(i){let a=await i.getAttribute("id").catch(()=>null),o=await i.getAttribute("name").catch(()=>null),c=await i.getAttribute("title").catch(()=>null);a?n=`#${a}`:o?n=`iframe[name='${o}']`:c&&(n=`iframe[title='${c}']`),await i.dispose().catch(()=>{})}}catch{}t.push(n),s=s.parentFrame()}return t.reverse().join("||")}async function tn(r,e,t){let s=r.url(),n=await r.title().catch(()=>""),i={maxElements:120,maxTextLen:80},a=await r.evaluate(Gd,i).catch(()=>[])??[],o=[],c=r.mainFrame();for(let d of r.frames())if(d!==c){if(o.length+a.length>=120)break;try{let p=await By(d,c);if(p===null)continue;let g=await d.evaluate(Gd,i).catch(()=>[])??[];for(let f of g)o.push(`${f} frame="${p}"`)}catch{}}let l=[...a,...o].slice(0,120).join(`
790
+ `),u=await r.evaluate(({maxLen:d})=>document.body?.innerHTML?.slice(0,d)??"",{maxLen:8e3}).catch(()=>"");return{url:s,title:n,interactiveElements:l,htmlSnapshot:u,previousSteps:e,variables:t}}var Gd,zd=b(()=>{"use strict";m();Gd=({maxElements:r,maxTextLen:e})=>{let t=["button",'[role="button"]',"a[href]",'input:not([type="hidden"])',"textarea","select",'[role="link"]','[role="tab"]','[role="checkbox"]','[role="radio"]','[role="menuitem"]','[role="option"]','[role="combobox"]','[role="listbox"]','[role="switch"]'];function s(l){let u=l.getAttribute("aria-labelledby");return u?u.split(/\s+/).map(d=>document.getElementById(d)?.textContent?.trim()??"").filter(Boolean).join(" "):""}function n(l){let u=l.getAttribute("id");if(u){let p=document.querySelector(`label[for="${u}"]`);if(p)return(p.textContent??"").trim().slice(0,60)}let d=l.closest("label");if(d){let p=d.cloneNode(!0);return p.querySelectorAll("input,textarea,select").forEach(g=>g.remove()),(p.textContent??"").trim().slice(0,60)}return""}function i(l){let u=window.getComputedStyle(l);if(u.display==="none"||u.visibility==="hidden"||u.opacity==="0")return!1;let d=l.getBoundingClientRect();return d.width>0&&d.height>0}function a(l){return l.getAttribute("data-testid")??l.getAttribute("data-cy")??l.getAttribute("data-qa")??l.getAttribute("data-test")??""}let o=new Set,c=[];for(let l of t){if(c.length>=r)break;for(let u of Array.from(document.querySelectorAll(l))){if(c.length>=r)break;if(o.has(u)||!i(u))continue;o.add(u);let d=u.tagName.toLowerCase(),p=u.getAttribute("role")??d,g=(u.textContent??"").trim().replace(/\s+/g," ").slice(0,e),f=u.getAttribute("aria-label")??"",h=s(u),S=n(u),I=a(u),v=u.getAttribute("name")??"",k=u.getAttribute("id")??"",T=u.getAttribute("placeholder")??"",P=u.getAttribute("type")??"",j=d==="a"?(u.getAttribute("href")??"").slice(0,60):"",J=d==="select"||d==="input"?u.value?.slice(0,40):"",M=[`<${d}>`];I&&M.push(`data-testid="${I}"`),f&&M.push(`aria-label="${f}"`),h&&M.push(`aria-labelledby="${h}"`),S&&M.push(`label="${S}"`),T&&M.push(`placeholder="${T}"`),g&&M.push(`text="${g}"`),P&&M.push(`type="${P}"`),v&&M.push(`name="${v}"`),k&&M.push(`id="${k}"`),j&&M.push(`href="${j}"`),J&&M.push(`value="${J}"`),p!==d&&M.push(`role="${p}"`),c.push(M.join(" "))}}return c}});function Uy(r){return r.testId?`page.getByTestId('${r.testId}')`:r.ariaLabel?`page.getByRole('${r.role||r.tag}', { name: '${r.ariaLabel}' })`:r.labelText&&(r.tag==="input"||r.tag==="textarea"||r.tag==="select")?`page.getByLabel('${r.labelText}')`:r.placeholder?`page.getByPlaceholder('${r.placeholder}')`:r.tag==="a"&&r.text?`page.getByRole('link', { name: '${r.text}' })`:(r.tag==="button"||r.role==="button")&&r.text?`page.getByRole('button', { name: '${r.text}' })`:r.role&&r.text?`page.getByRole('${r.role}', { name: '${r.text}' })`:r.text?`page.getByText('${r.text}')`:r.id?`page.locator('#${r.id}')`:r.name?`page.locator('[name="${r.name}"]')`:r.inputType?`page.locator('${r.tag}[type="${r.inputType}"]')`:`page.locator('${r.tag}')`}async function co(r){let t=(await r.evaluate(()=>{let i=["button",'[role="button"]',"a[href]",'input:not([type="hidden"])',"textarea","select",'[role="link"]','[role="tab"]','[role="checkbox"]','[role="radio"]','[role="menuitem"]','[role="option"]','[role="combobox"]','[role="switch"]'];function a(p){let g=p.getAttribute("aria-labelledby");return g?g.split(/\s+/).map(f=>document.getElementById(f)?.textContent?.trim()??"").filter(Boolean).join(" "):""}function o(p){let g=p.getAttribute("id");if(g){let h=document.querySelector(`label[for="${g}"]`);if(h)return(h.textContent??"").trim().slice(0,60)}let f=p.closest("label");if(f){let h=f.cloneNode(!0);return h.querySelectorAll("input,textarea,select").forEach(S=>S.remove()),(h.textContent??"").trim().slice(0,60)}return""}let c=new Set,l=[],u=window.innerWidth,d=window.innerHeight;for(let p of i){for(let g of Array.from(document.querySelectorAll(p))){if(c.has(g))continue;let f=window.getComputedStyle(g);if(f.display==="none"||f.visibility==="hidden"||f.opacity==="0")continue;let h=g.getBoundingClientRect();if(h.width<=0||h.height<=0||h.right<0||h.bottom<0||h.left>u||h.top>d)continue;c.add(g);let S=g.tagName.toLowerCase(),I=g.getAttribute("role")??"",v=(g.textContent??"").trim().replace(/\s+/g," ").slice(0,60),k=g.getAttribute("aria-label")??"",T=a(g),P=o(g),j=g.getAttribute("data-testid")??g.getAttribute("data-cy")??g.getAttribute("data-qa")??g.getAttribute("data-test")??"",J=g.getAttribute("placeholder")??"",M=S==="a"?g.getAttribute("href")??"":"",Ee=g.getAttribute("id")??"",lt=g.getAttribute("name")??"",Ve=g.getAttribute("type")??"";if(l.push({tag:S,role:I,text:v,ariaLabel:k,ariaLabelledBy:T,labelText:P,testId:j,placeholder:J,href:M,id:Ee,name:lt,inputType:Ve,x:Math.round(h.left),y:Math.round(h.top),width:Math.round(h.width),height:Math.round(h.height)}),l.length>=80)break}if(l.length>=80)break}return l})).map((i,a)=>{let o=Uy(i),c=i.ariaLabel||i.labelText||i.text||i.placeholder||i.testId||i.href||`${i.tag}[${a}]`,l=`[${a+1}] ${i.tag}${i.role?`(${i.role})`:""} "${c.slice(0,50)}" \u2192 ${o}`;return{index:a+1,tag:i.tag,role:i.role||i.tag,selector:o,description:l,x:i.x,y:i.y,width:i.width,height:i.height}});await r.evaluate(({els:i,overlayId:a})=>{let o=document.getElementById(a);o&&o.remove();let c="http://www.w3.org/2000/svg",l=document.createElementNS(c,"svg");l.id=a,l.setAttribute("xmlns",c),l.style.cssText=["position:fixed","top:0","left:0","width:100%","height:100%","pointer-events:none","z-index:2147483647"].join(";");let u=(d,p)=>{let g=d.toLowerCase(),f=p.toLowerCase();return g==="button"||f==="button"?"#FF6B6B":g==="a"||f==="link"?"#96CEB4":g==="input"||g==="textarea"?"#4ECDC4":g==="select"||f==="combobox"?"#45B7D1":f==="menuitem"||f==="tab"?"#DDA0DD":"#FFE66D"};for(let d of i){let p=u(d.tag,d.role),g=document.createElementNS(c,"rect");g.setAttribute("x",String(d.x+1)),g.setAttribute("y",String(d.y+1)),g.setAttribute("width",String(Math.max(d.width-2,4))),g.setAttribute("height",String(Math.max(d.height-2,4))),g.setAttribute("fill","none"),g.setAttribute("stroke",p),g.setAttribute("stroke-width","2"),g.setAttribute("stroke-dasharray","4,3"),l.appendChild(g);let f=d.index>=10?22:16,h=16,S=d.index<d.x-f?d.x-f:d.x,I=d.y<h?d.y:d.y-h+2,v=document.createElementNS(c,"rect");v.setAttribute("x",String(S)),v.setAttribute("y",String(I)),v.setAttribute("width",String(f)),v.setAttribute("height",String(h)),v.setAttribute("fill",p),v.setAttribute("rx","3"),l.appendChild(v);let k=document.createElementNS(c,"text");k.setAttribute("x",String(S+f/2)),k.setAttribute("y",String(I+12)),k.setAttribute("fill","#000"),k.setAttribute("font-size","11"),k.setAttribute("font-family","monospace"),k.setAttribute("font-weight","bold"),k.setAttribute("text-anchor","middle"),k.textContent=String(d.index),l.appendChild(k)}document.documentElement.appendChild(l)},{els:t.map(i=>({index:i.index,x:i.x,y:i.y,width:i.width,height:i.height,tag:i.tag,role:i.role})),overlayId:oo});let s=await r.screenshot({type:"png",fullPage:!1});await r.evaluate(i=>document.getElementById(i)?.remove(),oo);let n=t.map(i=>i.description).join(`
791
+ `);return{screenshot:s,elements:t,elementMap:n}}async function lo(r){await r.evaluate(e=>document.getElementById(e)?.remove(),oo).catch(()=>{})}var oo,qd=b(()=>{"use strict";m();oo="__testassuremind_som__"});function Xd(r){let e=r.replace(/^```[\w]*\n?/gm,"").replace(/^```\s*$/gm,"").trim();return e.includes("---")?e.split("---").map(t=>t.trim()).filter(t=>t.length>0):e.split(`
792
+ `).map(t=>t.trim()).filter(t=>t.length>0&&t.startsWith("await"))}var $e,ci,Kd=b(()=>{"use strict";m();zd();qd();At();io();N();oi();Ar();$e=E("self-healing"),ci=class{constructor(e,t,s,n=!1){this.provider=e;this.maxLevel=t;this.ragManager=s;this.healAssertionLocators=n}async heal(e,t,s,n,i,a){if(t.failureKind==="assertion")return $e.info({stepId:e.id},"Assertion failure \u2014 skipping all healing levels (possible application bug)"),null;if(t.failureKind==="assertion-locator-missing"){if(!this.healAssertionLocators)return $e.info({stepId:e.id},"Assertion-locator heal disabled \u2014 skipping"),null;try{let c=await this.level2Regenerate(e,t,s,n,i,a);if(c!==null)return $e.info({stepId:e.id},"Assertion locator healed (matcher preserved)"),{...c,strategy:"regenerate"}}catch(c){$e.debug({err:c,stepId:e.id},"Assertion-locator heal attempt threw")}return null}let o=e.stepType==="api"||tt(e.instruction)==="api";for(let c=1;c<=this.maxLevel;c++){if(o&&(c===3||c===4)){$e.debug({stepId:e.id,level:c},`Skipping DOM-specific level ${c} for API step`);continue}$e.debug({stepId:e.id,level:c,isApi:o},`Attempting heal level ${c}`);try{let l=await this.tryLevel(c,e,t,s,n,i,a,o);if(l!==null)return $e.info({stepId:e.id,level:c,strategy:l.strategy},"Healing succeeded"),l}catch(l){$e.debug({err:l,level:c,stepId:e.id},`Level ${c} healing attempt threw`)}}return $e.warn({stepId:e.id,maxLevel:this.maxLevel},"All healing levels exhausted"),null}async tryLevel(e,t,s,n,i,a,o,c=!1){switch(e){case 1:return this.level1Retry(s,i);case 2:return c?this.level2ApiRegenerate(t,s,i,a,o):this.level2Regenerate(t,s,n,i,a,o);case 3:return this.level3MultiSelector(t,s,n,i,a,o);case 4:return this.level4Visual(t,i,a,o);case 5:return this.level5Decompose(t,s,n,i,a,o);case 6:return this.level6Manual(t,s);default:return null}}async level1Retry(e,t){return await t.waitForLoadState("networkidle",{timeout:5e3}).catch(()=>{}),await t.waitForTimeout(1e3),await wt(e.failedCode,t),{code:e.failedCode,level:1,strategy:"retry"}}async level2Regenerate(e,t,s,n,i,a){if(this.provider.supportsVision)try{let d=await co(n);$e.debug({stepId:e.id},"Level 2: using SoM vision healing");let p=await this.provider.analyzeWithSoM(d.screenshot,d.elementMap,e.instruction),g=Kt(De(p),i,a);return await wt(g,n),{code:g,level:2,strategy:"regenerate"}}catch(d){$e.debug({stepId:e.id,err:d},"SoM vision failed, falling back to text regeneration"),await lo(n)}let o=await tn(n,s,i),c="";if(this.ragManager)try{let d=this.ragManager.healingCorpus.retrieve(e.instruction,t.error,2);d.length>0&&(c=`
757
793
 
758
794
  Similar past fixes that worked:
759
- `+d.map((g,m)=>` ${m+1}. Error: ${g.error}
760
- Fix: ${g.healedCode}`).join(`
761
- `),Xe.debug({stepId:e.id,matches:d.length},"RAG healing corpus matches found"))}catch{}let l=await this.provider.healSelector(e.instruction+c,t.failedCode,t.error,o),u=Gt(Oe(l),i,a);return await ft(u,n),{code:u,level:2,strategy:"regenerate"}}async level2ApiRegenerate(e,t,s,n,i){let a=await Ws(s,[],n),o=`[API STEP] Fix this failing API test step. Only fix the REQUEST \u2014 the URL, headers, body, or HTTP method. NEVER change expect() assertions or expected status codes. Common fixable issues: wrong endpoint URL, missing auth header, incorrect request body schema. Keep all assertions exactly as they are. Step: ${e.instruction}`,c=await this.provider.healSelector(o,t.failedCode,t.error,a),l=Gt(Oe(c),n,i);return await ft(l,s),{code:l,level:2,strategy:"regenerate"}}async level3MultiSelector(e,t,s,n,i,a){let o=await Ws(n,s,i),c=`Generate 5 different Playwright selector strategies (one per line, separated by "---") for this step: ${e.instruction}`,l=await this.provider.healSelector(c,t.failedCode,t.error,o),u=kd(l);for(let d of u)try{let g=Gt(Oe(d),i,a);return await ft(g,n),{code:g,level:3,strategy:"multi-selector"}}catch{}return null}async level4Visual(e,t,s,n){if(!this.provider.supportsVision)return Xe.debug({stepId:e.id},"Skipping SoM visual healing \u2014 provider lacks vision"),null;try{let i=await Za(t);Xe.debug({stepId:e.id,elementCount:i.elements.length},"Level 4: SoM screenshot captured");let a=await this.provider.analyzeWithSoM(i.screenshot,i.elementMap,e.instruction),o=Gt(Oe(a),s,n);return await ft(o,t),{code:o,level:4,strategy:"visual"}}catch(i){return await eo(t),Xe.debug({stepId:e.id,err:i},"Level 4 SoM failed"),null}}async level5Decompose(e,t,s,n,i,a){let o=await Ws(n,s,i),c='Break this failing step into 3-5 sequential micro-actions (separate each with "---"): '+e.instruction,l=await this.provider.healSelector(c,t.failedCode,t.error,o),u=kd(l),d=[];for(let g of u){let m=Gt(Oe(g),i,a);await ft(m,n),d.push(m)}return{code:d.join(`
762
- `),level:5,strategy:"decompose"}}level6Manual(e,t){return Xe.warn({stepId:e.id,instruction:e.instruction,error:t.error},"Level 6: manual intervention required \u2014 marking step for human review"),null}}});function gy(r){for(let e of py)if(e.test(r))return"assertion";for(let e of my)if(e.test(r))return"infra";return"assertion"}async function ro(r,e,t){let s=Date.now(),n={...t.variables,...Object.fromEntries(t.sharedVariables)},i=r.generatedCode.includes("{{");i&&st.warn({stepId:r.id,variableKeys:Object.keys(n),variableCount:Object.keys(n).length},"Interpolating variables into step code");let a=Gt(r.generatedCode,n,t.config.baseUrl);if(i&&st.warn({stepId:r.id,before:r.generatedCode,after:a},"Variable interpolation result"),!a.trim()&&r.stepType!=="mock")return st.warn({stepId:r.id},"Step has no generated code \u2014 skipping"),$t(r,"skipped",a,Date.now()-s);if(r.stepType==="mock"&&r.mockUrl&&r.mockResponse)try{await e.route(r.mockUrl,f=>f.fulfill({status:r.mockStatus??200,contentType:"application/json",body:r.mockResponse??""}));let m=$t(r,"passed",a,Date.now()-s);return await e.unrouteAll().catch(()=>{}),m}catch(m){let f=m instanceof Error?m.message:String(m);return $t(r,"failed",a,Date.now()-s,f)}let o={setVariable:(m,f)=>{t.sharedVariables.set(m,f),st.info({stepId:r.id,key:m,value:f.slice(0,50)},"Runtime variable set")},getVariable:m=>t.sharedVariables.get(m)},c=r.retries??t.config.retries??0,l=r.timeout??t.config.timeout,u=r.stepType!=="api"?e.url():"",d;for(let m=0;m<=c;m++)try{await fy(ft(a,e,l,t.config.pageLoad??"domcontentloaded",o),l);let f;if(r.stepType!=="api")try{let C=e.url();(u!==C||u==="about:blank"||u==="")&&C&&!C.startsWith("about:")&&(f=C)}catch{}let h;if(r.runAudit&&r.stepType!=="api")try{h=f??(e.url()||void 0)}catch{}if(t.ragManager&&a.trim())try{t.ragManager.codeCorpus.ingest(r.instruction,a,e.url())}catch{}if(t.config.screenshot==="on"){let C=await $d(e,t,r.id,"pass");return{...$t(r,"passed",a,Date.now()-s,void 0,C),navigatedToUrl:f,auditUrl:h}}return{...$t(r,"passed",a,Date.now()-s),navigatedToUrl:f,auditUrl:h}}catch(f){if(d=f,m<c){st.debug({stepId:r.id,attempt:m,stepRetries:c},"Step failed \u2014 retrying");continue}}let g=d;{let m=g instanceof Error?g.message:String(g);st.debug({stepId:r.id,error:m},"Step failed on first attempt");let f=r.runAudit&&r.stepType!=="api"?(()=>{try{return e.url()||void 0}catch{return}})():void 0,h;t.config.screenshot!=="off"&&(h=await $d(e,t,r.id,"fail"));let C=gy(m);if(C==="assertion")return st.info({stepId:r.id,error:m},"Assertion failure detected \u2014 NOT healing (possible application bug)"),{...$t(r,"failed",a,Date.now()-s,m,h),...f?{auditUrl:f}:{}};if(!t.config.healing.enabled)return{...$t(r,"failed",a,Date.now()-s,m,h),...f?{auditUrl:f}:{}};if(t.ragManager)try{t.ragManager.errorCatalog.record(m,e.url())}catch{}st.debug({stepId:r.id,failureKind:C},"Infrastructure failure \u2014 attempting to heal");let P={stepId:r.id,instruction:r.instruction,error:m,pageUrl:e.url(),failedCode:a,failureKind:C},v=t.budget.shouldHeal(P);if(!v.heal)return st.info({stepId:r.id,reason:v.reason},"Healing skipped"),{...$t(r,"failed",a,Date.now()-s,m,h),...f?{auditUrl:f}:{}};let k=new ti(t.provider,t.config.healing.maxLevel,t.ragManager);try{let R=await k.heal(r,P,t.previousSteps,e,t.variables,t.config.baseUrl);if(R!==null){let I=R.code.trim()!==a.trim();if(I){if(t.budget.recordSpend(.005),t.ragManager)try{t.ragManager.healingCorpus.ingest({instruction:r.instruction,error:m,failedCode:a,healedCode:R.code,strategy:R.strategy,level:R.level,url:e.url()}),t.ragManager.errorCatalog.record(m,e.url(),R.code)}catch{}t.healingReporter.record({runId:t.runId,suiteId:t.suiteId,caseId:t.caseId,stepId:r.id,stepInstruction:r.instruction,failedCode:a,healedCode:R.code,error:m,strategy:R.strategy,level:R.level,pageUrl:e.url()})}return st.info({stepId:r.id,level:R.level,strategy:R.strategy,codeChanged:I},I?"Step passed after healing (code NOT saved \u2014 awaits human review)":"Step passed after smart retry (no code change)"),$t(r,"passed",a,Date.now()-s,void 0,h,I?R.code:void 0)}}catch(R){let I=R instanceof Error?R.message:String(R);st.warn({stepId:r.id,error:I},"Healing threw an error"),t.budget.recordHealFailure(r.id)}return{...$t(r,"failed",a,Date.now()-s,m,h),...f?{auditUrl:f}:{}}}}function $t(r,e,t,s,n,i,a){let o=r.stepType??Ze(r.instruction);return{stepId:r.id,instruction:r.instruction,status:e,code:t,duration:s,stepType:o,...n!==void 0&&{error:n},...i!==void 0&&{screenshotPath:i},...a!==void 0&&{healed:!0,healedCode:a}}}async function $d(r,e,t,s){try{await r.waitForLoadState("load",{timeout:5e3}).catch(()=>{});let n=to.default.join(e.rootDir,"results","screenshots"),i=`${e.runId}_${e.caseId}_${t}_${s}.png`,a=to.default.join(n,i);return await r.screenshot({path:a,fullPage:!0}),a}catch(n){st.debug({err:n},"Screenshot capture failed");return}}function fy(r,e){return Promise.race([r,new Promise((t,s)=>setTimeout(()=>s(new Error(`Step timed out after ${e}ms`)),e))])}var to,st,py,my,_d=w(()=>{"use strict";p();to=x(require("path"));Ja();ei();Ad();Ir();F();ei();st=E("executor"),py=[/expect\(.*\)\.(toBe|toEqual|toContain|toMatch|toHaveText|toHaveValue|toBeChecked|toBeVisible|toBeHidden|toBeEnabled|toBeDisabled|toHaveCount|toHaveAttribute|toHaveClass|toHaveCSS|toHaveURL|toHaveTitle)/i,/AssertionError/i,/AssertError/i,/Expected.*received/i,/Expected.*but got/i,/expect\..*Error/i,/expected\s+\d{3}.*received\s+\d{3}/i,/expected\s+status\s+.*\d{3}/i,/toBe\(\d{3}\).*Received:\s*\d{3}/i,/Expected:.*\d{3}.*Received:.*\d{3}/i,/Error:.*expect.*to(Be|Equal|Contain|Match|Have)/i],my=[/locator\.(click|fill|type|check|selectOption|press).*timeout/i,/waiting for (locator|selector)/i,/element is not (visible|attached|enabled|stable)/i,/page\.(goto|waitForSelector|waitForURL|waitForNavigation).*timeout/i,/net::ERR_/i,/ECONNREFUSED|ECONNRESET|ETIMEDOUT|ENOTFOUND/i,/Target closed|Target page, context or browser has been closed/i,/frame was detached/i,/navigation interrupted/i,/Timeout \d+ms exceeded/i,/Step timed out after \d+ms/i,/strict mode violation/i,/No element matches/i,/page\.request\.(get|post|put|delete|patch).*ECONNREFUSED/i,/socket hang up/i,/ERR_CONNECTION/i]});async function Od(r){await r.addInitScript(hy)}var hy,Ld=w(()=>{"use strict";p();hy=`(function () {
795
+ `+d.map((p,g)=>` ${g+1}. Error: ${p.error}
796
+ Fix: ${p.healedCode}`).join(`
797
+ `),$e.debug({stepId:e.id,matches:d.length},"RAG healing corpus matches found"))}catch{}let l=await this.provider.healSelector(e.instruction+c,t.failedCode,t.error,o),u=Kt(De(l),i,a);return await wt(u,n),{code:u,level:2,strategy:"regenerate"}}async level2ApiRegenerate(e,t,s,n,i){let a=await tn(s,[],n),o=`[API STEP] Fix this failing API test step. Only fix the REQUEST \u2014 the URL, headers, body, or HTTP method. NEVER change expect() assertions or expected status codes. Common fixable issues: wrong endpoint URL, missing auth header, incorrect request body schema. Keep all assertions exactly as they are. Step: ${e.instruction}`,c=await this.provider.healSelector(o,t.failedCode,t.error,a),l=Kt(De(c),n,i);return await wt(l,s),{code:l,level:2,strategy:"regenerate"}}async level3MultiSelector(e,t,s,n,i,a){let o=await tn(n,s,i),c=`Generate 5 different Playwright selector strategies (one per line, separated by "---") for this step: ${e.instruction}`,l=await this.provider.healSelector(c,t.failedCode,t.error,o),u=Xd(l);for(let d of u)try{let p=Kt(De(d),i,a);return await wt(p,n),{code:p,level:3,strategy:"multi-selector"}}catch{}return null}async level4Visual(e,t,s,n){if(!this.provider.supportsVision)return $e.debug({stepId:e.id},"Skipping SoM visual healing \u2014 provider lacks vision"),null;try{let i=await co(t);$e.debug({stepId:e.id,elementCount:i.elements.length},"Level 4: SoM screenshot captured");let a=await this.provider.analyzeWithSoM(i.screenshot,i.elementMap,e.instruction),o=Kt(De(a),s,n);return await wt(o,t),{code:o,level:4,strategy:"visual"}}catch(i){return await lo(t),$e.debug({stepId:e.id,err:i},"Level 4 SoM failed"),null}}async level5Decompose(e,t,s,n,i,a){let o=await tn(n,s,i),c='Break this failing step into 3-5 sequential micro-actions (separate each with "---"): '+e.instruction,l=await this.provider.healSelector(c,t.failedCode,t.error,o),u=Xd(l),d=[];for(let p of u){let g=Kt(De(p),i,a);await wt(g,n),d.push(g)}return{code:d.join(`
798
+ `),level:5,strategy:"decompose"}}level6Manual(e,t){return $e.warn({stepId:e.id,instruction:e.instruction,error:t.error},"Level 6: manual intervention required \u2014 marking step for human review"),null}}});function zy(r){for(let e of Hy)if(e.test(r)){for(let t of Gy)if(t.test(r))return"assertion-locator-missing";return"assertion"}for(let e of Vy)if(e.test(r))return"infra";return"assertion"}async function po(r,e,t){let s=Date.now(),n={...t.variables,...Object.fromEntries(t.sharedVariables)},i=r.generatedCode.includes("{{");i&&We.warn({stepId:r.id,variableKeys:Object.keys(n),variableCount:Object.keys(n).length},"Interpolating variables into step code");let a=Kt(r.generatedCode,n,t.config.baseUrl);if(i&&We.warn({stepId:r.id,before:r.generatedCode,after:a},"Variable interpolation result"),!a.trim()&&r.stepType!=="mock")return We.warn({stepId:r.id},"Step has no generated code \u2014 skipping"),bt(r,"skipped",a,Date.now()-s);if(r.stepType==="mock"&&r.mockUrl&&r.mockResponse)try{await e.route(r.mockUrl,f=>f.fulfill({status:r.mockStatus??200,contentType:"application/json",body:r.mockResponse??""}));let g=bt(r,"passed",a,Date.now()-s);return await e.unrouteAll().catch(()=>{}),g}catch(g){let f=g instanceof Error?g.message:String(g);return bt(r,"failed",a,Date.now()-s,f)}let o={setVariable:(g,f)=>{t.sharedVariables.set(g,f),We.info({stepId:r.id,key:g,value:f.slice(0,50)},"Runtime variable set")},getVariable:g=>t.sharedVariables.get(g)},c=r.retries??t.config.retries??0,l=r.timeout??t.config.timeout,u=r.stepType!=="api"?e.url():"",d;for(let g=0;g<=c;g++)try{await qy(wt(a,e,l,t.config.pageLoad??"domcontentloaded",o),l);let f;if(r.stepType!=="api")try{let S=e.url();(u!==S||u==="about:blank"||u==="")&&S&&!S.startsWith("about:")&&(f=S)}catch{}let h;if(r.runAudit&&r.stepType!=="api")try{h=f??(e.url()||void 0)}catch{}if(t.ragManager&&a.trim())try{t.ragManager.codeCorpus.ingest(r.instruction,a,e.url())}catch{}if(t.config.screenshot==="on"){let S=await Wd(e,t,r.id,"pass");return{...bt(r,"passed",a,Date.now()-s,void 0,S),navigatedToUrl:f,auditUrl:h}}return{...bt(r,"passed",a,Date.now()-s),navigatedToUrl:f,auditUrl:h}}catch(f){if(d=f,g<c){We.debug({stepId:r.id,attempt:g,stepRetries:c},"Step failed \u2014 retrying");continue}}let p=d;{let g=p instanceof Error?p.message:String(p);We.debug({stepId:r.id,error:g},"Step failed on first attempt");let f=r.runAudit&&r.stepType!=="api"?(()=>{try{return e.url()||void 0}catch{return}})():void 0,h;t.config.screenshot!=="off"&&(h=await Wd(e,t,r.id,"fail"));let S=zy(g);if(S==="assertion")return We.info({stepId:r.id,error:g},"Assertion failure detected \u2014 NOT healing (possible application bug)"),{...bt(r,"failed",a,Date.now()-s,g,h),...f?{auditUrl:f}:{}};if(S==="assertion-locator-missing"&&!t.config.healing.healAssertionLocators)return We.info({stepId:r.id,error:g},"Assertion locator not found \u2014 healing disabled (enable healing.healAssertionLocators to fix locators inside assertions)"),{...bt(r,"failed",a,Date.now()-s,g,h),...f?{auditUrl:f}:{}};if(!t.config.healing.enabled)return{...bt(r,"failed",a,Date.now()-s,g,h),...f?{auditUrl:f}:{}};if(t.ragManager)try{t.ragManager.errorCatalog.record(g,e.url())}catch{}We.debug({stepId:r.id,failureKind:S},"Infrastructure failure \u2014 attempting to heal");let I={stepId:r.id,instruction:r.instruction,error:g,pageUrl:e.url(),failedCode:a,failureKind:S},v=t.budget.shouldHeal(I);if(!v.heal)return We.info({stepId:r.id,reason:v.reason},"Healing skipped"),{...bt(r,"failed",a,Date.now()-s,g,h),...f?{auditUrl:f}:{}};let k=new ci(t.provider,t.config.healing.maxLevel,t.ragManager,t.config.healing.healAssertionLocators);try{let T=await k.heal(r,I,t.previousSteps,e,t.variables,t.config.baseUrl);if(T!==null){let P=T.code.trim()!==a.trim();if(P){if(t.budget.recordSpend(.005),t.ragManager)try{t.ragManager.healingCorpus.ingest({instruction:r.instruction,error:g,failedCode:a,healedCode:T.code,strategy:T.strategy,level:T.level,url:e.url()}),t.ragManager.errorCatalog.record(g,e.url(),T.code)}catch{}t.healingReporter.record({runId:t.runId,suiteId:t.suiteId,caseId:t.caseId,stepId:r.id,stepInstruction:r.instruction,failedCode:a,healedCode:T.code,error:g,strategy:T.strategy,level:T.level,pageUrl:e.url()})}return We.info({stepId:r.id,level:T.level,strategy:T.strategy,codeChanged:P},P?"Step passed after healing (code NOT saved \u2014 awaits human review)":"Step passed after smart retry (no code change)"),bt(r,"passed",a,Date.now()-s,void 0,h,P?T.code:void 0)}}catch(T){let P=T instanceof Error?T.message:String(T);We.warn({stepId:r.id,error:P},"Healing threw an error"),t.budget.recordHealFailure(r.id)}return{...bt(r,"failed",a,Date.now()-s,g,h),...f?{auditUrl:f}:{}}}}function bt(r,e,t,s,n,i,a){let o=r.stepType??tt(r.instruction);return{stepId:r.id,instruction:r.instruction,status:e,code:t,duration:s,stepType:o,...n!==void 0&&{error:n},...i!==void 0&&{screenshotPath:i},...a!==void 0&&{healed:!0,healedCode:a}}}async function Wd(r,e,t,s){try{await r.waitForLoadState("load",{timeout:5e3}).catch(()=>{});let n=uo.default.join(e.rootDir,"results","screenshots"),i=`${e.runId}_${e.caseId}_${t}_${s}.png`,a=uo.default.join(n,i);return await r.screenshot({path:a,fullPage:!0}),a}catch(n){We.debug({err:n},"Screenshot capture failed");return}}function qy(r,e){return Promise.race([r,new Promise((t,s)=>setTimeout(()=>s(new Error(`Step timed out after ${e}ms`)),e))])}var uo,We,Hy,Vy,Gy,Jd=b(()=>{"use strict";m();uo=x(require("path"));io();oi();Kd();Ar();N();oi();We=E("executor"),Hy=[/expect\(.*\)\.(toBe|toEqual|toContain|toMatch|toHaveText|toHaveValue|toBeChecked|toBeVisible|toBeHidden|toBeEnabled|toBeDisabled|toHaveCount|toHaveAttribute|toHaveClass|toHaveCSS|toHaveURL|toHaveTitle)/i,/AssertionError/i,/AssertError/i,/Expected.*received/i,/Expected.*but got/i,/expect\..*Error/i,/expected\s+\d{3}.*received\s+\d{3}/i,/expected\s+status\s+.*\d{3}/i,/toBe\(\d{3}\).*Received:\s*\d{3}/i,/Expected:.*\d{3}.*Received:.*\d{3}/i,/Error:.*expect.*to(Be|Equal|Contain|Match|Have)/i],Vy=[/locator\.(click|fill|type|check|selectOption|press).*timeout/i,/waiting for (locator|selector)/i,/element is not (visible|attached|enabled|stable)/i,/page\.(goto|waitForSelector|waitForURL|waitForNavigation).*timeout/i,/net::ERR_/i,/ECONNREFUSED|ECONNRESET|ETIMEDOUT|ENOTFOUND/i,/Target closed|Target page, context or browser has been closed/i,/frame was detached/i,/navigation interrupted/i,/Timeout \d+ms exceeded/i,/Step timed out after \d+ms/i,/strict mode violation/i,/No element matches/i,/page\.request\.(get|post|put|delete|patch).*ECONNREFUSED/i,/socket hang up/i,/ERR_CONNECTION/i],Gy=[/element\(s\) not found/i,/waiting for (locator|selector)/i,/no element(s)? (match|found)/i,/locator resolved to 0 elements/i,/frame.*not found|no frame/i]});async function Yd(r){await r.addInitScript(Xy)}var Xy,Qd=b(()=>{"use strict";m();Xy=`(function () {
763
799
  if (window.__tm_highlighter_installed__) return;
764
800
  window.__tm_highlighter_installed__ = true;
765
801
 
@@ -901,13 +937,13 @@ Similar past fixes that worked:
901
937
  }
902
938
  }, { capture: true, passive: true });
903
939
 
904
- })();`});async function Nd(r,e){switch(e.type){case"inline":return e.data??[];case"json-file":{if(!e.path)throw new Error("JSON data source requires a path");let t=so.default.resolve(r,e.path);if(!await Js.default.pathExists(t))throw new Error(`Data file not found: ${t}`);let s=await Js.default.readJson(t);if(!Array.isArray(s))throw new Error("JSON data file must contain an array of objects");return Dd.info({path:t,rows:s.length},"Loaded JSON data rows"),s.map(n=>Object.fromEntries(Object.entries(n).map(([i,a])=>[i,String(a)])))}case"csv-file":{if(!e.path)throw new Error("CSV data source requires a path");let t=so.default.resolve(r,e.path);if(!await Js.default.pathExists(t))throw new Error(`Data file not found: ${t}`);let n=(await Js.default.readFile(t,"utf8")).trim().split(`
905
- `).map(o=>o.trim()).filter(Boolean);if(n.length<2)return[];let i=n[0].split(",").map(o=>o.trim()),a=n.slice(1).map(o=>{let c=o.split(",").map(u=>u.trim()),l={};return i.forEach((u,d)=>{l[u]=c[d]??""}),l});return Dd.info({path:t,rows:a.length},"Loaded CSV data rows"),a}default:return[]}}var so,Js,Dd,Md=w(()=>{"use strict";p();so=x(require("path")),Js=x(require("fs-extra"));F();Dd=E("data-loader")});function Fd(r){return _t.default.join(r,".assuremind","visual-regression.json")}function jd(r,e){return _t.default.join(r,"results","visual-diffs",e,"summary.json")}function yy(r){return _t.default.join(r,"results","visual-diffs")}function Bd(r){return _t.default.join(r,"baselines")}async function Ys(r){let e=Fd(r);if(!await zt.default.pathExists(e))return{...no};try{let t=await de(e);return{...no,...t}}catch{return{...no}}}async function Ud(r,e){await K(Fd(r),e)}async function ri(r,e){await K(jd(r,e.runId),e)}async function si(r,e){return await de(jd(r,e))}async function Hd(r){let e=yy(r);if(!await zt.default.pathExists(e))return[];let t=await zt.default.readdir(e,{withFileTypes:!0}),s=[];for(let n of t){if(!n.isDirectory())continue;let i=_t.default.join(e,n.name,"summary.json");if(await zt.default.pathExists(i))try{let a=await de(i),o=a.diffs??[];s.push({runId:a.runId,timestamp:a.timestamp,totalDiffs:o.length,passed:o.filter(c=>c.status==="passed").length,failed:o.filter(c=>c.status==="failed").length,newCount:o.filter(c=>c.status==="new").length,approved:o.filter(c=>c.status==="approved").length,rejected:o.filter(c=>c.status==="rejected").length})}catch{}}return s.sort((n,i)=>new Date(i.timestamp).getTime()-new Date(n.timestamp).getTime()),s}async function Vd(r,e,t,s){let n=await si(r,e),i=n.diffs.find(a=>a.stepId===t);if(!i)throw new Error(`Diff entry not found for stepId "${t}" in run "${e}"`);return i.status=s,await ri(r,n),n}async function Gd(r,e){let t=await si(r,e);for(let s of t.diffs)(s.status==="failed"||s.status==="new")&&(s.status="approved");return await ri(r,t),t}async function zd(r){let e=Bd(r);if(!await zt.default.pathExists(e))return[];let t=[];async function s(n){let i=await zt.default.readdir(n,{withFileTypes:!0});for(let a of i){let o=_t.default.join(n,a.name);if(a.isDirectory())await s(o);else if(a.name.endsWith(".png")){let c=_t.default.relative(e,o).replace(/\\/g,"/"),l=c.split("/"),u=await zt.default.stat(o);t.push({path:o,relativePath:c,suite:l.length>1?l[0]:"",caseName:l.length>2?l[1]:"",fileName:a.name,sizeBytes:u.size})}}}return await s(e),t}async function qd(r,e){let t=Bd(r),s=_t.default.resolve(e);if(!s.startsWith(_t.default.resolve(t)))throw new Error("Path is outside baselines directory");await zt.default.remove(s)}var _t,zt,no,io=w(()=>{"use strict";p();_t=x(require("path")),zt=x(require("fs-extra"));Ve();no={enabled:!1,defaultThreshold:.5,fullPage:!0,maskSelectors:[]}});async function Xd(r){let e=await nt.default.readFile(r);return new Promise((t,s)=>{new ni.PNG().parse(e,(i,a)=>{i?s(i):t(a)})})}function wy(r){return ni.PNG.sync.write(r)}async function Wd(r,e,t,s={}){let{threshold:n=.1,diffThreshold:i=.5}=s;if(!await nt.default.pathExists(r))return await nt.default.ensureDir(as.default.dirname(r)),await nt.default.copy(e,r),{match:!0,diffPercentage:0,diffPixels:0,totalPixels:0,baselinePath:r,actualPath:e};let[o,c]=await Promise.all([Xd(r),Xd(e)]);if(o.width!==c.width||o.height!==c.height){await nt.default.ensureDir(as.default.dirname(t));let k=t.replace(/\.png$/,"-baseline.png"),R=t.replace(/\.png$/,"-actual.png");await Promise.all([nt.default.copy(r,k),nt.default.copy(e,R)]);let I=Math.max(o.width*o.height,c.width*c.height);return{match:!1,diffPercentage:100,diffPixels:I,totalPixels:I,baselinePath:r,actualPath:e,error:`Size mismatch: baseline ${o.width}x${o.height} vs actual ${c.width}x${c.height}`}}let{width:l,height:u}=o,d=new ni.PNG({width:l,height:u}),g=(0,Kd.default)(o.data,c.data,d.data,l,u,{threshold:n}),m=l*u,f=m>0?g/m*100:0,h=f<=i;await nt.default.ensureDir(as.default.dirname(t));let C=wy(d),P=t.replace(/\.png$/,"-baseline.png"),v=t.replace(/\.png$/,"-actual.png");return await Promise.all([nt.default.writeFile(t,C),nt.default.copy(r,P),nt.default.copy(e,v)]),{match:h,diffPercentage:Math.round(f*100)/100,diffPixels:g,totalPixels:m,diffImagePath:t,baselinePath:r,actualPath:e}}function Jd(r,e,t,s,n,i){return as.default.join(r,"baselines",e,t,`${s}-${n}-${i.width}x${i.height}.png`)}function Yd(r,e,t,s,n){return as.default.join(r,"results","visual-diffs",e,`${t}-${s}-${n.width}x${n.height}-diff.png`)}var Kd,ni,nt,as,Qd=w(()=>{"use strict";p();Kd=x(require("pixelmatch")),ni=require("pngjs"),nt=x(require("fs-extra")),as=x(require("path"))});var ep=xt((KE,Zd)=>{"use strict";p();Zd.exports=r=>{if(typeof r!="string")throw new TypeError("Expected a string");return r.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}});var rp=xt((JE,tp)=>{"use strict";p();var os=1e3,cs=os*60,ls=cs*60,Fr=ls*24,by=Fr*7,vy=Fr*365.25;tp.exports=function(r,e){e=e||{};var t=typeof r;if(t==="string"&&r.length>0)return xy(r);if(t==="number"&&isFinite(r))return e.long?Cy(r):Sy(r);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(r))};function xy(r){if(r=String(r),!(r.length>100)){var e=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(r);if(e){var t=parseFloat(e[1]),s=(e[2]||"ms").toLowerCase();switch(s){case"years":case"year":case"yrs":case"yr":case"y":return t*vy;case"weeks":case"week":case"w":return t*by;case"days":case"day":case"d":return t*Fr;case"hours":case"hour":case"hrs":case"hr":case"h":return t*ls;case"minutes":case"minute":case"mins":case"min":case"m":return t*cs;case"seconds":case"second":case"secs":case"sec":case"s":return t*os;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return t;default:return}}}}function Sy(r){var e=Math.abs(r);return e>=Fr?Math.round(r/Fr)+"d":e>=ls?Math.round(r/ls)+"h":e>=cs?Math.round(r/cs)+"m":e>=os?Math.round(r/os)+"s":r+"ms"}function Cy(r){var e=Math.abs(r);return e>=Fr?ii(r,e,Fr,"day"):e>=ls?ii(r,e,ls,"hour"):e>=cs?ii(r,e,cs,"minute"):e>=os?ii(r,e,os,"second"):r+" ms"}function ii(r,e,t,s){var n=e>=t*1.5;return Math.round(r/t)+" "+s+(n?"s":"")}});var ao=xt((QE,sp)=>{"use strict";p();function Ey(r){t.debug=t,t.default=t,t.coerce=c,t.disable=a,t.enable=n,t.enabled=o,t.humanize=rp(),t.destroy=l,Object.keys(r).forEach(u=>{t[u]=r[u]}),t.names=[],t.skips=[],t.formatters={};function e(u){let d=0;for(let g=0;g<u.length;g++)d=(d<<5)-d+u.charCodeAt(g),d|=0;return t.colors[Math.abs(d)%t.colors.length]}t.selectColor=e;function t(u){let d,g=null,m,f;function h(...C){if(!h.enabled)return;let P=h,v=Number(new Date),k=v-(d||v);P.diff=k,P.prev=d,P.curr=v,d=v,C[0]=t.coerce(C[0]),typeof C[0]!="string"&&C.unshift("%O");let R=0;C[0]=C[0].replace(/%([a-zA-Z%])/g,(B,Y)=>{if(B==="%%")return"%";R++;let j=t.formatters[Y];if(typeof j=="function"){let Ee=C[R];B=j.call(P,Ee),C.splice(R,1),R--}return B}),t.formatArgs.call(P,C),(P.log||t.log).apply(P,C)}return h.namespace=u,h.useColors=t.useColors(),h.color=t.selectColor(u),h.extend=s,h.destroy=t.destroy,Object.defineProperty(h,"enabled",{enumerable:!0,configurable:!1,get:()=>g!==null?g:(m!==t.namespaces&&(m=t.namespaces,f=t.enabled(u)),f),set:C=>{g=C}}),typeof t.init=="function"&&t.init(h),h}function s(u,d){let g=t(this.namespace+(typeof d>"u"?":":d)+u);return g.log=this.log,g}function n(u){t.save(u),t.namespaces=u,t.names=[],t.skips=[];let d=(typeof u=="string"?u:"").trim().replace(/\s+/g,",").split(",").filter(Boolean);for(let g of d)g[0]==="-"?t.skips.push(g.slice(1)):t.names.push(g)}function i(u,d){let g=0,m=0,f=-1,h=0;for(;g<u.length;)if(m<d.length&&(d[m]===u[g]||d[m]==="*"))d[m]==="*"?(f=m,h=g,m++):(g++,m++);else if(f!==-1)m=f+1,h++,g=h;else return!1;for(;m<d.length&&d[m]==="*";)m++;return m===d.length}function a(){let u=[...t.names,...t.skips.map(d=>"-"+d)].join(",");return t.enable(""),u}function o(u){for(let d of t.skips)if(i(u,d))return!1;for(let d of t.names)if(i(u,d))return!0;return!1}function c(u){return u instanceof Error?u.stack||u.message:u}function l(){console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")}return t.enable(t.load()),t}sp.exports=Ey});var np=xt((Be,ai)=>{"use strict";p();Be.formatArgs=Iy;Be.save=Ry;Be.load=Ty;Be.useColors=Py;Be.storage=ky();Be.destroy=(()=>{let r=!1;return()=>{r||(r=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."))}})();Be.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"];function Py(){if(typeof window<"u"&&window.process&&(window.process.type==="renderer"||window.process.__nwjs))return!0;if(typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))return!1;let r;return typeof document<"u"&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||typeof window<"u"&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||typeof navigator<"u"&&navigator.userAgent&&(r=navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/))&&parseInt(r[1],10)>=31||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)}function Iy(r){if(r[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+r[0]+(this.useColors?"%c ":" ")+"+"+ai.exports.humanize(this.diff),!this.useColors)return;let e="color: "+this.color;r.splice(1,0,e,"color: inherit");let t=0,s=0;r[0].replace(/%[a-zA-Z%]/g,n=>{n!=="%%"&&(t++,n==="%c"&&(s=t))}),r.splice(s,0,e)}Be.log=console.debug||console.log||(()=>{});function Ry(r){try{r?Be.storage.setItem("debug",r):Be.storage.removeItem("debug")}catch{}}function Ty(){let r;try{r=Be.storage.getItem("debug")||Be.storage.getItem("DEBUG")}catch{}return!r&&typeof process<"u"&&"env"in process&&(r=process.env.DEBUG),r}function ky(){try{return localStorage}catch{}}ai.exports=ao()(Be);var{formatters:Ay}=ai.exports;Ay.j=function(r){try{return JSON.stringify(r)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}}});var ap=xt((tP,ip)=>{"use strict";p();ip.exports=(r,e=process.argv)=>{let t=r.startsWith("-")?"":r.length===1?"-":"--",s=e.indexOf(t+r),n=e.indexOf("--");return s!==-1&&(n===-1||s<n)}});var lp=xt((sP,cp)=>{"use strict";p();var $y=require("os"),op=require("tty"),it=ap(),{env:xe}=process,fr;it("no-color")||it("no-colors")||it("color=false")||it("color=never")?fr=0:(it("color")||it("colors")||it("color=true")||it("color=always"))&&(fr=1);"FORCE_COLOR"in xe&&(xe.FORCE_COLOR==="true"?fr=1:xe.FORCE_COLOR==="false"?fr=0:fr=xe.FORCE_COLOR.length===0?1:Math.min(parseInt(xe.FORCE_COLOR,10),3));function oo(r){return r===0?!1:{level:r,hasBasic:!0,has256:r>=2,has16m:r>=3}}function co(r,e){if(fr===0)return 0;if(it("color=16m")||it("color=full")||it("color=truecolor"))return 3;if(it("color=256"))return 2;if(r&&!e&&fr===void 0)return 0;let t=fr||0;if(xe.TERM==="dumb")return t;if(process.platform==="win32"){let s=$y.release().split(".");return Number(s[0])>=10&&Number(s[2])>=10586?Number(s[2])>=14931?3:2:1}if("CI"in xe)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI","GITHUB_ACTIONS","BUILDKITE"].some(s=>s in xe)||xe.CI_NAME==="codeship"?1:t;if("TEAMCITY_VERSION"in xe)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(xe.TEAMCITY_VERSION)?1:0;if(xe.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in xe){let s=parseInt((xe.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(xe.TERM_PROGRAM){case"iTerm.app":return s>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(xe.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(xe.TERM)||"COLORTERM"in xe?1:t}function _y(r){let e=co(r,r&&r.isTTY);return oo(e)}cp.exports={supportsColor:_y,stdout:oo(co(!0,op.isatty(1))),stderr:oo(co(!0,op.isatty(2)))}});var dp=xt((Se,ci)=>{"use strict";p();var Oy=require("tty"),oi=require("util");Se.init=By;Se.log=My;Se.formatArgs=Dy;Se.save=Fy;Se.load=jy;Se.useColors=Ly;Se.destroy=oi.deprecate(()=>{},"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");Se.colors=[6,2,3,4,5,1];try{let r=lp();r&&(r.stderr||r).level>=2&&(Se.colors=[20,21,26,27,32,33,38,39,40,41,42,43,44,45,56,57,62,63,68,69,74,75,76,77,78,79,80,81,92,93,98,99,112,113,128,129,134,135,148,149,160,161,162,163,164,165,166,167,168,169,170,171,172,173,178,179,184,185,196,197,198,199,200,201,202,203,204,205,206,207,208,209,214,215,220,221])}catch{}Se.inspectOpts=Object.keys(process.env).filter(r=>/^debug_/i.test(r)).reduce((r,e)=>{let t=e.substring(6).toLowerCase().replace(/_([a-z])/g,(n,i)=>i.toUpperCase()),s=process.env[e];return/^(yes|on|true|enabled)$/i.test(s)?s=!0:/^(no|off|false|disabled)$/i.test(s)?s=!1:s==="null"?s=null:s=Number(s),r[t]=s,r},{});function Ly(){return"colors"in Se.inspectOpts?!!Se.inspectOpts.colors:Oy.isatty(process.stderr.fd)}function Dy(r){let{namespace:e,useColors:t}=this;if(t){let s=this.color,n="\x1B[3"+(s<8?s:"8;5;"+s),i=` ${n};1m${e} \x1B[0m`;r[0]=i+r[0].split(`
940
+ })();`});async function ep(r,e){switch(e.type){case"inline":return e.data??[];case"json-file":{if(!e.path)throw new Error("JSON data source requires a path");let t=mo.default.resolve(r,e.path);if(!await rn.default.pathExists(t))throw new Error(`Data file not found: ${t}`);let s=await rn.default.readJson(t);if(!Array.isArray(s))throw new Error("JSON data file must contain an array of objects");return Zd.info({path:t,rows:s.length},"Loaded JSON data rows"),s.map(n=>Object.fromEntries(Object.entries(n).map(([i,a])=>[i,String(a)])))}case"csv-file":{if(!e.path)throw new Error("CSV data source requires a path");let t=mo.default.resolve(r,e.path);if(!await rn.default.pathExists(t))throw new Error(`Data file not found: ${t}`);let n=(await rn.default.readFile(t,"utf8")).trim().split(`
941
+ `).map(o=>o.trim()).filter(Boolean);if(n.length<2)return[];let i=n[0].split(",").map(o=>o.trim()),a=n.slice(1).map(o=>{let c=o.split(",").map(u=>u.trim()),l={};return i.forEach((u,d)=>{l[u]=c[d]??""}),l});return Zd.info({path:t,rows:a.length},"Loaded CSV data rows"),a}default:return[]}}var mo,rn,Zd,tp=b(()=>{"use strict";m();mo=x(require("path")),rn=x(require("fs-extra"));N();Zd=E("data-loader")});function rp(r){return Ot.default.join(r,".assuremind","visual-regression.json")}function sp(r,e){return Ot.default.join(r,"results","visual-diffs",e,"summary.json")}function Ky(r){return Ot.default.join(r,"results","visual-diffs")}function np(r){return Ot.default.join(r,"baselines")}async function sn(r){let e=rp(r);if(!await Wt.default.pathExists(e))return{...go};try{let t=await ue(e);return{...go,...t}}catch{return{...go}}}async function ip(r,e){await K(rp(r),e)}async function li(r,e){await K(sp(r,e.runId),e)}async function ui(r,e){return await ue(sp(r,e))}async function ap(r){let e=Ky(r);if(!await Wt.default.pathExists(e))return[];let t=await Wt.default.readdir(e,{withFileTypes:!0}),s=[];for(let n of t){if(!n.isDirectory())continue;let i=Ot.default.join(e,n.name,"summary.json");if(await Wt.default.pathExists(i))try{let a=await ue(i),o=a.diffs??[];s.push({runId:a.runId,timestamp:a.timestamp,totalDiffs:o.length,passed:o.filter(c=>c.status==="passed").length,failed:o.filter(c=>c.status==="failed").length,newCount:o.filter(c=>c.status==="new").length,approved:o.filter(c=>c.status==="approved").length,rejected:o.filter(c=>c.status==="rejected").length})}catch{}}return s.sort((n,i)=>new Date(i.timestamp).getTime()-new Date(n.timestamp).getTime()),s}async function op(r,e,t,s){let n=await ui(r,e),i=n.diffs.find(a=>a.stepId===t);if(!i)throw new Error(`Diff entry not found for stepId "${t}" in run "${e}"`);return i.status=s,await li(r,n),n}async function cp(r,e){let t=await ui(r,e);for(let s of t.diffs)(s.status==="failed"||s.status==="new")&&(s.status="approved");return await li(r,t),t}async function lp(r){let e=np(r);if(!await Wt.default.pathExists(e))return[];let t=[];async function s(n){let i=await Wt.default.readdir(n,{withFileTypes:!0});for(let a of i){let o=Ot.default.join(n,a.name);if(a.isDirectory())await s(o);else if(a.name.endsWith(".png")){let c=Ot.default.relative(e,o).replace(/\\/g,"/"),l=c.split("/"),u=await Wt.default.stat(o);t.push({path:o,relativePath:c,suite:l.length>1?l[0]:"",caseName:l.length>2?l[1]:"",fileName:a.name,sizeBytes:u.size})}}}return await s(e),t}async function up(r,e){let t=np(r),s=Ot.default.resolve(e);if(!s.startsWith(Ot.default.resolve(t)))throw new Error("Path is outside baselines directory");await Wt.default.remove(s)}var Ot,Wt,go,fo=b(()=>{"use strict";m();Ot=x(require("path")),Wt=x(require("fs-extra"));ze();go={enabled:!1,defaultThreshold:.5,fullPage:!0,maskSelectors:[]}});async function dp(r){let e=await it.default.readFile(r);return new Promise((t,s)=>{new di.PNG().parse(e,(i,a)=>{i?s(i):t(a)})})}function Wy(r){return di.PNG.sync.write(r)}async function mp(r,e,t,s={}){let{threshold:n=.1,diffThreshold:i=.5}=s;if(!await it.default.pathExists(r))return await it.default.ensureDir(ds.default.dirname(r)),await it.default.copy(e,r),{match:!0,diffPercentage:0,diffPixels:0,totalPixels:0,baselinePath:r,actualPath:e};let[o,c]=await Promise.all([dp(r),dp(e)]);if(o.width!==c.width||o.height!==c.height){await it.default.ensureDir(ds.default.dirname(t));let k=t.replace(/\.png$/,"-baseline.png"),T=t.replace(/\.png$/,"-actual.png");await Promise.all([it.default.copy(r,k),it.default.copy(e,T)]);let P=Math.max(o.width*o.height,c.width*c.height);return{match:!1,diffPercentage:100,diffPixels:P,totalPixels:P,baselinePath:r,actualPath:e,error:`Size mismatch: baseline ${o.width}x${o.height} vs actual ${c.width}x${c.height}`}}let{width:l,height:u}=o,d=new di.PNG({width:l,height:u}),p=(0,pp.default)(o.data,c.data,d.data,l,u,{threshold:n}),g=l*u,f=g>0?p/g*100:0,h=f<=i;await it.default.ensureDir(ds.default.dirname(t));let S=Wy(d),I=t.replace(/\.png$/,"-baseline.png"),v=t.replace(/\.png$/,"-actual.png");return await Promise.all([it.default.writeFile(t,S),it.default.copy(r,I),it.default.copy(e,v)]),{match:h,diffPercentage:Math.round(f*100)/100,diffPixels:p,totalPixels:g,diffImagePath:t,baselinePath:r,actualPath:e}}function gp(r,e,t,s,n,i){return ds.default.join(r,"baselines",e,t,`${s}-${n}-${i.width}x${i.height}.png`)}function fp(r,e,t,s,n){return ds.default.join(r,"results","visual-diffs",e,`${t}-${s}-${n.width}x${n.height}-diff.png`)}var pp,di,it,ds,hp=b(()=>{"use strict";m();pp=x(require("pixelmatch")),di=require("pngjs"),it=x(require("fs-extra")),ds=x(require("path"))});var wp=Et((TI,yp)=>{"use strict";m();yp.exports=r=>{if(typeof r!="string")throw new TypeError("Expected a string");return r.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}});var vp=Et((AI,bp)=>{"use strict";m();var ps=1e3,ms=ps*60,gs=ms*60,Hr=gs*24,Jy=Hr*7,Yy=Hr*365.25;bp.exports=function(r,e){e=e||{};var t=typeof r;if(t==="string"&&r.length>0)return Qy(r);if(t==="number"&&isFinite(r))return e.long?ew(r):Zy(r);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(r))};function Qy(r){if(r=String(r),!(r.length>100)){var e=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(r);if(e){var t=parseFloat(e[1]),s=(e[2]||"ms").toLowerCase();switch(s){case"years":case"year":case"yrs":case"yr":case"y":return t*Yy;case"weeks":case"week":case"w":return t*Jy;case"days":case"day":case"d":return t*Hr;case"hours":case"hour":case"hrs":case"hr":case"h":return t*gs;case"minutes":case"minute":case"mins":case"min":case"m":return t*ms;case"seconds":case"second":case"secs":case"sec":case"s":return t*ps;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return t;default:return}}}}function Zy(r){var e=Math.abs(r);return e>=Hr?Math.round(r/Hr)+"d":e>=gs?Math.round(r/gs)+"h":e>=ms?Math.round(r/ms)+"m":e>=ps?Math.round(r/ps)+"s":r+"ms"}function ew(r){var e=Math.abs(r);return e>=Hr?pi(r,e,Hr,"day"):e>=gs?pi(r,e,gs,"hour"):e>=ms?pi(r,e,ms,"minute"):e>=ps?pi(r,e,ps,"second"):r+" ms"}function pi(r,e,t,s){var n=e>=t*1.5;return Math.round(r/t)+" "+s+(n?"s":"")}});var ho=Et((_I,xp)=>{"use strict";m();function tw(r){t.debug=t,t.default=t,t.coerce=c,t.disable=a,t.enable=n,t.enabled=o,t.humanize=vp(),t.destroy=l,Object.keys(r).forEach(u=>{t[u]=r[u]}),t.names=[],t.skips=[],t.formatters={};function e(u){let d=0;for(let p=0;p<u.length;p++)d=(d<<5)-d+u.charCodeAt(p),d|=0;return t.colors[Math.abs(d)%t.colors.length]}t.selectColor=e;function t(u){let d,p=null,g,f;function h(...S){if(!h.enabled)return;let I=h,v=Number(new Date),k=v-(d||v);I.diff=k,I.prev=d,I.curr=v,d=v,S[0]=t.coerce(S[0]),typeof S[0]!="string"&&S.unshift("%O");let T=0;S[0]=S[0].replace(/%([a-zA-Z%])/g,(j,J)=>{if(j==="%%")return"%";T++;let M=t.formatters[J];if(typeof M=="function"){let Ee=S[T];j=M.call(I,Ee),S.splice(T,1),T--}return j}),t.formatArgs.call(I,S),(I.log||t.log).apply(I,S)}return h.namespace=u,h.useColors=t.useColors(),h.color=t.selectColor(u),h.extend=s,h.destroy=t.destroy,Object.defineProperty(h,"enabled",{enumerable:!0,configurable:!1,get:()=>p!==null?p:(g!==t.namespaces&&(g=t.namespaces,f=t.enabled(u)),f),set:S=>{p=S}}),typeof t.init=="function"&&t.init(h),h}function s(u,d){let p=t(this.namespace+(typeof d>"u"?":":d)+u);return p.log=this.log,p}function n(u){t.save(u),t.namespaces=u,t.names=[],t.skips=[];let d=(typeof u=="string"?u:"").trim().replace(/\s+/g,",").split(",").filter(Boolean);for(let p of d)p[0]==="-"?t.skips.push(p.slice(1)):t.names.push(p)}function i(u,d){let p=0,g=0,f=-1,h=0;for(;p<u.length;)if(g<d.length&&(d[g]===u[p]||d[g]==="*"))d[g]==="*"?(f=g,h=p,g++):(p++,g++);else if(f!==-1)g=f+1,h++,p=h;else return!1;for(;g<d.length&&d[g]==="*";)g++;return g===d.length}function a(){let u=[...t.names,...t.skips.map(d=>"-"+d)].join(",");return t.enable(""),u}function o(u){for(let d of t.skips)if(i(u,d))return!1;for(let d of t.names)if(i(u,d))return!0;return!1}function c(u){return u instanceof Error?u.stack||u.message:u}function l(){console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")}return t.enable(t.load()),t}xp.exports=tw});var Sp=Et((He,mi)=>{"use strict";m();He.formatArgs=sw;He.save=nw;He.load=iw;He.useColors=rw;He.storage=aw();He.destroy=(()=>{let r=!1;return()=>{r||(r=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."))}})();He.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"];function rw(){if(typeof window<"u"&&window.process&&(window.process.type==="renderer"||window.process.__nwjs))return!0;if(typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))return!1;let r;return typeof document<"u"&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||typeof window<"u"&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||typeof navigator<"u"&&navigator.userAgent&&(r=navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/))&&parseInt(r[1],10)>=31||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)}function sw(r){if(r[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+r[0]+(this.useColors?"%c ":" ")+"+"+mi.exports.humanize(this.diff),!this.useColors)return;let e="color: "+this.color;r.splice(1,0,e,"color: inherit");let t=0,s=0;r[0].replace(/%[a-zA-Z%]/g,n=>{n!=="%%"&&(t++,n==="%c"&&(s=t))}),r.splice(s,0,e)}He.log=console.debug||console.log||(()=>{});function nw(r){try{r?He.storage.setItem("debug",r):He.storage.removeItem("debug")}catch{}}function iw(){let r;try{r=He.storage.getItem("debug")||He.storage.getItem("DEBUG")}catch{}return!r&&typeof process<"u"&&"env"in process&&(r=process.env.DEBUG),r}function aw(){try{return localStorage}catch{}}mi.exports=ho()(He);var{formatters:ow}=mi.exports;ow.j=function(r){try{return JSON.stringify(r)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}}});var Ep=Et((DI,Cp)=>{"use strict";m();Cp.exports=(r,e=process.argv)=>{let t=r.startsWith("-")?"":r.length===1?"-":"--",s=e.indexOf(t+r),n=e.indexOf("--");return s!==-1&&(n===-1||s<n)}});var Rp=Et((NI,Pp)=>{"use strict";m();var cw=require("os"),Ip=require("tty"),at=Ep(),{env:xe}=process,br;at("no-color")||at("no-colors")||at("color=false")||at("color=never")?br=0:(at("color")||at("colors")||at("color=true")||at("color=always"))&&(br=1);"FORCE_COLOR"in xe&&(xe.FORCE_COLOR==="true"?br=1:xe.FORCE_COLOR==="false"?br=0:br=xe.FORCE_COLOR.length===0?1:Math.min(parseInt(xe.FORCE_COLOR,10),3));function yo(r){return r===0?!1:{level:r,hasBasic:!0,has256:r>=2,has16m:r>=3}}function wo(r,e){if(br===0)return 0;if(at("color=16m")||at("color=full")||at("color=truecolor"))return 3;if(at("color=256"))return 2;if(r&&!e&&br===void 0)return 0;let t=br||0;if(xe.TERM==="dumb")return t;if(process.platform==="win32"){let s=cw.release().split(".");return Number(s[0])>=10&&Number(s[2])>=10586?Number(s[2])>=14931?3:2:1}if("CI"in xe)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI","GITHUB_ACTIONS","BUILDKITE"].some(s=>s in xe)||xe.CI_NAME==="codeship"?1:t;if("TEAMCITY_VERSION"in xe)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(xe.TEAMCITY_VERSION)?1:0;if(xe.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in xe){let s=parseInt((xe.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(xe.TERM_PROGRAM){case"iTerm.app":return s>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(xe.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(xe.TERM)||"COLORTERM"in xe?1:t}function lw(r){let e=wo(r,r&&r.isTTY);return yo(e)}Pp.exports={supportsColor:lw,stdout:yo(wo(!0,Ip.isatty(1))),stderr:yo(wo(!0,Ip.isatty(2)))}});var kp=Et((Se,fi)=>{"use strict";m();var uw=require("tty"),gi=require("util");Se.init=yw;Se.log=gw;Se.formatArgs=pw;Se.save=fw;Se.load=hw;Se.useColors=dw;Se.destroy=gi.deprecate(()=>{},"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");Se.colors=[6,2,3,4,5,1];try{let r=Rp();r&&(r.stderr||r).level>=2&&(Se.colors=[20,21,26,27,32,33,38,39,40,41,42,43,44,45,56,57,62,63,68,69,74,75,76,77,78,79,80,81,92,93,98,99,112,113,128,129,134,135,148,149,160,161,162,163,164,165,166,167,168,169,170,171,172,173,178,179,184,185,196,197,198,199,200,201,202,203,204,205,206,207,208,209,214,215,220,221])}catch{}Se.inspectOpts=Object.keys(process.env).filter(r=>/^debug_/i.test(r)).reduce((r,e)=>{let t=e.substring(6).toLowerCase().replace(/_([a-z])/g,(n,i)=>i.toUpperCase()),s=process.env[e];return/^(yes|on|true|enabled)$/i.test(s)?s=!0:/^(no|off|false|disabled)$/i.test(s)?s=!1:s==="null"?s=null:s=Number(s),r[t]=s,r},{});function dw(){return"colors"in Se.inspectOpts?!!Se.inspectOpts.colors:uw.isatty(process.stderr.fd)}function pw(r){let{namespace:e,useColors:t}=this;if(t){let s=this.color,n="\x1B[3"+(s<8?s:"8;5;"+s),i=` ${n};1m${e} \x1B[0m`;r[0]=i+r[0].split(`
906
942
  `).join(`
907
- `+i),r.push(n+"m+"+ci.exports.humanize(this.diff)+"\x1B[0m")}else r[0]=Ny()+e+" "+r[0]}function Ny(){return Se.inspectOpts.hideDate?"":new Date().toISOString()+" "}function My(...r){return process.stderr.write(oi.formatWithOptions(Se.inspectOpts,...r)+`
908
- `)}function Fy(r){r?process.env.DEBUG=r:delete process.env.DEBUG}function jy(){return process.env.DEBUG}function By(r){r.inspectOpts={};let e=Object.keys(Se.inspectOpts);for(let t=0;t<e.length;t++)r.inspectOpts[e[t]]=Se.inspectOpts[e[t]]}ci.exports=ao()(Se);var{formatters:up}=ci.exports;up.o=function(r){return this.inspectOpts.colors=this.useColors,oi.inspect(r,this.inspectOpts).split(`
909
- `).map(e=>e.trim()).join(" ")};up.O=function(r){return this.inspectOpts.colors=this.useColors,oi.inspect(r,this.inspectOpts)}});var pp=xt((aP,lo)=>{"use strict";p();typeof process>"u"||process.type==="renderer"||process.browser===!0||process.__nwjs?lo.exports=np():lo.exports=dp()});function li(r){if(!r)throw new Error("name must be non-empty")}function Uy(r,e){for(var t=0,s=r.length,n;t<s;)n=t+s>>>1,r[n].startTime<e.startTime?t=n+1:s=n;r.splice(t,0,e)}var Ce,hp,mp,uo,gp,fp,pi,mi,Qs,gi,ui,di,yp=w(()=>{"use strict";p();Ce=typeof performance<"u"&&performance;mp=process.hrtime,uo=function(){var r=mp();return r[0]*1e9+r[1]},gp=uo(),hp=function(){return(uo()-gp)/1e6};fp=Ce&&Ce.now?function(){return Ce.now()}:hp;Ce&&Ce.mark&&Ce.measure&&Ce.getEntriesByName&&Ce.getEntriesByType&&Ce.clearMarks&&Ce.clearMeasures&&Ce.clearResourceTimings?(pi=function(r){li(r),Ce.mark("start "+r)},mi=function(r){li(r),Ce.mark("end "+r);var e=Ce.measure(r,"start "+r,"end "+r);if(e)return e;var t=Ce.getEntriesByName(r);return t[t.length-1]},Qs=function(){return Ce.getEntriesByType("measure")},gi=function(){Ce.clearMarks(),Ce.clearMeasures()}):(ui={},di=[],pi=function(r){li(r);var e=fp();ui["$"+r]=e},mi=function(r){li(r);var e=fp(),t=ui["$"+r];if(!t)throw new Error("no known mark: "+r);var s={startTime:t,name:r,duration:e-t,entryType:"measure"};return Uy(di,s),s},Qs=function(){return di},gi=function(){ui={},di=[]})});var ps,vp,yr,hr,us,ds,po,wp,Vy,bp,ms,ce,mo=w(()=>{"use strict";p();ps=x(require("process"),1),vp=require("events"),yr=x(pp(),1);yp();hr=ps.default.platform==="win32",us=ps.default.browser,ds={red:us?"crimson":1,yellow:us?"gold":3,cyan:us?"darkturquoise":6,green:us?"forestgreen":2,blue:us?"steelblue":4,magenta:us?"palevioletred":5};yr.default.colors=[ds.cyan,ds.green,ds.blue,ds.magenta];po=class extends vp.EventEmitter{constructor(e){super(e)}issueStatus(e,t){(e==="status"||e==="statusEnd")&&this.emit(e,[e,...t])}issueWarning(e,t){this.emit("warning",[e,...t])}},wp={},Vy=25,ms=class r{static _logToStdErr(e,t){r.loggerfn(e)(...t)}static loggerfn(e){e=`LH:${e}`;let t=wp[e];return t||(t=(0,yr.default)(e),wp[e]=t,e.endsWith("error")?t.color=ds.red:e.endsWith("warn")&&(t.color=ds.yellow)),t}static setLevel(e){switch(bp=e,e){case"silent":yr.default.enable("-LH:*");break;case"verbose":yr.default.enable("LH:*");break;case"warn":yr.default.enable("-LH:*, LH:*:warn, LH:*:error");break;case"error":yr.default.enable("-LH:*, LH:*:error");break;default:yr.default.enable("LH:*, -LH:*:verbose")}}static formatProtocol(e,t,s){let n=!ps.default||ps.default.browser?1/0:ps.default.stdout.columns,i=t.method||"?????",a=n-i.length-e.length-Vy,o=t.params&&i!=="IO.read"?JSON.stringify(t.params).substr(0,a):"";r._logToStdErr(`${e}:${s||""}`,[i,o])}static isVerbose(){return bp==="verbose"}static time({msg:e,id:t,args:s=[]},n="log"){pi(t),r[n]("status",e,...s)}static timeEnd({msg:e,id:t,args:s=[]},n="verbose"){r[n]("statusEnd",e,...s),mi(t)}static log(e,...t){return r.events.issueStatus(e,t),r._logToStdErr(e,t)}static warn(e,...t){return r.events.issueWarning(e,t),r._logToStdErr(`${e}:warn`,t)}static error(e,...t){return r._logToStdErr(`${e}:error`,t)}static verbose(e,...t){return r.events.issueStatus(e,t),r._logToStdErr(`${e}:verbose`,t)}static greenify(e){return`${r.green}${e}${r.reset}`}static redify(e){return`${r.red}${e}${r.reset}`}static get green(){return"\x1B[32m"}static get red(){return"\x1B[31m"}static get yellow(){return"\x1B[33m"}static get purple(){return"\x1B[95m"}static get reset(){return"\x1B[0m"}static get bold(){return"\x1B[1m"}static get dim(){return"\x1B[2m"}static get tick(){return hr?"\u221A":"\u2713"}static get cross(){return hr?"\xD7":"\u2718"}static get whiteSmallSquare(){return hr?"\u0387":"\u25AB"}static get heavyHorizontal(){return hr?"\u2500":"\u2501"}static get heavyVertical(){return hr?"\u2502 ":"\u2503 "}static get heavyUpAndRight(){return hr?"\u2514":"\u2517"}static get heavyVerticalAndRight(){return hr?"\u251C":"\u2523"}static get heavyDownAndHorizontal(){return hr?"\u252C":"\u2533"}static get doubleLightHorizontal(){return"\u2500\u2500"}};ms.events=new po;ms.takeTimeEntries=()=>{let r=Qs();return gi(),r};ms.getTimeEntries=()=>Qs();ce=ms});var Cp=xt((dP,Sp)=>{"use strict";p();var xp=require("fs"),go;function Gy(){try{return xp.statSync("/.dockerenv"),!0}catch{return!1}}function zy(){try{return xp.readFileSync("/proc/self/cgroup","utf8").includes("docker")}catch{return!1}}Sp.exports=()=>(go===void 0&&(go=Gy()||zy()),go)});var Ip=xt((mP,fo)=>{"use strict";p();var qy=require("os"),Xy=require("fs"),Ep=Cp(),Pp=()=>{if(process.platform!=="linux")return!1;if(qy.release().toLowerCase().includes("microsoft"))return!Ep();try{return Xy.readFileSync("/proc/version","utf8").toLowerCase().includes("microsoft")?!Ep():!1}catch{return!1}};process.env.__IS_WSL_TEST__?fo.exports=Pp:fo.exports=Pp()});function ht(r,e){return typeof r>"u"?e:r}async function Ap(r){return new Promise(e=>setTimeout(e,r))}function Ot(){return kp.default?"wsl":process.platform}function $p(){switch(Ot()){case"darwin":case"linux":return Jy();case"wsl":process.env.TEMP=ho(`${process.env.PATH}`);case"win32":return Yy();default:throw new Zs}}function Ky(r=""){let e=/\/mnt\/([a-z])\//.exec(r);if(!e)return r;let t=e[1];return r.replace(`/mnt/${t}/`,`${t.toUpperCase()}:\\`).replace(/\//g,"\\")}function _p(r=""){if(/[a-z]:\\/iu.test(r))return r;try{return yi.default.execFileSync("wslpath",["-w",r]).toString().trim()}catch{return Ky(r)}}function wi(r,e){try{return yi.default.execFileSync("wslpath",["-u",r]).toString().trim()}catch{return e}}function Wy(r){let t=/\/mnt\/([a-z])\/Users\/([^\/:]+)\/AppData\//.exec(r)||[];return`/mnt/${t[1]}/Users/${t[2]}/AppData/Local`}function ho(r){let t=/\/([a-z])\/Users\/([^\/:]+)\/AppData\//.exec(r)||[];return wi(`${t[1]}:\\Users\\${t[2]}\\AppData\\Local`,Wy(r))}function Jy(){return yi.default.execSync("mktemp -d -t lighthouse.XXXXXXX").toString().trim()}function Yy(){let r=process.env.TEMP||process.env.TMP||(process.env.SystemRoot||process.env.windir)+"\\temp",e=Math.floor(Math.random()*9e7+1e7),t=(0,Rp.join)(r,"lighthouse."+e);return(0,Tp.mkdirSync)(t,{recursive:!0}),t}var Rp,yi,Tp,kp,gs,fi,hi,Zs,en,yo=w(()=>{"use strict";p();Rp=require("path"),yi=x(require("child_process"),1),Tp=require("fs"),kp=x(Ip(),1);gs=class extends Error{constructor(e="Unexpected error",t){return super(),this.message=e,this.code=t,this.stack=new Error().stack,this}},fi=class extends gs{constructor(){super(...arguments),this.message="The CHROME_PATH environment variable must be set to a Chrome/Chromium executable no older than Chrome stable.",this.code="ERR_LAUNCHER_PATH_NOT_SET"}},hi=class extends gs{constructor(){super(...arguments),this.message="userDataDir must be false or a path.",this.code="ERR_LAUNCHER_INVALID_USER_DATA_DIRECTORY"}},Zs=class extends gs{constructor(){super(...arguments),this.message=`Platform ${Ot()} is not supported.`,this.code="ERR_LAUNCHER_UNSUPPORTED_PLATFORM"}},en=class extends gs{constructor(){super(...arguments),this.message="No Chrome installations found.",this.code="ERR_LAUNCHER_NOT_INSTALLED"}}});var bi={};Q(bi,{darwin:()=>Lp,darwinFast:()=>vo,linux:()=>Qy,win32:()=>Dp,wsl:()=>Zy});function vo(){let r=[process.env.CHROME_PATH,process.env.LIGHTHOUSE_CHROMIUM_PATH,"/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary","/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"];for(let e of r)if(e&&wr(e))return e;return Lp()[0]}function Lp(){let r=["/Contents/MacOS/Google Chrome Canary","/Contents/MacOS/Google Chrome"],e="/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister",t=[],s=xo();s&&t.push(s),(0,hs.execSync)(`${e} -dump | grep -i 'google chrome\\( canary\\)\\?\\.app' | awk '{$1=""; print $0}'`).toString().split(bo).forEach(a=>{r.forEach(o=>{let c=at.default.join(a.substring(0,a.indexOf(".app")+4).trim(),o);wr(c)&&t.indexOf(c)===-1&&t.push(c)})});let n=(0,fs.default)(process.env.HOME||(0,wo.homedir)()),i=[{regex:new RegExp(`^${n}/Applications/.*Chrome\\.app`),weight:50},{regex:new RegExp(`^${n}/Applications/.*Chrome Canary\\.app`),weight:51},{regex:/^\/Applications\/.*Chrome.app/,weight:100},{regex:/^\/Applications\/.*Chrome Canary.app/,weight:101},{regex:/^\/Volumes\/.*Chrome.app/,weight:-2},{regex:/^\/Volumes\/.*Chrome Canary.app/,weight:-1}];return process.env.LIGHTHOUSE_CHROMIUM_PATH&&i.unshift({regex:new RegExp((0,fs.default)(process.env.LIGHTHOUSE_CHROMIUM_PATH)),weight:150}),process.env.CHROME_PATH&&i.unshift({regex:new RegExp((0,fs.default)(process.env.CHROME_PATH)),weight:151}),Np(t,i)}function xo(){if(wr(process.env.CHROME_PATH))return process.env.CHROME_PATH;if(wr(process.env.LIGHTHOUSE_CHROMIUM_PATH))return ce.warn("ChromeLauncher","LIGHTHOUSE_CHROMIUM_PATH is deprecated, use CHROME_PATH env variable instead."),process.env.LIGHTHOUSE_CHROMIUM_PATH}function Qy(){let r=[],e=xo();if(e&&r.push(e),[at.default.join((0,wo.homedir)(),".local/share/applications/"),"/usr/share/applications/"].forEach(i=>{r=r.concat(tw(i))}),["google-chrome-stable","google-chrome","chromium-browser","chromium"].forEach(i=>{try{let a=(0,hs.execFileSync)("which",[i],{stdio:"pipe"}).toString().split(bo)[0];wr(a)&&r.push(a)}catch{}}),!r.length)throw new fi;let n=[{regex:/chrome-wrapper$/,weight:51},{regex:/google-chrome-stable$/,weight:50},{regex:/google-chrome$/,weight:49},{regex:/chromium-browser$/,weight:48},{regex:/chromium$/,weight:47}];return process.env.LIGHTHOUSE_CHROMIUM_PATH&&n.unshift({regex:new RegExp((0,fs.default)(process.env.LIGHTHOUSE_CHROMIUM_PATH)),weight:100}),process.env.CHROME_PATH&&n.unshift({regex:new RegExp((0,fs.default)(process.env.CHROME_PATH)),weight:101}),Np(ew(r.filter(Boolean)),n)}function Zy(){return process.env.LOCALAPPDATA=ho(`${process.env.PATH}`),process.env.PROGRAMFILES=wi("C:/Program Files","/mnt/c/Program Files"),process.env["PROGRAMFILES(X86)"]=wi("C:/Program Files (x86)","/mnt/c/Program Files (x86)"),Dp()}function Dp(){let r=[],e=[`${at.default.sep}Google${at.default.sep}Chrome SxS${at.default.sep}Application${at.default.sep}chrome.exe`,`${at.default.sep}Google${at.default.sep}Chrome${at.default.sep}Application${at.default.sep}chrome.exe`],t=[process.env.LOCALAPPDATA,process.env.PROGRAMFILES,process.env["PROGRAMFILES(X86)"]].filter(Boolean),s=xo();return s&&r.push(s),t.forEach(n=>e.forEach(i=>{let a=at.default.join(n,i);wr(a)&&r.push(a)})),r}function Np(r,e){return r.map(s=>{for(let n of e)if(n.regex.test(s))return{path:s,weight:n.weight};return{path:s,weight:10}}).sort((s,n)=>n.weight-s.weight).map(s=>s.path)}function wr(r){if(!r)return!1;try{return Op.default.accessSync(r),!0}catch{return!1}}function ew(r){return Array.from(new Set(r))}function tw(r){let e=/(^[^ ]+).*/,t="^Exec=/.*/(google-chrome|chrome|chromium)-.*",s=[];if(wr(r)){let n;try{n=(0,hs.execSync)(`grep -ER "${t}" ${r} | awk -F '=' '{print $2}'`,{stdio:"pipe"})}catch{n=(0,hs.execSync)(`grep -Er "${t}" ${r} | awk -F '=' '{print $2}'`,{stdio:"pipe"})}n=n.toString().split(bo).map(i=>i.replace(e,"$1")),n.forEach(i=>wr(i)&&s.push(i))}return s}var Op,at,wo,hs,fs,bo,Mp=w(()=>{"use strict";p();Op=x(require("fs"),1),at=x(require("path"),1),wo=require("os"),hs=require("child_process"),fs=x(ep(),1);mo();yo();bo=/\r?\n/});function jp(){return new Promise((r,e)=>{let t=(0,Fp.createServer)();t.listen(0),t.once("listening",()=>{let{port:s}=t.address();t.close(()=>r(s))}),t.once("error",e)})}var Fp,Bp=w(()=>{"use strict";p();Fp=require("http");});var So,Up=w(()=>{"use strict";p();So=["--disable-features="+["Translate","OptimizationHints","MediaRouter","DialMediaRouteProvider","CalculateNativeWinOcclusion","InterestFeedContentSuggestions","CertificateTransparencyComponentUpdater","AutofillServerCommunication","PrivacySandboxSettings4","RenderDocument"].join(","),"--disable-extensions","--disable-component-extensions-with-background-pages","--disable-background-networking","--disable-component-update","--disable-client-side-phishing-detection","--disable-sync","--metrics-recording-only","--disable-default-apps","--mute-audio","--no-default-browser-check","--no-first-run","--disable-backgrounding-occluded-windows","--disable-renderer-backgrounding","--disable-background-timer-throttling","--disable-ipc-flooding-protection","--password-store=basic","--use-mock-keychain","--force-fieldtrials=*BackgroundTracing/default/","--disable-hang-monitor","--disable-prompt-on-repost","--disable-domain-reliability","--propagate-iph-for-testing"]});async function ow(r={}){r.handleSIGINT=ht(r.handleSIGINT,!0);let e=new tn(r);r.handleSIGINT&&ys.size===0&&process.on(Hp,Vp),ys.add(e),await e.launch();let t=()=>{ys.delete(e),ys.size===0&&process.removeListener(Hp,Vp),e.kill()};return{pid:e.pid,port:e.port,process:e.chromeProcess,remoteDebuggingPipes:e.remoteDebuggingPipes,kill:t}}function cw(){let r=tn.getFirstInstallation();if(!r)throw new en;return r}function zp(){let r=[];for(let e of ys)try{e.kill(),ys.delete(e)}catch(t){r.push(t)}return r}var rw,Gp,vi,sw,nw,Hp,iw,aw,ys,Vp,tn,qp=w(()=>{"use strict";p();rw=x(require("fs"),1),Gp=x(require("net"),1);Mp();Bp();Up();yo();vi=require("child_process");mo();sw=Ot()==="wsl",nw=Ot()==="win32",Hp="SIGINT",iw=130,aw=new Set(["darwin","linux","win32","wsl"]),ys=new Set,Vp=()=>{zp(),process.exit(iw)};tn=class r{constructor(e={},t={}){if(this.opts=e,this.tmpDirandPidFileReady=!1,this.remoteDebuggingPipes=null,this.fs=t.fs||rw,this.spawn=t.spawn||vi.spawn,ce.setLevel(ht(this.opts.logLevel,"silent")),this.startingUrl=ht(this.opts.startingUrl,"about:blank"),this.chromeFlags=ht(this.opts.chromeFlags,[]),this.prefs=ht(this.opts.prefs,{}),this.requestedPort=ht(this.opts.port,0),this.portStrictMode=e.portStrictMode,this.chromePath=this.opts.chromePath,this.ignoreDefaultFlags=ht(this.opts.ignoreDefaultFlags,!1),this.connectionPollInterval=ht(this.opts.connectionPollInterval,500),this.maxConnectionRetries=ht(this.opts.maxConnectionRetries,50),this.envVars=ht(e.envVars,Object.assign({},process.env)),typeof this.opts.userDataDir=="boolean")if(!this.opts.userDataDir)this.useDefaultProfile=!0,this.userDataDir=void 0;else throw new hi;else this.useDefaultProfile=!1,this.userDataDir=this.opts.userDataDir;this.useRemoteDebuggingPipe=this.chromeFlags.some(s=>s.startsWith("--remote-debugging-pipe"))}get flags(){let e=this.ignoreDefaultFlags?[]:So.slice();return this.port&&e.push(`--remote-debugging-port=${this.port}`),!this.ignoreDefaultFlags&&Ot()==="linux"&&e.push("--disable-setuid-sandbox"),this.useDefaultProfile||e.push(`--user-data-dir=${sw?_p(this.userDataDir):this.userDataDir}`),process.env.HEADLESS&&e.push("--headless"),e.push(...this.chromeFlags),e.push(this.startingUrl),e}static defaultFlags(){return So.slice()}static getFirstInstallation(){return Ot()==="darwin"?vo():bi[Ot()]()[0]}static getInstallations(){return bi[Ot()]()}makeTmpDir(){return $p()}prepare(){let e=Ot();if(!aw.has(e))throw new Zs;this.userDataDir=this.userDataDir||this.makeTmpDir(),this.outFile=this.fs.openSync(`${this.userDataDir}/chrome-out.log`,"a"),this.errFile=this.fs.openSync(`${this.userDataDir}/chrome-err.log`,"a"),this.setBrowserPrefs(),this.pidFile=`${this.userDataDir}/chrome.pid`,ce.verbose("ChromeLauncher",`created ${this.userDataDir}`),this.tmpDirandPidFileReady=!0}setBrowserPrefs(){if(Object.keys(this.prefs).length===0)return;let e=`${this.userDataDir}/Default`;this.fs.existsSync(e)||this.fs.mkdirSync(e,{recursive:!0});let t=`${e}/Preferences`;try{if(this.fs.existsSync(t)){let s=this.fs.readFileSync(t,"utf-8"),n=JSON.parse(s);this.fs.writeFileSync(t,JSON.stringify({...n,...this.prefs}),"utf-8")}else this.fs.writeFileSync(t,JSON.stringify({...this.prefs}),"utf-8")}catch(s){ce.log("ChromeLauncher",`Failed to set browser prefs: ${s.message}`)}}async launch(){if(this.requestedPort!==0){this.port=this.requestedPort;try{await this.isDebuggerReady(),ce.log("ChromeLauncher",`Found existing Chrome already running using port ${this.port}, using that.`);return}catch{if(this.portStrictMode)throw new Error(`found no Chrome at port ${this.requestedPort}`);ce.log("ChromeLauncher",`No debugging port found on port ${this.port}, launching a new Chrome.`)}}if(this.chromePath===void 0){let e=r.getFirstInstallation();if(!e)throw new en;this.chromePath=e}return this.tmpDirandPidFileReady||this.prepare(),this.pid=await this.spawnProcess(this.chromePath),Promise.resolve()}async spawnProcess(e){let s=await(async()=>this.chromeProcess?(ce.log("ChromeLauncher",`Chrome already running with pid ${this.chromeProcess.pid}.`),this.chromeProcess.pid):(this.requestedPort===0&&(this.useRemoteDebuggingPipe?this.port=0:this.port=await jp()),ce.verbose("ChromeLauncher",`Launching with command:
910
- "${e}" ${this.flags.join(" ")}`),this.chromeProcess=this.spawn(e,this.flags,{detached:process.platform!=="win32",stdio:this.useRemoteDebuggingPipe?["ignore",this.outFile,this.errFile,"pipe","pipe"]:["ignore",this.outFile,this.errFile],env:this.envVars}),this.chromeProcess.pid&&this.fs.writeFileSync(this.pidFile,this.chromeProcess.pid.toString()),this.useRemoteDebuggingPipe&&(this.remoteDebuggingPipes={incoming:this.chromeProcess.stdio[4],outgoing:this.chromeProcess.stdio[3]}),ce.verbose("ChromeLauncher",`Chrome running with pid ${this.chromeProcess.pid} on port ${this.port}.`),this.chromeProcess.pid))();return this.port!==0&&await this.waitUntilReady(),s}cleanup(e){e&&(e.removeAllListeners(),e.end(),e.destroy(),e.unref())}isDebuggerReady(){return new Promise((e,t)=>{let s=Gp.createConnection(this.port,"127.0.0.1");s.once("error",n=>{this.cleanup(s),t(n)}),s.once("connect",()=>{this.cleanup(s),e()})})}waitUntilReady(){let e=this;return new Promise((t,s)=>{let n=0,i="Waiting for browser.",a=()=>{n===0&&ce.log("ChromeLauncher",i),n++,i+="..",ce.log("ChromeLauncher",i),e.isDebuggerReady().then(()=>{ce.log("ChromeLauncher",i+`${ce.greenify(ce.tick)}`),t()}).catch(o=>{if(n>e.maxConnectionRetries){ce.error("ChromeLauncher",o.message);let c=this.fs.readFileSync(`${this.userDataDir}/chrome-err.log`,{encoding:"utf-8"});return ce.error("ChromeLauncher",`Logging contents of ${this.userDataDir}/chrome-err.log`),ce.error("ChromeLauncher",c),s(o)}Ap(e.connectionPollInterval).then(a)})};a()})}kill(){if(this.chromeProcess){this.chromeProcess.on("close",()=>{delete this.chromeProcess,this.destroyTmp()}),ce.log("ChromeLauncher",`Killing Chrome instance ${this.chromeProcess.pid}`);try{if(nw){let e=(0,vi.spawnSync)(`taskkill /pid ${this.chromeProcess.pid} /T /F`,{shell:!0,encoding:"utf-8"}),{stderr:t}=e;t&&ce.error("ChromeLauncher","taskkill stderr",t)}else this.chromeProcess.pid&&process.kill(-this.chromeProcess.pid,"SIGKILL")}catch(e){let t=`Chrome could not be killed ${e.message}`;ce.warn("ChromeLauncher",t)}this.destroyTmp()}}destroyTmp(){if(this.outFile&&(this.fs.closeSync(this.outFile),delete this.outFile),this.userDataDir===void 0||this.opts.userDataDir!==void 0)return;this.errFile&&(this.fs.closeSync(this.errFile),delete this.errFile),(this.fs.rmSync||this.fs.rmdirSync)(this.userDataDir,{recursive:!0,force:!0,maxRetries:10})}}});var Xp={};Q(Xp,{Launcher:()=>tn,getChromePath:()=>cw,killAll:()=>zp,launch:()=>ow});var Kp=w(()=>{"use strict";p();qp()});var Zp={};Q(Zp,{getActiveRunId:()=>lw,runTests:()=>Po,stopActiveRun:()=>Eo});function Yp(r){return r.steps.length===0?!1:r.steps.every(e=>(e.stepType??Ze(e.instruction))==="api")}function Qp(r){return r.type==="api"}function xi(r){return r.type==="audit"||r.type==="performance"}function Eo(){Si&&Si()}function lw(){return Co}async function Po(r,e,t,s){let n=(0,Jp.randomUUID)(),i=new Date().toISOString(),a=vr.default.join(r,"tests"),o=!1;Co=n,Si=()=>{o=!0,le.info({runId:n},"Run stop requested")};let c=t.environment??"dev",l=t.environmentUrls?.[c];l&&(t={...t,baseUrl:l}),le.info({runId:n,runConfig:e,environment:c,baseUrl:t.baseUrl},"Run started");let u=await vc(r,n),d=(P,v,k)=>{let R=new Date().toISOString(),I=k?" "+JSON.stringify(k):"";u.write(`[${R}] [${P.toUpperCase()}] ${v}${I}`)};d("info","Run started",{runId:n,environment:c,baseUrl:t.baseUrl});let g=new Kn,m=new Yn,f=new Qn(r,n,c),h=await Ys(r),C=[];h.enabled&&(t.screenshot!=="on"&&(t={...t,screenshot:"on"}),d("info","Visual regression enabled \u2014 screenshots forced ON",{threshold:h.defaultThreshold,fullPage:h.fullPage}));try{let P=await dw(a,e);P.length===0&&le.warn({runConfig:e},"No tests matched the run config");let v=await pw(r,e.env),k=new Map,R=[];for(let _ of P){if(_.testCase.dataSource)try{let Z=await Nd(r,_.testCase.dataSource);if(Z.length>0){Z.forEach((oe,te)=>R.push({..._,dataRow:oe,dataRowIndex:te})),le.info({caseId:_.testCase.id,rows:Z.length},"Expanded data-driven case");continue}}catch(Z){le.warn({err:Z,caseId:_.testCase.id},"Failed to load data rows \u2014 running case once")}R.push(_)}if(s?.broadcast("run:start",{runId:n,totalTests:R.length}),t.mcp?.proactiveHealing&&t.mcp?.enabled){le.info("Proactive healing enabled \u2014 validating selectors before run");let _=null;try{_=new pt({headless:t.mcp.headless,actionTimeout:t.mcp.actionTimeout,idleTimeout:t.mcp.idleTimeout});for(let Z of R)for(let oe of Z.testCase.steps){if(!oe.generatedCode.trim())continue;let te=await od(_,t.baseUrl,oe.generatedCode);te.ok||(s?.broadcast("healing:proactive",{runId:n,caseId:Z.testCase.id,stepId:oe.id,instruction:oe.instruction,missing:te.checks.filter(M=>!M.found).map(M=>({selector:M.selector,suggestion:M.suggestion}))}),le.warn({stepId:oe.id,missing:te.missing},`Proactive check: ${te.missing} selector(s) may be broken`))}}catch(Z){le.warn({err:Z},"Proactive healing check failed \u2014 continuing with run")}finally{await _?.disconnect()}}let I;if(t.rag?.enabled)try{I=await Xn.create(r,t.rag),le.info(I.getStats(),"RAG memory loaded"),d("info","RAG memory loaded",I.getStats())}catch(_){le.warn({err:_},"RAG initialization failed \u2014 continuing without memory")}let B=tt(r,void 0,void 0,I),Y=B.getPrimaryProvider(),j=new Wn(t.healing.dailyBudget),Ee=t.browsers,vt=[],Ue=R.length>0&&R.every(({suite:_,testCase:Z})=>(Qp(_)||Yp(Z))&&!xi(_));Ue&&(le.info("All test cases are API-only \u2014 no browser will be launched"),d("info","API-only run detected \u2014 skipping browser launch"));let We=new Map;if(Ue)for(let _ of Ee)We.set(_,null);else{let _=await Promise.all(Ee.map(async Z=>({name:Z,instance:await g.launchBrowser(Z,t)})));for(let{name:Z,instance:oe}of _)We.set(Z,oe)}let ks=[];for(let _ of Ee){let Z=We.get(_)??null;for(let oe of R)ks.push({browserName:_,browser:Z,...oe})}let er=(await mw(ks,t.parallel,async({browserName:_,browser:Z,suite:oe,testCase:te,dataRow:M,dataRowIndex:Je})=>{if(o)return null;let tr=M?{...v,...M}:v,G=M?`${te.name} [row ${(Je??0)+1}]`:te.name;s?.broadcast("run:case",{runId:n,suiteId:oe.id,caseId:`${te.id}_${_}`,caseName:Ee.length>1?`${G} [${_}]`:G,browser:_,status:"running"});let ue=`${te.id}_${_}`;d("info",`Case started: ${oe.name} > ${G}`,{suiteId:oe.id,caseId:te.id,browser:_});let q=await uw(r,n,oe,te,_,Z,t,tr,k,Y,j,m,g,s,d,ue,I,h,C);return q.suiteType=oe.type,M!==void 0&&(q.caseResult.dataRowIndex=Je,q.caseResult.dataRow=M,q.caseResult.caseName=G),s?.broadcast("run:case:done",{runId:n,suiteId:oe.id,caseId:te.id,status:q.caseResult.status}),d("info",`Case finished: ${G} [${_}] \u2014 ${q.caseResult.status.toUpperCase()}`,{duration:q.caseResult.duration,steps:q.caseResult.steps.length,passed:q.caseResult.steps.filter(he=>he.status==="passed").length,failed:q.caseResult.steps.filter(he=>he.status==="failed").length}),{...q,browserName:_}})).filter(Boolean);if(Ee.length>1)for(let _ of Ee){let Z=er.filter(te=>te.browserName===_),oe=Wp(Z,_);vt.push(...oe)}else{let _=Wp(er);vt.push(..._)}let As=new Date().toISOString(),Pe=gw(n,i,As,vt,c);if(Pe.logFilePath=u.logFilePath,d("info",`Run finished: ${Pe.status.toUpperCase()}`,{totalTests:Pe.totalTests,passed:Pe.passed,failed:Pe.failed,skipped:Pe.skipped,duration:Pe.duration}),u.close(),await Vu(r,Pe),t.reporting.allure&&(await f.writeResults(Pe),xd(r,n).catch(_=>{le.warn({err:_ instanceof Error?_.message:String(_),runId:n},"Allure report generation failed")})),t.reporting.json){let _=vr.default.join(r,"results",`run-${n}.json`);await br.default.ensureDir(vr.default.dirname(_)),await br.default.writeJson(_,Pe,{spaces:2})}if(h.enabled&&C.length>0&&(await ri(r,{runId:n,timestamp:As,diffs:C}),d("info",`Visual regression: ${C.length} comparisons saved`,{passed:C.filter(_=>_.status==="passed").length,failed:C.filter(_=>_.status==="failed").length,new:C.filter(_=>_.status==="new").length})),await m.flush(r,n),await B.getCache().persist(),I)try{await I.persist(),le.info(I.getStats(),"RAG memory persisted")}catch(_){le.warn({err:_},"RAG persistence failed")}return le.info({runId:n,passed:Pe.passed,failed:Pe.failed,total:Pe.totalTests,healingSpend:j.totalSpent},"Run finished"),Pe}finally{Si=null,Co=null,await g.closeAll(),o&&s?.broadcast("run:stopped",{runId:n})}}async function uw(r,e,t,s,n,i,a,o,c,l,u,d,g,m,f,h,C,P,v){let k=h??s.id,R=new Date().toISOString(),I=[],B=[],Y=Qp(t)||Yp(s),j=xi(t)?{...a,screenshot:"off",video:"off",trace:"off"}:a,Ee=!Y&&j.trace!=="off"?vr.default.join(r,"results","traces",`${e}_${s.id}_${n}.zip`):void 0,vt=null,Ue;if(Y)Ue=await g.createApiOnlyPage(a.baseUrl),le.debug({caseName:s.name},"API-only case \u2014 zero browser, using standalone HTTP client");else{if(!i)throw new Error("Browser required for UI test cases");vt=await g.newContext(i,j,vr.default.join(r,"results","videos")),Ue=await g.newPage(vt),await Od(Ue)}let We="passed",ks=!1,Dt=[],er,As=async te=>{let M=s.timeout??t.timeout??j.timeout,Je=M!==j.timeout?{...j,timeout:M}:j;try{await ro({...te,strategy:"primary",stepType:"ui",lastHealed:null},Ue,{runId:e,suiteId:t.id,caseId:s.id,browser:n,rootDir:r,previousSteps:B,variables:o,sharedVariables:c,config:Je,provider:l,budget:u,healingReporter:d})}catch{}};try{for(let M of s.caseHooks?.before??[])await As(M);for(let M of s.steps){if(ks){I.push({stepId:M.id,instruction:M.instruction,status:"skipped",code:M.generatedCode,duration:0});continue}m?.broadcast("run:step",{runId:e,caseId:k,stepId:M.id,instruction:M.instruction,status:"running",duration:0});let Je=s.timeout??t.timeout??j.timeout,tr=Je!==j.timeout?{...j,timeout:Je}:j,G=await ro(M,Ue,{runId:e,suiteId:t.id,caseId:s.id,browser:n,rootDir:r,previousSteps:B,variables:o,sharedVariables:c,config:tr,provider:l,budget:u,healingReporter:d,ragManager:C});if(m?.broadcast("run:step",{runId:e,caseId:k,stepId:G.stepId,instruction:G.instruction,status:G.status,duration:G.duration}),!Y&&m){try{let he=await Ue.screenshot({type:"jpeg",quality:60});m.broadcast("run:screenshot",{runId:e,caseId:k,stepId:G.stepId,image:he.toString("base64"),timestamp:Date.now()})}catch{}let q=g.drainConsoleLogs(Ue);q.length>0&&m.broadcast("run:console",{runId:e,caseId:k,stepId:G.stepId,logs:q})}let ue=G.status==="failed"?"error":"info";if(f?.(ue,` Step ${M.order}: ${G.instruction} \u2014 ${G.status.toUpperCase()} (${G.duration}ms)`,{...G.error?{error:G.error}:{},...G.healed?{healed:!0}:{}}),I.push(G),P?.enabled&&v&&!Y&&M.visualCheck&&G.status==="passed"&&G.screenshotPath)try{let q=a.viewport??{width:1280,height:720},he=It(t.name),Nt=It(s.name),xr=Jd(r,he,Nt,M.id,n,q),$s=Yd(r,e,M.id,n,q),Ye=await Wd(xr,G.screenshotPath,$s,{threshold:.1,diffThreshold:P.defaultThreshold}),Sr=Ye.totalPixels===0?"new":Ye.match?"passed":"failed";v.push({stepId:M.id,caseId:s.id,caseName:s.name,suiteName:t.name,suiteId:t.id,browser:n,viewport:`${q.width}x${q.height}`,diffPercentage:Ye.diffPercentage,threshold:P.defaultThreshold,status:Sr,baselinePath:Ye.baselinePath,actualPath:Ye.actualPath,diffPath:Ye.diffImagePath??$s}),f?.("info",` Visual: ${M.id} \u2014 ${Sr} (diff: ${Ye.diffPercentage}%)`,{baseline:xr})}catch(q){le.debug({err:q,stepId:M.id},"Visual regression comparison failed")}G.status==="passed"?B.push({instruction:M.instruction,code:G.code}):G.status==="failed"&&(We="failed",ks=!0)}let te=(()=>{let M=s.lighthouseCategories;return M&&M.length>0?M:xi(t)?["performance","accessibility","seo"]:null})();if(!Y&&n==="chromium"&&i&&te!==null){let M=new Map(s.steps.map(ue=>[ue.id,ue])),tr=s.steps.some(ue=>ue.runAudit===!0)?I.map((ue,q)=>({s:ue,idx:q})).filter(({s:ue})=>M.get(ue.stepId)?.runAudit===!0&&!!(ue.auditUrl??ue.navigatedToUrl)):[],G=te;if(tr.length>0){f?.("info",`--- LIGHTHOUSE AUDIT [${G.join(", ")}] ---`);try{let{default:ue}=await import("lighthouse"),q=await Promise.resolve().then(()=>(Kp(),Xp)),he=q.launch??q.default?.launch,{chromium:Nt}=await import("playwright"),xr=Nt.executablePath(),$s=vr.default.join(r,"results",".lh-profiles");await br.default.ensureDir($s);for(let Ye=0;Ye<tr.length;Ye++){let{s:Sr,idx:Jo}=tr[Ye],Br=Sr.auditUrl??Sr.navigatedToUrl;f?.("info",` Auditing: ${Br}`);let Bi=null,Ui=vr.default.join($s,`audit-${Date.now()}-${Ye}`);try{await br.default.ensureDir(Ui),Bi=await he({chromePath:xr,chromeFlags:["--headless","--no-sandbox","--disable-gpu"],userDataDir:Ui,logLevel:"silent"});let Ur=(await Promise.race([ue(Br,{port:Bi.port,output:"json",logLevel:"silent",onlyCategories:G,disableStorageReset:!0,screenEmulation:{disabled:!0},throttlingMethod:"simulate",formFactor:"desktop"}),new Promise((Hr,Ft)=>setTimeout(()=>Ft(new Error("Lighthouse audit timed out after 60s")),6e4))]))?.lhr,Yo=Ur?.audits??{},Qo=Ur?.categories??{},rr=Hr=>{let Ft=Yo[Hr]?.numericValue;return Ft!=null&&isFinite(Ft)?Ft:void 0},Hi=Hr=>{let Ft=Qo[Hr]?.score;return Ft!=null?Math.round(Ft*100):void 0},Zo=Hr=>(Qo[Hr]?.auditRefs??[]).filter(Cr=>(Cr.weight??0)>0).map(Cr=>{let ln=Yo[Cr.id],sr=ln?.score??null,_s=sr!==null&&sr>0&&sr<1;return{id:Cr.id,title:ln?.title??Cr.id,passed:sr===1,partial:_s||void 0,na:sr===null||void 0}}).sort((Cr,ln)=>{let sr=_s=>_s.na?3:_s.passed?4:_s.partial?1:0;return sr(Cr)-sr(ln)}),Mt=G.includes("performance"),ec=G.includes("accessibility"),tc=G.includes("seo"),ct={url:Br,stepIndex:Jo,stepInstruction:Sr.instruction,score:Mt?Hi("performance"):void 0,a11yScore:ec?Hi("accessibility"):void 0,seoScore:tc?Hi("seo"):void 0,fcp:Mt?rr("first-contentful-paint"):void 0,lcp:Mt?rr("largest-contentful-paint"):void 0,cls:Mt?rr("cumulative-layout-shift"):void 0,ttfb:Mt?rr("server-response-time"):void 0,tbt:Mt?rr("total-blocking-time"):void 0,si:Mt?rr("speed-index"):void 0,tti:Mt?rr("interactive"):void 0,inp:Mt?rr("interaction-to-next-paint"):void 0,a11yAudits:ec?Zo("accessibility"):void 0,seoAudits:tc?Zo("seo"):void 0};Dt.push(ct),f?.("info",` Perf: ${ct.score??"--"} | A11y: ${ct.a11yScore??"--"} | SEO: ${ct.seoScore??"--"} | FCP: ${ct.fcp!=null?(ct.fcp/1e3).toFixed(2)+"s":"--"} | LCP: ${ct.lcp!=null?(ct.lcp/1e3).toFixed(2)+"s":"--"} | CLS: ${ct.cls?.toFixed(3)??"--"} | TTFB: ${ct.ttfb!=null?(ct.ttfb/1e3).toFixed(2)+"s":"--"}`)}catch(cn){let Ur=cn instanceof Error?cn.message:String(cn);le.warn({url:Br,err:Ur},"Lighthouse audit failed for URL"),f?.("warn",` Lighthouse failed for ${Br}: ${Ur}`),Dt.push({url:Br,stepIndex:Jo,stepInstruction:Sr.instruction,lighthouseError:Ur})}finally{try{await Bi?.kill()}catch{}try{await br.default.remove(Ui)}catch{}}}}catch(ue){let q=ue instanceof Error?ue.message:String(ue);le.warn({err:q},"Lighthouse import/init failed"),f?.("warn",` Lighthouse init failed: ${q}`);let he=new Set(Dt.map(Nt=>Nt.stepIndex));for(let{s:Nt,idx:xr}of tr)he.has(xr)||Dt.push({url:Nt.auditUrl??Nt.navigatedToUrl,stepIndex:xr,stepInstruction:Nt.instruction,lighthouseError:`Lighthouse unavailable: ${q}`})}f?.("info","------------------------------------")}xi(t)&&Dt.length>0&&We==="passed"&&Dt.some(he=>!he.lighthouseError&&(he.score!=null&&he.score<50||he.a11yScore!=null&&he.a11yScore<50||he.seoScore!=null&&he.seoScore<50))&&(We="failed",f?.("warn"," Case FAILED: one or more Lighthouse scores below 50 (Poor threshold)"))}else!Y&&n!=="chromium"&&(Dt=I.map((M,Je)=>({s:M,idx:Je})).filter(({s:M})=>!!M.navigatedToUrl).map(({s:M,idx:Je})=>({url:M.navigatedToUrl,stepIndex:Je,stepInstruction:M.instruction,lighthouseError:"Lighthouse only available for Chromium"})));for(let M of s.caseHooks?.after??[])await As(M);Y||(er=await Ue.video()?.path().catch(()=>{}))}finally{Y||vt&&(await g.closeContext(vt,j,Ee),(j.video==="retain-on-failure"||j.video==="on-first-retry")&&We==="passed"&&er&&await br.default.remove(er).catch(()=>{}),(j.trace==="retain-on-failure"||j.trace==="on-first-retry")&&We==="passed"&&Ee&&await br.default.remove(Ee).catch(()=>{}))}let Pe,_;if(!Y){let te=j.video==="retain-on-failure"||j.video==="on-first-retry";Pe=j.video!=="off"&&er?te&&We==="passed"?void 0:er:void 0;let M=j.trace==="retain-on-failure"||j.trace==="on-first-retry";_=j.trace==="off"||M&&We==="passed"?void 0:Ee}let Z=new Date().toISOString(),oe=new Date(Z).getTime()-new Date(R).getTime();return{suiteId:t.id,suiteName:t.name,caseResult:{caseId:s.id,caseName:s.name,status:We,steps:I,duration:oe,browser:n,device:a.device||void 0,startedAt:R,finishedAt:Z,videoPath:Pe,tracePath:_,pageLoads:Dt}}}async function dw(r,e){let t=await Pr(r),s=[];for(let n of t){if(e.type&&n.type!==e.type)continue;if(e.suite){let o=e.suite.toLowerCase(),c=n.name.toLowerCase().includes(o),l=n.id===e.suite;if(!c&&!l)continue}let i=await pe(r,n.id);if(!i){le.warn({suiteId:n.id},"Suite directory not found \u2014 skipping");continue}let a=await qe(i);for(let o of a){if(e.test){let c=e.test.toLowerCase(),l=o.name.toLowerCase().includes(c),u=o.id===e.test;if(!l&&!u)continue}e.tag&&!o.tags.includes(e.tag)||!e.all&&!e.type&&!e.suite&&!e.test&&!e.tag||s.push({suite:n,testCase:o})}}return s}async function pw(r,e){try{let t=await et(r,e??"dev"),s=Object.keys(t).length;return le.info({count:s,env:e??"dev",rootDir:r},"Variables loaded"),t}catch(t){return le.warn({err:t instanceof Error?t.message:String(t)},"Failed to load variables \u2014 running without variable substitution"),{}}}async function mw(r,e,t){let s=[],n=[...r];async function i(){for(;n.length>0;){let o=n.shift();o!==void 0&&s.push(await t(o))}}let a=Array.from({length:Math.min(e,r.length||1)},()=>i());return await Promise.all(a),s}function Wp(r,e){let t=new Map;for(let n of r){let i=n.suiteId,a=t.get(i)??[];a.push(n),t.set(i,a)}let s=[];for(let[n,i]of t){let a=i[0];if(!a)continue;let o=i.map(g=>g.caseResult),c=o.some(g=>g.status==="failed")?"failed":"passed",l=o[0]?.startedAt??new Date().toISOString(),u=o[o.length-1]?.finishedAt??new Date().toISOString(),d=new Date(u).getTime()-new Date(l).getTime();s.push({suiteId:n,suiteName:e?`${a.suiteName} [${e}]`:a.suiteName,suiteType:a.suiteType,status:c,cases:o,duration:d,browser:o[0]?.browser??"chromium",startedAt:l,finishedAt:u})}return s}function gw(r,e,t,s,n){let i=s.flatMap(d=>d.cases),a=i.filter(d=>d.status==="passed").length,o=i.filter(d=>d.status==="failed").length,c=i.filter(d=>d.status==="skipped").length,l=i.length,u=new Date(t).getTime()-new Date(e).getTime();return{runId:r,status:o>0?"failed":"passed",environment:n,suites:s,duration:u,startedAt:e,finishedAt:t,totalTests:l,passed:a,failed:o,skipped:c}}var vr,Jp,br,le,Si,Co,Io=w(()=>{"use strict";p();vr=x(require("path")),Jp=require("crypto"),br=x(require("fs-extra"));ze();dt();lr();Xs();dr();Vs();id();cd();ld();dd();md();yd();Sd();_d();Ld();Md();Ir();io();Qd();Rt();F();le=E("runner");Si=null,Co=null});async function em(r){let e=r.rootDir;r.post("/run",async(t,s)=>{let n=ww.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid run config",details:n.error.issues});try{let i=await J(e),a=n.data,o={...i,headless:a.headed!==void 0?!a.headed:!1,browsers:a.browsers?.length?a.browsers:i.browsers,parallel:a.parallel??i.parallel,screenshot:a.screenshot??i.screenshot,video:a.video??i.video,trace:a.trace??i.trace,device:a.device??i.device,...a.ci?{headless:!0}:{}},c=r.wsManager,l=new Date().toISOString();return Ro.info({runConfig:a},"Run requested via API"),Po(e,a,o,c).then(u=>{c.broadcast("run:complete",{runId:u.runId,passed:u.passed,failed:u.failed,skipped:u.skipped,duration:u.duration}),Ro.info({runId:u.runId,status:u.status},"API-triggered run complete")}).catch(u=>{Ro.error({err:u},"API-triggered run failed"),c.broadcast("run:error",{error:u instanceof Error?u.message:String(u)})}),s.status(202).send({status:"accepted",startedAt:l,message:"Run started \u2014 subscribe to WebSocket for progress"})}catch(i){return b(s,500,"Failed to start run",i)}}),r.post("/run/stop",async(t,s)=>(Eo(),s.status(202).send({status:"stopping"}))),r.get("/run",async(t,s)=>{let n=bw.safeParse(t.query);if(!n.success)return s.status(400).send({error:"Invalid query",details:n.error.issues});try{let i=await Bn(e,n.data.limit);return s.send(i)}catch(i){return b(s,500,"Failed to list run results",i)}}),r.get("/run/:runId",async(t,s)=>{try{let n=await Dr(e,t.params.runId);return s.send(n)}catch{return s.status(404).send({error:`Run "${t.params.runId}" not found`})}})}var me,Ro,fw,hw,yw,ww,bw,tm=w(()=>{"use strict";p();me=require("zod");Io();_e();Xs();ae();F();Ro=E("routes/run"),fw=me.z.enum(["off","on","only-on-failure"]),hw=me.z.enum(["off","on","on-first-retry","retain-on-failure"]),yw=me.z.enum(["off","on","on-first-retry","retain-on-failure"]),ww=me.z.object({all:me.z.boolean().optional(),suite:me.z.string().optional(),tag:me.z.string().optional(),test:me.z.string().optional(),browsers:me.z.array(me.z.string()).optional(),env:me.z.string().optional(),parallel:me.z.number().int().positive().optional(),headed:me.z.boolean().optional(),ci:me.z.boolean().optional(),reporter:me.z.array(me.z.string()).optional(),noHealing:me.z.boolean().optional(),screenshot:fw.optional(),video:hw.optional(),trace:yw.optional(),device:me.z.string().optional()}),bw=me.z.object({limit:me.z.coerce.number().int().positive().max(100).default(20)})});async function To(r){let e;if(r.startsWith("http://")||r.startsWith("https://")){let t=r;t.includes("#")&&(t=t.split("#")[0]);let s=t.replace(/\/$/,""),n=[t,`${t}.json`,`${s}/swagger.json`,`${s}/openapi.json`,`${s}/openapi.yaml`,`${s}/openapi.yml`,`${s}/swagger.yaml`,`${s}/api-docs`,`${s}/api-docs.json`,`${s}/v2/swagger.json`,`${s}/v2/openapi.yaml`,`${s}/v2/openapi.json`,`${s}/v3/api-docs`,`${s}/v3/openapi.yaml`,s.replace(/\/[^/]+$/,"")+"/swagger.json",s.replace(/\/[^/]+$/,"")+"/openapi.json",s.replace(/\/[^/]+$/,"")+"/openapi.yaml",s.replace(/\/[^/]+$/,"")+"/openapi.yml",s.replace(/\/[^/]+\/[^/]+$/,"")+"/openapi.yaml",s.replace(/\/[^/]+\/[^/]+$/,"")+"/swagger.json"];try{let c=await fetch(t,{headers:{Accept:"text/html, */*"},signal:AbortSignal.timeout(1e4)});if(c.ok){let l=await c.text();if(l.includes("<!")||l.includes("<html")){let u=[/Redoc\.init\(\s*['"]([^'"]+)['"]/,/spec-url=['"]([^'"]+)['"]/i,/url:\s*['"]([^'"]+\.(?:json|yaml|yml))['"]/,/specUrl:\s*['"]([^'"]+)['"]/,/["']([^"']*(?:openapi|swagger)[^"']*\.(?:json|yaml|yml))["']/i,/href=['"]([^'"]*\.(?:json|yaml|yml))['"][^>]*>.*?(?:openapi|swagger|spec|api-doc)/i];for(let d of u){let g=l.match(d);if(g?.[1]){let m=g[1];m.startsWith("/")?m=`${new URL(t).origin}${m}`:m.startsWith("http")||(m=new URL(m,t).href),n.unshift(m),rn.info({specUrl:m,pattern:d.source},"Extracted spec URL from HTML page")}}}}}catch{}let i=[...new Set(n)],a=!1,o=[];for(let c of i)try{rn.debug({tryUrl:c},"Trying to fetch OpenAPI spec");let l=await fetch(c,{headers:{Accept:"application/json, application/yaml, */*"},signal:AbortSignal.timeout(15e3)});if(l.ok){let u=l.headers.get("content-type")??"",d=await l.text(),g=u.includes("json")||d.trimStart().startsWith("{")||d.trimStart().startsWith("["),m=u.includes("yaml")||u.includes("yml")||c.endsWith(".yaml")||c.endsWith(".yml");if(g||m)try{if(e=g?JSON.parse(d):Ci.default.load(d),e&&(e.openapi||e.swagger||e.paths)){a=!0,rn.info({tryUrl:c,format:m?"YAML":"JSON"},"Successfully fetched OpenAPI spec");break}o.push(`${c}: Parsed but not a valid OpenAPI spec`)}catch{o.push(`${c}: Response is not valid ${m?"YAML":"JSON"}`)}else{if(!u.includes("html")&&!d.trimStart().startsWith("<!"))try{let f=Ci.default.load(d);if(f&&typeof f=="object"&&(f.openapi||f.swagger||f.paths)){e=f,a=!0,rn.info({tryUrl:c,format:"YAML (text/plain)"},"Successfully fetched OpenAPI spec");break}}catch{}o.push(`${c}: Response is HTML/text, not JSON or YAML (content-type: ${u})`)}}else o.push(`${c}: HTTP ${l.status}`)}catch(l){o.push(`${c}: ${l instanceof Error?l.message:String(l)}`)}if(!a)throw new Error(`Could not auto-discover the OpenAPI spec from this URL.
943
+ `+i),r.push(n+"m+"+fi.exports.humanize(this.diff)+"\x1B[0m")}else r[0]=mw()+e+" "+r[0]}function mw(){return Se.inspectOpts.hideDate?"":new Date().toISOString()+" "}function gw(...r){return process.stderr.write(gi.formatWithOptions(Se.inspectOpts,...r)+`
944
+ `)}function fw(r){r?process.env.DEBUG=r:delete process.env.DEBUG}function hw(){return process.env.DEBUG}function yw(r){r.inspectOpts={};let e=Object.keys(Se.inspectOpts);for(let t=0;t<e.length;t++)r.inspectOpts[e[t]]=Se.inspectOpts[e[t]]}fi.exports=ho()(Se);var{formatters:Tp}=fi.exports;Tp.o=function(r){return this.inspectOpts.colors=this.useColors,gi.inspect(r,this.inspectOpts).split(`
945
+ `).map(e=>e.trim()).join(" ")};Tp.O=function(r){return this.inspectOpts.colors=this.useColors,gi.inspect(r,this.inspectOpts)}});var Ap=Et((BI,bo)=>{"use strict";m();typeof process>"u"||process.type==="renderer"||process.browser===!0||process.__nwjs?bo.exports=Sp():bo.exports=kp()});function hi(r){if(!r)throw new Error("name must be non-empty")}function ww(r,e){for(var t=0,s=r.length,n;t<s;)n=t+s>>>1,r[n].startTime<e.startTime?t=n+1:s=n;r.splice(t,0,e)}var Ce,Op,$p,vo,_p,Lp,bi,vi,nn,xi,yi,wi,Dp=b(()=>{"use strict";m();Ce=typeof performance<"u"&&performance;$p=process.hrtime,vo=function(){var r=$p();return r[0]*1e9+r[1]},_p=vo(),Op=function(){return(vo()-_p)/1e6};Lp=Ce&&Ce.now?function(){return Ce.now()}:Op;Ce&&Ce.mark&&Ce.measure&&Ce.getEntriesByName&&Ce.getEntriesByType&&Ce.clearMarks&&Ce.clearMeasures&&Ce.clearResourceTimings?(bi=function(r){hi(r),Ce.mark("start "+r)},vi=function(r){hi(r),Ce.mark("end "+r);var e=Ce.measure(r,"start "+r,"end "+r);if(e)return e;var t=Ce.getEntriesByName(r);return t[t.length-1]},nn=function(){return Ce.getEntriesByType("measure")},xi=function(){Ce.clearMarks(),Ce.clearMeasures()}):(yi={},wi=[],bi=function(r){hi(r);var e=Lp();yi["$"+r]=e},vi=function(r){hi(r);var e=Lp(),t=yi["$"+r];if(!t)throw new Error("no known mark: "+r);var s={startTime:t,name:r,duration:e-t,entryType:"measure"};return ww(wi,s),s},nn=function(){return wi},xi=function(){yi={},wi=[]})});var ys,Mp,xr,vr,fs,hs,xo,Fp,vw,Np,ws,ce,So=b(()=>{"use strict";m();ys=x(require("process"),1),Mp=require("events"),xr=x(Ap(),1);Dp();vr=ys.default.platform==="win32",fs=ys.default.browser,hs={red:fs?"crimson":1,yellow:fs?"gold":3,cyan:fs?"darkturquoise":6,green:fs?"forestgreen":2,blue:fs?"steelblue":4,magenta:fs?"palevioletred":5};xr.default.colors=[hs.cyan,hs.green,hs.blue,hs.magenta];xo=class extends Mp.EventEmitter{constructor(e){super(e)}issueStatus(e,t){(e==="status"||e==="statusEnd")&&this.emit(e,[e,...t])}issueWarning(e,t){this.emit("warning",[e,...t])}},Fp={},vw=25,ws=class r{static _logToStdErr(e,t){r.loggerfn(e)(...t)}static loggerfn(e){e=`LH:${e}`;let t=Fp[e];return t||(t=(0,xr.default)(e),Fp[e]=t,e.endsWith("error")?t.color=hs.red:e.endsWith("warn")&&(t.color=hs.yellow)),t}static setLevel(e){switch(Np=e,e){case"silent":xr.default.enable("-LH:*");break;case"verbose":xr.default.enable("LH:*");break;case"warn":xr.default.enable("-LH:*, LH:*:warn, LH:*:error");break;case"error":xr.default.enable("-LH:*, LH:*:error");break;default:xr.default.enable("LH:*, -LH:*:verbose")}}static formatProtocol(e,t,s){let n=!ys.default||ys.default.browser?1/0:ys.default.stdout.columns,i=t.method||"?????",a=n-i.length-e.length-vw,o=t.params&&i!=="IO.read"?JSON.stringify(t.params).substr(0,a):"";r._logToStdErr(`${e}:${s||""}`,[i,o])}static isVerbose(){return Np==="verbose"}static time({msg:e,id:t,args:s=[]},n="log"){bi(t),r[n]("status",e,...s)}static timeEnd({msg:e,id:t,args:s=[]},n="verbose"){r[n]("statusEnd",e,...s),vi(t)}static log(e,...t){return r.events.issueStatus(e,t),r._logToStdErr(e,t)}static warn(e,...t){return r.events.issueWarning(e,t),r._logToStdErr(`${e}:warn`,t)}static error(e,...t){return r._logToStdErr(`${e}:error`,t)}static verbose(e,...t){return r.events.issueStatus(e,t),r._logToStdErr(`${e}:verbose`,t)}static greenify(e){return`${r.green}${e}${r.reset}`}static redify(e){return`${r.red}${e}${r.reset}`}static get green(){return"\x1B[32m"}static get red(){return"\x1B[31m"}static get yellow(){return"\x1B[33m"}static get purple(){return"\x1B[95m"}static get reset(){return"\x1B[0m"}static get bold(){return"\x1B[1m"}static get dim(){return"\x1B[2m"}static get tick(){return vr?"\u221A":"\u2713"}static get cross(){return vr?"\xD7":"\u2718"}static get whiteSmallSquare(){return vr?"\u0387":"\u25AB"}static get heavyHorizontal(){return vr?"\u2500":"\u2501"}static get heavyVertical(){return vr?"\u2502 ":"\u2503 "}static get heavyUpAndRight(){return vr?"\u2514":"\u2517"}static get heavyVerticalAndRight(){return vr?"\u251C":"\u2523"}static get heavyDownAndHorizontal(){return vr?"\u252C":"\u2533"}static get doubleLightHorizontal(){return"\u2500\u2500"}};ws.events=new xo;ws.takeTimeEntries=()=>{let r=nn();return xi(),r};ws.getTimeEntries=()=>nn();ce=ws});var Up=Et((zI,Bp)=>{"use strict";m();var jp=require("fs"),Co;function xw(){try{return jp.statSync("/.dockerenv"),!0}catch{return!1}}function Sw(){try{return jp.readFileSync("/proc/self/cgroup","utf8").includes("docker")}catch{return!1}}Bp.exports=()=>(Co===void 0&&(Co=xw()||Sw()),Co)});var Gp=Et((XI,Eo)=>{"use strict";m();var Cw=require("os"),Ew=require("fs"),Hp=Up(),Vp=()=>{if(process.platform!=="linux")return!1;if(Cw.release().toLowerCase().includes("microsoft"))return!Hp();try{return Ew.readFileSync("/proc/version","utf8").toLowerCase().includes("microsoft")?!Hp():!1}catch{return!1}};process.env.__IS_WSL_TEST__?Eo.exports=Vp:Eo.exports=Vp()});function vt(r,e){return typeof r>"u"?e:r}async function Kp(r){return new Promise(e=>setTimeout(e,r))}function Dt(){return Xp.default?"wsl":process.platform}function Wp(){switch(Dt()){case"darwin":case"linux":return Rw();case"wsl":process.env.TEMP=Io(`${process.env.PATH}`);case"win32":return Tw();default:throw new an}}function Iw(r=""){let e=/\/mnt\/([a-z])\//.exec(r);if(!e)return r;let t=e[1];return r.replace(`/mnt/${t}/`,`${t.toUpperCase()}:\\`).replace(/\//g,"\\")}function Jp(r=""){if(/[a-z]:\\/iu.test(r))return r;try{return Ei.default.execFileSync("wslpath",["-w",r]).toString().trim()}catch{return Iw(r)}}function Ii(r,e){try{return Ei.default.execFileSync("wslpath",["-u",r]).toString().trim()}catch{return e}}function Pw(r){let t=/\/mnt\/([a-z])\/Users\/([^\/:]+)\/AppData\//.exec(r)||[];return`/mnt/${t[1]}/Users/${t[2]}/AppData/Local`}function Io(r){let t=/\/([a-z])\/Users\/([^\/:]+)\/AppData\//.exec(r)||[];return Ii(`${t[1]}:\\Users\\${t[2]}\\AppData\\Local`,Pw(r))}function Rw(){return Ei.default.execSync("mktemp -d -t lighthouse.XXXXXXX").toString().trim()}function Tw(){let r=process.env.TEMP||process.env.TMP||(process.env.SystemRoot||process.env.windir)+"\\temp",e=Math.floor(Math.random()*9e7+1e7),t=(0,zp.join)(r,"lighthouse."+e);return(0,qp.mkdirSync)(t,{recursive:!0}),t}var zp,Ei,qp,Xp,bs,Si,Ci,an,on,Po=b(()=>{"use strict";m();zp=require("path"),Ei=x(require("child_process"),1),qp=require("fs"),Xp=x(Gp(),1);bs=class extends Error{constructor(e="Unexpected error",t){return super(),this.message=e,this.code=t,this.stack=new Error().stack,this}},Si=class extends bs{constructor(){super(...arguments),this.message="The CHROME_PATH environment variable must be set to a Chrome/Chromium executable no older than Chrome stable.",this.code="ERR_LAUNCHER_PATH_NOT_SET"}},Ci=class extends bs{constructor(){super(...arguments),this.message="userDataDir must be false or a path.",this.code="ERR_LAUNCHER_INVALID_USER_DATA_DIRECTORY"}},an=class extends bs{constructor(){super(...arguments),this.message=`Platform ${Dt()} is not supported.`,this.code="ERR_LAUNCHER_UNSUPPORTED_PLATFORM"}},on=class extends bs{constructor(){super(...arguments),this.message="No Chrome installations found.",this.code="ERR_LAUNCHER_NOT_INSTALLED"}}});var Pi={};Q(Pi,{darwin:()=>Qp,darwinFast:()=>ko,linux:()=>kw,win32:()=>Zp,wsl:()=>Aw});function ko(){let r=[process.env.CHROME_PATH,process.env.LIGHTHOUSE_CHROMIUM_PATH,"/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary","/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"];for(let e of r)if(e&&Sr(e))return e;return Qp()[0]}function Qp(){let r=["/Contents/MacOS/Google Chrome Canary","/Contents/MacOS/Google Chrome"],e="/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister",t=[],s=Ao();s&&t.push(s),(0,xs.execSync)(`${e} -dump | grep -i 'google chrome\\( canary\\)\\?\\.app' | awk '{$1=""; print $0}'`).toString().split(To).forEach(a=>{r.forEach(o=>{let c=ot.default.join(a.substring(0,a.indexOf(".app")+4).trim(),o);Sr(c)&&t.indexOf(c)===-1&&t.push(c)})});let n=(0,vs.default)(process.env.HOME||(0,Ro.homedir)()),i=[{regex:new RegExp(`^${n}/Applications/.*Chrome\\.app`),weight:50},{regex:new RegExp(`^${n}/Applications/.*Chrome Canary\\.app`),weight:51},{regex:/^\/Applications\/.*Chrome.app/,weight:100},{regex:/^\/Applications\/.*Chrome Canary.app/,weight:101},{regex:/^\/Volumes\/.*Chrome.app/,weight:-2},{regex:/^\/Volumes\/.*Chrome Canary.app/,weight:-1}];return process.env.LIGHTHOUSE_CHROMIUM_PATH&&i.unshift({regex:new RegExp((0,vs.default)(process.env.LIGHTHOUSE_CHROMIUM_PATH)),weight:150}),process.env.CHROME_PATH&&i.unshift({regex:new RegExp((0,vs.default)(process.env.CHROME_PATH)),weight:151}),em(t,i)}function Ao(){if(Sr(process.env.CHROME_PATH))return process.env.CHROME_PATH;if(Sr(process.env.LIGHTHOUSE_CHROMIUM_PATH))return ce.warn("ChromeLauncher","LIGHTHOUSE_CHROMIUM_PATH is deprecated, use CHROME_PATH env variable instead."),process.env.LIGHTHOUSE_CHROMIUM_PATH}function kw(){let r=[],e=Ao();if(e&&r.push(e),[ot.default.join((0,Ro.homedir)(),".local/share/applications/"),"/usr/share/applications/"].forEach(i=>{r=r.concat(_w(i))}),["google-chrome-stable","google-chrome","chromium-browser","chromium"].forEach(i=>{try{let a=(0,xs.execFileSync)("which",[i],{stdio:"pipe"}).toString().split(To)[0];Sr(a)&&r.push(a)}catch{}}),!r.length)throw new Si;let n=[{regex:/chrome-wrapper$/,weight:51},{regex:/google-chrome-stable$/,weight:50},{regex:/google-chrome$/,weight:49},{regex:/chromium-browser$/,weight:48},{regex:/chromium$/,weight:47}];return process.env.LIGHTHOUSE_CHROMIUM_PATH&&n.unshift({regex:new RegExp((0,vs.default)(process.env.LIGHTHOUSE_CHROMIUM_PATH)),weight:100}),process.env.CHROME_PATH&&n.unshift({regex:new RegExp((0,vs.default)(process.env.CHROME_PATH)),weight:101}),em($w(r.filter(Boolean)),n)}function Aw(){return process.env.LOCALAPPDATA=Io(`${process.env.PATH}`),process.env.PROGRAMFILES=Ii("C:/Program Files","/mnt/c/Program Files"),process.env["PROGRAMFILES(X86)"]=Ii("C:/Program Files (x86)","/mnt/c/Program Files (x86)"),Zp()}function Zp(){let r=[],e=[`${ot.default.sep}Google${ot.default.sep}Chrome SxS${ot.default.sep}Application${ot.default.sep}chrome.exe`,`${ot.default.sep}Google${ot.default.sep}Chrome${ot.default.sep}Application${ot.default.sep}chrome.exe`],t=[process.env.LOCALAPPDATA,process.env.PROGRAMFILES,process.env["PROGRAMFILES(X86)"]].filter(Boolean),s=Ao();return s&&r.push(s),t.forEach(n=>e.forEach(i=>{let a=ot.default.join(n,i);Sr(a)&&r.push(a)})),r}function em(r,e){return r.map(s=>{for(let n of e)if(n.regex.test(s))return{path:s,weight:n.weight};return{path:s,weight:10}}).sort((s,n)=>n.weight-s.weight).map(s=>s.path)}function Sr(r){if(!r)return!1;try{return Yp.default.accessSync(r),!0}catch{return!1}}function $w(r){return Array.from(new Set(r))}function _w(r){let e=/(^[^ ]+).*/,t="^Exec=/.*/(google-chrome|chrome|chromium)-.*",s=[];if(Sr(r)){let n;try{n=(0,xs.execSync)(`grep -ER "${t}" ${r} | awk -F '=' '{print $2}'`,{stdio:"pipe"})}catch{n=(0,xs.execSync)(`grep -Er "${t}" ${r} | awk -F '=' '{print $2}'`,{stdio:"pipe"})}n=n.toString().split(To).map(i=>i.replace(e,"$1")),n.forEach(i=>Sr(i)&&s.push(i))}return s}var Yp,ot,Ro,xs,vs,To,tm=b(()=>{"use strict";m();Yp=x(require("fs"),1),ot=x(require("path"),1),Ro=require("os"),xs=require("child_process"),vs=x(wp(),1);So();Po();To=/\r?\n/});function sm(){return new Promise((r,e)=>{let t=(0,rm.createServer)();t.listen(0),t.once("listening",()=>{let{port:s}=t.address();t.close(()=>r(s))}),t.once("error",e)})}var rm,nm=b(()=>{"use strict";m();rm=require("http");});var $o,im=b(()=>{"use strict";m();$o=["--disable-features="+["Translate","OptimizationHints","MediaRouter","DialMediaRouteProvider","CalculateNativeWinOcclusion","InterestFeedContentSuggestions","CertificateTransparencyComponentUpdater","AutofillServerCommunication","PrivacySandboxSettings4","RenderDocument"].join(","),"--disable-extensions","--disable-component-extensions-with-background-pages","--disable-background-networking","--disable-component-update","--disable-client-side-phishing-detection","--disable-sync","--metrics-recording-only","--disable-default-apps","--mute-audio","--no-default-browser-check","--no-first-run","--disable-backgrounding-occluded-windows","--disable-renderer-backgrounding","--disable-background-timer-throttling","--disable-ipc-flooding-protection","--password-store=basic","--use-mock-keychain","--force-fieldtrials=*BackgroundTracing/default/","--disable-hang-monitor","--disable-prompt-on-repost","--disable-domain-reliability","--propagate-iph-for-testing"]});async function Mw(r={}){r.handleSIGINT=vt(r.handleSIGINT,!0);let e=new cn(r);r.handleSIGINT&&Ss.size===0&&process.on(am,om),Ss.add(e),await e.launch();let t=()=>{Ss.delete(e),Ss.size===0&&process.removeListener(am,om),e.kill()};return{pid:e.pid,port:e.port,process:e.chromeProcess,remoteDebuggingPipes:e.remoteDebuggingPipes,kill:t}}function jw(){let r=cn.getFirstInstallation();if(!r)throw new on;return r}function lm(){let r=[];for(let e of Ss)try{e.kill(),Ss.delete(e)}catch(t){r.push(t)}return r}var Lw,cm,Ri,Ow,Dw,am,Fw,Nw,Ss,om,cn,um=b(()=>{"use strict";m();Lw=x(require("fs"),1),cm=x(require("net"),1);tm();nm();im();Po();Ri=require("child_process");So();Ow=Dt()==="wsl",Dw=Dt()==="win32",am="SIGINT",Fw=130,Nw=new Set(["darwin","linux","win32","wsl"]),Ss=new Set,om=()=>{lm(),process.exit(Fw)};cn=class r{constructor(e={},t={}){if(this.opts=e,this.tmpDirandPidFileReady=!1,this.remoteDebuggingPipes=null,this.fs=t.fs||Lw,this.spawn=t.spawn||Ri.spawn,ce.setLevel(vt(this.opts.logLevel,"silent")),this.startingUrl=vt(this.opts.startingUrl,"about:blank"),this.chromeFlags=vt(this.opts.chromeFlags,[]),this.prefs=vt(this.opts.prefs,{}),this.requestedPort=vt(this.opts.port,0),this.portStrictMode=e.portStrictMode,this.chromePath=this.opts.chromePath,this.ignoreDefaultFlags=vt(this.opts.ignoreDefaultFlags,!1),this.connectionPollInterval=vt(this.opts.connectionPollInterval,500),this.maxConnectionRetries=vt(this.opts.maxConnectionRetries,50),this.envVars=vt(e.envVars,Object.assign({},process.env)),typeof this.opts.userDataDir=="boolean")if(!this.opts.userDataDir)this.useDefaultProfile=!0,this.userDataDir=void 0;else throw new Ci;else this.useDefaultProfile=!1,this.userDataDir=this.opts.userDataDir;this.useRemoteDebuggingPipe=this.chromeFlags.some(s=>s.startsWith("--remote-debugging-pipe"))}get flags(){let e=this.ignoreDefaultFlags?[]:$o.slice();return this.port&&e.push(`--remote-debugging-port=${this.port}`),!this.ignoreDefaultFlags&&Dt()==="linux"&&e.push("--disable-setuid-sandbox"),this.useDefaultProfile||e.push(`--user-data-dir=${Ow?Jp(this.userDataDir):this.userDataDir}`),process.env.HEADLESS&&e.push("--headless"),e.push(...this.chromeFlags),e.push(this.startingUrl),e}static defaultFlags(){return $o.slice()}static getFirstInstallation(){return Dt()==="darwin"?ko():Pi[Dt()]()[0]}static getInstallations(){return Pi[Dt()]()}makeTmpDir(){return Wp()}prepare(){let e=Dt();if(!Nw.has(e))throw new an;this.userDataDir=this.userDataDir||this.makeTmpDir(),this.outFile=this.fs.openSync(`${this.userDataDir}/chrome-out.log`,"a"),this.errFile=this.fs.openSync(`${this.userDataDir}/chrome-err.log`,"a"),this.setBrowserPrefs(),this.pidFile=`${this.userDataDir}/chrome.pid`,ce.verbose("ChromeLauncher",`created ${this.userDataDir}`),this.tmpDirandPidFileReady=!0}setBrowserPrefs(){if(Object.keys(this.prefs).length===0)return;let e=`${this.userDataDir}/Default`;this.fs.existsSync(e)||this.fs.mkdirSync(e,{recursive:!0});let t=`${e}/Preferences`;try{if(this.fs.existsSync(t)){let s=this.fs.readFileSync(t,"utf-8"),n=JSON.parse(s);this.fs.writeFileSync(t,JSON.stringify({...n,...this.prefs}),"utf-8")}else this.fs.writeFileSync(t,JSON.stringify({...this.prefs}),"utf-8")}catch(s){ce.log("ChromeLauncher",`Failed to set browser prefs: ${s.message}`)}}async launch(){if(this.requestedPort!==0){this.port=this.requestedPort;try{await this.isDebuggerReady(),ce.log("ChromeLauncher",`Found existing Chrome already running using port ${this.port}, using that.`);return}catch{if(this.portStrictMode)throw new Error(`found no Chrome at port ${this.requestedPort}`);ce.log("ChromeLauncher",`No debugging port found on port ${this.port}, launching a new Chrome.`)}}if(this.chromePath===void 0){let e=r.getFirstInstallation();if(!e)throw new on;this.chromePath=e}return this.tmpDirandPidFileReady||this.prepare(),this.pid=await this.spawnProcess(this.chromePath),Promise.resolve()}async spawnProcess(e){let s=await(async()=>this.chromeProcess?(ce.log("ChromeLauncher",`Chrome already running with pid ${this.chromeProcess.pid}.`),this.chromeProcess.pid):(this.requestedPort===0&&(this.useRemoteDebuggingPipe?this.port=0:this.port=await sm()),ce.verbose("ChromeLauncher",`Launching with command:
946
+ "${e}" ${this.flags.join(" ")}`),this.chromeProcess=this.spawn(e,this.flags,{detached:process.platform!=="win32",stdio:this.useRemoteDebuggingPipe?["ignore",this.outFile,this.errFile,"pipe","pipe"]:["ignore",this.outFile,this.errFile],env:this.envVars}),this.chromeProcess.pid&&this.fs.writeFileSync(this.pidFile,this.chromeProcess.pid.toString()),this.useRemoteDebuggingPipe&&(this.remoteDebuggingPipes={incoming:this.chromeProcess.stdio[4],outgoing:this.chromeProcess.stdio[3]}),ce.verbose("ChromeLauncher",`Chrome running with pid ${this.chromeProcess.pid} on port ${this.port}.`),this.chromeProcess.pid))();return this.port!==0&&await this.waitUntilReady(),s}cleanup(e){e&&(e.removeAllListeners(),e.end(),e.destroy(),e.unref())}isDebuggerReady(){return new Promise((e,t)=>{let s=cm.createConnection(this.port,"127.0.0.1");s.once("error",n=>{this.cleanup(s),t(n)}),s.once("connect",()=>{this.cleanup(s),e()})})}waitUntilReady(){let e=this;return new Promise((t,s)=>{let n=0,i="Waiting for browser.",a=()=>{n===0&&ce.log("ChromeLauncher",i),n++,i+="..",ce.log("ChromeLauncher",i),e.isDebuggerReady().then(()=>{ce.log("ChromeLauncher",i+`${ce.greenify(ce.tick)}`),t()}).catch(o=>{if(n>e.maxConnectionRetries){ce.error("ChromeLauncher",o.message);let c=this.fs.readFileSync(`${this.userDataDir}/chrome-err.log`,{encoding:"utf-8"});return ce.error("ChromeLauncher",`Logging contents of ${this.userDataDir}/chrome-err.log`),ce.error("ChromeLauncher",c),s(o)}Kp(e.connectionPollInterval).then(a)})};a()})}kill(){if(this.chromeProcess){this.chromeProcess.on("close",()=>{delete this.chromeProcess,this.destroyTmp()}),ce.log("ChromeLauncher",`Killing Chrome instance ${this.chromeProcess.pid}`);try{if(Dw){let e=(0,Ri.spawnSync)(`taskkill /pid ${this.chromeProcess.pid} /T /F`,{shell:!0,encoding:"utf-8"}),{stderr:t}=e;t&&ce.error("ChromeLauncher","taskkill stderr",t)}else this.chromeProcess.pid&&process.kill(-this.chromeProcess.pid,"SIGKILL")}catch(e){let t=`Chrome could not be killed ${e.message}`;ce.warn("ChromeLauncher",t)}this.destroyTmp()}}destroyTmp(){if(this.outFile&&(this.fs.closeSync(this.outFile),delete this.outFile),this.userDataDir===void 0||this.opts.userDataDir!==void 0)return;this.errFile&&(this.fs.closeSync(this.errFile),delete this.errFile),(this.fs.rmSync||this.fs.rmdirSync)(this.userDataDir,{recursive:!0,force:!0,maxRetries:10})}}});var dm={};Q(dm,{Launcher:()=>cn,getChromePath:()=>jw,killAll:()=>lm,launch:()=>Mw});var pm=b(()=>{"use strict";m();um()});var ym={};Q(ym,{getActiveRunId:()=>Bw,runTests:()=>Oo,stopActiveRun:()=>Lo});function fm(r){return r.steps.length===0?!1:r.steps.every(e=>(e.stepType??tt(e.instruction))==="api")}function hm(r){return r.type==="api"}function Ti(r){return r.type==="audit"||r.type==="performance"}function Lo(){ki&&ki()}function Bw(){return _o}async function Oo(r,e,t,s){let n=(0,gm.randomUUID)(),i=new Date().toISOString(),a=Jt.default.join(r,"tests"),o=!1;_o=n,ki=()=>{o=!0,le.info({runId:n},"Run stop requested")};let c=t.environment??"dev",l=t.environmentUrls?.[c];l&&(t={...t,baseUrl:l}),le.info({runId:n,runConfig:e,environment:c,baseUrl:t.baseUrl},"Run started");let u=await Lc(r,n),d=(I,v,k)=>{let T=new Date().toISOString(),P=k?" "+JSON.stringify(k):"";u.write(`[${T}] [${I.toUpperCase()}] ${v}${P}`)};d("info","Run started",{runId:n,environment:c,baseUrl:t.baseUrl});let p=new ti,g=new ni,f=new ii(r,n,c),h=await sn(r),S=[];h.enabled&&(t.screenshot!=="on"&&(t={...t,screenshot:"on"}),d("info","Visual regression enabled \u2014 screenshots forced ON",{threshold:h.defaultThreshold,fullPage:h.fullPage}));try{let I=await Hw(a,e);I.length===0&&le.warn({runConfig:e},"No tests matched the run config");let v=await Vw(r,e.env),k=new Map,T=[];for(let _ of I){if(_.testCase.dataSource)try{let Z=await ep(r,_.testCase.dataSource);if(Z.length>0){Z.forEach((ie,we)=>T.push({..._,dataRow:ie,dataRowIndex:we})),le.info({caseId:_.testCase.id,rows:Z.length},"Expanded data-driven case");continue}}catch(Z){le.warn({err:Z,caseId:_.testCase.id},"Failed to load data rows \u2014 running case once")}T.push(_)}if(s?.broadcast("run:start",{runId:n,totalTests:T.length}),t.mcp?.proactiveHealing&&t.mcp?.enabled){le.info("Proactive healing enabled \u2014 validating selectors before run");let _=null;try{_=new ft({headless:t.mcp.headless,actionTimeout:t.mcp.actionTimeout,idleTimeout:t.mcp.idleTimeout});for(let Z of T)for(let ie of Z.testCase.steps){if(!ie.generatedCode.trim())continue;let we=await Id(_,t.baseUrl,ie.generatedCode);we.ok||(s?.broadcast("healing:proactive",{runId:n,caseId:Z.testCase.id,stepId:ie.id,instruction:ie.instruction,missing:we.checks.filter(be=>!be.found).map(be=>({selector:be.selector,suggestion:be.suggestion}))}),le.warn({stepId:ie.id,missing:we.missing},`Proactive check: ${we.missing} selector(s) may be broken`))}}catch(Z){le.warn({err:Z},"Proactive healing check failed \u2014 continuing with run")}finally{await _?.disconnect()}}let P;if(t.rag?.enabled)try{P=await Zn.create(r,t.rag),le.info(P.getStats(),"RAG memory loaded"),d("info","RAG memory loaded",P.getStats())}catch(_){le.warn({err:_},"RAG initialization failed \u2014 continuing without memory")}let j=st(r,void 0,void 0,P),J=j.getPrimaryProvider(),M=new ri(t.healing.dailyBudget),Ee=t.browsers,lt=[],Ve=T.length>0&&T.every(({suite:_,testCase:Z})=>(hm(_)||fm(Z))&&!Ti(_));Ve&&(le.info("All test cases are API-only \u2014 no browser will be launched"),d("info","API-only run detected \u2014 skipping browser launch"));let Ye=new Map;if(Ve)for(let _ of Ee)Ye.set(_,null);else{let _=await Promise.all(Ee.map(async Z=>({name:Z,instance:await p.launchBrowser(Z,t)})));for(let{name:Z,instance:ie}of _)Ye.set(Z,ie)}let Fs=[];for(let _ of Ee){let Z=Ye.get(_)??null;for(let ie of T)Fs.push({browserName:_,browser:Z,...ie})}let nr=(await Gw(Fs,t.parallel,async({browserName:_,browser:Z,suite:ie,testCase:we,dataRow:be,dataRowIndex:U})=>{if(o)return null;let ut=be?{...v,...be}:v,Qe=be?`${we.name} [row ${(U??0)+1}]`:we.name;s?.broadcast("run:case",{runId:n,suiteId:ie.id,caseId:`${we.id}_${_}`,caseName:Ee.length>1?`${Qe} [${_}]`:Qe,browser:_,status:"running"});let Y=`${we.id}_${_}`;d("info",`Case started: ${ie.name} > ${Qe}`,{suiteId:ie.id,caseId:we.id,browser:_});let q=await Uw(r,n,ie,we,_,Z,t,ut,k,J,M,g,p,s,d,Y,P,h,S);return q.suiteType=ie.type,be!==void 0&&(q.caseResult.dataRowIndex=U,q.caseResult.dataRow=be,q.caseResult.caseName=Qe),s?.broadcast("run:case:done",{runId:n,suiteId:ie.id,caseId:we.id,status:q.caseResult.status}),d("info",`Case finished: ${Qe} [${_}] \u2014 ${q.caseResult.status.toUpperCase()}`,{duration:q.caseResult.duration,steps:q.caseResult.steps.length,passed:q.caseResult.steps.filter(ae=>ae.status==="passed").length,failed:q.caseResult.steps.filter(ae=>ae.status==="failed").length}),{...q,browserName:_}})).filter(Boolean);if(Ee.length>1)for(let _ of Ee){let Z=nr.filter(we=>we.browserName===_),ie=mm(Z,_);lt.push(...ie)}else{let _=mm(nr);lt.push(..._)}let Ns=new Date().toISOString(),Ie=zw(n,i,Ns,lt,c);if(Ie.logFilePath=u.logFilePath,d("info",`Run finished: ${Ie.status.toUpperCase()}`,{totalTests:Ie.totalTests,passed:Ie.passed,failed:Ie.failed,skipped:Ie.skipped,duration:Ie.duration}),u.close(),await od(r,Ie),t.reporting.allure&&(await f.writeResults(Ie),jd(r,n).catch(_=>{le.warn({err:_ instanceof Error?_.message:String(_),runId:n},"Allure report generation failed")})),t.reporting.json){let _=Jt.default.join(r,"results",`run-${n}.json`);await Cr.default.ensureDir(Jt.default.dirname(_)),await Cr.default.writeJson(_,Ie,{spaces:2})}if(h.enabled&&S.length>0&&(await li(r,{runId:n,timestamp:Ns,diffs:S}),d("info",`Visual regression: ${S.length} comparisons saved`,{passed:S.filter(_=>_.status==="passed").length,failed:S.filter(_=>_.status==="failed").length,new:S.filter(_=>_.status==="new").length})),await g.flush(r,n),await j.getCache().persist(),P)try{await P.persist(),le.info(P.getStats(),"RAG memory persisted")}catch(_){le.warn({err:_},"RAG persistence failed")}return le.info({runId:n,passed:Ie.passed,failed:Ie.failed,total:Ie.totalTests,healingSpend:M.totalSpent},"Run finished"),Ie}finally{ki=null,_o=null,await p.closeAll(),o&&s?.broadcast("run:stopped",{runId:n})}}async function Uw(r,e,t,s,n,i,a,o,c,l,u,d,p,g,f,h,S,I,v){let k=h??s.id,T=new Date().toISOString(),P=[],j=[],J=hm(t)||fm(s),M=Ti(t)?{...a,screenshot:"off",video:"off",trace:"off"}:a,Ee=!J&&M.trace!=="off"?Jt.default.join(r,"results","traces",`${e}_${s.id}_${n}.zip`):void 0,lt=null,Ve;if(J)Ve=await p.createApiOnlyPage(a.baseUrl),le.debug({caseName:s.name},"API-only case \u2014 zero browser, using standalone HTTP client");else{if(!i)throw new Error("Browser required for UI test cases");lt=await p.newContext(i,M,Jt.default.join(r,"results","videos"),Jt.default.join(r,"results","downloads",e)),Ve=await p.newPage(lt),await Yd(Ve)}let Ye="passed",Fs=!1,Mt=[],nr,Ns=[],Ie=async be=>{let U=s.timeout??t.timeout??M.timeout,ut=U!==M.timeout?{...M,timeout:U}:M;try{await po({...be,strategy:"primary",stepType:"ui",lastHealed:null},Ve,{runId:e,suiteId:t.id,caseId:s.id,browser:n,rootDir:r,previousSteps:j,variables:o,sharedVariables:c,config:ut,provider:l,budget:u,healingReporter:d})}catch{}};try{for(let U of s.caseHooks?.before??[])await Ie(U);for(let U of s.steps){if(Fs){P.push({stepId:U.id,instruction:U.instruction,status:"skipped",code:U.generatedCode,duration:0});continue}g?.broadcast("run:step",{runId:e,caseId:k,stepId:U.id,instruction:U.instruction,status:"running",duration:0});let ut=s.timeout??t.timeout??M.timeout,Qe=ut!==M.timeout?{...M,timeout:ut}:M,Y=await po(U,Ve,{runId:e,suiteId:t.id,caseId:s.id,browser:n,rootDir:r,previousSteps:j,variables:o,sharedVariables:c,config:Qe,provider:l,budget:u,healingReporter:d,ragManager:S});if(g?.broadcast("run:step",{runId:e,caseId:k,stepId:Y.stepId,instruction:Y.instruction,status:Y.status,duration:Y.duration}),!J&&g){try{let Oe=await Ve.screenshot({type:"jpeg",quality:60});g.broadcast("run:screenshot",{runId:e,caseId:k,stepId:Y.stepId,image:Oe.toString("base64"),timestamp:Date.now()})}catch{}let ae=p.drainConsoleLogs(Ve);ae.length>0&&g.broadcast("run:console",{runId:e,caseId:k,stepId:Y.stepId,logs:ae})}let q=Y.status==="failed"?"error":"info";if(f?.(q,` Step ${U.order}: ${Y.instruction} \u2014 ${Y.status.toUpperCase()} (${Y.duration}ms)`,{...Y.error?{error:Y.error}:{},...Y.healed?{healed:!0}:{}}),P.push(Y),I?.enabled&&v&&!J&&U.visualCheck&&Y.status==="passed"&&Y.screenshotPath)try{let ae=a.viewport??{width:1280,height:720},Oe=kt(t.name),jt=kt(s.name),Ir=gp(r,Oe,jt,U.id,n,ae),Ms=fp(r,e,U.id,n,ae),Ze=await mp(Ir,Y.screenshotPath,Ms,{threshold:.1,diffThreshold:I.defaultThreshold}),Pr=Ze.totalPixels===0?"new":Ze.match?"passed":"failed";v.push({stepId:U.id,caseId:s.id,caseName:s.name,suiteName:t.name,suiteId:t.id,browser:n,viewport:`${ae.width}x${ae.height}`,diffPercentage:Ze.diffPercentage,threshold:I.defaultThreshold,status:Pr,baselinePath:Ze.baselinePath,actualPath:Ze.actualPath,diffPath:Ze.diffImagePath??Ms}),f?.("info",` Visual: ${U.id} \u2014 ${Pr} (diff: ${Ze.diffPercentage}%)`,{baseline:Ir})}catch(ae){le.debug({err:ae,stepId:U.id},"Visual regression comparison failed")}Y.status==="passed"?j.push({instruction:U.instruction,code:Y.code}):Y.status==="failed"&&(Ye="failed",Fs=!0)}let be=(()=>{let U=s.lighthouseCategories;return U&&U.length>0?U:Ti(t)?["performance","accessibility","seo"]:null})();if(!J&&n==="chromium"&&i&&be!==null){let U=new Map(s.steps.map(q=>[q.id,q])),Qe=s.steps.some(q=>q.runAudit===!0)?P.map((q,ae)=>({s:q,idx:ae})).filter(({s:q})=>U.get(q.stepId)?.runAudit===!0&&!!(q.auditUrl??q.navigatedToUrl)):[],Y=be;if(Qe.length>0){f?.("info",`--- LIGHTHOUSE AUDIT [${Y.join(", ")}] ---`);try{let{default:q}=await import("lighthouse"),ae=await Promise.resolve().then(()=>(pm(),dm)),Oe=ae.launch??ae.default?.launch,{chromium:jt}=await import("playwright"),Ir=jt.executablePath(),Ms=Jt.default.join(r,"results",".lh-profiles");await Cr.default.ensureDir(Ms);for(let Ze=0;Ze<Qe.length;Ze++){let{s:Pr,idx:lc}=Qe[Ze],zr=Pr.auditUrl??Pr.navigatedToUrl;f?.("info",` Auditing: ${zr}`);let Ki=null,Wi=Jt.default.join(Ms,`audit-${Date.now()}-${Ze}`);try{await Cr.default.ensureDir(Wi),Ki=await Oe({chromePath:Ir,chromeFlags:["--headless","--no-sandbox","--disable-gpu"],userDataDir:Wi,logLevel:"silent"});let qr=(await Promise.race([q(zr,{port:Ki.port,output:"json",logLevel:"silent",onlyCategories:Y,disableStorageReset:!0,screenEmulation:{disabled:!0},throttlingMethod:"simulate",formFactor:"desktop"}),new Promise((Xr,Ut)=>setTimeout(()=>Ut(new Error("Lighthouse audit timed out after 60s")),6e4))]))?.lhr,uc=qr?.audits??{},dc=qr?.categories??{},ir=Xr=>{let Ut=uc[Xr]?.numericValue;return Ut!=null&&isFinite(Ut)?Ut:void 0},Ji=Xr=>{let Ut=dc[Xr]?.score;return Ut!=null?Math.round(Ut*100):void 0},pc=Xr=>(dc[Xr]?.auditRefs??[]).filter(Rr=>(Rr.weight??0)>0).map(Rr=>{let fn=uc[Rr.id],ar=fn?.score??null,js=ar!==null&&ar>0&&ar<1;return{id:Rr.id,title:fn?.title??Rr.id,passed:ar===1,partial:js||void 0,na:ar===null||void 0}}).sort((Rr,fn)=>{let ar=js=>js.na?3:js.passed?4:js.partial?1:0;return ar(Rr)-ar(fn)}),Bt=Y.includes("performance"),mc=Y.includes("accessibility"),gc=Y.includes("seo"),dt={url:zr,stepIndex:lc,stepInstruction:Pr.instruction,score:Bt?Ji("performance"):void 0,a11yScore:mc?Ji("accessibility"):void 0,seoScore:gc?Ji("seo"):void 0,fcp:Bt?ir("first-contentful-paint"):void 0,lcp:Bt?ir("largest-contentful-paint"):void 0,cls:Bt?ir("cumulative-layout-shift"):void 0,ttfb:Bt?ir("server-response-time"):void 0,tbt:Bt?ir("total-blocking-time"):void 0,si:Bt?ir("speed-index"):void 0,tti:Bt?ir("interactive"):void 0,inp:Bt?ir("interaction-to-next-paint"):void 0,a11yAudits:mc?pc("accessibility"):void 0,seoAudits:gc?pc("seo"):void 0};Mt.push(dt),f?.("info",` Perf: ${dt.score??"--"} | A11y: ${dt.a11yScore??"--"} | SEO: ${dt.seoScore??"--"} | FCP: ${dt.fcp!=null?(dt.fcp/1e3).toFixed(2)+"s":"--"} | LCP: ${dt.lcp!=null?(dt.lcp/1e3).toFixed(2)+"s":"--"} | CLS: ${dt.cls?.toFixed(3)??"--"} | TTFB: ${dt.ttfb!=null?(dt.ttfb/1e3).toFixed(2)+"s":"--"}`)}catch(gn){let qr=gn instanceof Error?gn.message:String(gn);le.warn({url:zr,err:qr},"Lighthouse audit failed for URL"),f?.("warn",` Lighthouse failed for ${zr}: ${qr}`),Mt.push({url:zr,stepIndex:lc,stepInstruction:Pr.instruction,lighthouseError:qr})}finally{try{await Ki?.kill()}catch{}try{await Cr.default.remove(Wi)}catch{}}}}catch(q){let ae=q instanceof Error?q.message:String(q);le.warn({err:ae},"Lighthouse import/init failed"),f?.("warn",` Lighthouse init failed: ${ae}`);let Oe=new Set(Mt.map(jt=>jt.stepIndex));for(let{s:jt,idx:Ir}of Qe)Oe.has(Ir)||Mt.push({url:jt.auditUrl??jt.navigatedToUrl,stepIndex:Ir,stepInstruction:jt.instruction,lighthouseError:`Lighthouse unavailable: ${ae}`})}f?.("info","------------------------------------")}Ti(t)&&Mt.length>0&&Ye==="passed"&&Mt.some(Oe=>!Oe.lighthouseError&&(Oe.score!=null&&Oe.score<50||Oe.a11yScore!=null&&Oe.a11yScore<50||Oe.seoScore!=null&&Oe.seoScore<50))&&(Ye="failed",f?.("warn"," Case FAILED: one or more Lighthouse scores below 50 (Poor threshold)"))}else!J&&n!=="chromium"&&(Mt=P.map((U,ut)=>({s:U,idx:ut})).filter(({s:U})=>!!U.navigatedToUrl).map(({s:U,idx:ut})=>({url:U.navigatedToUrl,stepIndex:ut,stepInstruction:U.instruction,lighthouseError:"Lighthouse only available for Chromium"})));for(let U of s.caseHooks?.after??[])await Ie(U);J||(nr=await Ve.video()?.path().catch(()=>{}))}finally{J||lt&&(await p.closeContext(lt,M,Ee),Ns=p.takeDownloads(lt),(M.video==="retain-on-failure"||M.video==="on-first-retry")&&Ye==="passed"&&nr&&await Cr.default.remove(nr).catch(()=>{}),(M.trace==="retain-on-failure"||M.trace==="on-first-retry")&&Ye==="passed"&&Ee&&await Cr.default.remove(Ee).catch(()=>{}))}let _,Z;if(!J){let be=M.video==="retain-on-failure"||M.video==="on-first-retry";_=M.video!=="off"&&nr?be&&Ye==="passed"?void 0:nr:void 0;let U=M.trace==="retain-on-failure"||M.trace==="on-first-retry";Z=M.trace==="off"||U&&Ye==="passed"?void 0:Ee}let ie=new Date().toISOString(),we=new Date(ie).getTime()-new Date(T).getTime();return{suiteId:t.id,suiteName:t.name,caseResult:{caseId:s.id,caseName:s.name,status:Ye,steps:P,duration:we,browser:n,device:a.device||void 0,startedAt:T,finishedAt:ie,videoPath:_,tracePath:Z,downloadPaths:Ns,pageLoads:Mt}}}async function Hw(r,e){let t=await kr(r),s=[];for(let n of t){if(e.type&&n.type!==e.type)continue;if(e.suite){let o=e.suite.toLowerCase(),c=n.name.toLowerCase().includes(o),l=n.id===e.suite;if(!c&&!l)continue}let i=await de(r,n.id);if(!i){le.warn({suiteId:n.id},"Suite directory not found \u2014 skipping");continue}let a=await Ke(i);for(let o of a){if(e.test){let c=e.test.toLowerCase(),l=o.name.toLowerCase().includes(c),u=o.id===e.test;if(!l&&!u)continue}e.tag&&!o.tags.includes(e.tag)||!e.all&&!e.type&&!e.suite&&!e.test&&!e.tag||s.push({suite:n,testCase:o})}}return s}async function Vw(r,e){try{let t=await rt(r,e??"dev"),s=Object.keys(t).length;return le.info({count:s,env:e??"dev",rootDir:r},"Variables loaded"),t}catch(t){return le.warn({err:t instanceof Error?t.message:String(t)},"Failed to load variables \u2014 running without variable substitution"),{}}}async function Gw(r,e,t){let s=[],n=[...r];async function i(){for(;n.length>0;){let o=n.shift();o!==void 0&&s.push(await t(o))}}let a=Array.from({length:Math.min(e,r.length||1)},()=>i());return await Promise.all(a),s}function mm(r,e){let t=new Map;for(let n of r){let i=n.suiteId,a=t.get(i)??[];a.push(n),t.set(i,a)}let s=[];for(let[n,i]of t){let a=i[0];if(!a)continue;let o=i.map(p=>p.caseResult),c=o.some(p=>p.status==="failed")?"failed":"passed",l=o[0]?.startedAt??new Date().toISOString(),u=o[o.length-1]?.finishedAt??new Date().toISOString(),d=new Date(u).getTime()-new Date(l).getTime();s.push({suiteId:n,suiteName:e?`${a.suiteName} [${e}]`:a.suiteName,suiteType:a.suiteType,status:c,cases:o,duration:d,browser:o[0]?.browser??"chromium",startedAt:l,finishedAt:u})}return s}function zw(r,e,t,s,n){let i=s.flatMap(d=>d.cases),a=i.filter(d=>d.status==="passed").length,o=i.filter(d=>d.status==="failed").length,c=i.filter(d=>d.status==="skipped").length,l=i.length,u=new Date(t).getTime()-new Date(e).getTime();return{runId:r,status:o>0?"failed":"passed",environment:n,suites:s,duration:u,startedAt:e,finishedAt:t,totalTests:l,passed:a,failed:o,skipped:c}}var Jt,gm,Cr,le,ki,_o,Do=b(()=>{"use strict";m();Jt=x(require("path")),gm=require("crypto"),Cr=x(require("fs-extra"));Xe();gt();pr();Zs();gr();Ws();Cd();Pd();Rd();kd();$d();Dd();Bd();Jd();Qd();tp();Ar();fo();hp();At();N();le=E("runner");ki=null,_o=null});async function wm(r){let e=r.rootDir;r.post("/run",async(t,s)=>{let n=Ww.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid run config",details:n.error.issues});try{let i=await G(e),a=n.data,o={...i,headless:a.headed!==void 0?!a.headed:!1,browsers:a.browsers?.length?a.browsers:i.browsers,parallel:a.parallel??i.parallel,screenshot:a.screenshot??i.screenshot,video:a.video??i.video,trace:a.trace??i.trace,device:a.device??i.device,...a.ci?{headless:!0}:{}},c=r.wsManager,l=new Date().toISOString();return Fo.info({runConfig:a},"Run requested via API"),Oo(e,a,o,c).then(u=>{c.broadcast("run:complete",{runId:u.runId,passed:u.passed,failed:u.failed,skipped:u.skipped,duration:u.duration}),Fo.info({runId:u.runId,status:u.status},"API-triggered run complete")}).catch(u=>{Fo.error({err:u},"API-triggered run failed"),c.broadcast("run:error",{error:u instanceof Error?u.message:String(u)})}),s.status(202).send({status:"accepted",startedAt:l,message:"Run started \u2014 subscribe to WebSocket for progress"})}catch(i){return w(s,500,"Failed to start run",i)}}),r.post("/run/stop",async(t,s)=>(Lo(),s.status(202).send({status:"stopping"}))),r.get("/run",async(t,s)=>{let n=Jw.safeParse(t.query);if(!n.success)return s.status(400).send({error:"Invalid query",details:n.error.issues});try{let i=await qn(e,n.data.limit);return s.send(i)}catch(i){return w(s,500,"Failed to list run results",i)}}),r.get("/run/:runId",async(t,s)=>{try{let n=await Br(e,t.params.runId);return s.send(n)}catch{return s.status(404).send({error:`Run "${t.params.runId}" not found`})}})}var pe,Fo,qw,Xw,Kw,Ww,Jw,bm=b(()=>{"use strict";m();pe=require("zod");Do();Te();Zs();re();N();Fo=E("routes/run"),qw=pe.z.enum(["off","on","only-on-failure"]),Xw=pe.z.enum(["off","on","on-first-retry","retain-on-failure"]),Kw=pe.z.enum(["off","on","on-first-retry","retain-on-failure"]),Ww=pe.z.object({all:pe.z.boolean().optional(),suite:pe.z.string().optional(),tag:pe.z.string().optional(),test:pe.z.string().optional(),browsers:pe.z.array(pe.z.string()).optional(),env:pe.z.string().optional(),parallel:pe.z.number().int().positive().optional(),headed:pe.z.boolean().optional(),ci:pe.z.boolean().optional(),reporter:pe.z.array(pe.z.string()).optional(),noHealing:pe.z.boolean().optional(),screenshot:qw.optional(),video:Xw.optional(),trace:Kw.optional(),device:pe.z.string().optional()}),Jw=pe.z.object({limit:pe.z.coerce.number().int().positive().max(100).default(20)})});async function No(r){let e;if(r.startsWith("http://")||r.startsWith("https://")){let t=r;t.includes("#")&&(t=t.split("#")[0]);let s=t.replace(/\/$/,""),n=[t,`${t}.json`,`${s}/swagger.json`,`${s}/openapi.json`,`${s}/openapi.yaml`,`${s}/openapi.yml`,`${s}/swagger.yaml`,`${s}/api-docs`,`${s}/api-docs.json`,`${s}/v2/swagger.json`,`${s}/v2/openapi.yaml`,`${s}/v2/openapi.json`,`${s}/v3/api-docs`,`${s}/v3/openapi.yaml`,s.replace(/\/[^/]+$/,"")+"/swagger.json",s.replace(/\/[^/]+$/,"")+"/openapi.json",s.replace(/\/[^/]+$/,"")+"/openapi.yaml",s.replace(/\/[^/]+$/,"")+"/openapi.yml",s.replace(/\/[^/]+\/[^/]+$/,"")+"/openapi.yaml",s.replace(/\/[^/]+\/[^/]+$/,"")+"/swagger.json"];try{let c=await fetch(t,{headers:{Accept:"text/html, */*"},signal:AbortSignal.timeout(1e4)});if(c.ok){let l=await c.text();if(l.includes("<!")||l.includes("<html")){let u=[/Redoc\.init\(\s*['"]([^'"]+)['"]/,/spec-url=['"]([^'"]+)['"]/i,/url:\s*['"]([^'"]+\.(?:json|yaml|yml))['"]/,/specUrl:\s*['"]([^'"]+)['"]/,/["']([^"']*(?:openapi|swagger)[^"']*\.(?:json|yaml|yml))["']/i,/href=['"]([^'"]*\.(?:json|yaml|yml))['"][^>]*>.*?(?:openapi|swagger|spec|api-doc)/i];for(let d of u){let p=l.match(d);if(p?.[1]){let g=p[1];g.startsWith("/")?g=`${new URL(t).origin}${g}`:g.startsWith("http")||(g=new URL(g,t).href),n.unshift(g),ln.info({specUrl:g,pattern:d.source},"Extracted spec URL from HTML page")}}}}}catch{}let i=[...new Set(n)],a=!1,o=[];for(let c of i)try{ln.debug({tryUrl:c},"Trying to fetch OpenAPI spec");let l=await fetch(c,{headers:{Accept:"application/json, application/yaml, */*"},signal:AbortSignal.timeout(15e3)});if(l.ok){let u=l.headers.get("content-type")??"",d=await l.text(),p=u.includes("json")||d.trimStart().startsWith("{")||d.trimStart().startsWith("["),g=u.includes("yaml")||u.includes("yml")||c.endsWith(".yaml")||c.endsWith(".yml");if(p||g)try{if(e=p?JSON.parse(d):Ai.default.load(d),e&&(e.openapi||e.swagger||e.paths)){a=!0,ln.info({tryUrl:c,format:g?"YAML":"JSON"},"Successfully fetched OpenAPI spec");break}o.push(`${c}: Parsed but not a valid OpenAPI spec`)}catch{o.push(`${c}: Response is not valid ${g?"YAML":"JSON"}`)}else{if(!u.includes("html")&&!d.trimStart().startsWith("<!"))try{let f=Ai.default.load(d);if(f&&typeof f=="object"&&(f.openapi||f.swagger||f.paths)){e=f,a=!0,ln.info({tryUrl:c,format:"YAML (text/plain)"},"Successfully fetched OpenAPI spec");break}}catch{}o.push(`${c}: Response is HTML/text, not JSON or YAML (content-type: ${u})`)}}else o.push(`${c}: HTTP ${l.status}`)}catch(l){o.push(`${c}: ${l instanceof Error?l.message:String(l)}`)}if(!a)throw new Error(`Could not auto-discover the OpenAPI spec from this URL.
911
947
  This may be a developer portal that loads the spec dynamically.
912
948
 
913
949
  Try one of these instead:
@@ -917,8 +953,8 @@ Try one of these instead:
917
953
 
918
954
  Details:
919
955
  ${o.map(c=>` \u2022 ${c}`).join(`
920
- `)}`)}else try{e=JSON.parse(r)}catch{e=Ci.default.load(r)}return vw(e)}function vw(r){let t=(r.info??{}).title??"API",s="";r.servers&&Array.isArray(r.servers)&&r.servers.length>0?s=r.servers[0].url??"":r.host&&(s=`${r.schemes?.[0]??"https"}://${r.host}${r.basePath??""}`);let n=r.paths??{},i=[];for(let[a,o]of Object.entries(n))for(let[c,l]of Object.entries(o)){if(["get","post","put","delete","patch"].indexOf(c)===-1)continue;let u=l,d=u.tags??["Default"],g=u.summary??u.operationId??`${c.toUpperCase()} ${a}`,m=(u.parameters??[]).map(P=>({name:P.name,in:P.in,required:P.required??!1,type:P.schema?.type??P.type??"string"})),f;if(u.requestBody){let v=u.requestBody.content;if(v){let k=Object.keys(v)[0],R=v[k]?.schema??{},I=v[k]?.example??R.example;f={contentType:k,schema:R,example:I}}}let h=u.responses??{},C=Object.entries(h).map(([P,v])=>({status:parseInt(P,10)||0,description:v.description??""}));i.push({method:c.toUpperCase(),path:a,summary:g,tag:d[0],parameters:m,requestBody:f,responses:C})}return rn.info({title:t,endpointCount:i.length},"Parsed OpenAPI spec"),{title:t,baseUrl:s,endpoints:i}}var Ci,rn,rm=w(()=>{"use strict";p();Ci=x(require("js-yaml"));F();rn=E("swagger-parser")});function ko(r){let e=r.trim();if(/^[A-Z][A-Z0-9_]+-\d+$/i.test(e))return e.toUpperCase();try{let t=new URL(e),s=t.pathname.match(/\/browse\/([A-Z][A-Z0-9_]+-\d+)/i);if(s)return s[1].toUpperCase();let n=t.searchParams.get("selectedIssue");if(n&&/^[A-Z][A-Z0-9_]+-\d+$/i.test(n))return n.toUpperCase();let i=t.pathname.match(/\/issue\/([A-Z][A-Z0-9_]+-\d+)/i);if(i)return i[1].toUpperCase()}catch{let t=e.match(/([A-Z][A-Z0-9_]+-\d+)/i);if(t)return t[1].toUpperCase()}return null}function xw(){let r=process.env.JIRA_BASE_URL,e=process.env.JIRA_EMAIL,t=process.env.JIRA_API_TOKEN;return!r||!e||!t?null:{baseUrl:r.replace(/\/+$/,""),email:e,apiToken:t}}function Pi(r){if(!r||typeof r!="object")return"";let e=r;if(e.type==="text"&&typeof e.text=="string")return e.text;if(Array.isArray(e.content)){let t=e.content.map(n=>Pi(n)),s=new Set(["paragraph","heading","bulletList","orderedList","listItem","blockquote","codeBlock","rule"]);return typeof e.type=="string"&&s.has(e.type)?t.join("")+`
921
- `:t.join("")}return""}async function Ao(r){let e=xw();if(!e)throw new Error("Jira not configured \u2014 set JIRA_BASE_URL, JIRA_EMAIL, and JIRA_API_TOKEN in your .env file. [JIRA_NOT_CONFIGURED]");let t="Basic "+Buffer.from(`${e.email}:${e.apiToken}`).toString("base64"),s=`${e.baseUrl}/rest/api/3/issue/${encodeURIComponent(r)}?fields=summary,description,comment,issuetype,status,priority,labels,customfield_10020`;qt.info({issueKey:r,url:s.replace(/\/rest.*/,"/...")},"Fetching Jira issue");let n=await fetch(s,{method:"GET",headers:{Authorization:t,Accept:"application/json"}});if(n.status===401||n.status===403)throw new Error(`Jira authentication failed (${n.status}). Check JIRA_EMAIL and JIRA_API_TOKEN in your .env file.`);if(n.status===404)throw new Error(`Jira issue "${r}" not found. Verify the issue key and that your account has access.`);if(n.status===429)throw new Error("Jira API rate limit exceeded. Please try again in a few seconds.");if(!n.ok){let g=await n.text().catch(()=>"Unknown error");throw new Error(`Jira API returned ${n.status}: ${g}`)}let i=await n.json(),a=i.fields??{},o="";typeof a.description=="string"?o=a.description:a.description&&typeof a.description=="object"&&(o=Pi(a.description).trim());let c="",l=a.customfield_10020;if(typeof l=="string"?c=l:l&&typeof l=="object"&&(c=Pi(l).trim()),!c&&o){let g=o.match(/(?:acceptance\s+criteria|AC|given\s*\/?\s*when\s*\/?\s*then)[:\s]*\n?([\s\S]*?)(?:\n\n|\n(?=[A-Z])|\n(?=#{1,3}\s)|$)/i);g&&(c=g[1].trim())}let u=[],d=a.comment;if(d&&Array.isArray(d.comments))for(let g of d.comments.slice(-5)){let m=g.body,f=typeof m=="string"?m:m?Pi(m).trim():"";f&&u.push(f)}return{issueKey:String(i.key??r),summary:String(a.summary??""),description:o,acceptanceCriteria:c,comments:u,issueType:a.issuetype?.name??"Unknown",status:a.status?.name??"Unknown",priority:a.priority?.name??"Medium",labels:Array.isArray(a.labels)?a.labels:[]}}function sm(r,e){let t=[];return t.push(`## Jira Issue: ${r.issueKey}`),t.push(`**Summary:** ${r.summary}`),t.push(`**Type:** ${r.issueType} | **Status:** ${r.status} | **Priority:** ${r.priority}`),r.labels.length>0&&t.push(`**Labels:** ${r.labels.join(", ")}`),r.description&&t.push(`
956
+ `)}`)}else try{e=JSON.parse(r)}catch{e=Ai.default.load(r)}return Yw(e)}function Yw(r){let t=(r.info??{}).title??"API",s="";r.servers&&Array.isArray(r.servers)&&r.servers.length>0?s=r.servers[0].url??"":r.host&&(s=`${r.schemes?.[0]??"https"}://${r.host}${r.basePath??""}`);let n=r.paths??{},i=[];for(let[a,o]of Object.entries(n))for(let[c,l]of Object.entries(o)){if(["get","post","put","delete","patch"].indexOf(c)===-1)continue;let u=l,d=u.tags??["Default"],p=u.summary??u.operationId??`${c.toUpperCase()} ${a}`,g=(u.parameters??[]).map(I=>({name:I.name,in:I.in,required:I.required??!1,type:I.schema?.type??I.type??"string"})),f;if(u.requestBody){let v=u.requestBody.content;if(v){let k=Object.keys(v)[0],T=v[k]?.schema??{},P=v[k]?.example??T.example;f={contentType:k,schema:T,example:P}}}let h=u.responses??{},S=Object.entries(h).map(([I,v])=>({status:parseInt(I,10)||0,description:v.description??""}));i.push({method:c.toUpperCase(),path:a,summary:p,tag:d[0],parameters:g,requestBody:f,responses:S})}return ln.info({title:t,endpointCount:i.length},"Parsed OpenAPI spec"),{title:t,baseUrl:s,endpoints:i}}var Ai,ln,vm=b(()=>{"use strict";m();Ai=x(require("js-yaml"));N();ln=E("swagger-parser")});function Mo(r){let e=r.trim();if(/^[A-Z][A-Z0-9_]+-\d+$/i.test(e))return e.toUpperCase();try{let t=new URL(e),s=t.pathname.match(/\/browse\/([A-Z][A-Z0-9_]+-\d+)/i);if(s)return s[1].toUpperCase();let n=t.searchParams.get("selectedIssue");if(n&&/^[A-Z][A-Z0-9_]+-\d+$/i.test(n))return n.toUpperCase();let i=t.pathname.match(/\/issue\/([A-Z][A-Z0-9_]+-\d+)/i);if(i)return i[1].toUpperCase()}catch{let t=e.match(/([A-Z][A-Z0-9_]+-\d+)/i);if(t)return t[1].toUpperCase()}return null}function Qw(){let r=process.env.JIRA_BASE_URL,e=process.env.JIRA_EMAIL,t=process.env.JIRA_API_TOKEN;return!r||!e||!t?null:{baseUrl:r.replace(/\/+$/,""),email:e,apiToken:t}}function _i(r){if(!r||typeof r!="object")return"";let e=r;if(e.type==="text"&&typeof e.text=="string")return e.text;if(Array.isArray(e.content)){let t=e.content.map(n=>_i(n)),s=new Set(["paragraph","heading","bulletList","orderedList","listItem","blockquote","codeBlock","rule"]);return typeof e.type=="string"&&s.has(e.type)?t.join("")+`
957
+ `:t.join("")}return""}async function jo(r){let e=Qw();if(!e)throw new Error("Jira not configured \u2014 set JIRA_BASE_URL, JIRA_EMAIL, and JIRA_API_TOKEN in your .env file. [JIRA_NOT_CONFIGURED]");let t="Basic "+Buffer.from(`${e.email}:${e.apiToken}`).toString("base64"),s=`${e.baseUrl}/rest/api/3/issue/${encodeURIComponent(r)}?fields=summary,description,comment,issuetype,status,priority,labels,customfield_10020`;Yt.info({issueKey:r,url:s.replace(/\/rest.*/,"/...")},"Fetching Jira issue");let n=await fetch(s,{method:"GET",headers:{Authorization:t,Accept:"application/json"}});if(n.status===401||n.status===403)throw new Error(`Jira authentication failed (${n.status}). Check JIRA_EMAIL and JIRA_API_TOKEN in your .env file.`);if(n.status===404)throw new Error(`Jira issue "${r}" not found. Verify the issue key and that your account has access.`);if(n.status===429)throw new Error("Jira API rate limit exceeded. Please try again in a few seconds.");if(!n.ok){let p=await n.text().catch(()=>"Unknown error");throw new Error(`Jira API returned ${n.status}: ${p}`)}let i=await n.json(),a=i.fields??{},o="";typeof a.description=="string"?o=a.description:a.description&&typeof a.description=="object"&&(o=_i(a.description).trim());let c="",l=a.customfield_10020;if(typeof l=="string"?c=l:l&&typeof l=="object"&&(c=_i(l).trim()),!c&&o){let p=o.match(/(?:acceptance\s+criteria|AC|given\s*\/?\s*when\s*\/?\s*then)[:\s]*\n?([\s\S]*?)(?:\n\n|\n(?=[A-Z])|\n(?=#{1,3}\s)|$)/i);p&&(c=p[1].trim())}let u=[],d=a.comment;if(d&&Array.isArray(d.comments))for(let p of d.comments.slice(-5)){let g=p.body,f=typeof g=="string"?g:g?_i(g).trim():"";f&&u.push(f)}return{issueKey:String(i.key??r),summary:String(a.summary??""),description:o,acceptanceCriteria:c,comments:u,issueType:a.issuetype?.name??"Unknown",status:a.status?.name??"Unknown",priority:a.priority?.name??"Medium",labels:Array.isArray(a.labels)?a.labels:[]}}function xm(r,e){let t=[];return t.push(`## Jira Issue: ${r.issueKey}`),t.push(`**Summary:** ${r.summary}`),t.push(`**Type:** ${r.issueType} | **Status:** ${r.status} | **Priority:** ${r.priority}`),r.labels.length>0&&t.push(`**Labels:** ${r.labels.join(", ")}`),r.description&&t.push(`
922
958
  ### Description
923
959
  ${r.description}`),r.acceptanceCriteria&&t.push(`
924
960
  ### Acceptance Criteria
@@ -926,9 +962,9 @@ ${r.acceptanceCriteria}`),r.comments.length>0&&(t.push(`
926
962
  ### Relevant Comments`),r.comments.forEach((s,n)=>t.push(`${n+1}. ${s}`))),e&&e.trim()&&t.push(`
927
963
  ### Additional Context (User Input)
928
964
  ${e.trim()}`),t.join(`
929
- `)}async function nm(r){let e=r.rootDir;r.post("/story/fetch-jira",async(i,a)=>{let o=Cw.safeParse(i.body);if(!o.success)return a.status(400).send({error:"Invalid request",details:o.error.issues});let c=ko(o.data.jiraUrl);if(!c)return a.status(400).send({error:"Invalid Jira URL",details:"Could not extract an issue key. Expected format: https://domain.atlassian.net/browse/PROJ-123 or PROJ-123"});try{let l=await Ao(c);return a.status(200).send(l)}catch(l){let u=l instanceof Error&&l.message.includes("not configured")?400:l instanceof Error&&(l.message.includes("401")||l.message.includes("403"))?401:l instanceof Error&&l.message.includes("not found")?404:l instanceof Error&&l.message.includes("rate limit")?429:500;return b(a,u,"Failed to fetch Jira issue",l)}}),r.post("/story/generate",async(i,a)=>{let o=Sw.safeParse(i.body);if(!o.success)return a.status(400).send({error:"Invalid request",details:o.error.issues});try{let c=Ei.default.join(e,"tests"),l=o.data.story;if(o.data.jiraUrl){let g=ko(o.data.jiraUrl);if(g)try{let m=await Ao(g);l=sm(m,o.data.story||void 0),qt.info({issueKey:g},"Enriched story with Jira content")}catch(m){if(!l||l.length<10)return b(a,400,"Jira fetch failed and no user story provided",m);qt.warn({err:m},"Failed to fetch Jira issue \u2014 proceeding with user story only")}}if(!l||l.length<10)return a.status(400).send({error:"Not enough content to generate tests. Provide a story or a valid Jira link."});qt.info({suiteName:o.data.suiteName},"Story generation requested");let{suiteId:u,suiteName:d}=await zs(l,{rootDir:e,outputDir:c,suiteName:o.data.suiteName});return a.status(201).send({message:"Suite generated successfully",suiteId:u,suiteName:d})}catch(c){return b(a,500,"Failed to generate suite from story",c)}});let t=ge.z.object({story:ge.z.string().min(10),suiteName:ge.z.string().min(1).optional(),jiraUrl:ge.z.string().optional()}),s=ge.z.object({stories:ge.z.array(t).min(1).max(500),concurrency:ge.z.number().int().min(1).max(5).default(3)});r.post("/story/generate-bulk",async(i,a)=>{let o=s.safeParse(i.body);if(!o.success)return a.status(400).send({error:"Invalid request",details:o.error.issues});let{stories:c,concurrency:l}=o.data,u=Ei.default.join(e,"tests"),d=r.wsManager;qt.info({total:c.length,concurrency:l},"Bulk story generation requested");let g=await Promise.all(c.map(async m=>{if(!m.jiraUrl)return{story:m.story,suiteName:m.suiteName};let f=ko(m.jiraUrl);if(!f)return{story:m.story,suiteName:m.suiteName};try{let h=await Ao(f);return{story:sm(h,m.story),suiteName:m.suiteName??h.summary}}catch{return qt.warn({issueKey:f},"Failed to fetch Jira issue for bulk item \u2014 using raw story"),{story:m.story,suiteName:m.suiteName}}}));return Oa(g,{rootDir:e,outputDir:u},d,l).catch(m=>{qt.error({err:m},"Bulk story generation error")}),a.status(202).send({message:`Processing ${c.length} stories in the background`,total:c.length})}),r.post("/story/swagger-preview",async(i,a)=>{let o=i.body;if(!o.specUrl)return a.status(400).send({error:"specUrl is required"});try{let c=await To(o.specUrl),l=[...new Set(c.endpoints.map(u=>u.tag))];return a.send({title:c.title,baseUrl:c.baseUrl,totalEndpoints:c.endpoints.length,tags:l,endpoints:c.endpoints.map(u=>({method:u.method,path:u.path,summary:u.summary,tag:u.tag}))})}catch(c){return b(a,500,"Could not fetch OpenAPI spec",c)}});let n=ge.z.object({specUrl:ge.z.string().min(1,"Swagger/OpenAPI spec URL or JSON is required"),suiteName:ge.z.string().min(1).optional(),tags:ge.z.array(ge.z.string()).optional(),requirements:ge.z.string().optional()});r.post("/story/generate-from-swagger",{config:{requestTimeout:12e4}},async(i,a)=>{let o=n.safeParse(i.body);if(!o.success)return a.status(400).send({error:"Invalid request",details:o.error.issues});try{let c=await To(o.data.specUrl);qt.info({title:c.title,endpoints:c.endpoints.length},"Parsed OpenAPI spec");let l=c.endpoints;if(o.data.tags&&o.data.tags.length>0){let P=new Set(o.data.tags.map(v=>v.toLowerCase()));l=l.filter(v=>P.has(v.tag.toLowerCase()))}if(l.length===0)return a.status(400).send({error:"No endpoints found matching the specified tags"});let u=20,d=l.length;l.length>u&&(qt.warn({total:l.length,max:u},"Capping endpoints to max"),l=l.slice(0,u));let g=[`## API Test Suite: ${c.title}`,`Base URL: ${c.baseUrl}`,"","Generate API test cases for the following endpoints. Each test step should use Playwright request API (page.request.get/post/put/delete/patch). Include proper assertions for status codes and response bodies.",""];o.data.requirements?.trim()&&(g.push("### Additional Requirements"),g.push(o.data.requirements.trim()),g.push(""));for(let P of l)g.push(`### ${P.method} ${P.path}`),g.push(` Summary: ${P.summary}`),P.parameters.length>0&&g.push(` Parameters: ${P.parameters.map(v=>`${v.name} (${v.in}, ${v.type}${v.required?", required":""})`).join(", ")}`),P.requestBody&&(g.push(` Request Body: ${P.requestBody.contentType}`),P.requestBody.example&&g.push(` Example: ${JSON.stringify(P.requestBody.example)}`)),g.push(` Responses: ${P.responses.map(v=>`${v.status} (${v.description})`).join(", ")}`),g.push("");let m=g.join(`
930
- `),f=o.data.suiteName??`${c.title} API Tests`,h=Ei.default.join(e,"tests"),{suiteId:C}=await zs(m,{rootDir:e,outputDir:h,suiteName:f,type:"api"});return a.status(201).send({message:"API test suite generated from OpenAPI spec",suiteId:C,suiteName:f,endpointsFound:l.length,totalEndpoints:d,specTitle:c.title})}catch(c){return b(a,500,"Failed to generate suite from OpenAPI spec",c)}})}var Ei,ge,qt,Sw,Cw,im=w(()=>{"use strict";p();Ei=x(require("path")),ge=require("zod");dr();rm();ae();F();qt=E("routes/story");Sw=ge.z.object({story:ge.z.string().default(""),suiteName:ge.z.string().min(1).optional(),jiraUrl:ge.z.string().optional()}).refine(r=>r.story.length>=10||!!r.jiraUrl&&r.jiraUrl.trim().length>0,{message:"Provide a user story (\u2265 10 chars) or a Jira link",path:["story"]}),Cw=ge.z.object({jiraUrl:ge.z.string().min(1,"Jira URL is required")})});async function am(r){let e=r.rootDir;r.get("/report",async(t,s)=>{let n=Pw.safeParse(t.query);if(!n.success)return s.status(400).send({error:"Invalid query",details:n.error.issues});try{let i=await Bn(e,n.data.limit);return s.send(i)}catch(i){return b(s,500,"Failed to list reports",i)}}),r.get("/report/:runId",async(t,s)=>{try{let n=await Dr(e,t.params.runId);return s.send(n)}catch{return s.status(404).send({error:`Report for run "${t.params.runId}" not found`})}}),r.delete("/report/:runId",async(t,s)=>{try{return await Gu(e,t.params.runId),Ew.info({runId:t.params.runId},"Run result deleted"),s.status(204).send()}catch{return s.status(404).send({error:`Report for run "${t.params.runId}" not found`})}})}var $o,Ew,Pw,om=w(()=>{"use strict";p();$o=require("zod");Xs();ae();F();Ew=E("routes/report"),Pw=$o.z.object({limit:$o.z.coerce.number().int().positive().max(100).default(20)})});function cm(r){return _o.default.join(r,"results","baselines")}function lm(r,e){return _o.default.join(cm(r),`${e}.png`)}async function um(r,e,t){let s=cm(r);await Ii.default.ensureDir(s),await Ii.default.copy(t,lm(r,e),{overwrite:!0})}async function dm(r,e){return Ii.default.pathExists(lm(r,e))}var _o,Ii,pm=w(()=>{"use strict";p();_o=x(require("path")),Ii=x(require("fs-extra"))});async function mm(r){r.get("/results/:category/:filename",async(e,t)=>{let{category:s,filename:n}=e.params;if(!["screenshots","videos","traces","logs","baselines"].includes(s))return t.status(404).send({error:"Unknown media category"});let i=jr.default.basename(n),a=jr.default.join(r.rootDir,"results",s,i);if(!await ws.default.pathExists(a))return t.status(404).send({error:`File not found: ${i}`});let o=jr.default.extname(i).toLowerCase(),c=Iw[o]??"application/octet-stream";o===".zip"&&t.header("Content-Disposition",`attachment; filename="${i}"`);let l=await ws.default.stat(a);return t.header("Content-Length",l.size),t.type(c).send(ws.default.createReadStream(a))}),r.post("/baselines/:stepId/capture",async(e,t)=>{try{let s=e.body;if(!s?.screenshotPath)return t.status(400).send({error:"screenshotPath required"});let n=jr.default.isAbsolute(s.screenshotPath)?s.screenshotPath:jr.default.join(r.rootDir,s.screenshotPath);return await ws.default.pathExists(n)?(await um(r.rootDir,e.params.stepId,n),t.send({saved:!0})):t.status(404).send({error:"Screenshot not found"})}catch(s){return b(t,500,"Failed to save baseline",s)}}),r.get("/baselines/:stepId",async(e,t)=>{try{if(!await dm(r.rootDir,e.params.stepId))return t.send({hasBaseline:!1});let n=jr.default.join(r.rootDir,"results","baselines",`${e.params.stepId}.png`),i=await ws.default.stat(n).catch(()=>null);return t.send({hasBaseline:!0,capturedAt:i?.mtimeMs??Date.now()})}catch(s){return b(t,500,"Failed to check baseline",s)}})}var jr,ws,Iw,gm=w(()=>{"use strict";p();jr=x(require("path")),ws=x(require("fs-extra"));pm();ae();Iw={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webm":"video/webm",".mp4":"video/mp4",".zip":"application/zip",".log":"text/plain",".txt":"text/plain"}});function Ri(r){return{type:"doc",version:1,content:r.split(`
931
- `).map(t=>({type:"paragraph",content:t.trim()?[{type:"text",text:t}]:[]}))}}var N,Ti,fm=w(()=>{"use strict";p();F();N=E("xray-client");Ti=class{config;authHeader;xrayToken=null;constructor(e){this.config={...e,jiraBaseUrl:e.jiraBaseUrl.replace(/\/+$/,""),projectKey:e.projectKey.trim().toUpperCase()},this.authHeader="Basic "+Buffer.from(`${e.jiraEmail}:${e.jiraApiToken}`).toString("base64")}async jiraRequest(e,t,s){let n=`${this.config.jiraBaseUrl}/rest/api/3${t}`;N.debug({method:e,url:n},"Jira API request");let i={Authorization:this.authHeader,Accept:"application/json"};s!==void 0&&(i["Content-Type"]="application/json");let a=await fetch(n,{method:e,headers:i,body:s!==void 0?JSON.stringify(s):void 0});if(!a.ok){let o=await a.text();throw N.error({status:a.status,url:n,body:o},"Jira API error"),new Error(`Jira API ${e} ${t} \u2192 ${a.status}: ${o}`)}if(a.status!==204)return a.json()}async getXrayToken(){if(this.xrayToken)return this.xrayToken;if(!this.config.xrayClientId||!this.config.xrayClientSecret)return"";let e=await fetch("https://xray.cloud.getxray.app/api/v2/authenticate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_id:this.config.xrayClientId,client_secret:this.config.xrayClientSecret})});if(!e.ok){let t=await e.text();throw new Error(`Xray auth failed: ${e.status} \u2014 ${t}`)}return this.xrayToken=await e.json(),this.xrayToken}async xrayRequest(e,t,s){let n=await this.getXrayToken(),a=`${n?"https://xray.cloud.getxray.app/api/v2":`${this.config.jiraBaseUrl}/rest/raven/2.0/api`}${t}`;N.debug({method:e,url:a},"Xray API request");let o={Accept:"application/json"};n?o.Authorization=`Bearer ${n}`:o.Authorization=this.authHeader,s!==void 0&&(o["Content-Type"]="application/json");let c=await fetch(a,{method:e,headers:o,body:s!==void 0?JSON.stringify(s):void 0});if(!c.ok){let l=await c.text();throw N.error({status:c.status,url:a,body:l},"Xray API error"),new Error(`Xray API ${e} ${t} \u2192 ${c.status}: ${l}`)}if(c.status!==204)return c.json()}async findIssueByKey(e){try{return await this.jiraRequest("GET",`/issue/${e}`)}catch{return null}}async searchIssues(e,t=50){return(await this.jiraRequest("POST","/search",{jql:e,maxResults:t,fields:["summary","status","issuetype","labels","updated"]})).issues}async createTest(e,t,s){return this.isXrayCloud?this.createTestCloud(e,t,s):this.createTestServerDC(e,t)}async createTestCloud(e,t,s){let n=`[${t}] ${e.name}`,i=e.description||`Automated test case: ${e.name}`,a=e.steps.length>0?`steps: [${e.steps.map(m=>`{ action: ${JSON.stringify(m.instruction)}, data: ${JSON.stringify(m.generatedCode?`Strategy: ${m.strategy}`:"")}, result: "Step completes successfully" }`).join(`,
965
+ `)}async function Sm(r){let e=r.rootDir;r.post("/story/fetch-jira",async(i,a)=>{let o=eb.safeParse(i.body);if(!o.success)return a.status(400).send({error:"Invalid request",details:o.error.issues});let c=Mo(o.data.jiraUrl);if(!c)return a.status(400).send({error:"Invalid Jira URL",details:"Could not extract an issue key. Expected format: https://domain.atlassian.net/browse/PROJ-123 or PROJ-123"});try{let l=await jo(c);return a.status(200).send(l)}catch(l){let u=l instanceof Error&&l.message.includes("not configured")?400:l instanceof Error&&(l.message.includes("401")||l.message.includes("403"))?401:l instanceof Error&&l.message.includes("not found")?404:l instanceof Error&&l.message.includes("rate limit")?429:500;return w(a,u,"Failed to fetch Jira issue",l)}}),r.post("/story/generate",async(i,a)=>{let o=Zw.safeParse(i.body);if(!o.success)return a.status(400).send({error:"Invalid request",details:o.error.issues});try{let c=$i.default.join(e,"tests"),l=o.data.story;if(o.data.jiraUrl){let p=Mo(o.data.jiraUrl);if(p)try{let g=await jo(p);l=xm(g,o.data.story||void 0),Yt.info({issueKey:p},"Enriched story with Jira content")}catch(g){if(!l||l.length<10)return w(a,400,"Jira fetch failed and no user story provided",g);Yt.warn({err:g},"Failed to fetch Jira issue \u2014 proceeding with user story only")}}if(!l||l.length<10)return a.status(400).send({error:"Not enough content to generate tests. Provide a story or a valid Jira link."});Yt.info({suiteName:o.data.suiteName},"Story generation requested");let{suiteId:u,suiteName:d}=await Ys(l,{rootDir:e,outputDir:c,suiteName:o.data.suiteName});return a.status(201).send({message:"Suite generated successfully",suiteId:u,suiteName:d})}catch(c){return w(a,500,"Failed to generate suite from story",c)}});let t=me.z.object({story:me.z.string().min(10),suiteName:me.z.string().min(1).optional(),jiraUrl:me.z.string().optional()}),s=me.z.object({stories:me.z.array(t).min(1).max(500),concurrency:me.z.number().int().min(1).max(5).default(3)});r.post("/story/generate-bulk",async(i,a)=>{let o=s.safeParse(i.body);if(!o.success)return a.status(400).send({error:"Invalid request",details:o.error.issues});let{stories:c,concurrency:l}=o.data,u=$i.default.join(e,"tests"),d=r.wsManager;Yt.info({total:c.length,concurrency:l},"Bulk story generation requested");let p=await Promise.all(c.map(async g=>{if(!g.jiraUrl)return{story:g.story,suiteName:g.suiteName};let f=Mo(g.jiraUrl);if(!f)return{story:g.story,suiteName:g.suiteName};try{let h=await jo(f);return{story:xm(h,g.story),suiteName:g.suiteName??h.summary}}catch{return Yt.warn({issueKey:f},"Failed to fetch Jira issue for bulk item \u2014 using raw story"),{story:g.story,suiteName:g.suiteName}}}));return Ha(p,{rootDir:e,outputDir:u},d,l).catch(g=>{Yt.error({err:g},"Bulk story generation error")}),a.status(202).send({message:`Processing ${c.length} stories in the background`,total:c.length})}),r.post("/story/swagger-preview",async(i,a)=>{let o=i.body;if(!o.specUrl)return a.status(400).send({error:"specUrl is required"});try{let c=await No(o.specUrl),l=[...new Set(c.endpoints.map(u=>u.tag))];return a.send({title:c.title,baseUrl:c.baseUrl,totalEndpoints:c.endpoints.length,tags:l,endpoints:c.endpoints.map(u=>({method:u.method,path:u.path,summary:u.summary,tag:u.tag}))})}catch(c){return w(a,500,"Could not fetch OpenAPI spec",c)}});let n=me.z.object({specUrl:me.z.string().min(1,"Swagger/OpenAPI spec URL or JSON is required"),suiteName:me.z.string().min(1).optional(),tags:me.z.array(me.z.string()).optional(),requirements:me.z.string().optional()});r.post("/story/generate-from-swagger",{config:{requestTimeout:12e4}},async(i,a)=>{let o=n.safeParse(i.body);if(!o.success)return a.status(400).send({error:"Invalid request",details:o.error.issues});try{let c=await No(o.data.specUrl);Yt.info({title:c.title,endpoints:c.endpoints.length},"Parsed OpenAPI spec");let l=c.endpoints;if(o.data.tags&&o.data.tags.length>0){let I=new Set(o.data.tags.map(v=>v.toLowerCase()));l=l.filter(v=>I.has(v.tag.toLowerCase()))}if(l.length===0)return a.status(400).send({error:"No endpoints found matching the specified tags"});let u=20,d=l.length;l.length>u&&(Yt.warn({total:l.length,max:u},"Capping endpoints to max"),l=l.slice(0,u));let p=[`## API Test Suite: ${c.title}`,`Base URL: ${c.baseUrl}`,"","Generate API test cases for the following endpoints. Each test step should use Playwright request API (page.request.get/post/put/delete/patch). Include proper assertions for status codes and response bodies.",""];o.data.requirements?.trim()&&(p.push("### Additional Requirements"),p.push(o.data.requirements.trim()),p.push(""));for(let I of l)p.push(`### ${I.method} ${I.path}`),p.push(` Summary: ${I.summary}`),I.parameters.length>0&&p.push(` Parameters: ${I.parameters.map(v=>`${v.name} (${v.in}, ${v.type}${v.required?", required":""})`).join(", ")}`),I.requestBody&&(p.push(` Request Body: ${I.requestBody.contentType}`),I.requestBody.example&&p.push(` Example: ${JSON.stringify(I.requestBody.example)}`)),p.push(` Responses: ${I.responses.map(v=>`${v.status} (${v.description})`).join(", ")}`),p.push("");let g=p.join(`
966
+ `),f=o.data.suiteName??`${c.title} API Tests`,h=$i.default.join(e,"tests"),{suiteId:S}=await Ys(g,{rootDir:e,outputDir:h,suiteName:f,type:"api"});return a.status(201).send({message:"API test suite generated from OpenAPI spec",suiteId:S,suiteName:f,endpointsFound:l.length,totalEndpoints:d,specTitle:c.title})}catch(c){return w(a,500,"Failed to generate suite from OpenAPI spec",c)}})}var $i,me,Yt,Zw,eb,Cm=b(()=>{"use strict";m();$i=x(require("path")),me=require("zod");gr();vm();re();N();Yt=E("routes/story");Zw=me.z.object({story:me.z.string().default(""),suiteName:me.z.string().min(1).optional(),jiraUrl:me.z.string().optional()}).refine(r=>r.story.length>=10||!!r.jiraUrl&&r.jiraUrl.trim().length>0,{message:"Provide a user story (\u2265 10 chars) or a Jira link",path:["story"]}),eb=me.z.object({jiraUrl:me.z.string().min(1,"Jira URL is required")})});function Em(r,e){let t=Es.default.basename(e);return t!==e?null:Es.default.join(r,"results","downloads",t)}async function Im(r){let e=r.rootDir;r.get("/report",async(t,s)=>{let n=rb.safeParse(t.query);if(!n.success)return s.status(400).send({error:"Invalid query",details:n.error.issues});try{let i=await qn(e,n.data.limit);return s.send(i)}catch(i){return w(s,500,"Failed to list reports",i)}}),r.get("/report/:runId",async(t,s)=>{try{let n=await Br(e,t.params.runId);return s.send(n)}catch{return s.status(404).send({error:`Report for run "${t.params.runId}" not found`})}}),r.get("/report/:runId/downloads",async(t,s)=>{try{let n=Em(e,t.params.runId);if(!n||!await Cs.default.pathExists(n))return s.send([]);let i=await Cs.default.readdir(n,{withFileTypes:!0}),a=await Promise.all(i.filter(o=>o.isFile()).map(async o=>{let c=await Cs.default.stat(Es.default.join(n,o.name));return{name:o.name,size:c.size}}));return a.sort((o,c)=>o.name.localeCompare(c.name)),s.send(a)}catch(n){return w(s,500,"Failed to list downloads",n)}}),r.get("/report/:runId/downloads/:file",async(t,s)=>{try{let n=Em(e,t.params.runId),i=Es.default.basename(t.params.file);if(!n||i!==t.params.file)return s.status(400).send({error:"Invalid path"});let a=Es.default.join(n,i);return await Cs.default.pathExists(a)?(s.header("Content-Disposition",`attachment; filename="${i}"`),s.type("application/octet-stream"),s.send(Cs.default.createReadStream(a))):s.status(404).send({error:"File not found"})}catch(n){return w(s,500,"Failed to download file",n)}}),r.delete("/report/:runId",async(t,s)=>{try{return await cd(e,t.params.runId),tb.info({runId:t.params.runId},"Run result deleted"),s.status(204).send()}catch{return s.status(404).send({error:`Report for run "${t.params.runId}" not found`})}})}var Es,Cs,Bo,tb,rb,Pm=b(()=>{"use strict";m();Es=x(require("path")),Cs=x(require("fs-extra")),Bo=require("zod");Zs();re();N();tb=E("routes/report");rb=Bo.z.object({limit:Bo.z.coerce.number().int().positive().max(100).default(20)})});function Rm(r){return Uo.default.join(r,"results","baselines")}function Tm(r,e){return Uo.default.join(Rm(r),`${e}.png`)}async function km(r,e,t){let s=Rm(r);await Li.default.ensureDir(s),await Li.default.copy(t,Tm(r,e),{overwrite:!0})}async function Am(r,e){return Li.default.pathExists(Tm(r,e))}var Uo,Li,$m=b(()=>{"use strict";m();Uo=x(require("path")),Li=x(require("fs-extra"))});async function _m(r){r.get("/results/:category/:filename",async(e,t)=>{let{category:s,filename:n}=e.params;if(!["screenshots","videos","traces","logs","baselines"].includes(s))return t.status(404).send({error:"Unknown media category"});let i=Vr.default.basename(n),a=Vr.default.join(r.rootDir,"results",s,i);if(!await Is.default.pathExists(a))return t.status(404).send({error:`File not found: ${i}`});let o=Vr.default.extname(i).toLowerCase(),c=sb[o]??"application/octet-stream";o===".zip"&&t.header("Content-Disposition",`attachment; filename="${i}"`);let l=await Is.default.stat(a);return t.header("Content-Length",l.size),t.type(c).send(Is.default.createReadStream(a))}),r.post("/baselines/:stepId/capture",async(e,t)=>{try{let s=e.body;if(!s?.screenshotPath)return t.status(400).send({error:"screenshotPath required"});let n=Vr.default.isAbsolute(s.screenshotPath)?s.screenshotPath:Vr.default.join(r.rootDir,s.screenshotPath);return await Is.default.pathExists(n)?(await km(r.rootDir,e.params.stepId,n),t.send({saved:!0})):t.status(404).send({error:"Screenshot not found"})}catch(s){return w(t,500,"Failed to save baseline",s)}}),r.get("/baselines/:stepId",async(e,t)=>{try{if(!await Am(r.rootDir,e.params.stepId))return t.send({hasBaseline:!1});let n=Vr.default.join(r.rootDir,"results","baselines",`${e.params.stepId}.png`),i=await Is.default.stat(n).catch(()=>null);return t.send({hasBaseline:!0,capturedAt:i?.mtimeMs??Date.now()})}catch(s){return w(t,500,"Failed to check baseline",s)}})}var Vr,Is,sb,Lm=b(()=>{"use strict";m();Vr=x(require("path")),Is=x(require("fs-extra"));$m();re();sb={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webm":"video/webm",".mp4":"video/mp4",".zip":"application/zip",".log":"text/plain",".txt":"text/plain"}});function Oi(r){return{type:"doc",version:1,content:r.split(`
967
+ `).map(t=>({type:"paragraph",content:t.trim()?[{type:"text",text:t}]:[]}))}}var F,Di,Om=b(()=>{"use strict";m();N();F=E("xray-client");Di=class{config;authHeader;xrayToken=null;constructor(e){this.config={...e,jiraBaseUrl:e.jiraBaseUrl.replace(/\/+$/,""),projectKey:e.projectKey.trim().toUpperCase()},this.authHeader="Basic "+Buffer.from(`${e.jiraEmail}:${e.jiraApiToken}`).toString("base64")}async jiraRequest(e,t,s){let n=`${this.config.jiraBaseUrl}/rest/api/3${t}`;F.debug({method:e,url:n},"Jira API request");let i={Authorization:this.authHeader,Accept:"application/json"};s!==void 0&&(i["Content-Type"]="application/json");let a=await fetch(n,{method:e,headers:i,body:s!==void 0?JSON.stringify(s):void 0});if(!a.ok){let o=await a.text();throw F.error({status:a.status,url:n,body:o},"Jira API error"),new Error(`Jira API ${e} ${t} \u2192 ${a.status}: ${o}`)}if(a.status!==204)return a.json()}async getXrayToken(){if(this.xrayToken)return this.xrayToken;if(!this.config.xrayClientId||!this.config.xrayClientSecret)return"";let e=await fetch("https://xray.cloud.getxray.app/api/v2/authenticate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_id:this.config.xrayClientId,client_secret:this.config.xrayClientSecret})});if(!e.ok){let t=await e.text();throw new Error(`Xray auth failed: ${e.status} \u2014 ${t}`)}return this.xrayToken=await e.json(),this.xrayToken}async xrayRequest(e,t,s){let n=await this.getXrayToken(),a=`${n?"https://xray.cloud.getxray.app/api/v2":`${this.config.jiraBaseUrl}/rest/raven/2.0/api`}${t}`;F.debug({method:e,url:a},"Xray API request");let o={Accept:"application/json"};n?o.Authorization=`Bearer ${n}`:o.Authorization=this.authHeader,s!==void 0&&(o["Content-Type"]="application/json");let c=await fetch(a,{method:e,headers:o,body:s!==void 0?JSON.stringify(s):void 0});if(!c.ok){let l=await c.text();throw F.error({status:c.status,url:a,body:l},"Xray API error"),new Error(`Xray API ${e} ${t} \u2192 ${c.status}: ${l}`)}if(c.status!==204)return c.json()}async findIssueByKey(e){try{return await this.jiraRequest("GET",`/issue/${e}`)}catch{return null}}async searchIssues(e,t=50){return(await this.jiraRequest("POST","/search",{jql:e,maxResults:t,fields:["summary","status","issuetype","labels","updated"]})).issues}async createTest(e,t,s){return this.isXrayCloud?this.createTestCloud(e,t,s):this.createTestServerDC(e,t)}async createTestCloud(e,t,s){let n=`[${t}] ${e.name}`,i=e.description||`Automated test case: ${e.name}`,a=e.steps.length>0?`steps: [${e.steps.map(g=>`{ action: ${JSON.stringify(g.instruction)}, data: ${JSON.stringify(g.generatedCode?`Strategy: ${g.strategy}`:"")}, result: "Step completes successfully" }`).join(`,
932
968
  `)}],`:"",c=`mutation {
933
969
  createTest(
934
970
  testType: { name: "Manual" },
@@ -948,7 +984,7 @@ ${e.trim()}`),t.join(`
948
984
  }
949
985
  warnings
950
986
  }
951
- }`;N.info({caseName:e.name,projectKey:this.config.projectKey,folderPath:s},"Creating Test via Xray Cloud GraphQL");let l=await this.xrayGraphQL(c);if(!l?.createTest?.test)throw new Error("Xray createTest returned no test data");let u=l.createTest.test,d=u.jira?.key??"",g=l.createTest.warnings;return g&&g.length>0&&N.warn({warnings:g,jiraKey:d},"Xray createTest warnings"),N.info({issueId:u.issueId,jiraKey:d,stepCount:e.steps.length,folderPath:s},"Xray Test created via GraphQL"),{id:u.issueId,key:d,self:""}}async createTestServerDC(e,t){let s=this.config.testIssueType??"Test",n={project:{key:this.config.projectKey},summary:`[${t}] ${e.name}`,description:Ri(e.description||`Automated test case: ${e.name}`),issuetype:{name:s},labels:["assuremind",...e.tags]};N.info({caseName:e.name,projectKey:this.config.projectKey},"Creating Xray Test via Jira REST");let i=await this.jiraRequest("POST","/issue",{fields:n});return e.steps.length>0&&await this.addTestStepsServerDC(i.key,e.steps),{id:i.id,key:i.key,self:i.self}}async updateTest(e,t,s){let n={summary:`[${s}] ${t.name}`,description:Ri(t.description||`Automated test case: ${t.name}`),labels:["assuremind",...t.tags]};N.info({issueKey:e.key,caseName:t.name},"Updating Xray Test"),await this.jiraRequest("PUT",`/issue/${e.key}`,{fields:n}),t.steps.length>0&&await this.replaceTestSteps(e,t.steps)}async createTestSet(e,t){return this.isXrayCloud?this.createTestSetCloud(e,t):this.createTestSetServerDC(e)}async createTestSetCloud(e,t){let n=`mutation {
987
+ }`;F.info({caseName:e.name,projectKey:this.config.projectKey,folderPath:s},"Creating Test via Xray Cloud GraphQL");let l=await this.xrayGraphQL(c);if(!l?.createTest?.test)throw new Error("Xray createTest returned no test data");let u=l.createTest.test,d=u.jira?.key??"",p=l.createTest.warnings;return p&&p.length>0&&F.warn({warnings:p,jiraKey:d},"Xray createTest warnings"),F.info({issueId:u.issueId,jiraKey:d,stepCount:e.steps.length,folderPath:s},"Xray Test created via GraphQL"),{id:u.issueId,key:d,self:""}}async createTestServerDC(e,t){let s=this.config.testIssueType??"Test",n={project:{key:this.config.projectKey},summary:`[${t}] ${e.name}`,description:Oi(e.description||`Automated test case: ${e.name}`),issuetype:{name:s},labels:["assuremind",...e.tags]};F.info({caseName:e.name,projectKey:this.config.projectKey},"Creating Xray Test via Jira REST");let i=await this.jiraRequest("POST","/issue",{fields:n});return e.steps.length>0&&await this.addTestStepsServerDC(i.key,e.steps),{id:i.id,key:i.key,self:i.self}}async updateTest(e,t,s){let n={summary:`[${s}] ${t.name}`,description:Oi(t.description||`Automated test case: ${t.name}`),labels:["assuremind",...t.tags]};F.info({issueKey:e.key,caseName:t.name},"Updating Xray Test"),await this.jiraRequest("PUT",`/issue/${e.key}`,{fields:n}),t.steps.length>0&&await this.replaceTestSteps(e,t.steps)}async createTestSet(e,t){return this.isXrayCloud?this.createTestSetCloud(e,t):this.createTestSetServerDC(e)}async createTestSetCloud(e,t){let n=`mutation {
952
988
  createTestSet(
953
989
  ${t&&t.length>0?`testIssueIds: [${t.map(l=>`"${l}"`).join(", ")}],`:""}
954
990
  jira: {
@@ -965,7 +1001,7 @@ ${e.trim()}`),t.join(`
965
1001
  }
966
1002
  warnings
967
1003
  }
968
- }`;N.info({suiteName:e.name,projectKey:this.config.projectKey,testCount:t?.length},"Creating Test Set via Xray Cloud GraphQL");let i=await this.xrayGraphQL(n);if(!i?.createTestSet?.testSet)throw new Error("Xray createTestSet returned no data");let a=i.createTestSet.testSet,o=a.jira?.key??"",c=i.createTestSet.warnings;return c&&c.length>0&&N.warn({warnings:c,jiraKey:o},"Xray createTestSet warnings"),N.info({issueId:a.issueId,jiraKey:o},"Xray Test Set created via GraphQL"),{id:a.issueId,key:o,self:""}}async createTestSetServerDC(e){let t=this.config.testSetIssueType??"Test Set",s={project:{key:this.config.projectKey},summary:e.name,description:Ri(e.description||`Automated test suite: ${e.name}`),issuetype:{name:t},labels:["assuremind",...e.tags]};N.info({suiteName:e.name,projectKey:this.config.projectKey},"Creating Xray Test Set via Jira REST");let n=await this.jiraRequest("POST","/issue",{fields:s});return{id:n.id,key:n.key,self:n.self}}async updateTestSet(e,t){let s={summary:t.name,description:Ri(t.description||`Automated test suite: ${t.name}`),labels:["assuremind",...t.tags]};N.info({issueKey:e,suiteName:t.name},"Updating Xray Test Set"),await this.jiraRequest("PUT",`/issue/${e}`,{fields:s})}get isXrayCloud(){return!!(this.config.xrayClientId&&this.config.xrayClientSecret)}async addTestSteps(e,t){if(this.isXrayCloud){let s=await this.resolveXrayIssueId(e.key,"Test");if(!s){N.warn({testKey:e.key},"Cannot add steps \u2014 Test not found in Xray yet");return}await this.addTestStepsCloud(s,t)}else await this.addTestStepsServerDC(e.key,t)}async addTestStepsCloud(e,t){let s=0;for(let n of t){let i=n.instruction,a=n.generatedCode?`Generated code (strategy: ${n.strategy})`:"",o="Step completes successfully";try{await this.xrayGraphQL(`mutation {
1004
+ }`;F.info({suiteName:e.name,projectKey:this.config.projectKey,testCount:t?.length},"Creating Test Set via Xray Cloud GraphQL");let i=await this.xrayGraphQL(n);if(!i?.createTestSet?.testSet)throw new Error("Xray createTestSet returned no data");let a=i.createTestSet.testSet,o=a.jira?.key??"",c=i.createTestSet.warnings;return c&&c.length>0&&F.warn({warnings:c,jiraKey:o},"Xray createTestSet warnings"),F.info({issueId:a.issueId,jiraKey:o},"Xray Test Set created via GraphQL"),{id:a.issueId,key:o,self:""}}async createTestSetServerDC(e){let t=this.config.testSetIssueType??"Test Set",s={project:{key:this.config.projectKey},summary:e.name,description:Oi(e.description||`Automated test suite: ${e.name}`),issuetype:{name:t},labels:["assuremind",...e.tags]};F.info({suiteName:e.name,projectKey:this.config.projectKey},"Creating Xray Test Set via Jira REST");let n=await this.jiraRequest("POST","/issue",{fields:s});return{id:n.id,key:n.key,self:n.self}}async updateTestSet(e,t){let s={summary:t.name,description:Oi(t.description||`Automated test suite: ${t.name}`),labels:["assuremind",...t.tags]};F.info({issueKey:e,suiteName:t.name},"Updating Xray Test Set"),await this.jiraRequest("PUT",`/issue/${e}`,{fields:s})}get isXrayCloud(){return!!(this.config.xrayClientId&&this.config.xrayClientSecret)}async addTestSteps(e,t){if(this.isXrayCloud){let s=await this.resolveXrayIssueId(e.key,"Test");if(!s){F.warn({testKey:e.key},"Cannot add steps \u2014 Test not found in Xray yet");return}await this.addTestStepsCloud(s,t)}else await this.addTestStepsServerDC(e.key,t)}async addTestStepsCloud(e,t){let s=0;for(let n of t){let i=n.instruction,a=n.generatedCode?`Generated code (strategy: ${n.strategy})`:"",o="Step completes successfully";try{await this.xrayGraphQL(`mutation {
969
1005
  addTestStep(
970
1006
  issueId: "${e}",
971
1007
  step: {
@@ -977,7 +1013,7 @@ ${e.trim()}`),t.join(`
977
1013
  id
978
1014
  action
979
1015
  }
980
- }`),s++}catch(c){let l=c instanceof Error?c.message:String(c);if(l.includes("not found")){N.warn({xrayIssueId:e},"Xray issue not found during step add \u2014 aborting");break}N.warn({xrayIssueId:e,step:i,err:l},"Failed to add test step")}}s>0?N.info({xrayIssueId:e,added:s,total:t.length},"Test steps added via Xray Cloud GraphQL"):t.length>0&&N.warn({xrayIssueId:e},"Failed to add any steps")}async addTestStepsServerDC(e,t){let s=t.map((n,i)=>({index:i+1,action:n.instruction,data:n.generatedCode?`Generated code (strategy: ${n.strategy})`:"",result:"Step completes successfully"}));try{await this.xrayRequest("PUT",`/test/${e}/step`,s),N.debug({testIssueKey:e,stepCount:t.length},"Test steps added")}catch(n){N.warn({testIssueKey:e,err:n},"Bulk step add failed, trying one-by-one");for(let i of s)try{await this.xrayRequest("POST",`/test/${e}/step`,i)}catch(a){N.warn({testIssueKey:e,step:i.index,err:a},"Individual step add failed")}}}async replaceTestSteps(e,t){if(this.isXrayCloud){let s=await this.resolveXrayIssueId(e.key,"Test");if(!s){N.warn({testKey:e.key},"Cannot replace steps \u2014 Test not found in Xray");return}await this.addTestStepsCloud(s,t);return}try{let s=await this.xrayRequest("GET",`/test/${e.key}/step`);for(let n of s)await this.xrayRequest("DELETE",`/test/${e.key}/step/${n.id}`)}catch{N.debug({testIssueKey:e.key},"No existing steps to delete (or endpoint unavailable)")}await this.addTestStepsServerDC(e.key,t)}async linkTestsToTestSet(e,t){if(t.length!==0)if(this.isXrayCloud)await this.linkTestsCloud(e,t);else try{await this.xrayRequest("POST",`/testset/${e.key}/test`,{add:t.map(s=>s.key)}),N.info({testSetKey:e.key,count:t.length},"Tests linked to Test Set")}catch(s){N.warn({testSetKey:e.key,err:s},"Xray link API failed, trying Jira issue links"),await this.linkViaJiraIssueLinks(e.key,t.map(n=>n.key))}}async linkTestsCloud(e,t){N.info({testSetKey:e.key,testKeys:t.map(i=>i.key)},"Resolving Xray IDs for linking");let s=await this.resolveXrayIssueId(e.key,"Test Set");if(!s){N.error({testSetKey:e.key},"Cannot link \u2014 Test Set not found in Xray");return}let n=[];for(let i of t){let a=await this.resolveXrayIssueId(i.key,"Test");a?n.push(a):N.warn({testKey:i.key},"Could not resolve Xray ID for test \u2014 skipping")}if(n.length===0){N.warn({testSetKey:e.key},"No test IDs resolved \u2014 skipping link");return}try{let i=await this.xrayGraphQL(`mutation {
1016
+ }`),s++}catch(c){let l=c instanceof Error?c.message:String(c);if(l.includes("not found")){F.warn({xrayIssueId:e},"Xray issue not found during step add \u2014 aborting");break}F.warn({xrayIssueId:e,step:i,err:l},"Failed to add test step")}}s>0?F.info({xrayIssueId:e,added:s,total:t.length},"Test steps added via Xray Cloud GraphQL"):t.length>0&&F.warn({xrayIssueId:e},"Failed to add any steps")}async addTestStepsServerDC(e,t){let s=t.map((n,i)=>({index:i+1,action:n.instruction,data:n.generatedCode?`Generated code (strategy: ${n.strategy})`:"",result:"Step completes successfully"}));try{await this.xrayRequest("PUT",`/test/${e}/step`,s),F.debug({testIssueKey:e,stepCount:t.length},"Test steps added")}catch(n){F.warn({testIssueKey:e,err:n},"Bulk step add failed, trying one-by-one");for(let i of s)try{await this.xrayRequest("POST",`/test/${e}/step`,i)}catch(a){F.warn({testIssueKey:e,step:i.index,err:a},"Individual step add failed")}}}async replaceTestSteps(e,t){if(this.isXrayCloud){let s=await this.resolveXrayIssueId(e.key,"Test");if(!s){F.warn({testKey:e.key},"Cannot replace steps \u2014 Test not found in Xray");return}await this.addTestStepsCloud(s,t);return}try{let s=await this.xrayRequest("GET",`/test/${e.key}/step`);for(let n of s)await this.xrayRequest("DELETE",`/test/${e.key}/step/${n.id}`)}catch{F.debug({testIssueKey:e.key},"No existing steps to delete (or endpoint unavailable)")}await this.addTestStepsServerDC(e.key,t)}async linkTestsToTestSet(e,t){if(t.length!==0)if(this.isXrayCloud)await this.linkTestsCloud(e,t);else try{await this.xrayRequest("POST",`/testset/${e.key}/test`,{add:t.map(s=>s.key)}),F.info({testSetKey:e.key,count:t.length},"Tests linked to Test Set")}catch(s){F.warn({testSetKey:e.key,err:s},"Xray link API failed, trying Jira issue links"),await this.linkViaJiraIssueLinks(e.key,t.map(n=>n.key))}}async linkTestsCloud(e,t){F.info({testSetKey:e.key,testKeys:t.map(i=>i.key)},"Resolving Xray IDs for linking");let s=await this.resolveXrayIssueId(e.key,"Test Set");if(!s){F.error({testSetKey:e.key},"Cannot link \u2014 Test Set not found in Xray");return}let n=[];for(let i of t){let a=await this.resolveXrayIssueId(i.key,"Test");a?n.push(a):F.warn({testKey:i.key},"Could not resolve Xray ID for test \u2014 skipping")}if(n.length===0){F.warn({testSetKey:e.key},"No test IDs resolved \u2014 skipping link");return}try{let i=await this.xrayGraphQL(`mutation {
981
1017
  addTestsToTestSet(
982
1018
  issueId: "${s}",
983
1019
  testIssueIds: [${n.map(a=>`"${a}"`).join(", ")}]
@@ -985,7 +1021,7 @@ ${e.trim()}`),t.join(`
985
1021
  addedTests
986
1022
  warning
987
1023
  }
988
- }`);i&&N.info({testSetKey:e.key,xrayTestSetId:s,count:n.length,added:i.addTestsToTestSet?.addedTests?.length,warning:i.addTestsToTestSet?.warning},"Tests linked to Test Set via Xray Cloud")}catch(i){N.error({testSetKey:e.key,xrayTestSetId:s,err:i instanceof Error?i.message:String(i)},"linkTestsCloud failed")}}sleep(e){return new Promise(t=>setTimeout(t,e))}async linkViaJiraIssueLinks(e,t){for(let s of t)try{await this.jiraRequest("POST","/issueLink",{type:{name:"Test Set"},inwardIssue:{key:e},outwardIssue:{key:s}})}catch(n){N.error({testSetKey:e,testKey:s,err:n},"Failed to link test to test set")}}async createFolderAndAddTests(e,t){if(!this.isXrayCloud){N.debug("Folder creation skipped \u2014 only supported on Xray Cloud");return}if(t.length===0)return;let s=`/${e}`;try{let i=(await this.jiraRequest("GET",`/project/${this.config.projectKey}`)).id;try{await this.xrayGraphQL(`mutation {
1024
+ }`);i&&F.info({testSetKey:e.key,xrayTestSetId:s,count:n.length,added:i.addTestsToTestSet?.addedTests?.length,warning:i.addTestsToTestSet?.warning},"Tests linked to Test Set via Xray Cloud")}catch(i){F.error({testSetKey:e.key,xrayTestSetId:s,err:i instanceof Error?i.message:String(i)},"linkTestsCloud failed")}}sleep(e){return new Promise(t=>setTimeout(t,e))}async linkViaJiraIssueLinks(e,t){for(let s of t)try{await this.jiraRequest("POST","/issueLink",{type:{name:"Test Set"},inwardIssue:{key:e},outwardIssue:{key:s}})}catch(n){F.error({testSetKey:e,testKey:s,err:n},"Failed to link test to test set")}}async createFolderAndAddTests(e,t){if(!this.isXrayCloud){F.debug("Folder creation skipped \u2014 only supported on Xray Cloud");return}if(t.length===0)return;let s=`/${e}`;try{let i=(await this.jiraRequest("GET",`/project/${this.config.projectKey}`)).id;try{await this.xrayGraphQL(`mutation {
989
1025
  createFolder(
990
1026
  projectId: "${i}",
991
1027
  path: ${JSON.stringify(s)}
@@ -995,7 +1031,7 @@ ${e.trim()}`),t.join(`
995
1031
  path
996
1032
  }
997
1033
  }
998
- }`),N.info({folderPath:s,projectId:i},"Test Repository folder created")}catch(o){if((o instanceof Error?o.message:String(o)).includes("already exists"))N.info({folderPath:s},"Test Repository folder already exists \u2014 reusing");else throw o}let a=[];for(let o of t){let c=await this.resolveXrayIssueId(o.key,"Test");c?a.push(c):N.warn({testKey:o.key},"Could not resolve Xray ID for folder \u2014 skipping")}if(a.length===0){N.warn({folderPath:s},"No Xray IDs resolved \u2014 cannot add tests to folder");return}N.info({folderPath:s,xrayTestIds:a},"Adding tests to folder with resolved Xray IDs");try{await this.xrayGraphQL(`mutation {
1034
+ }`),F.info({folderPath:s,projectId:i},"Test Repository folder created")}catch(o){if((o instanceof Error?o.message:String(o)).includes("already exists"))F.info({folderPath:s},"Test Repository folder already exists \u2014 reusing");else throw o}let a=[];for(let o of t){let c=await this.resolveXrayIssueId(o.key,"Test");c?a.push(c):F.warn({testKey:o.key},"Could not resolve Xray ID for folder \u2014 skipping")}if(a.length===0){F.warn({folderPath:s},"No Xray IDs resolved \u2014 cannot add tests to folder");return}F.info({folderPath:s,xrayTestIds:a},"Adding tests to folder with resolved Xray IDs");try{await this.xrayGraphQL(`mutation {
999
1035
  addTestsToFolder(
1000
1036
  projectId: "${i}",
1001
1037
  path: ${JSON.stringify(s)},
@@ -1004,7 +1040,7 @@ ${e.trim()}`),t.join(`
1004
1040
  folder { name }
1005
1041
  warnings
1006
1042
  }
1007
- }`),N.info({folderPath:s,count:a.length},"Tests added to folder")}catch(o){N.warn({folderPath:s,err:o instanceof Error?o.message:String(o)},"Failed to add tests to folder")}}catch(n){N.error({folderName:e,err:n instanceof Error?n.message:String(n)},"FAILED to create folder or add tests \u2014 tests exist but are unorganized")}}async xrayGraphQL(e){let t=await this.getXrayToken(),n=await fetch("https://xray.cloud.getxray.app/api/v2/graphql",{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify({query:e})});if(!n.ok){let a=await n.text();throw N.warn({status:n.status,body:a},"Xray Cloud GraphQL request failed"),new Error(`Xray GraphQL \u2192 ${n.status}: ${a}`)}let i=await n.json();if(i.errors&&i.errors.length>0)throw N.warn({errors:i.errors},"Xray Cloud GraphQL returned errors"),new Error(`Xray GraphQL errors: ${i.errors.map(a=>a.message).join("; ")}`);return i.data??null}async resolveXrayIssueId(e,t="Test"){if(!this.isXrayCloud)return null;let s=t==="Test Set"?"getTestSets":"getTests",n=t==="Test Set"?"getTestSets":"getTests",i=[0,5e3,1e4,2e4];for(let a=0;a<i.length;a++){i[a]>0&&(N.info({jiraKey:e,attempt:a,delay:i[a]},`Waiting ${i[a]/1e3}s before retry`),await this.sleep(i[a]));try{let o=`{
1043
+ }`),F.info({folderPath:s,count:a.length},"Tests added to folder")}catch(o){F.warn({folderPath:s,err:o instanceof Error?o.message:String(o)},"Failed to add tests to folder")}}catch(n){F.error({folderName:e,err:n instanceof Error?n.message:String(n)},"FAILED to create folder or add tests \u2014 tests exist but are unorganized")}}async xrayGraphQL(e){let t=await this.getXrayToken(),n=await fetch("https://xray.cloud.getxray.app/api/v2/graphql",{method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify({query:e})});if(!n.ok){let a=await n.text();throw F.warn({status:n.status,body:a},"Xray Cloud GraphQL request failed"),new Error(`Xray GraphQL \u2192 ${n.status}: ${a}`)}let i=await n.json();if(i.errors&&i.errors.length>0)throw F.warn({errors:i.errors},"Xray Cloud GraphQL returned errors"),new Error(`Xray GraphQL errors: ${i.errors.map(a=>a.message).join("; ")}`);return i.data??null}async resolveXrayIssueId(e,t="Test"){if(!this.isXrayCloud)return null;let s=t==="Test Set"?"getTestSets":"getTests",n=t==="Test Set"?"getTestSets":"getTests",i=[0,5e3,1e4,2e4];for(let a=0;a<i.length;a++){i[a]>0&&(F.info({jiraKey:e,attempt:a,delay:i[a]},`Waiting ${i[a]/1e3}s before retry`),await this.sleep(i[a]));try{let o=`{
1008
1044
  ${s}(jql: "key = ${e}", limit: 1) {
1009
1045
  total
1010
1046
  results {
@@ -1012,23 +1048,23 @@ ${e.trim()}`),t.join(`
1012
1048
  jira(fields: ["key", "summary"])
1013
1049
  }
1014
1050
  }
1015
- }`;N.info({jiraKey:e,attempt:a,query:s},`Querying Xray for ${t} issueId`);let l=(await this.xrayGraphQL(o))?.[n];N.info({jiraKey:e,attempt:a,total:l?.total,resultCount:l?.results?.length,raw:JSON.stringify(l)},`Xray ${s} response`);let u=l?.results;if(u&&u.length>0&&u[0].issueId)return N.info({jiraKey:e,xrayIssueId:u[0].issueId,attempt:a},`Resolved Xray issueId for ${t}`),u[0].issueId;N.warn({jiraKey:e,attempt:a,total:l?.total},`Xray has not indexed ${t} yet \u2014 no results`)}catch(o){N.warn({jiraKey:e,attempt:a,err:o instanceof Error?o.message:String(o)},`resolveXrayIssueId attempt ${a} failed`)}}return N.error({jiraKey:e},`Could not resolve Xray issueId for ${t} after ${i.length} attempts`),null}async validate(){try{return{valid:!0,issueTypes:((await this.jiraRequest("GET",`/project/${this.config.projectKey}`)).issueTypes??[]).map(s=>s.name)}}catch(e){return{valid:!1,error:`Cannot connect to Jira project "${this.config.projectKey}": ${e instanceof Error?e.message:String(e)}`}}}}});var we,AI,Rw,Tw,hm,ym=w(()=>{"use strict";p();we=require("zod"),AI=we.z.enum(["not-created","created","synced","update-pending"]),Rw=we.z.object({caseId:we.z.string().min(1),xrayTestId:we.z.string().min(1),xrayTestIssueId:we.z.string().min(1),lastSyncedAt:we.z.string().datetime(),lastSyncHash:we.z.string()}),Tw=we.z.object({suiteId:we.z.string().min(1),xrayTestSetId:we.z.string().min(1),xrayTestSetIssueId:we.z.string().min(1),lastSyncedAt:we.z.string().datetime(),lastSyncHash:we.z.string(),cases:we.z.array(Rw).default([])}),hm=we.z.object({projectKey:we.z.string().min(1),suites:we.z.array(Tw).default([]),updatedAt:we.z.string().datetime()})});function bm(r){return Oo.default.join(r,"assuremind-data",kw)}async function vm(r){let e=bm(r);if(!await Lo.default.pathExists(e))return{projectKey:"",suites:[],updatedAt:new Date().toISOString()};let t=await de(e),s=hm.safeParse(t);return s.success?s.data:(wm.warn({path:e,errors:s.error.issues},"Invalid xray-mapping.json \u2014 returning empty"),{projectKey:"",suites:[],updatedAt:new Date().toISOString()})}async function Xt(r,e){let t=bm(r);await Lo.default.ensureDir(Oo.default.dirname(t));let s={...e,updatedAt:new Date().toISOString()};await K(t,s),wm.debug({path:t},"Xray mapping written")}function Kt(r,e){return r.suites.find(t=>t.suiteId===e)}function ki(r,e){for(let t of r.suites){let s=t.cases.find(n=>n.caseId===e);if(s)return{suiteMapping:t,caseMapping:s}}}function Wt(r,e){let t=r.suites.findIndex(n=>n.suiteId===e.suiteId),s=[...r.suites];return t>=0?s[t]=e:s.push(e),{...r,suites:s,updatedAt:new Date().toISOString()}}function sn(r,e){let t=r.cases.findIndex(n=>n.caseId===e.caseId),s=[...r.cases];return t>=0?s[t]=e:s.push(e),{...r,cases:s}}var Oo,Lo,wm,kw,xm=w(()=>{"use strict";p();Oo=x(require("path")),Lo=x(require("fs-extra"));ym();Ve();F();wm=E("xray-store"),kw="xray-mapping.json"});function Cm(r){return Sm.default.createHash("sha256").update(JSON.stringify(r)).digest("hex").slice(0,16)}function bs(r){return Cm({name:r.name,description:r.description,tags:r.tags})}function nn(r){return Cm({name:r.name,description:r.description,tags:r.tags,priority:r.priority,steps:r.steps.map(e=>({instruction:e.instruction,code:e.generatedCode}))})}var Sm,yt,Ai,Em=w(()=>{"use strict";p();Sm=x(require("crypto"));fm();xm();ze();dt();F();yt=E("xray-service");Ai=class{client;rootDir;testsDir;projectKey;constructor(e,t){this.rootDir=e,this.testsDir=`${e}/tests`,this.projectKey=t.projectKey.trim().toUpperCase(),this.client=new Ti(t)}async readMapping(){let e=await vm(this.rootDir);return e.projectKey||(e.projectKey=this.projectKey),e}async getAllStatuses(){let e=await this.readMapping(),t=await Pr(this.testsDir),s=[];for(let n of t)s.push(await this.getSuiteStatus(n,e));return s}async getSuiteStatusById(e){let t=await pe(this.testsDir,e);if(!t)return null;let s=await ve(t),n=await this.readMapping();return this.getSuiteStatus(s,n)}async getSuiteStatus(e,t){let s=Kt(t,e.id),n=await pe(this.testsDir,e.id),i=n?await qe(n):[],a="not-created";s&&(a=bs(e)===s.lastSyncHash?"synced":"update-pending");let o=i.map(c=>{let l=s?.cases.find(d=>d.caseId===c.id),u="not-created";return l&&(u=nn(c)===l.lastSyncHash?"synced":"update-pending"),{caseId:c.id,status:u,xrayTestId:l?.xrayTestId??null,lastSyncedAt:l?.lastSyncedAt??null}});return{suiteId:e.id,status:a,xrayTestSetId:s?.xrayTestSetId??null,lastSyncedAt:s?.lastSyncedAt??null,cases:o}}async createAll(){let e=await Pr(this.testsDir),t=[];for(let s of e){let n=await this.createSuite(s.id);t.push(...n.results)}return this.summarizeResults(t)}async createSuite(e){let t=await this.readMapping(),s=await pe(this.testsDir,e);if(!s)return this.summarizeResults([{success:!1,suiteId:e,action:"failed",error:"Suite not found"}]);let n=await ve(s),i=await qe(s),a=[],o=Kt(t,e);if(o)return yt.info({suiteId:e},"Suite already mapped in Xray \u2014 delegating to sync"),this.syncSuite(e);let c=`/${n.name}`,l=[];for(let g of i){let m=ki(t,g.id);if(m){a.push({success:!0,caseId:g.id,xrayKey:m.caseMapping.xrayTestId,action:"skipped"});continue}try{let f=await this.client.createTest(g,n.name,c),h=new Date().toISOString(),C={caseId:g.id,xrayTestId:f.key,xrayTestIssueId:f.id,lastSyncedAt:h,lastSyncHash:nn(g)};o||(o={suiteId:e,xrayTestSetId:"",xrayTestSetIssueId:"",lastSyncedAt:h,lastSyncHash:bs(n),cases:[]}),o=sn(o,C),t=Wt(t,o),await Xt(this.rootDir,t),l.push(f.id),a.push({success:!0,caseId:g.id,xrayKey:f.key,xrayId:f.id,action:"created"}),yt.info({caseId:g.id,xrayKey:f.key,xrayId:f.id},"Test created")}catch(f){a.push({success:!1,caseId:g.id,action:"failed",error:f instanceof Error?f.message:String(f)})}}let u=[],d=Kt(t,e);if(d)for(let g of d.cases)u.push({key:g.xrayTestId,id:g.xrayTestIssueId});if(u.length>0)try{await this.client.createFolderAndAddTests(n.name,u),yt.info({folderPath:c,testCount:u.length},"Tests organized into folder")}catch(g){yt.warn({folderPath:c,err:g instanceof Error?g.message:String(g)},"Folder organization failed (non-fatal)")}if(!Kt(t,e)?.xrayTestSetId)try{let g=await this.client.createTestSet(n,l.length>0?l:void 0),m=new Date().toISOString();o={...o,xrayTestSetId:g.key,xrayTestSetIssueId:g.id,lastSyncedAt:m,lastSyncHash:bs(n)},t=Wt(t,o),await Xt(this.rootDir,t),a.push({success:!0,suiteId:e,xrayKey:g.key,action:"created"}),yt.info({suiteId:e,xrayKey:g.key,testCount:l.length},"Test Set created with linked tests")}catch(g){a.push({success:!1,suiteId:e,action:"failed",error:g instanceof Error?g.message:String(g)})}return this.summarizeResults(a)}async createSingleCase(e,t){let s=await this.readMapping(),n=await pe(this.testsDir,e);if(!n)return this.summarizeResults([{success:!1,caseId:t,action:"failed",error:"Suite not found"}]);let i=await ve(n),o=(await qe(n)).find(d=>d.id===t);if(!o)return this.summarizeResults([{success:!1,caseId:t,action:"failed",error:"Test case not found"}]);let c=Kt(s,e);if(!c)try{let d=await this.client.createTestSet(i),g=new Date().toISOString();c={suiteId:e,xrayTestSetId:d.key,xrayTestSetIssueId:d.id,lastSyncedAt:g,lastSyncHash:bs(i),cases:[]},s=Wt(s,c),await Xt(this.rootDir,s)}catch(d){return this.summarizeResults([{success:!1,suiteId:e,action:"failed",error:`Failed to create parent Test Set: ${d instanceof Error?d.message:String(d)}`}])}let l=`/${i.name}`,u=await this.createCase(e,o,i.name,s,c,l);if(u.result.xrayKey&&u.result.xrayId)try{await this.client.createFolderAndAddTests(i.name,[{key:u.result.xrayKey,id:u.result.xrayId}])}catch(d){yt.warn({err:d instanceof Error?d.message:String(d)},"Folder organization failed for single case (non-fatal)")}if(u.result.xrayId&&c.xrayTestSetIssueId)try{await this.client.linkTestsToTestSet({key:c.xrayTestSetId,id:c.xrayTestSetIssueId},[{key:u.result.xrayKey??"",id:u.result.xrayId}])}catch(d){yt.warn({err:d instanceof Error?d.message:String(d)},"Failed to link test to test set")}return this.summarizeResults([u.result])}async createCase(e,t,s,n,i,a){let o=ki(n,t.id);if(o)return{result:{success:!0,caseId:t.id,xrayKey:o.caseMapping.xrayTestId,action:"skipped"},mapping:n};try{let c=await this.client.createTest(t,s,a),l=new Date().toISOString(),u={caseId:t.id,xrayTestId:c.key,xrayTestIssueId:c.id,lastSyncedAt:l,lastSyncHash:nn(t)},d=sn(i,u),g=Wt(n,d);return await Xt(this.rootDir,g),yt.info({caseId:t.id,xrayKey:c.key,xrayId:c.id},"Test created"),{result:{success:!0,caseId:t.id,xrayKey:c.key,xrayId:c.id,action:"created"},mapping:g}}catch(c){return{result:{success:!1,caseId:t.id,action:"failed",error:c instanceof Error?c.message:String(c)},mapping:n}}}async syncAll(){let e=await Pr(this.testsDir),t=[];for(let s of e){let n=await this.syncSuite(s.id);t.push(...n.results)}return this.summarizeResults(t)}async syncSuite(e){let t=await this.readMapping(),s=await pe(this.testsDir,e);if(!s)return this.summarizeResults([{success:!1,suiteId:e,action:"failed",error:"Suite not found"}]);let n=await ve(s),i=await qe(s),a=[],o=Kt(t,e);if(!o)return this.createSuite(e);if(!o.xrayTestSetId)try{let u=o.cases.map(m=>m.xrayTestIssueId).filter(Boolean),d=await this.client.createTestSet(n,u.length>0?u:void 0),g=new Date().toISOString();o={...o,xrayTestSetId:d.key,xrayTestSetIssueId:d.id,lastSyncedAt:g,lastSyncHash:bs(n)},t=Wt(t,o),await Xt(this.rootDir,t),a.push({success:!0,suiteId:e,xrayKey:d.key,action:"created"}),yt.info({suiteId:e,xrayKey:d.key},"Test Set created during sync (was missing)")}catch(u){a.push({success:!1,suiteId:e,action:"failed",error:`Failed to create Test Set: ${u instanceof Error?u.message:String(u)}`})}let c=bs(n);if(o.xrayTestSetId&&c!==o.lastSyncHash)try{await this.client.updateTestSet(o.xrayTestSetId,n),o={...o,lastSyncedAt:new Date().toISOString(),lastSyncHash:c},t=Wt(t,o),await Xt(this.rootDir,t),a.push({success:!0,suiteId:e,xrayKey:o.xrayTestSetId,action:"synced"})}catch(u){a.push({success:!1,suiteId:e,action:"failed",error:u instanceof Error?u.message:String(u)})}else c===o.lastSyncHash&&a.push({success:!0,suiteId:e,xrayKey:o.xrayTestSetId,action:"skipped"});let l=[];for(let u of i){let d=o.cases.find(m=>m.caseId===u.id);if(!d){let m=await this.createCase(e,u,n.name,t,o);a.push(m.result),t=m.mapping,o=Kt(t,e)??o,m.result.xrayKey&&l.push(m.result.xrayKey);continue}let g=nn(u);if(g===d.lastSyncHash){a.push({success:!0,caseId:u.id,xrayKey:d.xrayTestId,action:"skipped"});continue}try{await this.client.updateTest({key:d.xrayTestId,id:d.xrayTestIssueId},u,n.name);let m={...d,lastSyncedAt:new Date().toISOString(),lastSyncHash:g},f=sn(o,m);t=Wt(t,f),o=f,await Xt(this.rootDir,t),a.push({success:!0,caseId:u.id,xrayKey:d.xrayTestId,action:"synced"})}catch(m){a.push({success:!1,caseId:u.id,action:"failed",error:m instanceof Error?m.message:String(m)})}}if(l.length>0&&o.xrayTestSetId&&o.xrayTestSetIssueId)try{let u=Kt(t,e),d=l.map(g=>{let m=u?.cases.find(f=>f.xrayTestId===g);return m?{key:m.xrayTestId,id:m.xrayTestIssueId}:null}).filter(g=>g!==null);if(d.length>0){await this.client.linkTestsToTestSet({key:o.xrayTestSetId,id:o.xrayTestSetIssueId},d);try{await this.client.createFolderAndAddTests(n.name,d)}catch(g){yt.warn({err:g instanceof Error?g.message:String(g)},"Folder organization failed for synced tests (non-fatal)")}}}catch(u){yt.warn({err:u},"Failed to link new tests to test set")}return this.summarizeResults(a)}async syncSingleCase(e,t){let s=await this.readMapping(),n=await pe(this.testsDir,e);if(!n)return this.summarizeResults([{success:!1,caseId:t,action:"failed",error:"Suite not found"}]);let i=await ve(n),o=(await qe(n)).find(u=>u.id===t);if(!o)return this.summarizeResults([{success:!1,caseId:t,action:"failed",error:"Test case not found"}]);let c=ki(s,t);if(!c)return this.createSingleCase(e,t);let l=nn(o);if(l===c.caseMapping.lastSyncHash)return this.summarizeResults([{success:!0,caseId:t,xrayKey:c.caseMapping.xrayTestId,action:"skipped"}]);try{await this.client.updateTest({key:c.caseMapping.xrayTestId,id:c.caseMapping.xrayTestIssueId},o,i.name);let u={...c.caseMapping,lastSyncedAt:new Date().toISOString(),lastSyncHash:l},d=sn(c.suiteMapping,u),g=Wt(s,d);return await Xt(this.rootDir,g),this.summarizeResults([{success:!0,caseId:t,xrayKey:c.caseMapping.xrayTestId,action:"synced"}])}catch(u){return this.summarizeResults([{success:!1,caseId:t,action:"failed",error:u instanceof Error?u.message:String(u)}])}}async validate(){return this.client.validate()}summarizeResults(e){return{total:e.length,created:e.filter(t=>t.action==="created").length,synced:e.filter(t=>t.action==="synced").length,skipped:e.filter(t=>t.action==="skipped").length,failed:e.filter(t=>t.action==="failed").length,results:e}}}});function Pm(){let r=process.env.JIRA_BASE_URL,e=process.env.JIRA_EMAIL,t=process.env.JIRA_API_TOKEN,s=process.env.XRAY_PROJECT_KEY;return!r||!e||!t||!s?null:{jiraBaseUrl:r.replace(/\/+$/,""),jiraEmail:e,jiraApiToken:t,projectKey:s.trim().toUpperCase(),xrayClientId:process.env.XRAY_CLIENT_ID??void 0,xrayClientSecret:process.env.XRAY_CLIENT_SECRET??void 0,testIssueType:process.env.XRAY_TEST_ISSUE_TYPE??"Test",testSetIssueType:process.env.XRAY_TEST_SET_ISSUE_TYPE??"Test Set"}}async function Im(r){let e=r.rootDir;function t(){let n=Pm();return n?new Ai(e,n):null}function s(n){let i=t();return i||(n.status(422).send({error:"Xray integration not configured",detail:"Set JIRA_BASE_URL, JIRA_EMAIL, JIRA_API_TOKEN, and XRAY_PROJECT_KEY in your .env file.",code:"CONFIG_ERROR",featureHint:"XRAY_NOT_CONFIGURED"}),null)}r.get("/xray/enabled",async(n,i)=>{let a=Pm();return i.send({enabled:a!==null})}),r.get("/xray/status",async(n,i)=>{let a=s(i);if(a)try{let o=await a.getAllStatuses();return i.send(o)}catch(o){return b(i,500,"Failed to get Xray status",o)}}),r.get("/xray/status/:suiteId",async(n,i)=>{let a=s(i);if(a)try{let o=await a.getSuiteStatusById(n.params.suiteId);return o?i.send(o):i.status(404).send({error:"Suite not found"})}catch(o){return b(i,500,"Failed to get suite Xray status",o)}}),r.post("/xray/create-all",async(n,i)=>{let a=s(i);if(a)try{$i.info("Creating all suites and cases in Xray");let o=await a.createAll();return i.send(o)}catch(o){return b(i,500,"Failed to create in Xray",o)}}),r.post("/xray/create/suite/:suiteId",async(n,i)=>{let a=s(i);if(a)try{$i.info({suiteId:n.params.suiteId},"Creating suite in Xray");let o=await a.createSuite(n.params.suiteId);return i.send(o)}catch(o){return b(i,500,"Failed to create suite in Xray",o)}}),r.post("/xray/create/case/:suiteId/:caseId",async(n,i)=>{let a=s(i);if(a)try{let o=await a.createSingleCase(n.params.suiteId,n.params.caseId);return i.send(o)}catch(o){return b(i,500,"Failed to create case in Xray",o)}}),r.post("/xray/sync-all",async(n,i)=>{let a=s(i);if(a)try{$i.info("Syncing all suites and cases with Xray");let o=await a.syncAll();return i.send(o)}catch(o){return b(i,500,"Failed to sync with Xray",o)}}),r.post("/xray/sync/suite/:suiteId",async(n,i)=>{let a=s(i);if(a)try{$i.info({suiteId:n.params.suiteId},"Syncing suite with Xray");let o=await a.syncSuite(n.params.suiteId);return i.send(o)}catch(o){return b(i,500,"Failed to sync suite with Xray",o)}}),r.post("/xray/sync/case/:suiteId/:caseId",async(n,i)=>{let a=s(i);if(a)try{let o=await a.syncSingleCase(n.params.suiteId,n.params.caseId);return i.send(o)}catch(o){return b(i,500,"Failed to sync case with Xray",o)}}),r.get("/xray/validate",async(n,i)=>{let a=s(i);if(a)try{let o=await a.validate();return i.send(o)}catch(o){return b(i,500,"Failed to validate Xray connection",o)}})}var $i,Rm=w(()=>{"use strict";p();Em();ae();F();$i=E("xray-routes")});var Tm,Do,No,vs,xs,Mo=w(()=>{"use strict";p();Tm=x(require("simple-git")),Do=x(require("fs-extra")),No=x(require("path"));F();vs=E("git-service"),xs=class{git;rootDir;wsManager;constructor(e,t){this.rootDir=e,this.wsManager=t,this.git=(0,Tm.default)({baseDir:e,binary:"git",maxConcurrentProcesses:6,trimmed:!1})}broadcastLog(e,t,s){this.wsManager?.broadcast("git:log",{step:e,status:t,message:s,timestamp:Date.now()})}broadcastConflict(e){this.wsManager?.broadcast("git:conflict",{files:e})}broadcastDone(e){this.wsManager?.broadcast("git:operation-done",{operation:e})}async getStatus(){let e=await this.git.status();return{branch:e.current??"HEAD (detached)",tracking:e.tracking??null,isClean:e.isClean(),modified:e.modified,added:e.created,deleted:e.deleted,untracked:e.not_added,staged:e.staged,ahead:e.ahead,behind:e.behind,conflicted:e.conflicted}}async getBranches(){let e=await this.git.branchLocal(),t=[];try{t=(await this.git.branch(["-r"])).all}catch{}return{current:e.current,all:e.all,remote:t}}async checkout(e){this.broadcastLog("Checkout branch","running");try{await this.git.checkout(e),this.broadcastLog("Checkout branch","done",e),vs.info({branch:e},"Switched branch")}catch(t){let s=t instanceof Error?t.message:String(t);throw this.broadcastLog("Checkout branch","error",s),t}}async commit(e){this.broadcastLog("Stage files","running"),await this.git.add("."),this.broadcastLog("Stage files","done"),this.broadcastLog("Create commit","running");try{let s=(await this.git.commit(e)).commit||"unknown";return this.broadcastLog("Create commit","done",s),this.broadcastDone("commit"),vs.info({hash:s,message:e},"Commit created"),s}catch(t){let s=t instanceof Error?t.message:String(t);throw this.broadcastLog("Create commit","error",s),t}}async pull(e=!1){let t=e?"Pull with rebase":"Pull latest changes";this.broadcastLog(t,"running");try{let s=e?{"--rebase":null}:{};await this.git.pull(void 0,void 0,s),this.broadcastLog(t,"done",e?"Rebase successful":"Pull successful"),this.broadcastDone("pull"),vs.info({rebase:e},"Pull completed")}catch(s){let n=s instanceof Error?s.message:String(s);if(n.includes("CONFLICT")||n.includes("conflict")||n.includes("could not apply")){this.broadcastLog(t,"error","Merge conflict detected");let i=await this.git.status();i.conflicted.length>0&&this.broadcastConflict(i.conflicted)}else this.broadcastLog(t,"error",n);throw s}}async push(){this.broadcastLog("Push to origin","running");try{await this.git.push(),this.broadcastLog("Push to origin","done"),this.broadcastDone("push"),vs.info("Push completed")}catch(e){let t=e instanceof Error?e.message:String(e);throw this.broadcastLog("Push to origin","error",t),e}}async fullSync(e){try{this.broadcastLog("Pull with rebase","running");try{await this.git.pull(void 0,void 0,{"--rebase":null}),this.broadcastLog("Pull with rebase","done","Rebase successful")}catch(s){let n=s instanceof Error?s.message:String(s);if(n.includes("CONFLICT")||n.includes("conflict")||n.includes("could not apply")){this.broadcastLog("Pull with rebase","error","Merge conflict detected");let i=await this.git.status();throw i.conflicted.length>0&&this.broadcastConflict(i.conflicted),s}this.broadcastLog("Pull with rebase","done","Skipped (no remote or up to date)")}if(this.broadcastLog("Stage files","running"),await this.git.add("."),this.broadcastLog("Stage files","done"),this.broadcastLog("Create commit","running"),(await this.git.status()).isClean())this.broadcastLog("Create commit","done","Nothing to commit (clean)");else{let s=await this.git.commit(e);this.broadcastLog("Create commit","done",s.commit||"done")}this.broadcastLog("Push to origin","running");try{await this.git.push(),this.broadcastLog("Push to origin","done")}catch(s){let n=s instanceof Error?s.message:String(s);throw this.broadcastLog("Push to origin","error",n),s}this.broadcastDone("full-sync"),vs.info("Full sync completed")}catch(t){throw this.broadcastDone("full-sync"),t}}async getLog(e=30){return(await this.git.log({maxCount:e})).all.map(s=>({hash:s.hash,shortHash:s.hash.slice(0,7),date:s.date,message:s.message,author:s.author_name}))}async getDiff(e=!1){if(e)return this.git.diff(["--cached"]);let t=await this.git.diff();return[await this.git.diff(["--cached"]),t].filter(Boolean).join(`
1016
- `)}async getConflictedFiles(){return(await this.git.status()).conflicted}async getFileConflictContent(e){let t=No.default.join(this.rootDir,e),s=await Do.default.readFile(t,"utf-8"),n="",i="",a="none";for(let o of s.split(`
1051
+ }`;F.info({jiraKey:e,attempt:a,query:s},`Querying Xray for ${t} issueId`);let l=(await this.xrayGraphQL(o))?.[n];F.info({jiraKey:e,attempt:a,total:l?.total,resultCount:l?.results?.length,raw:JSON.stringify(l)},`Xray ${s} response`);let u=l?.results;if(u&&u.length>0&&u[0].issueId)return F.info({jiraKey:e,xrayIssueId:u[0].issueId,attempt:a},`Resolved Xray issueId for ${t}`),u[0].issueId;F.warn({jiraKey:e,attempt:a,total:l?.total},`Xray has not indexed ${t} yet \u2014 no results`)}catch(o){F.warn({jiraKey:e,attempt:a,err:o instanceof Error?o.message:String(o)},`resolveXrayIssueId attempt ${a} failed`)}}return F.error({jiraKey:e},`Could not resolve Xray issueId for ${t} after ${i.length} attempts`),null}async validate(){try{return{valid:!0,issueTypes:((await this.jiraRequest("GET",`/project/${this.config.projectKey}`)).issueTypes??[]).map(s=>s.name)}}catch(e){return{valid:!1,error:`Cannot connect to Jira project "${this.config.projectKey}": ${e instanceof Error?e.message:String(e)}`}}}}});var he,uR,nb,ib,Dm,Fm=b(()=>{"use strict";m();he=require("zod"),uR=he.z.enum(["not-created","created","synced","update-pending"]),nb=he.z.object({caseId:he.z.string().min(1),xrayTestId:he.z.string().min(1),xrayTestIssueId:he.z.string().min(1),lastSyncedAt:he.z.string().datetime(),lastSyncHash:he.z.string()}),ib=he.z.object({suiteId:he.z.string().min(1),xrayTestSetId:he.z.string().min(1),xrayTestSetIssueId:he.z.string().min(1),lastSyncedAt:he.z.string().datetime(),lastSyncHash:he.z.string(),cases:he.z.array(nb).default([])}),Dm=he.z.object({projectKey:he.z.string().min(1),suites:he.z.array(ib).default([]),updatedAt:he.z.string().datetime()})});function Mm(r){return Ho.default.join(r,"assuremind-data",ab)}async function jm(r){let e=Mm(r);if(!await Vo.default.pathExists(e))return{projectKey:"",suites:[],updatedAt:new Date().toISOString()};let t=await ue(e),s=Dm.safeParse(t);return s.success?s.data:(Nm.warn({path:e,errors:s.error.issues},"Invalid xray-mapping.json \u2014 returning empty"),{projectKey:"",suites:[],updatedAt:new Date().toISOString()})}async function Qt(r,e){let t=Mm(r);await Vo.default.ensureDir(Ho.default.dirname(t));let s={...e,updatedAt:new Date().toISOString()};await K(t,s),Nm.debug({path:t},"Xray mapping written")}function Zt(r,e){return r.suites.find(t=>t.suiteId===e)}function Fi(r,e){for(let t of r.suites){let s=t.cases.find(n=>n.caseId===e);if(s)return{suiteMapping:t,caseMapping:s}}}function er(r,e){let t=r.suites.findIndex(n=>n.suiteId===e.suiteId),s=[...r.suites];return t>=0?s[t]=e:s.push(e),{...r,suites:s,updatedAt:new Date().toISOString()}}function un(r,e){let t=r.cases.findIndex(n=>n.caseId===e.caseId),s=[...r.cases];return t>=0?s[t]=e:s.push(e),{...r,cases:s}}var Ho,Vo,Nm,ab,Bm=b(()=>{"use strict";m();Ho=x(require("path")),Vo=x(require("fs-extra"));Fm();ze();N();Nm=E("xray-store"),ab="xray-mapping.json"});function Hm(r){return Um.default.createHash("sha256").update(JSON.stringify(r)).digest("hex").slice(0,16)}function Ps(r){return Hm({name:r.name,description:r.description,tags:r.tags})}function dn(r){return Hm({name:r.name,description:r.description,tags:r.tags,priority:r.priority,steps:r.steps.map(e=>({instruction:e.instruction,code:e.generatedCode}))})}var Um,xt,Ni,Vm=b(()=>{"use strict";m();Um=x(require("crypto"));Om();Bm();Xe();gt();N();xt=E("xray-service");Ni=class{client;rootDir;testsDir;projectKey;constructor(e,t){this.rootDir=e,this.testsDir=`${e}/tests`,this.projectKey=t.projectKey.trim().toUpperCase(),this.client=new Di(t)}async readMapping(){let e=await jm(this.rootDir);return e.projectKey||(e.projectKey=this.projectKey),e}async getAllStatuses(){let e=await this.readMapping(),t=await kr(this.testsDir),s=[];for(let n of t)s.push(await this.getSuiteStatus(n,e));return s}async getSuiteStatusById(e){let t=await de(this.testsDir,e);if(!t)return null;let s=await ve(t),n=await this.readMapping();return this.getSuiteStatus(s,n)}async getSuiteStatus(e,t){let s=Zt(t,e.id),n=await de(this.testsDir,e.id),i=n?await Ke(n):[],a="not-created";s&&(a=Ps(e)===s.lastSyncHash?"synced":"update-pending");let o=i.map(c=>{let l=s?.cases.find(d=>d.caseId===c.id),u="not-created";return l&&(u=dn(c)===l.lastSyncHash?"synced":"update-pending"),{caseId:c.id,status:u,xrayTestId:l?.xrayTestId??null,lastSyncedAt:l?.lastSyncedAt??null}});return{suiteId:e.id,status:a,xrayTestSetId:s?.xrayTestSetId??null,lastSyncedAt:s?.lastSyncedAt??null,cases:o}}async createAll(){let e=await kr(this.testsDir),t=[];for(let s of e){let n=await this.createSuite(s.id);t.push(...n.results)}return this.summarizeResults(t)}async createSuite(e){let t=await this.readMapping(),s=await de(this.testsDir,e);if(!s)return this.summarizeResults([{success:!1,suiteId:e,action:"failed",error:"Suite not found"}]);let n=await ve(s),i=await Ke(s),a=[],o=Zt(t,e);if(o)return xt.info({suiteId:e},"Suite already mapped in Xray \u2014 delegating to sync"),this.syncSuite(e);let c=`/${n.name}`,l=[];for(let p of i){let g=Fi(t,p.id);if(g){a.push({success:!0,caseId:p.id,xrayKey:g.caseMapping.xrayTestId,action:"skipped"});continue}try{let f=await this.client.createTest(p,n.name,c),h=new Date().toISOString(),S={caseId:p.id,xrayTestId:f.key,xrayTestIssueId:f.id,lastSyncedAt:h,lastSyncHash:dn(p)};o||(o={suiteId:e,xrayTestSetId:"",xrayTestSetIssueId:"",lastSyncedAt:h,lastSyncHash:Ps(n),cases:[]}),o=un(o,S),t=er(t,o),await Qt(this.rootDir,t),l.push(f.id),a.push({success:!0,caseId:p.id,xrayKey:f.key,xrayId:f.id,action:"created"}),xt.info({caseId:p.id,xrayKey:f.key,xrayId:f.id},"Test created")}catch(f){a.push({success:!1,caseId:p.id,action:"failed",error:f instanceof Error?f.message:String(f)})}}let u=[],d=Zt(t,e);if(d)for(let p of d.cases)u.push({key:p.xrayTestId,id:p.xrayTestIssueId});if(u.length>0)try{await this.client.createFolderAndAddTests(n.name,u),xt.info({folderPath:c,testCount:u.length},"Tests organized into folder")}catch(p){xt.warn({folderPath:c,err:p instanceof Error?p.message:String(p)},"Folder organization failed (non-fatal)")}if(!Zt(t,e)?.xrayTestSetId)try{let p=await this.client.createTestSet(n,l.length>0?l:void 0),g=new Date().toISOString();o={...o,xrayTestSetId:p.key,xrayTestSetIssueId:p.id,lastSyncedAt:g,lastSyncHash:Ps(n)},t=er(t,o),await Qt(this.rootDir,t),a.push({success:!0,suiteId:e,xrayKey:p.key,action:"created"}),xt.info({suiteId:e,xrayKey:p.key,testCount:l.length},"Test Set created with linked tests")}catch(p){a.push({success:!1,suiteId:e,action:"failed",error:p instanceof Error?p.message:String(p)})}return this.summarizeResults(a)}async createSingleCase(e,t){let s=await this.readMapping(),n=await de(this.testsDir,e);if(!n)return this.summarizeResults([{success:!1,caseId:t,action:"failed",error:"Suite not found"}]);let i=await ve(n),o=(await Ke(n)).find(d=>d.id===t);if(!o)return this.summarizeResults([{success:!1,caseId:t,action:"failed",error:"Test case not found"}]);let c=Zt(s,e);if(!c)try{let d=await this.client.createTestSet(i),p=new Date().toISOString();c={suiteId:e,xrayTestSetId:d.key,xrayTestSetIssueId:d.id,lastSyncedAt:p,lastSyncHash:Ps(i),cases:[]},s=er(s,c),await Qt(this.rootDir,s)}catch(d){return this.summarizeResults([{success:!1,suiteId:e,action:"failed",error:`Failed to create parent Test Set: ${d instanceof Error?d.message:String(d)}`}])}let l=`/${i.name}`,u=await this.createCase(e,o,i.name,s,c,l);if(u.result.xrayKey&&u.result.xrayId)try{await this.client.createFolderAndAddTests(i.name,[{key:u.result.xrayKey,id:u.result.xrayId}])}catch(d){xt.warn({err:d instanceof Error?d.message:String(d)},"Folder organization failed for single case (non-fatal)")}if(u.result.xrayId&&c.xrayTestSetIssueId)try{await this.client.linkTestsToTestSet({key:c.xrayTestSetId,id:c.xrayTestSetIssueId},[{key:u.result.xrayKey??"",id:u.result.xrayId}])}catch(d){xt.warn({err:d instanceof Error?d.message:String(d)},"Failed to link test to test set")}return this.summarizeResults([u.result])}async createCase(e,t,s,n,i,a){let o=Fi(n,t.id);if(o)return{result:{success:!0,caseId:t.id,xrayKey:o.caseMapping.xrayTestId,action:"skipped"},mapping:n};try{let c=await this.client.createTest(t,s,a),l=new Date().toISOString(),u={caseId:t.id,xrayTestId:c.key,xrayTestIssueId:c.id,lastSyncedAt:l,lastSyncHash:dn(t)},d=un(i,u),p=er(n,d);return await Qt(this.rootDir,p),xt.info({caseId:t.id,xrayKey:c.key,xrayId:c.id},"Test created"),{result:{success:!0,caseId:t.id,xrayKey:c.key,xrayId:c.id,action:"created"},mapping:p}}catch(c){return{result:{success:!1,caseId:t.id,action:"failed",error:c instanceof Error?c.message:String(c)},mapping:n}}}async syncAll(){let e=await kr(this.testsDir),t=[];for(let s of e){let n=await this.syncSuite(s.id);t.push(...n.results)}return this.summarizeResults(t)}async syncSuite(e){let t=await this.readMapping(),s=await de(this.testsDir,e);if(!s)return this.summarizeResults([{success:!1,suiteId:e,action:"failed",error:"Suite not found"}]);let n=await ve(s),i=await Ke(s),a=[],o=Zt(t,e);if(!o)return this.createSuite(e);if(!o.xrayTestSetId)try{let u=o.cases.map(g=>g.xrayTestIssueId).filter(Boolean),d=await this.client.createTestSet(n,u.length>0?u:void 0),p=new Date().toISOString();o={...o,xrayTestSetId:d.key,xrayTestSetIssueId:d.id,lastSyncedAt:p,lastSyncHash:Ps(n)},t=er(t,o),await Qt(this.rootDir,t),a.push({success:!0,suiteId:e,xrayKey:d.key,action:"created"}),xt.info({suiteId:e,xrayKey:d.key},"Test Set created during sync (was missing)")}catch(u){a.push({success:!1,suiteId:e,action:"failed",error:`Failed to create Test Set: ${u instanceof Error?u.message:String(u)}`})}let c=Ps(n);if(o.xrayTestSetId&&c!==o.lastSyncHash)try{await this.client.updateTestSet(o.xrayTestSetId,n),o={...o,lastSyncedAt:new Date().toISOString(),lastSyncHash:c},t=er(t,o),await Qt(this.rootDir,t),a.push({success:!0,suiteId:e,xrayKey:o.xrayTestSetId,action:"synced"})}catch(u){a.push({success:!1,suiteId:e,action:"failed",error:u instanceof Error?u.message:String(u)})}else c===o.lastSyncHash&&a.push({success:!0,suiteId:e,xrayKey:o.xrayTestSetId,action:"skipped"});let l=[];for(let u of i){let d=o.cases.find(g=>g.caseId===u.id);if(!d){let g=await this.createCase(e,u,n.name,t,o);a.push(g.result),t=g.mapping,o=Zt(t,e)??o,g.result.xrayKey&&l.push(g.result.xrayKey);continue}let p=dn(u);if(p===d.lastSyncHash){a.push({success:!0,caseId:u.id,xrayKey:d.xrayTestId,action:"skipped"});continue}try{await this.client.updateTest({key:d.xrayTestId,id:d.xrayTestIssueId},u,n.name);let g={...d,lastSyncedAt:new Date().toISOString(),lastSyncHash:p},f=un(o,g);t=er(t,f),o=f,await Qt(this.rootDir,t),a.push({success:!0,caseId:u.id,xrayKey:d.xrayTestId,action:"synced"})}catch(g){a.push({success:!1,caseId:u.id,action:"failed",error:g instanceof Error?g.message:String(g)})}}if(l.length>0&&o.xrayTestSetId&&o.xrayTestSetIssueId)try{let u=Zt(t,e),d=l.map(p=>{let g=u?.cases.find(f=>f.xrayTestId===p);return g?{key:g.xrayTestId,id:g.xrayTestIssueId}:null}).filter(p=>p!==null);if(d.length>0){await this.client.linkTestsToTestSet({key:o.xrayTestSetId,id:o.xrayTestSetIssueId},d);try{await this.client.createFolderAndAddTests(n.name,d)}catch(p){xt.warn({err:p instanceof Error?p.message:String(p)},"Folder organization failed for synced tests (non-fatal)")}}}catch(u){xt.warn({err:u},"Failed to link new tests to test set")}return this.summarizeResults(a)}async syncSingleCase(e,t){let s=await this.readMapping(),n=await de(this.testsDir,e);if(!n)return this.summarizeResults([{success:!1,caseId:t,action:"failed",error:"Suite not found"}]);let i=await ve(n),o=(await Ke(n)).find(u=>u.id===t);if(!o)return this.summarizeResults([{success:!1,caseId:t,action:"failed",error:"Test case not found"}]);let c=Fi(s,t);if(!c)return this.createSingleCase(e,t);let l=dn(o);if(l===c.caseMapping.lastSyncHash)return this.summarizeResults([{success:!0,caseId:t,xrayKey:c.caseMapping.xrayTestId,action:"skipped"}]);try{await this.client.updateTest({key:c.caseMapping.xrayTestId,id:c.caseMapping.xrayTestIssueId},o,i.name);let u={...c.caseMapping,lastSyncedAt:new Date().toISOString(),lastSyncHash:l},d=un(c.suiteMapping,u),p=er(s,d);return await Qt(this.rootDir,p),this.summarizeResults([{success:!0,caseId:t,xrayKey:c.caseMapping.xrayTestId,action:"synced"}])}catch(u){return this.summarizeResults([{success:!1,caseId:t,action:"failed",error:u instanceof Error?u.message:String(u)}])}}async validate(){return this.client.validate()}summarizeResults(e){return{total:e.length,created:e.filter(t=>t.action==="created").length,synced:e.filter(t=>t.action==="synced").length,skipped:e.filter(t=>t.action==="skipped").length,failed:e.filter(t=>t.action==="failed").length,results:e}}}});function Gm(){let r=process.env.JIRA_BASE_URL,e=process.env.JIRA_EMAIL,t=process.env.JIRA_API_TOKEN,s=process.env.XRAY_PROJECT_KEY;return!r||!e||!t||!s?null:{jiraBaseUrl:r.replace(/\/+$/,""),jiraEmail:e,jiraApiToken:t,projectKey:s.trim().toUpperCase(),xrayClientId:process.env.XRAY_CLIENT_ID??void 0,xrayClientSecret:process.env.XRAY_CLIENT_SECRET??void 0,testIssueType:process.env.XRAY_TEST_ISSUE_TYPE??"Test",testSetIssueType:process.env.XRAY_TEST_SET_ISSUE_TYPE??"Test Set"}}async function zm(r){let e=r.rootDir;function t(){let n=Gm();return n?new Ni(e,n):null}function s(n){let i=t();return i||(n.status(422).send({error:"Xray integration not configured",detail:"Set JIRA_BASE_URL, JIRA_EMAIL, JIRA_API_TOKEN, and XRAY_PROJECT_KEY in your .env file.",code:"CONFIG_ERROR",featureHint:"XRAY_NOT_CONFIGURED"}),null)}r.get("/xray/enabled",async(n,i)=>{let a=Gm();return i.send({enabled:a!==null})}),r.get("/xray/status",async(n,i)=>{let a=s(i);if(a)try{let o=await a.getAllStatuses();return i.send(o)}catch(o){return w(i,500,"Failed to get Xray status",o)}}),r.get("/xray/status/:suiteId",async(n,i)=>{let a=s(i);if(a)try{let o=await a.getSuiteStatusById(n.params.suiteId);return o?i.send(o):i.status(404).send({error:"Suite not found"})}catch(o){return w(i,500,"Failed to get suite Xray status",o)}}),r.post("/xray/create-all",async(n,i)=>{let a=s(i);if(a)try{Mi.info("Creating all suites and cases in Xray");let o=await a.createAll();return i.send(o)}catch(o){return w(i,500,"Failed to create in Xray",o)}}),r.post("/xray/create/suite/:suiteId",async(n,i)=>{let a=s(i);if(a)try{Mi.info({suiteId:n.params.suiteId},"Creating suite in Xray");let o=await a.createSuite(n.params.suiteId);return i.send(o)}catch(o){return w(i,500,"Failed to create suite in Xray",o)}}),r.post("/xray/create/case/:suiteId/:caseId",async(n,i)=>{let a=s(i);if(a)try{let o=await a.createSingleCase(n.params.suiteId,n.params.caseId);return i.send(o)}catch(o){return w(i,500,"Failed to create case in Xray",o)}}),r.post("/xray/sync-all",async(n,i)=>{let a=s(i);if(a)try{Mi.info("Syncing all suites and cases with Xray");let o=await a.syncAll();return i.send(o)}catch(o){return w(i,500,"Failed to sync with Xray",o)}}),r.post("/xray/sync/suite/:suiteId",async(n,i)=>{let a=s(i);if(a)try{Mi.info({suiteId:n.params.suiteId},"Syncing suite with Xray");let o=await a.syncSuite(n.params.suiteId);return i.send(o)}catch(o){return w(i,500,"Failed to sync suite with Xray",o)}}),r.post("/xray/sync/case/:suiteId/:caseId",async(n,i)=>{let a=s(i);if(a)try{let o=await a.syncSingleCase(n.params.suiteId,n.params.caseId);return i.send(o)}catch(o){return w(i,500,"Failed to sync case with Xray",o)}}),r.get("/xray/validate",async(n,i)=>{let a=s(i);if(a)try{let o=await a.validate();return i.send(o)}catch(o){return w(i,500,"Failed to validate Xray connection",o)}})}var Mi,qm=b(()=>{"use strict";m();Vm();re();N();Mi=E("xray-routes")});var Xm,Go,zo,Rs,Ts,qo=b(()=>{"use strict";m();Xm=x(require("simple-git")),Go=x(require("fs-extra")),zo=x(require("path"));N();Rs=E("git-service"),Ts=class{git;rootDir;wsManager;constructor(e,t){this.rootDir=e,this.wsManager=t,this.git=(0,Xm.default)({baseDir:e,binary:"git",maxConcurrentProcesses:6,trimmed:!1})}broadcastLog(e,t,s){this.wsManager?.broadcast("git:log",{step:e,status:t,message:s,timestamp:Date.now()})}broadcastConflict(e){this.wsManager?.broadcast("git:conflict",{files:e})}broadcastDone(e){this.wsManager?.broadcast("git:operation-done",{operation:e})}async getStatus(){let e=await this.git.status();return{branch:e.current??"HEAD (detached)",tracking:e.tracking??null,isClean:e.isClean(),modified:e.modified,added:e.created,deleted:e.deleted,untracked:e.not_added,staged:e.staged,ahead:e.ahead,behind:e.behind,conflicted:e.conflicted}}async getBranches(){let e=await this.git.branchLocal(),t=[];try{t=(await this.git.branch(["-r"])).all}catch{}return{current:e.current,all:e.all,remote:t}}async checkout(e){this.broadcastLog("Checkout branch","running");try{await this.git.checkout(e),this.broadcastLog("Checkout branch","done",e),Rs.info({branch:e},"Switched branch")}catch(t){let s=t instanceof Error?t.message:String(t);throw this.broadcastLog("Checkout branch","error",s),t}}async commit(e){this.broadcastLog("Stage files","running"),await this.git.add("."),this.broadcastLog("Stage files","done"),this.broadcastLog("Create commit","running");try{let s=(await this.git.commit(e)).commit||"unknown";return this.broadcastLog("Create commit","done",s),this.broadcastDone("commit"),Rs.info({hash:s,message:e},"Commit created"),s}catch(t){let s=t instanceof Error?t.message:String(t);throw this.broadcastLog("Create commit","error",s),t}}async pull(e=!1){let t=e?"Pull with rebase":"Pull latest changes";this.broadcastLog(t,"running");try{let s=e?{"--rebase":null}:{};await this.git.pull(void 0,void 0,s),this.broadcastLog(t,"done",e?"Rebase successful":"Pull successful"),this.broadcastDone("pull"),Rs.info({rebase:e},"Pull completed")}catch(s){let n=s instanceof Error?s.message:String(s);if(n.includes("CONFLICT")||n.includes("conflict")||n.includes("could not apply")){this.broadcastLog(t,"error","Merge conflict detected");let i=await this.git.status();i.conflicted.length>0&&this.broadcastConflict(i.conflicted)}else this.broadcastLog(t,"error",n);throw s}}async push(){this.broadcastLog("Push to origin","running");try{await this.git.push(),this.broadcastLog("Push to origin","done"),this.broadcastDone("push"),Rs.info("Push completed")}catch(e){let t=e instanceof Error?e.message:String(e);throw this.broadcastLog("Push to origin","error",t),e}}async fullSync(e){try{this.broadcastLog("Pull with rebase","running");try{await this.git.pull(void 0,void 0,{"--rebase":null}),this.broadcastLog("Pull with rebase","done","Rebase successful")}catch(s){let n=s instanceof Error?s.message:String(s);if(n.includes("CONFLICT")||n.includes("conflict")||n.includes("could not apply")){this.broadcastLog("Pull with rebase","error","Merge conflict detected");let i=await this.git.status();throw i.conflicted.length>0&&this.broadcastConflict(i.conflicted),s}this.broadcastLog("Pull with rebase","done","Skipped (no remote or up to date)")}if(this.broadcastLog("Stage files","running"),await this.git.add("."),this.broadcastLog("Stage files","done"),this.broadcastLog("Create commit","running"),(await this.git.status()).isClean())this.broadcastLog("Create commit","done","Nothing to commit (clean)");else{let s=await this.git.commit(e);this.broadcastLog("Create commit","done",s.commit||"done")}this.broadcastLog("Push to origin","running");try{await this.git.push(),this.broadcastLog("Push to origin","done")}catch(s){let n=s instanceof Error?s.message:String(s);throw this.broadcastLog("Push to origin","error",n),s}this.broadcastDone("full-sync"),Rs.info("Full sync completed")}catch(t){throw this.broadcastDone("full-sync"),t}}async getLog(e=30){return(await this.git.log({maxCount:e})).all.map(s=>({hash:s.hash,shortHash:s.hash.slice(0,7),date:s.date,message:s.message,author:s.author_name}))}async getDiff(e=!1){if(e)return this.git.diff(["--cached"]);let t=await this.git.diff();return[await this.git.diff(["--cached"]),t].filter(Boolean).join(`
1052
+ `)}async getConflictedFiles(){return(await this.git.status()).conflicted}async getFileConflictContent(e){let t=zo.default.join(this.rootDir,e),s=await Go.default.readFile(t,"utf-8"),n="",i="",a="none";for(let o of s.split(`
1017
1053
  `)){if(o.startsWith("<<<<<<<")){a="ours";continue}if(o.startsWith("=======")){a="theirs";continue}if(o.startsWith(">>>>>>>")){a="none";continue}a==="ours"?n+=o+`
1018
1054
  `:a==="theirs"&&(i+=o+`
1019
- `)}return{ours:n.trimEnd(),theirs:i.trimEnd()}}async resolveConflict(e,t){let s=No.default.join(this.rootDir,e);await Do.default.writeFile(s,t,"utf-8"),await this.git.add(e),vs.info({filePath:e},"Conflict resolved")}async continueRebase(){this.broadcastLog("Continuing rebase...","running");try{await this.git.rebase(["--continue"]),this.broadcastLog("Rebase continued","done")}catch(e){let t=e instanceof Error?e.message:String(e);throw this.broadcastLog(`Rebase continue failed: ${t}`,"error"),e}}async abortRebase(){this.broadcastLog("Aborting rebase...","running");try{await this.git.rebase(["--abort"]),this.broadcastLog("Rebase aborted","done")}catch(e){let t=e instanceof Error?e.message:String(e);throw this.broadcastLog(`Rebase abort failed: ${t}`,"error"),e}}}});function km(r){return{url:"git://local",title:"Git Operations",interactiveElements:"",htmlSnapshot:r,previousSteps:[],variables:{}}}async function Am(r){if(!r.trim())return"chore: update files";let e=8e3,t=r.length>e?r.slice(0,e)+`
1055
+ `)}return{ours:n.trimEnd(),theirs:i.trimEnd()}}async resolveConflict(e,t){let s=zo.default.join(this.rootDir,e);await Go.default.writeFile(s,t,"utf-8"),await this.git.add(e),Rs.info({filePath:e},"Conflict resolved")}async continueRebase(){this.broadcastLog("Continuing rebase...","running");try{await this.git.rebase(["--continue"]),this.broadcastLog("Rebase continued","done")}catch(e){let t=e instanceof Error?e.message:String(e);throw this.broadcastLog(`Rebase continue failed: ${t}`,"error"),e}}async abortRebase(){this.broadcastLog("Aborting rebase...","running");try{await this.git.rebase(["--abort"]),this.broadcastLog("Rebase aborted","done")}catch(e){let t=e instanceof Error?e.message:String(e);throw this.broadcastLog(`Rebase abort failed: ${t}`,"error"),e}}}});function Km(r){return{url:"git://local",title:"Git Operations",interactiveElements:"",htmlSnapshot:r,previousSteps:[],variables:{}}}async function Wm(r){if(!r.trim())return"chore: update files";let e=8e3,t=r.length>e?r.slice(0,e)+`
1020
1056
  ... (diff truncated)`:r,s=["You are a developer writing a git commit message. Write it the way a human would \u2014 natural, specific, and varied.","Use Conventional Commits format: type(scope): description","Types: feat, fix, chore, refactor, docs, test, style, perf, ci, build","","Rules:","- Be specific about WHAT changed, not generic",`- Vary your word choices \u2014 don't always start with "add", "update", or "fix"`,'- Use active voice: "streamline login flow" not "login flow was streamlined"',"- Keep it under 72 characters","- Sound like a real developer, not a robot","- Each message should feel unique even for similar changes","",'Bad examples (too generic): "update files", "fix bug", "make changes"','Good examples: "feat(cart): wire up quantity stepper with debounced save", "fix(auth): guard against expired refresh tokens on silent renew", "refactor: collapse duplicated validation into shared helper"',"","Return ONLY the commit message. No quotes, no explanation, no markdown.","","Diff:","```",t,"```"].join(`
1021
- `);try{let a=(await Tr(void 0,{temperature:.4}).generateCode(s,km(t))).trim();return a=a.replace(/^["'`]+|["'`]+$/g,""),a=a.replace(/^(commit message:?\s*)/i,""),a=a.split(`
1022
- `)[0].trim(),_i.info({messageLength:a.length},"AI commit message generated"),a||"chore: update files"}catch(n){return _i.warn({err:n instanceof Error?n.message:String(n)},"AI commit message generation failed"),"chore: update files"}}async function $m(r,e,t){let s=[`Merge these two conflicting versions of the file "${t}" into a single resolved version.`,"Combine changes from both sides intelligently. Preserve the intent of both changes.","Return ONLY the merged file content, no explanation, no markdown code blocks.","","=== LOCAL VERSION (ours) ===",r,"","=== INCOMING VERSION (theirs) ===",e].join(`
1023
- `),n=km(`Conflict in: ${t}
1057
+ `);try{let a=(await Lr(void 0,{temperature:.4}).generateCode(s,Km(t))).trim();return a=a.replace(/^["'`]+|["'`]+$/g,""),a=a.replace(/^(commit message:?\s*)/i,""),a=a.split(`
1058
+ `)[0].trim(),ji.info({messageLength:a.length},"AI commit message generated"),a||"chore: update files"}catch(n){return ji.warn({err:n instanceof Error?n.message:String(n)},"AI commit message generation failed"),"chore: update files"}}async function Jm(r,e,t){let s=[`Merge these two conflicting versions of the file "${t}" into a single resolved version.`,"Combine changes from both sides intelligently. Preserve the intent of both changes.","Return ONLY the merged file content, no explanation, no markdown code blocks.","","=== LOCAL VERSION (ours) ===",r,"","=== INCOMING VERSION (theirs) ===",e].join(`
1059
+ `),n=Km(`Conflict in: ${t}
1024
1060
 
1025
1061
  Ours:
1026
1062
  ${r}
1027
1063
 
1028
1064
  Theirs:
1029
- ${e}`);try{let a=await Tr(void 0,{temperature:.4}).generateCode(s,n);return a=a.replace(/^```[\w]*\n?/,"").replace(/\n?```$/,""),_i.info({filePath:t,resultLength:a.length},"AI conflict resolution generated"),a}catch(i){throw _i.warn({filePath:t,err:i instanceof Error?i.message:String(i)},"AI conflict resolution failed"),i}}var _i,_m=w(()=>{"use strict";p();dr();F();_i=E("git-ai")});async function Om(r){let e=r.rootDir,t=r.wsManager,s=new xs(e,t),n=null,i=async()=>{if(n!==null)return n;try{await s.getStatus(),n=!0}catch{n=!1,Aw.info("Project directory is not a git repository \u2014 git features disabled")}return n},a={error:"not-a-git-repo",message:'Project directory is not a git repository. Run "git init" to enable git features.'};r.get("/git/status",async(o,c)=>{try{if(!await i())return c.code(200).send({branch:"",tracking:null,isClean:!0,modified:[],added:[],deleted:[],untracked:[],staged:[],ahead:0,behind:0,conflicted:[],notARepo:!0});let l=await s.getStatus();return c.send(l)}catch(l){return b(c,500,"Failed to get git status",l)}}),r.get("/git/branches",async(o,c)=>{try{if(!await i())return c.code(200).send({current:"",all:[],remote:[]});let l=await s.getBranches();return c.send(l)}catch(l){return b(c,500,"Failed to get branches",l)}}),r.get("/git/log",async(o,c)=>{try{if(!await i())return c.code(200).send([]);let l=o.query.count?parseInt(o.query.count,10):void 0,u=await s.getLog(l);return c.send(u)}catch(l){return b(c,500,"Failed to get git log",l)}}),r.get("/git/diff",async(o,c)=>{try{let l=o.query.staged==="true",u=await s.getDiff(l);return c.send({diff:u})}catch(l){return b(c,500,"Failed to get diff",l)}}),r.post("/git/checkout",async(o,c)=>{let l=$w.safeParse(o.body);if(!l.success)return c.status(400).send({error:"Invalid body",details:l.error.issues});try{return await s.checkout(l.data.branch),c.send({success:!0,branch:l.data.branch})}catch(u){return b(c,500,"Failed to checkout branch",u)}}),r.post("/git/commit",async(o,c)=>{let l=_w.safeParse(o.body);if(!l.success)return c.status(400).send({error:"Invalid body",details:l.error.issues});try{let u=await s.commit(l.data.message);return c.send({success:!0,hash:u})}catch(u){return b(c,500,"Failed to commit",u)}}),r.post("/git/pull",async(o,c)=>{let l=Ow.safeParse(o.body);if(!l.success)return c.status(400).send({error:"Invalid body",details:l.error.issues});try{return await s.pull(l.data.rebase),c.send({success:!0})}catch(u){let d=await s.getStatus().catch(()=>null);return d&&d.conflicted.length>0?c.status(409).send({error:"Merge conflict",conflicted:d.conflicted}):b(c,500,"Failed to pull",u)}}),r.post("/git/push",async(o,c)=>{try{return await s.push(),c.send({success:!0})}catch(l){return b(c,500,"Failed to push",l)}}),r.post("/git/full-sync",async(o,c)=>{let l=Lw.safeParse(o.body);if(!l.success)return c.status(400).send({error:"Invalid body",details:l.error.issues});try{return await s.fullSync(l.data.message),c.send({success:!0})}catch(u){let d=await s.getStatus().catch(()=>null);return d&&d.conflicted.length>0?c.status(409).send({error:"Merge conflict",conflicted:d.conflicted}):b(c,500,"Full sync failed",u)}}),r.post("/git/resolve-conflict",async(o,c)=>{let l=Dw.safeParse(o.body);if(!l.success)return c.status(400).send({error:"Invalid body",details:l.error.issues});try{return await s.resolveConflict(l.data.filePath,l.data.content),c.send({success:!0})}catch(u){return b(c,500,"Failed to resolve conflict",u)}}),r.post("/git/continue-rebase",async(o,c)=>{try{return await s.continueRebase(),c.send({success:!0})}catch(l){return b(c,500,"Failed to continue rebase",l)}}),r.post("/git/abort-rebase",async(o,c)=>{try{return await s.abortRebase(),c.send({success:!0})}catch(l){return b(c,500,"Failed to abort rebase",l)}}),r.get("/git/conflict-content/*",async(o,c)=>{try{let l=o.params["*"];if(!l)return c.status(400).send({error:"File path required"});let u=await s.getFileConflictContent(l);return c.send(u)}catch(l){return b(c,500,"Failed to get conflict content",l)}}),r.post("/git/generate-commit-message",async(o,c)=>{try{let l=await s.getDiff(),u=await Am(l);return c.send({message:u})}catch(l){return b(c,500,"Failed to generate commit message",l)}}),r.post("/git/resolve-conflict-ai",async(o,c)=>{let l=Nw.safeParse(o.body);if(!l.success)return c.status(400).send({error:"Invalid body",details:l.error.issues});try{let u=await $m(l.data.ours,l.data.theirs,l.data.filePath);return c.send({resolved:u})}catch(u){return b(c,500,"Failed to AI-resolve conflict",u)}}),r.get("/git/impact",async(o,c)=>{try{let{execa:l}=await import("execa"),{stdout:u}=await l("git",["diff","--name-only","HEAD"],{cwd:e}),d=u.split(`
1030
- `).filter(Boolean),{listSuiteDirs:g,readSuite:m}=await Promise.resolve().then(()=>(ze(),oa)),{listCases:f}=await Promise.resolve().then(()=>(dt(),Fc)),h=Oi.default.join(e,"tests"),C=await g(h),P=[];for(let v of C)try{let k=await m(v),R=await f(v);for(let I of R){let B=[I.name,I.description??"",...I.steps.map(Y=>Y.instruction)].join(" ").toLowerCase();for(let Y of d){let j=Oi.default.basename(Y).toLowerCase(),Ee=Oi.default.dirname(Y).toLowerCase();if(B.includes(j)||B.includes(Ee)){P.push({caseId:I.id,caseName:I.name,suiteId:k.id,suiteName:k.name,reason:`Mentions "${Y}"`});break}}}}catch{}return c.send({changedFiles:d,impactedCases:P})}catch(l){return b(c,500,"Failed to analyze impact",l)}})}var Oi,Ae,Aw,$w,_w,Ow,Lw,Dw,Nw,Lm=w(()=>{"use strict";p();Oi=x(require("path")),Ae=require("zod");Mo();_m();ae();F();Aw=E("git-routes"),$w=Ae.z.object({branch:Ae.z.string().min(1)}),_w=Ae.z.object({message:Ae.z.string().min(1)}),Ow=Ae.z.object({rebase:Ae.z.boolean().optional()}),Lw=Ae.z.object({message:Ae.z.string().min(1)}),Dw=Ae.z.object({filePath:Ae.z.string().min(1),content:Ae.z.string()}),Nw=Ae.z.object({filePath:Ae.z.string().min(1),ours:Ae.z.string(),theirs:Ae.z.string()})});function Dm(r){let e=r.trim().split(`
1031
- `).map(s=>s.trim()).filter(Boolean);if(e.length<2)return[];let t=e[0].split(",").map(s=>s.trim().replace(/^"|"$/g,""));return e.slice(1).map(s=>{let n=[],i="",a=!1;for(let c of s){if(c==='"'){a=!a;continue}if(c===","&&!a){n.push(i.trim()),i="";continue}i+=c}n.push(i.trim());let o={};return t.forEach((c,l)=>{o[c]=n[l]??""}),o})}async function Nm(r){let e=r.rootDir,t=wt.default.join(e,"tests","data");await ot.default.ensureDir(t),r.get("/data-files",async(s,n)=>{try{await ot.default.ensureDir(t);let a=(await ot.default.readdir(t,{withFileTypes:!0})).filter(o=>o.isFile()&&jo.some(c=>o.name.endsWith(c))).map(o=>({name:o.name,type:o.name.endsWith(".csv")?"csv":"json",path:`data/${o.name}`}));return n.send(a)}catch(i){return b(n,500,"Failed to list data files",i)}}),r.get("/data-files/:filename",async(s,n)=>{try{let i=wt.default.basename(s.params.filename),a=wt.default.join(t,i);if(!await ot.default.pathExists(a))return n.status(404).send({error:`Data file "${i}" not found`});let o=await ot.default.readFile(a,"utf8"),c;if(i.endsWith(".csv"))c=Dm(o);else{let l=JSON.parse(o);c=Array.isArray(l)?l.map(u=>Object.fromEntries(Object.entries(u).map(([d,g])=>[d,String(g)]))):[]}return n.send({filename:i,raw:o,rows:c,rowCount:c.length})}catch(i){return b(n,500,"Failed to read data file",i)}}),r.post("/data-files/upload",async(s,n)=>{try{let i=s.body,a=String(i.filename??"").trim(),o=String(i.content??"");if(!a)return n.status(400).send({error:"filename is required"});let c=wt.default.extname(a).toLowerCase();if(!jo.includes(c))return n.status(400).send({error:`Only ${jo.join(", ")} files are allowed`});let l=wt.default.basename(a),u=wt.default.join(t,l);await ot.default.ensureDir(t),await ot.default.writeFile(u,o,"utf8");let d=0;try{if(c===".csv")d=Dm(o).length;else{let g=JSON.parse(o);d=Array.isArray(g)?g.length:0}}catch{}return Fo.info({filename:l,rowCount:d},"Data file uploaded"),n.status(201).send({filename:l,path:`data/${l}`,rowCount:d})}catch(i){return b(n,500,"Failed to upload data file",i)}}),r.put("/data-files/:filename",async(s,n)=>{try{let i=wt.default.basename(s.params.filename),a=wt.default.join(t,i),o=s.body,c=String(o.content??"");return await ot.default.ensureDir(t),await ot.default.writeFile(a,c,"utf8"),Fo.info({filename:i},"Data file updated"),n.send({filename:i,path:`data/${i}`})}catch(i){return b(n,500,"Failed to update data file",i)}}),r.delete("/data-files/:filename",async(s,n)=>{try{let i=wt.default.basename(s.params.filename),a=wt.default.join(t,i);return await ot.default.pathExists(a)?(await ot.default.remove(a),Fo.info({filename:i},"Data file deleted"),n.status(204).send()):n.status(404).send({error:`Data file "${i}" not found`})}catch(i){return b(n,500,"Failed to delete data file",i)}})}var wt,ot,Fo,jo,Mm=w(()=>{"use strict";p();wt=x(require("path")),ot=x(require("fs-extra"));ae();F();Fo=E("routes/data-files"),jo=[".json",".csv"]});function Fm(r){switch(r){case"name":return 0;case"description":return 1;case"tag":return 2;case"instruction":return 3}}async function Bm(r){let e=jm.default.join(r.rootDir,"tests");r.get("/search",async(t,s)=>{let n=(t.query.q??"").trim();if(n.length<2)return s.send([]);try{let i=new RegExp(n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"i"),a=await Tt(e),o=[];for(let c of a){let l;try{l=await ve(c)}catch{continue}i.test(l.name)?o.push({type:"suite",suiteId:l.id,suiteName:l.name,matchedOn:"name"}):l.description&&i.test(l.description)?o.push({type:"suite",suiteId:l.id,suiteName:l.name,matchedOn:"description"}):l.tags?.some(d=>i.test(d))&&o.push({type:"suite",suiteId:l.id,suiteName:l.name,matchedOn:"tag"});let u;try{u=await qe(c)}catch{u=[]}for(let d of u){i.test(d.name)?o.push({type:"case",suiteId:l.id,suiteName:l.name,caseId:d.id,caseName:d.name,matchedOn:"name"}):d.description&&i.test(d.description)?o.push({type:"case",suiteId:l.id,suiteName:l.name,caseId:d.id,caseName:d.name,matchedOn:"description"}):d.tags?.some(g=>i.test(g))&&o.push({type:"case",suiteId:l.id,suiteName:l.name,caseId:d.id,caseName:d.name,matchedOn:"tag"});for(let g of d.steps??[])g.instruction&&i.test(g.instruction)&&o.push({type:"step",suiteId:l.id,suiteName:l.name,caseId:d.id,caseName:d.name,stepId:g.id,instruction:g.instruction,matchedOn:"instruction"})}if(o.length>=20)break}return o.sort((c,l)=>Fm(c.matchedOn)-Fm(l.matchedOn)),s.send(o.slice(0,20))}catch(i){return b(s,500,"Search failed",i)}})}var jm,Um=w(()=>{"use strict";p();jm=x(require("path"));ze();dt();ae()});function Bo(r,e,t){let s=["--all",`--browser ${r.join(" ")}`,`--parallel ${e}`,"--ci"];return t&&s.push(`--device "${t}"`),s.join(" ")}function Fw(r,e,t){let s=Bo(r,e,t);return`name: Assuremind Tests
1065
+ ${e}`);try{let a=await Lr(void 0,{temperature:.4}).generateCode(s,n);return a=a.replace(/^```[\w]*\n?/,"").replace(/\n?```$/,""),ji.info({filePath:t,resultLength:a.length},"AI conflict resolution generated"),a}catch(i){throw ji.warn({filePath:t,err:i instanceof Error?i.message:String(i)},"AI conflict resolution failed"),i}}var ji,Ym=b(()=>{"use strict";m();gr();N();ji=E("git-ai")});async function Qm(r){let e=r.rootDir,t=r.wsManager,s=new Ts(e,t),n=null,i=async()=>{if(n!==null)return n;try{await s.getStatus(),n=!0}catch{n=!1,ob.info("Project directory is not a git repository \u2014 git features disabled")}return n},a={error:"not-a-git-repo",message:'Project directory is not a git repository. Run "git init" to enable git features.'};r.get("/git/status",async(o,c)=>{try{if(!await i())return c.code(200).send({branch:"",tracking:null,isClean:!0,modified:[],added:[],deleted:[],untracked:[],staged:[],ahead:0,behind:0,conflicted:[],notARepo:!0});let l=await s.getStatus();return c.send(l)}catch(l){return w(c,500,"Failed to get git status",l)}}),r.get("/git/branches",async(o,c)=>{try{if(!await i())return c.code(200).send({current:"",all:[],remote:[]});let l=await s.getBranches();return c.send(l)}catch(l){return w(c,500,"Failed to get branches",l)}}),r.get("/git/log",async(o,c)=>{try{if(!await i())return c.code(200).send([]);let l=o.query.count?parseInt(o.query.count,10):void 0,u=await s.getLog(l);return c.send(u)}catch(l){return w(c,500,"Failed to get git log",l)}}),r.get("/git/diff",async(o,c)=>{try{let l=o.query.staged==="true",u=await s.getDiff(l);return c.send({diff:u})}catch(l){return w(c,500,"Failed to get diff",l)}}),r.post("/git/checkout",async(o,c)=>{let l=cb.safeParse(o.body);if(!l.success)return c.status(400).send({error:"Invalid body",details:l.error.issues});try{return await s.checkout(l.data.branch),c.send({success:!0,branch:l.data.branch})}catch(u){return w(c,500,"Failed to checkout branch",u)}}),r.post("/git/commit",async(o,c)=>{let l=lb.safeParse(o.body);if(!l.success)return c.status(400).send({error:"Invalid body",details:l.error.issues});try{let u=await s.commit(l.data.message);return c.send({success:!0,hash:u})}catch(u){return w(c,500,"Failed to commit",u)}}),r.post("/git/pull",async(o,c)=>{let l=ub.safeParse(o.body);if(!l.success)return c.status(400).send({error:"Invalid body",details:l.error.issues});try{return await s.pull(l.data.rebase),c.send({success:!0})}catch(u){let d=await s.getStatus().catch(()=>null);return d&&d.conflicted.length>0?c.status(409).send({error:"Merge conflict",conflicted:d.conflicted}):w(c,500,"Failed to pull",u)}}),r.post("/git/push",async(o,c)=>{try{return await s.push(),c.send({success:!0})}catch(l){return w(c,500,"Failed to push",l)}}),r.post("/git/full-sync",async(o,c)=>{let l=db.safeParse(o.body);if(!l.success)return c.status(400).send({error:"Invalid body",details:l.error.issues});try{return await s.fullSync(l.data.message),c.send({success:!0})}catch(u){let d=await s.getStatus().catch(()=>null);return d&&d.conflicted.length>0?c.status(409).send({error:"Merge conflict",conflicted:d.conflicted}):w(c,500,"Full sync failed",u)}}),r.post("/git/resolve-conflict",async(o,c)=>{let l=pb.safeParse(o.body);if(!l.success)return c.status(400).send({error:"Invalid body",details:l.error.issues});try{return await s.resolveConflict(l.data.filePath,l.data.content),c.send({success:!0})}catch(u){return w(c,500,"Failed to resolve conflict",u)}}),r.post("/git/continue-rebase",async(o,c)=>{try{return await s.continueRebase(),c.send({success:!0})}catch(l){return w(c,500,"Failed to continue rebase",l)}}),r.post("/git/abort-rebase",async(o,c)=>{try{return await s.abortRebase(),c.send({success:!0})}catch(l){return w(c,500,"Failed to abort rebase",l)}}),r.get("/git/conflict-content/*",async(o,c)=>{try{let l=o.params["*"];if(!l)return c.status(400).send({error:"File path required"});let u=await s.getFileConflictContent(l);return c.send(u)}catch(l){return w(c,500,"Failed to get conflict content",l)}}),r.post("/git/generate-commit-message",async(o,c)=>{try{let l=await s.getDiff(),u=await Wm(l);return c.send({message:u})}catch(l){return w(c,500,"Failed to generate commit message",l)}}),r.post("/git/resolve-conflict-ai",async(o,c)=>{let l=mb.safeParse(o.body);if(!l.success)return c.status(400).send({error:"Invalid body",details:l.error.issues});try{let u=await Jm(l.data.ours,l.data.theirs,l.data.filePath);return c.send({resolved:u})}catch(u){return w(c,500,"Failed to AI-resolve conflict",u)}}),r.get("/git/impact",async(o,c)=>{try{let{execa:l}=await import("execa"),{stdout:u}=await l("git",["diff","--name-only","HEAD"],{cwd:e}),d=u.split(`
1066
+ `).filter(Boolean),{listSuiteDirs:p,readSuite:g}=await Promise.resolve().then(()=>(Xe(),fa)),{listCases:f}=await Promise.resolve().then(()=>(gt(),Yc)),h=Bi.default.join(e,"tests"),S=await p(h),I=[];for(let v of S)try{let k=await g(v),T=await f(v);for(let P of T){let j=[P.name,P.description??"",...P.steps.map(J=>J.instruction)].join(" ").toLowerCase();for(let J of d){let M=Bi.default.basename(J).toLowerCase(),Ee=Bi.default.dirname(J).toLowerCase();if(j.includes(M)||j.includes(Ee)){I.push({caseId:P.id,caseName:P.name,suiteId:k.id,suiteName:k.name,reason:`Mentions "${J}"`});break}}}}catch{}return c.send({changedFiles:d,impactedCases:I})}catch(l){return w(c,500,"Failed to analyze impact",l)}})}var Bi,_e,ob,cb,lb,ub,db,pb,mb,Zm=b(()=>{"use strict";m();Bi=x(require("path")),_e=require("zod");qo();Ym();re();N();ob=E("git-routes"),cb=_e.z.object({branch:_e.z.string().min(1)}),lb=_e.z.object({message:_e.z.string().min(1)}),ub=_e.z.object({rebase:_e.z.boolean().optional()}),db=_e.z.object({message:_e.z.string().min(1)}),pb=_e.z.object({filePath:_e.z.string().min(1),content:_e.z.string()}),mb=_e.z.object({filePath:_e.z.string().min(1),ours:_e.z.string(),theirs:_e.z.string()})});function eg(r){let e=r.trim().split(`
1067
+ `).map(s=>s.trim()).filter(Boolean);if(e.length<2)return[];let t=e[0].split(",").map(s=>s.trim().replace(/^"|"$/g,""));return e.slice(1).map(s=>{let n=[],i="",a=!1;for(let c of s){if(c==='"'){a=!a;continue}if(c===","&&!a){n.push(i.trim()),i="";continue}i+=c}n.push(i.trim());let o={};return t.forEach((c,l)=>{o[c]=n[l]??""}),o})}async function tg(r){let e=r.rootDir,t=St.default.join(e,"tests","data");await ct.default.ensureDir(t),r.get("/data-files",async(s,n)=>{try{await ct.default.ensureDir(t);let a=(await ct.default.readdir(t,{withFileTypes:!0})).filter(o=>o.isFile()&&Ko.some(c=>o.name.endsWith(c))).map(o=>({name:o.name,type:o.name.endsWith(".csv")?"csv":"json",path:`data/${o.name}`}));return n.send(a)}catch(i){return w(n,500,"Failed to list data files",i)}}),r.get("/data-files/:filename",async(s,n)=>{try{let i=St.default.basename(s.params.filename),a=St.default.join(t,i);if(!await ct.default.pathExists(a))return n.status(404).send({error:`Data file "${i}" not found`});let o=await ct.default.readFile(a,"utf8"),c;if(i.endsWith(".csv"))c=eg(o);else{let l=JSON.parse(o);c=Array.isArray(l)?l.map(u=>Object.fromEntries(Object.entries(u).map(([d,p])=>[d,String(p)]))):[]}return n.send({filename:i,raw:o,rows:c,rowCount:c.length})}catch(i){return w(n,500,"Failed to read data file",i)}}),r.post("/data-files/upload",async(s,n)=>{try{let i=s.body,a=String(i.filename??"").trim(),o=String(i.content??"");if(!a)return n.status(400).send({error:"filename is required"});let c=St.default.extname(a).toLowerCase();if(!Ko.includes(c))return n.status(400).send({error:`Only ${Ko.join(", ")} files are allowed`});let l=St.default.basename(a),u=St.default.join(t,l);await ct.default.ensureDir(t),await ct.default.writeFile(u,o,"utf8");let d=0;try{if(c===".csv")d=eg(o).length;else{let p=JSON.parse(o);d=Array.isArray(p)?p.length:0}}catch{}return Xo.info({filename:l,rowCount:d},"Data file uploaded"),n.status(201).send({filename:l,path:`data/${l}`,rowCount:d})}catch(i){return w(n,500,"Failed to upload data file",i)}}),r.put("/data-files/:filename",async(s,n)=>{try{let i=St.default.basename(s.params.filename),a=St.default.join(t,i),o=s.body,c=String(o.content??"");return await ct.default.ensureDir(t),await ct.default.writeFile(a,c,"utf8"),Xo.info({filename:i},"Data file updated"),n.send({filename:i,path:`data/${i}`})}catch(i){return w(n,500,"Failed to update data file",i)}}),r.delete("/data-files/:filename",async(s,n)=>{try{let i=St.default.basename(s.params.filename),a=St.default.join(t,i);return await ct.default.pathExists(a)?(await ct.default.remove(a),Xo.info({filename:i},"Data file deleted"),n.status(204).send()):n.status(404).send({error:`Data file "${i}" not found`})}catch(i){return w(n,500,"Failed to delete data file",i)}})}var St,ct,Xo,Ko,rg=b(()=>{"use strict";m();St=x(require("path")),ct=x(require("fs-extra"));re();N();Xo=E("routes/data-files"),Ko=[".json",".csv"]});function sg(r){return Gr.default.basename(r).replace(/[^a-zA-Z0-9._-]+/g,"_").replace(/^\.+/,"")||"file"}async function ng(r){let e=r.rootDir,t=Gr.default.join(e,Wo);r.post("/files/upload",{bodyLimit:Jo+8*1024*1024},async(s,n)=>{let i=fb.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid upload",details:i.error.issues});try{let a=sg(i.data.name),o=Buffer.from(i.data.dataBase64,"base64");if(o.length>Jo)return n.status(413).send({error:`File exceeds ${Jo/(1024*1024)} MB limit`});await Er.default.ensureDir(t);let c=Gr.default.join(t,a);await Er.default.writeFile(c,o),gb.info({name:a,size:o.length},"Fixture file uploaded");let l=`${Wo.replace(/\\/g,"/")}/${a}`;return n.send({name:a,path:l,size:o.length})}catch(a){return w(n,500,"Failed to save uploaded file",a)}}),r.get("/files",async(s,n)=>{try{if(!await Er.default.pathExists(t))return n.send([]);let i=await Er.default.readdir(t,{withFileTypes:!0}),a=await Promise.all(i.filter(o=>o.isFile()).map(async o=>{let c=await Er.default.stat(Gr.default.join(t,o.name));return{name:o.name,path:`${Wo.replace(/\\/g,"/")}/${o.name}`,size:c.size,token:`{{FILE:${o.name}}}`}}));return a.sort((o,c)=>o.name.localeCompare(c.name)),n.send(a)}catch(i){return w(n,500,"Failed to list files",i)}}),r.delete("/files/:name",async(s,n)=>{try{let i=sg(s.params.name),a=Gr.default.join(t,i);return await Er.default.pathExists(a)?(await Er.default.remove(a),n.status(204).send()):n.status(404).send({error:`File "${i}" not found`})}catch(i){return w(n,500,"Failed to delete file",i)}})}var Gr,Er,Ui,gb,Wo,Jo,fb,ig=b(()=>{"use strict";m();Gr=x(require("path")),Er=x(require("fs-extra")),Ui=require("zod");re();N();gb=E("routes/files"),Wo=Gr.default.join("fixtures","uploads"),Jo=25*1024*1024,fb=Ui.z.object({name:Ui.z.string().min(1).max(255),dataBase64:Ui.z.string().min(1)})});function ag(r){switch(r){case"name":return 0;case"description":return 1;case"tag":return 2;case"instruction":return 3}}async function cg(r){let e=og.default.join(r.rootDir,"tests");r.get("/search",async(t,s)=>{let n=(t.query.q??"").trim();if(n.length<2)return s.send([]);try{let i=new RegExp(n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"i"),a=await $t(e),o=[];for(let c of a){let l;try{l=await ve(c)}catch{continue}i.test(l.name)?o.push({type:"suite",suiteId:l.id,suiteName:l.name,matchedOn:"name"}):l.description&&i.test(l.description)?o.push({type:"suite",suiteId:l.id,suiteName:l.name,matchedOn:"description"}):l.tags?.some(d=>i.test(d))&&o.push({type:"suite",suiteId:l.id,suiteName:l.name,matchedOn:"tag"});let u;try{u=await Ke(c)}catch{u=[]}for(let d of u){i.test(d.name)?o.push({type:"case",suiteId:l.id,suiteName:l.name,caseId:d.id,caseName:d.name,matchedOn:"name"}):d.description&&i.test(d.description)?o.push({type:"case",suiteId:l.id,suiteName:l.name,caseId:d.id,caseName:d.name,matchedOn:"description"}):d.tags?.some(p=>i.test(p))&&o.push({type:"case",suiteId:l.id,suiteName:l.name,caseId:d.id,caseName:d.name,matchedOn:"tag"});for(let p of d.steps??[])p.instruction&&i.test(p.instruction)&&o.push({type:"step",suiteId:l.id,suiteName:l.name,caseId:d.id,caseName:d.name,stepId:p.id,instruction:p.instruction,matchedOn:"instruction"})}if(o.length>=20)break}return o.sort((c,l)=>ag(c.matchedOn)-ag(l.matchedOn)),s.send(o.slice(0,20))}catch(i){return w(s,500,"Search failed",i)}})}var og,lg=b(()=>{"use strict";m();og=x(require("path"));Xe();gt();re()});function Zo(r,e,t){let s=["--all",`--browser ${r.join(" ")}`,`--parallel ${e}`,"--ci"];return t&&s.push(`--device "${t}"`),s.join(" ")}function hb(r,e,t){let s=Zo(r,e,t);return`name: Assuremind Tests
1032
1068
  on:
1033
1069
  push:
1034
1070
  branches: [main]
@@ -1051,7 +1087,7 @@ jobs:
1051
1087
  with:
1052
1088
  name: assuremind-results
1053
1089
  path: results/
1054
- `}function jw(r,e,t){let s=Bo(r,e,t);return`stages: [test]
1090
+ `}function yb(r,e,t){let s=Zo(r,e,t);return`stages: [test]
1055
1091
  test:
1056
1092
  stage: test
1057
1093
  image: mcr.microsoft.com/playwright:v1.40.0-jammy${t?`
@@ -1063,7 +1099,7 @@ test:
1063
1099
  when: always
1064
1100
  paths: [results/]
1065
1101
  expire_in: 7 days
1066
- `}function Bw(r,e,t){let s=Bo(r,e,t);return`pipeline {
1102
+ `}function wb(r,e,t){let s=Zo(r,e,t);return`pipeline {
1067
1103
  agent any
1068
1104
  stages {
1069
1105
  stage('Install') { steps { sh 'npm ci' } }
@@ -1074,7 +1110,7 @@ test:
1074
1110
  }
1075
1111
  post { always { archiveArtifacts artifacts: 'results/**', allowEmptyArchive: true } }
1076
1112
  }
1077
- `}async function Hm(r){r.post("/ci-config",async(e,t)=>{let s=Mw.safeParse(e.body);if(!s.success)return t.status(400).send({error:"Invalid CI config request",details:s.error.issues});try{let{platform:n,browsers:i,parallel:a,device:o}=s.data,c;return n==="github"?c=Fw(i,a,o):n==="gitlab"?c=jw(i,a,o):c=Bw(i,a,o),t.send({yaml:c,filename:Uw[n]})}catch(n){return b(t,500,"Failed to generate CI config",n)}})}var Jt,Mw,Uw,Vm=w(()=>{"use strict";p();Jt=require("zod");ae();Mw=Jt.z.object({platform:Jt.z.enum(["github","gitlab","jenkins"]),browsers:Jt.z.array(Jt.z.string()).default(["chromium"]),parallel:Jt.z.number().int().positive().default(2),headed:Jt.z.boolean().default(!1),env:Jt.z.string().optional(),device:Jt.z.string().optional()});Uw={github:".github/workflows/assuremind.yml",gitlab:".gitlab-ci.yml",jenkins:"Jenkinsfile"}});async function Gm(r){r.get("/templates",async(e,t)=>{try{return t.send(Hw)}catch(s){return b(t,500,"Failed to list templates",s)}})}var Hw,zm=w(()=>{"use strict";p();ae();Hw=[{id:"user-login",name:"User Login",description:"Standard login flow with credential validation",category:"auth",steps:[{instruction:"Navigate to the login page"},{instruction:"Enter the username in the username field"},{instruction:"Enter the password in the password field"},{instruction:"Click the login button"},{instruction:"Verify the dashboard page is displayed"}]},{id:"crud-record",name:"CRUD Operations",description:"Create, read, update, and delete a record",category:"crud",steps:[{instruction:"Navigate to the records list page"},{instruction:"Click the Create New button"},{instruction:"Fill in the required fields"},{instruction:"Click Save to create the record"},{instruction:"Verify the record appears in the list"},{instruction:"Click on the record to open it"},{instruction:"Edit one of the fields"},{instruction:"Save the changes"},{instruction:"Delete the record"},{instruction:"Verify the record is no longer in the list"}]},{id:"page-navigation",name:"Page Navigation",description:"Verify navigation between key pages",category:"navigation",steps:[{instruction:"Navigate to the home page"},{instruction:"Click the main navigation menu item"},{instruction:"Verify the correct page title is shown"},{instruction:"Use the browser back button"},{instruction:"Verify returning to the home page"}]},{id:"form-submission",name:"Form Submission",description:"Fill and submit a form with validation",category:"form",steps:[{instruction:"Navigate to the form page"},{instruction:"Fill in all required fields"},{instruction:"Attempt to submit the form with empty fields first"},{instruction:"Verify validation error messages are shown"},{instruction:"Fill in all required fields correctly"},{instruction:"Click the submit button"},{instruction:"Verify the success message is displayed"}]},{id:"api-health-check",name:"REST API Health Check",description:"Verify API endpoints return expected responses",category:"api",steps:[{instruction:"Send a GET request to the health check endpoint"},{instruction:"Verify the response status is 200"},{instruction:"Verify the response body contains status ok"},{instruction:"Send a GET request to the main API endpoint"},{instruction:"Verify the response contains the expected data structure"}]}]});async function qm(r){let e=r.rootDir;r.get("/flakiness",async(t,s)=>{try{let{suiteId:n,caseId:i}=t.query,o=(await Ua(e)).slice(0,20),c=new Map,l=new Map;for(let g of o)try{let m=await Dr(e,g);for(let f of m.suites)if(!(n&&f.suiteId!==n))for(let h of f.cases){if(i&&h.caseId!==i)continue;let C=c.get(h.caseId)??{caseName:h.caseName,passes:0,failures:0};h.status==="passed"?C.passes++:h.status==="failed"&&C.failures++,c.set(h.caseId,C),l.has(h.caseId)||l.set(h.caseId,new Map);let P=l.get(h.caseId);for(let v of h.steps){let k=P.get(v.stepId)??{instruction:v.instruction,passes:0,failures:0};v.status==="passed"?k.passes++:v.status==="failed"&&k.failures++,P.set(v.stepId,k)}}}catch{}let u=[];for(let[g,m]of c){let f=m.passes+m.failures,h=f>0?m.passes/f:1,C=f>=3&&h>0&&h<1,P=l.get(g),v=[];if(P)for(let[k,R]of P){let I=R.passes+R.failures,B=I>0?R.passes/I:1,Y=I>=3&&B>0&&B<1;v.push({stepId:k,instruction:R.instruction,passRate:B,runs:I,flaky:Y})}u.push({caseId:g,caseName:m.caseName,passRate:h,runs:f,flaky:C,steps:v})}let d={cases:u,generatedAt:new Date().toISOString()};return s.send(d)}catch(n){return b(s,500,"Failed to compute flakiness",n)}})}var Xm=w(()=>{"use strict";p();Xs();ae()});function Wm(r){return Uo.default.join(r,"tests",".step-library.json")}async function Ss(r){let e=Wm(r);if(!await Li.default.pathExists(e))return[];try{let t=await Li.default.readJson(e);return Array.isArray(t)?t.map(s=>Vw.parse(s)):[]}catch{return[]}}async function Ho(r,e){let t=Wm(r);await Li.default.ensureDir(Uo.default.dirname(t)),await K(t,e)}async function Jm(r,e){let t=await Ss(r),s=new Date().toISOString(),n={id:(0,Km.v4)(),name:e.name,instruction:e.instruction,generatedCode:e.generatedCode??"",tags:e.tags??[],createdAt:s,updatedAt:s};return t.push(n),await Ho(r,t),n}async function Vo(r,e,t){let s=await Ss(r),n=s.findIndex(i=>i.id===e);if(n<0)throw new Error(`Library step "${e}" not found`);return s[n]={...s[n],...t,updatedAt:new Date().toISOString()},await Ho(r,s),s[n]}async function Ym(r,e){let s=(await Ss(r)).filter(n=>n.id!==e);await Ho(r,s)}var Uo,Li,Km,Lt,Vw,Qm=w(()=>{"use strict";p();Uo=x(require("path")),Li=x(require("fs-extra")),Km=require("uuid"),Lt=require("zod");Ve();Vw=Lt.z.object({id:Lt.z.string(),name:Lt.z.string().min(1),instruction:Lt.z.string().min(1),generatedCode:Lt.z.string().optional().default(""),tags:Lt.z.array(Lt.z.string()).default([]),createdAt:Lt.z.string(),updatedAt:Lt.z.string()})});async function Zm(r){let e=r.rootDir;r.get("/step-library",async(t,s)=>{try{let n=await Ss(e);return s.send(n)}catch(n){return b(s,500,"Failed to list step library",n)}}),r.post("/step-library",async(t,s)=>{let n=Gw.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid request",details:n.error.issues});try{let i=await Jm(e,n.data);return s.status(201).send(i)}catch(i){return b(s,500,"Failed to create library step",i)}}),r.patch("/step-library/:id",async(t,s)=>{let n=zw.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid request",details:n.error.issues});try{let i=await Vo(e,t.params.id,n.data);return s.send(i)}catch(i){return b(s,500,"Failed to update library step",i)}}),r.delete("/step-library/:id",async(t,s)=>{try{return await Ym(e,t.params.id),s.status(204).send()}catch(n){return b(s,500,"Failed to delete library step",n)}}),r.post("/step-library/:id/generate",async(t,s)=>{let n;try{let a=(await Ss(e)).find(m=>m.id===t.params.id);if(!a)return s.status(404).send({error:`Library step "${t.params.id}" not found`});let o=await J(e),c=await et(e).catch(()=>({})),l=o.mcp?.enabled;l&&(n=new pt({headless:o.mcp?.headless??!0,actionTimeout:o.mcp?.actionTimeout??15e3,idleTimeout:o.mcp?.idleTimeout??3e4}));let u=tt(e,n,l?o.mcp?.actThenScript:!1),d=await u.generate(a.instruction,{url:o.baseUrl,title:"",interactiveElements:"",htmlSnapshot:"",previousSteps:[],variables:c});await u.getCache().persist();let g=await Vo(e,a.id,{generatedCode:d.code});return s.send({step:g,strategy:d.strategy,cost:d.cost})}catch(i){return b(s,500,"Failed to generate code for library step",i)}finally{n?.release()}})}var Ke,Gw,zw,eg=w(()=>{"use strict";p();Ke=require("zod");Qm();_e();lr();dr();Vs();ae();Gw=Ke.z.object({name:Ke.z.string().min(1),instruction:Ke.z.string().min(1),generatedCode:Ke.z.string().optional(),tags:Ke.z.array(Ke.z.string()).optional()}),zw=Ke.z.object({name:Ke.z.string().min(1).optional(),instruction:Ke.z.string().min(1).optional(),generatedCode:Ke.z.string().optional(),tags:Ke.z.array(Ke.z.string()).optional()})});function qw(){return`
1113
+ `}function pg(r,e,t,s){return r==="github"?hb(e,t,s):r==="gitlab"?yb(e,t,s):wb(e,t,s)}async function mg(r){let e=r.rootDir;r.post("/ci-config",async(t,s)=>{let n=ug.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid CI config request",details:n.error.issues});try{let{platform:i,browsers:a,parallel:o,device:c}=n.data,l=pg(i,a,o,c);return s.send({yaml:l,filename:dg[i]})}catch(i){return w(s,500,"Failed to generate CI config",i)}}),r.post("/ci-config/write",async(t,s)=>{let n=ug.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid CI config request",details:n.error.issues});try{if(!(await G(e)).ci?.writeToRepo)return s.status(403).send({error:"Writing CI files to the repo is disabled. Enable it in Settings \u2192 CI/CD Integration."});let{platform:a,browsers:o,parallel:c,device:l}=n.data,u=n.data.yaml?.trim()?n.data.yaml:pg(a,o,c,l),d=dg[a],p=Yo.default.join(e,d);return await Qo.default.ensureDir(Yo.default.dirname(p)),await Qo.default.writeFile(p,u,"utf-8"),s.send({written:!0,path:d})}catch(i){return w(s,500,"Failed to write CI config to repo",i)}})}var Yo,Qo,Ft,ug,dg,gg=b(()=>{"use strict";m();Yo=x(require("path")),Qo=x(require("fs-extra")),Ft=require("zod");re();Te();ug=Ft.z.object({platform:Ft.z.enum(["github","gitlab","jenkins"]),browsers:Ft.z.array(Ft.z.string()).default(["chromium"]),parallel:Ft.z.number().int().positive().default(2),headed:Ft.z.boolean().default(!1),env:Ft.z.string().optional(),device:Ft.z.string().optional(),yaml:Ft.z.string().optional()});dg={github:".github/workflows/assuremind.yml",gitlab:".gitlab-ci.yml",jenkins:"Jenkinsfile"}});async function fg(r){r.get("/templates",async(e,t)=>{try{return t.send(bb)}catch(s){return w(t,500,"Failed to list templates",s)}})}var bb,hg=b(()=>{"use strict";m();re();bb=[{id:"user-login",name:"User Login",description:"Standard login flow with credential validation",category:"auth",steps:[{instruction:"Navigate to the login page"},{instruction:"Enter the username in the username field"},{instruction:"Enter the password in the password field"},{instruction:"Click the login button"},{instruction:"Verify the dashboard page is displayed"}]},{id:"crud-record",name:"CRUD Operations",description:"Create, read, update, and delete a record",category:"crud",steps:[{instruction:"Navigate to the records list page"},{instruction:"Click the Create New button"},{instruction:"Fill in the required fields"},{instruction:"Click Save to create the record"},{instruction:"Verify the record appears in the list"},{instruction:"Click on the record to open it"},{instruction:"Edit one of the fields"},{instruction:"Save the changes"},{instruction:"Delete the record"},{instruction:"Verify the record is no longer in the list"}]},{id:"page-navigation",name:"Page Navigation",description:"Verify navigation between key pages",category:"navigation",steps:[{instruction:"Navigate to the home page"},{instruction:"Click the main navigation menu item"},{instruction:"Verify the correct page title is shown"},{instruction:"Use the browser back button"},{instruction:"Verify returning to the home page"}]},{id:"form-submission",name:"Form Submission",description:"Fill and submit a form with validation",category:"form",steps:[{instruction:"Navigate to the form page"},{instruction:"Fill in all required fields"},{instruction:"Attempt to submit the form with empty fields first"},{instruction:"Verify validation error messages are shown"},{instruction:"Fill in all required fields correctly"},{instruction:"Click the submit button"},{instruction:"Verify the success message is displayed"}]},{id:"api-health-check",name:"REST API Health Check",description:"Verify API endpoints return expected responses",category:"api",steps:[{instruction:"Send a GET request to the health check endpoint"},{instruction:"Verify the response status is 200"},{instruction:"Verify the response body contains status ok"},{instruction:"Send a GET request to the main API endpoint"},{instruction:"Verify the response contains the expected data structure"}]}]});async function yg(r){let e=r.rootDir;r.get("/flakiness",async(t,s)=>{try{let{suiteId:n,caseId:i}=t.query,o=(await Ja(e)).slice(0,20),c=new Map,l=new Map;for(let p of o)try{let g=await Br(e,p);for(let f of g.suites)if(!(n&&f.suiteId!==n))for(let h of f.cases){if(i&&h.caseId!==i)continue;let S=c.get(h.caseId)??{caseName:h.caseName,passes:0,failures:0};h.status==="passed"?S.passes++:h.status==="failed"&&S.failures++,c.set(h.caseId,S),l.has(h.caseId)||l.set(h.caseId,new Map);let I=l.get(h.caseId);for(let v of h.steps){let k=I.get(v.stepId)??{instruction:v.instruction,passes:0,failures:0};v.status==="passed"?k.passes++:v.status==="failed"&&k.failures++,I.set(v.stepId,k)}}}catch{}let u=[];for(let[p,g]of c){let f=g.passes+g.failures,h=f>0?g.passes/f:1,S=f>=3&&h>0&&h<1,I=l.get(p),v=[];if(I)for(let[k,T]of I){let P=T.passes+T.failures,j=P>0?T.passes/P:1,J=P>=3&&j>0&&j<1;v.push({stepId:k,instruction:T.instruction,passRate:j,runs:P,flaky:J})}u.push({caseId:p,caseName:g.caseName,passRate:h,runs:f,flaky:S,steps:v})}let d={cases:u,generatedAt:new Date().toISOString()};return s.send(d)}catch(n){return w(s,500,"Failed to compute flakiness",n)}})}var wg=b(()=>{"use strict";m();Zs();re()});function vg(r){return ec.default.join(r,"tests",".step-library.json")}async function ks(r){let e=vg(r);if(!await Hi.default.pathExists(e))return[];try{let t=await Hi.default.readJson(e);return Array.isArray(t)?t.map(s=>vb.parse(s)):[]}catch{return[]}}async function tc(r,e){let t=vg(r);await Hi.default.ensureDir(ec.default.dirname(t)),await K(t,e)}async function xg(r,e){let t=await ks(r),s=new Date().toISOString(),n={id:(0,bg.v4)(),name:e.name,instruction:e.instruction,generatedCode:e.generatedCode??"",tags:e.tags??[],createdAt:s,updatedAt:s};return t.push(n),await tc(r,t),n}async function rc(r,e,t){let s=await ks(r),n=s.findIndex(i=>i.id===e);if(n<0)throw new Error(`Library step "${e}" not found`);return s[n]={...s[n],...t,updatedAt:new Date().toISOString()},await tc(r,s),s[n]}async function Sg(r,e){let s=(await ks(r)).filter(n=>n.id!==e);await tc(r,s)}var ec,Hi,bg,Nt,vb,Cg=b(()=>{"use strict";m();ec=x(require("path")),Hi=x(require("fs-extra")),bg=require("uuid"),Nt=require("zod");ze();vb=Nt.z.object({id:Nt.z.string(),name:Nt.z.string().min(1),instruction:Nt.z.string().min(1),generatedCode:Nt.z.string().optional().default(""),tags:Nt.z.array(Nt.z.string()).default([]),createdAt:Nt.z.string(),updatedAt:Nt.z.string()})});async function Eg(r){let e=r.rootDir;r.get("/step-library",async(t,s)=>{try{let n=await ks(e);return s.send(n)}catch(n){return w(s,500,"Failed to list step library",n)}}),r.post("/step-library",async(t,s)=>{let n=xb.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid request",details:n.error.issues});try{let i=await xg(e,n.data);return s.status(201).send(i)}catch(i){return w(s,500,"Failed to create library step",i)}}),r.patch("/step-library/:id",async(t,s)=>{let n=Sb.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid request",details:n.error.issues});try{let i=await rc(e,t.params.id,n.data);return s.send(i)}catch(i){return w(s,500,"Failed to update library step",i)}}),r.delete("/step-library/:id",async(t,s)=>{try{return await Sg(e,t.params.id),s.status(204).send()}catch(n){return w(s,500,"Failed to delete library step",n)}}),r.post("/step-library/:id/generate",async(t,s)=>{let n;try{let a=(await ks(e)).find(g=>g.id===t.params.id);if(!a)return s.status(404).send({error:`Library step "${t.params.id}" not found`});let o=await G(e),c=await rt(e).catch(()=>({})),l=o.mcp?.enabled;l&&(n=new ft({headless:o.mcp?.headless??!0,actionTimeout:o.mcp?.actionTimeout??15e3,idleTimeout:o.mcp?.idleTimeout??3e4}));let u=st(e,n,l?o.mcp?.actThenScript:!1),d=await u.generate(a.instruction,{url:o.baseUrl,title:"",interactiveElements:"",htmlSnapshot:"",previousSteps:[],variables:c});await u.getCache().persist();let p=await rc(e,a.id,{generatedCode:d.code});return s.send({step:p,strategy:d.strategy,cost:d.cost})}catch(i){return w(s,500,"Failed to generate code for library step",i)}finally{n?.release()}})}var Je,xb,Sb,Ig=b(()=>{"use strict";m();Je=require("zod");Cg();Te();pr();gr();Ws();re();xb=Je.z.object({name:Je.z.string().min(1),instruction:Je.z.string().min(1),generatedCode:Je.z.string().optional(),tags:Je.z.array(Je.z.string()).optional()}),Sb=Je.z.object({name:Je.z.string().min(1).optional(),instruction:Je.z.string().min(1).optional(),generatedCode:Je.z.string().optional(),tags:Je.z.array(Je.z.string()).optional()})});function Cb(){return`
1078
1114
  (function() {
1079
1115
  if (window.__amListenersAttached) return;
1080
1116
  window.__amListenersAttached = true;
@@ -1246,7 +1282,9 @@ test:
1246
1282
  // Track the currently active input \u2014 only record value when user LEAVES the field
1247
1283
  var activeInput = null;
1248
1284
  var pendingInput = null;
1285
+ var inputDebounce = null; // auto-flush timer (safety net for iframes / no-blur cases)
1249
1286
  function flushInput() {
1287
+ if (inputDebounce) { clearTimeout(inputDebounce); inputDebounce = null; }
1250
1288
  if (pendingInput && activeInput) {
1251
1289
  var meta = getMeta(activeInput);
1252
1290
  var desc = descEl(meta);
@@ -1335,7 +1373,9 @@ test:
1335
1373
  safeSend(JSON.stringify({ action: action, instruction: instruction, meta: meta, url: location.href }));
1336
1374
  }, true);
1337
1375
 
1338
- // Input \u2014 mark element as active; capture final value on blur/Enter
1376
+ // Input \u2014 mark element as active; capture final value on blur/Enter.
1377
+ // Also arm a debounce timer so the value is recorded even when no blur fires
1378
+ // (common for inputs inside iframes when focus moves to the parent page).
1339
1379
  document.addEventListener('input', function(e) {
1340
1380
  var el = (e.composedPath && e.composedPath()[0]) || e.target;
1341
1381
  if (!el || !el.tagName) return;
@@ -1345,18 +1385,32 @@ test:
1345
1385
  if (['checkbox','radio','submit','button','file'].indexOf(ty) >= 0) return;
1346
1386
  activeInput = el;
1347
1387
  pendingInput = { action: 'fill', instruction: '', meta: null, value: '', url: location.href };
1388
+ if (inputDebounce) clearTimeout(inputDebounce);
1389
+ inputDebounce = setTimeout(function() {
1390
+ if (pendingInput && activeInput === el) flushInput();
1391
+ }, 900);
1348
1392
  }, true);
1349
1393
 
1350
- // Blur \u2014 user left the field \u2192 capture final value
1351
- document.addEventListener('blur', function(e) {
1394
+ // Blur / focusout \u2014 user left the field \u2192 capture final value.
1395
+ // focusout bubbles (blur does not), making this more reliable across frames.
1396
+ function onLeaveField(e) {
1352
1397
  var el = (e.composedPath && e.composedPath()[0]) || e.target;
1353
1398
  if (el && el === activeInput && pendingInput) flushInput();
1354
- }, true);
1399
+ }
1400
+ document.addEventListener('blur', onLeaveField, true);
1401
+ document.addEventListener('focusout', onLeaveField, true);
1355
1402
 
1356
- // Select change
1403
+ // Change \u2014 commits text inputs/textarea (and handles selects below)
1357
1404
  document.addEventListener('change', function(e) {
1358
1405
  var el = (e.composedPath && e.composedPath()[0]) || e.target;
1359
- if (!el || el.tagName.toLowerCase() !== 'select') return;
1406
+ if (!el) return;
1407
+ var tagName = el.tagName.toLowerCase();
1408
+ // Text inputs / textarea: flush the pending fill on commit
1409
+ if ((tagName === 'input' || tagName === 'textarea') && el === activeInput && pendingInput) {
1410
+ flushInput();
1411
+ return;
1412
+ }
1413
+ if (tagName !== 'select') return;
1360
1414
  flushInput();
1361
1415
  var meta = getMeta(el), desc = descEl(meta);
1362
1416
  var selText = el.options[el.selectedIndex] ? el.options[el.selectedIndex].text : el.value;
@@ -1445,65 +1499,65 @@ test:
1445
1499
  }
1446
1500
  }, true);
1447
1501
  })();
1448
- `}async function Xw(r,e){let t=[];if(e.shadowPath)return`${e.frameSelector?`frameLocator('${be(e.frameSelector)}').`:""}locator('${be(e.shadowPath)}')`;let s=!!e.frameSelector,n=s?`frameLocator('${be(e.frameSelector)}').`:"",i=s?r.frameLocator(e.frameSelector):r;try{let a=e.ariaRole||Kw(e.tag,e.type),o=e.ariaLabel||e.labelText||e.innerText||e.title||"",c=Ww(e.tag);e.testId&&t.push({name:"testid",locator:i.getByTestId(e.testId),pw:`${n}getByTestId('${be(e.testId)}')`}),a&&o&&o.length<=60&&(c&&t.push({name:"role+name+level",locator:i.getByRole(a,{name:o,exact:!0,level:c}),pw:`${n}getByRole('${a}', { name: '${be(o)}', level: ${c} })`}),t.push({name:"role+name-exact",locator:i.getByRole(a,{name:o,exact:!0}),pw:`${n}getByRole('${a}', { name: '${be(o)}' })`}),t.push({name:"role+name-fuzzy",locator:i.getByRole(a,{name:o,exact:!1}),pw:`${n}getByRole('${a}', { name: '${be(o)}' })`})),e.labelText&&(t.push({name:"label",locator:i.getByLabel(e.labelText,{exact:!0}),pw:`${n}getByLabel('${be(e.labelText)}')`}),t.push({name:"label-fuzzy",locator:i.getByLabel(e.labelText,{exact:!1}),pw:`${n}getByLabel('${be(e.labelText)}')`})),e.placeholder&&t.push({name:"placeholder",locator:i.getByPlaceholder(e.placeholder,{exact:!0}),pw:`${n}getByPlaceholder('${be(e.placeholder)}')`}),e.innerText&&e.innerText.length<=60&&(t.push({name:"text-exact",locator:i.getByText(e.innerText,{exact:!0}),pw:`${n}getByText('${be(e.innerText)}')`}),t.push({name:"text-fuzzy",locator:i.getByText(e.innerText,{exact:!1}),pw:`${n}getByText('${be(e.innerText)}')`})),e.cssPath&&t.push({name:"css",locator:i.locator(e.cssPath),pw:`${n}locator('${be(e.cssPath)}')`});for(let l of t)try{if(await l.locator.count()===1)return $e.debug({strategy:l.name,pw:l.pw,inIframe:s},"Locator resolved"),l.pw}catch{}return e.cssPath?`${n}locator('${be(e.cssPath)}')`:e.id?`${n}locator('#${be(e.id)}')`:`${n}locator('${be(e.tag)}')`}catch(a){return $e.warn({err:a,meta:e.cssPath},"Locator resolution failed \u2014 using CSS fallback"),e.cssPath?`${n}locator('${be(e.cssPath)}')`:`${n}locator('${be(e.tag)}')`}}function Kw(r,e){if(r==="button"||r==="input"&&e==="submit")return"button";if(r==="a")return"link";if(r==="input"){if(e==="checkbox")return"checkbox";if(e==="radio")return"radio";if(["text","email","password","search","tel","url","number",""].includes(e))return"textbox"}return r==="textarea"?"textbox":r==="select"?"combobox":r==="img"?"img":["h1","h2","h3","h4","h5","h6"].includes(r)?"heading":null}function Ww(r){let e=r.match(/^h([1-6])$/);return e?parseInt(e[1],10):null}function be(r){return r.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}var tg,$e,Di,rg=w(()=>{"use strict";p();tg=require("playwright");F();$e=E("recorder");Di=class{browser=null;context=null;page=null;actions=[];actionCounter=0;running=!1;options;_setLastUserActionTime=null;constructor(e){this.options=e}get isRunning(){return this.running}get recordedActions(){return[...this.actions]}async start(){if(this.running)throw new Error("Recorder is already running");$e.info({url:this.options.startUrl},"Starting recorder"),this.actions=[],this.actionCounter=0,this.running=!0;try{this.browser=await tg.chromium.launch({headless:!1,args:["--start-maximized"]}),this.context=await this.browser.newContext({viewport:this.options.viewport||{width:1280,height:720},ignoreHTTPSErrors:!0}),await this.context.exposeBinding("__amSend",(o,c)=>{this.handleRawAction(c)}),this.page=await this.context.newPage(),this.page.on("pageerror",o=>{$e.warn({error:o.message},"Page error during recording")});let e=qw(),t=async o=>{try{await o.evaluate(e),$e.debug({url:o.url(),name:o.name()},"Capture script injected into frame")}catch(c){$e.debug({err:c,url:o.url()},"Could not inject into frame (likely cross-origin)")}},s=async o=>{await t(o.mainFrame());for(let c of o.frames())c!==o.mainFrame()&&await t(c)};this.page.on("load",()=>{!this.running||!this.page||setTimeout(()=>s(this.page),150)}),this.page.on("frameattached",o=>{this.running&&o.waitForLoadState("load").then(()=>{t(o)}).catch(()=>{})}),this.page.on("framenavigated",o=>{!this.running||!this.page||o!==this.page.mainFrame()&&setTimeout(()=>t(o),150)});let n="",i=0,a=3e3;this.page.on("framenavigated",o=>{if(!this.running||!this.page||o!==this.page.mainFrame())return;let c=o.url();if(c===n||c==="about:blank")return;n=c;let l=this.actionCounter===0;if(!l&&i>0){let d=Date.now()-i;if(d<a){$e.debug({url:c,elapsed:d},"Skipping redirect navigation after user action");return}}let u={id:`rec-${++this.actionCounter}`,order:this.actionCounter,action:"navigate",instruction:l?`Go to ${c}`:`Navigate to ${c}`,locator:"",url:c,timestamp:Date.now()};this.actions.push(u),this.options.onAction(u),$e.debug({action:u.instruction},"Recorded navigation")}),this._setLastUserActionTime=o=>{i=o},this.page.on("dialog",async o=>{if(!this.running)return;let c=o.type(),l=o.message();await o.accept().catch(()=>{});for(let u=this.actions.length-1;u>=0;u--){let d=this.actions[u];if(["click","fill","check","uncheck","select","press"].includes(d.action)){d.dialogHandler={type:"accept",dialogType:c,message:l};break}}$e.debug({dialogType:c,message:l},"Dialog auto-accepted and tagged on triggering action")}),this.page.on("close",()=>{this.running&&($e.info("Browser closed by user \u2014 stopping recorder"),this.running=!1,this.options.onStop?.(this.actions))}),await this.page.goto(this.options.startUrl,{waitUntil:"load",timeout:3e4}),await s(this.page),$e.info("Recorder started \u2014 browser is open for interaction")}catch(e){throw $e.error({err:e},"Failed to start recorder"),await this.cleanup(),e}}async stop(){if(!this.running)return this.actions;$e.info({actionCount:this.actions.length},"Stopping recorder"),this.running=!1;let e=[...this.actions];return await this.cleanup(),this.options.onStop?.(e),e}async handleRawAction(e){if(!(!this.running||!this.page))try{let t=JSON.parse(e),s=t.meta,n="";if(s&&this.page)try{n=await Xw(this.page,s)}catch(o){$e.warn({err:o},"Locator resolution failed \u2014 using CSS fallback"),n=s.cssPath?`locator('${be(s.cssPath)}')`:""}["click","fill","check","uncheck","select","press"].includes(t.action)&&this._setLastUserActionTime&&this._setLastUserActionTime(Date.now());let a={id:`rec-${++this.actionCounter}`,order:this.actionCounter,action:t.action,instruction:t.instruction,locator:n,value:t.value,url:t.url,timestamp:Date.now(),...t.soft?{soft:!0}:{},...s?.frameSelector?{frameSelector:s.frameSelector}:{},...s?.shadowPath?{shadowPath:s.shadowPath}:{}};this.actions.push(a),this.options.onAction(a),$e.debug({action:a.instruction,locator:n,strategy:"resolved"},"Recorded action")}catch(t){$e.warn({err:t,raw:e},"Failed to parse recorded action")}}async cleanup(){try{this.context&&await this.context.close().catch(()=>{}),this.browser&&await this.browser.close().catch(()=>{})}catch{}this.browser=null,this.context=null,this.page=null}}});async function sg(r){let e=r.rootDir,t=r.wsManager;r.post("/recorder/start",async(s,n)=>{try{if(bt?.isRunning)return n.status(409).send({error:"A recording session is already active. Stop it first."});let i=Yw.parse(s.body||{}),a=await J(e),o=i.url||a.baseUrl||"https://www.google.com";return bt=new Di({startUrl:o,viewport:i.viewport,onAction:c=>{t.broadcast("recorder:action",c)},onStop:c=>{t.broadcast("recorder:stopped",{actionCount:c.length}),Jw.info({actionCount:c.length},"Recording stopped (browser closed)")}}),await bt.start(),n.send({status:"recording",url:o,message:"Browser launched \u2014 interact with your app. Actions are streamed in real time."})}catch(i){return bt=null,b(n,500,"Failed to start recorder",i)}}),r.post("/recorder/stop",async(s,n)=>{try{if(!bt?.isRunning)return n.status(404).send({error:"No active recording session."});let i=await bt.stop();return bt=null,t.broadcast("recorder:stopped",{actionCount:i.length}),n.send({status:"stopped",actions:i,actionCount:i.length})}catch(i){return bt=null,b(n,500,"Failed to stop recorder",i)}}),r.get("/recorder/status",async(s,n)=>{let i=bt?.isRunning??!1,a=bt?.recordedActions.length??0;return n.send({recording:i,actionCount:a,actions:i?bt.recordedActions:[]})})}var Cs,Jw,Yw,bt,ng=w(()=>{"use strict";p();Cs=require("zod");rg();_e();ae();F();Jw=E("recorder-routes"),Yw=Cs.z.object({url:Cs.z.string().url().optional(),viewport:Cs.z.object({width:Cs.z.number().int().positive(),height:Cs.z.number().int().positive()}).optional()}),bt=null});var ig,ag=w(()=>{"use strict";p();Wa();ig=async r=>{r.get("/faker/generators",async(e,t)=>{let s=Zn();return t.send(s)})}});async function og(r){let e=r.rootDir;r.get("/visual-regression/config",async(t,s)=>{try{let n=await Ys(e);return s.send(n)}catch(n){return b(s,500,"Failed to read visual-regression config",n)}}),r.put("/visual-regression/config",async(t,s)=>{try{let n=t.body,i=await Ys(e),a={enabled:typeof n.enabled=="boolean"?n.enabled:i.enabled,defaultThreshold:typeof n.defaultThreshold=="number"?n.defaultThreshold:i.defaultThreshold,fullPage:typeof n.fullPage=="boolean"?n.fullPage:i.fullPage,maskSelectors:Array.isArray(n.maskSelectors)?n.maskSelectors:i.maskSelectors};return await Ud(e,a),s.send(a)}catch(n){return b(s,500,"Failed to save visual-regression config",n)}}),r.get("/visual-regression/baselines",async(t,s)=>{try{let n=await zd(e);return s.send(n)}catch(n){return b(s,500,"Failed to list baselines",n)}}),r.delete("/visual-regression/baselines",async(t,s)=>{try{let{path:n}=t.body;return n?(await qd(e,n),s.send({ok:!0})):s.status(400).send({error:'Missing "path" in request body'})}catch(n){return b(s,500,"Failed to delete baseline",n)}}),r.post("/visual-regression/baselines/update",async(t,s)=>{try{let{actualPath:n,baselinePath:i}=t.body;return!n||!i?s.status(400).send({error:"Missing actualPath or baselinePath"}):await Es.default.pathExists(n)?(await Es.default.ensureDir(an.default.dirname(i)),await Es.default.copy(n,i,{overwrite:!0}),s.send({ok:!0})):s.status(404).send({error:"Actual screenshot not found"})}catch(n){return b(s,500,"Failed to update baseline",n)}}),r.get("/visual-regression/diffs",async(t,s)=>{try{let n=await Hd(e);return s.send(n)}catch(n){return b(s,500,"Failed to list diff runs",n)}}),r.get("/visual-regression/diffs/:runId",async(t,s)=>{try{let{runId:n}=t.params,i=await si(e,n);return s.send(i)}catch(n){return b(s,500,"Failed to read diff summary",n)}}),r.patch("/visual-regression/diffs/:runId/:stepId",async(t,s)=>{try{let{runId:n,stepId:i}=t.params,{status:a}=t.body;if(!["approved","rejected"].includes(a))return s.status(400).send({error:'Status must be "approved" or "rejected"'});let o=await Vd(e,n,i,a);return s.send(o)}catch(n){return b(s,500,"Failed to update diff status",n)}}),r.post("/visual-regression/diffs/:runId/approve-all",async(t,s)=>{try{let{runId:n}=t.params,i=await Gd(e,n);return s.send(i)}catch(n){return b(s,500,"Failed to approve all diffs",n)}}),r.get("/visual-regression/image/*",async(t,s)=>{try{let n=t.params["*"];if(!n)return s.status(400).send({error:"Missing image path"});let i=an.default.resolve(e,n);if(!i.startsWith(an.default.resolve(e)))return s.status(403).send({error:"Forbidden"});if(!await Es.default.pathExists(i))return s.status(404).send({error:"Image not found"});let a=an.default.extname(i).toLowerCase(),c={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp"}[a]??"application/octet-stream",l=await Es.default.readFile(i);return s.type(c).send(l)}catch(n){return b(s,500,"Failed to serve image",n)}})}var Es,an,cg=w(()=>{"use strict";p();Es=x(require("fs-extra")),an=x(require("path"));ae();io()});function ug(r){return Ps.default.join(r,".assuremind","ci-integration.json")}function dg(r){return Ps.default.join(r,"results","quality-gates")}function sb(r,e){return Ps.default.join(dg(r),`${e}.json`)}async function Fi(r){let e=ug(r);if(!await Yt.default.pathExists(e))return Ni.parse({});try{let t=await Yt.default.readJson(e);return Ni.parse(t)}catch{return Ni.parse({})}}async function pg(r,e){let t=ug(r),s=Ni.parse(e);await Yt.default.ensureDir(Ps.default.dirname(t)),await K(t,s)}async function mg(r){let e=dg(r);if(!await Yt.default.pathExists(e))return[];try{let s=(await Yt.default.readdir(e)).filter(i=>i.endsWith(".json")).sort().reverse(),n=[];for(let i of s)try{let a=await Yt.default.readJson(Ps.default.join(e,i));n.push(lg.parse(a))}catch{}return n}catch{return[]}}async function gg(r,e){let t=sb(r,e);if(!await Yt.default.pathExists(t))return null;try{let s=await Yt.default.readJson(t);return lg.parse(s)}catch{return null}}var Ps,Yt,L,Mi,Qw,Zw,eb,tb,Ni,rb,lg,fg=w(()=>{"use strict";p();Ps=x(require("path")),Yt=x(require("fs-extra")),L=require("zod");Ve();Mi=L.z.enum(["every-run","failure","healing"]),Qw=L.z.object({enabled:L.z.boolean().default(!1),webhookUrl:L.z.string().default(""),on:L.z.array(Mi).default(["failure"])}),Zw=L.z.object({enabled:L.z.boolean().default(!1),recipients:L.z.array(L.z.string()).default([]),on:L.z.array(Mi).default(["failure"])}),eb=L.z.object({enabled:L.z.boolean().default(!1),webhookUrl:L.z.string().default(""),on:L.z.array(Mi).default(["failure"])}),tb=L.z.object({enabled:L.z.boolean().default(!1),url:L.z.string().default(""),headers:L.z.record(L.z.string()).default({}),on:L.z.array(Mi).default(["failure"])}),Ni=L.z.object({prComments:L.z.object({enabled:L.z.boolean().default(!1),provider:L.z.enum(["github","gitlab","azure-devops"]).default("github"),includeHealingSummary:L.z.boolean().default(!0),includeVisualDiffs:L.z.boolean().default(!1)}).default({}),qualityGate:L.z.object({enabled:L.z.boolean().default(!0),minPassRate:L.z.number().min(0).max(100).default(95),maxFlakyRate:L.z.number().min(0).max(100).default(10),maxDuration:L.z.number().min(0).default(0),requireTags:L.z.array(L.z.string()).default([])}).default({}),notifications:L.z.object({slack:Qw.default({}),email:Zw.default({}),teams:eb.default({}),customWebhook:tb.default({})}).default({})}),rb=L.z.object({name:L.z.string(),passed:L.z.boolean(),expected:L.z.string(),actual:L.z.string()}),lg=L.z.object({passed:L.z.boolean(),runId:L.z.string(),timestamp:L.z.string(),metrics:L.z.object({passRate:L.z.number(),totalTests:L.z.number(),passed:L.z.number(),failed:L.z.number(),skipped:L.z.number(),duration:L.z.number(),healingCount:L.z.number()}),gates:L.z.array(rb),reason:L.z.string().optional()})});function hg(r){let e=Math.floor(r/60),t=r%60;return e>0?`${e}m ${t}s`:`${t}s`}function nb(r){let e=r.passed+r.failed+r.skipped,t=e>0?(r.passed/e*100).toFixed(1):"0",s=r.failed>0?":x: Failed":":white_check_mark: Passed",n=[];if(r.suiteResults)for(let a of r.suiteResults)for(let o of a.cases)o.status==="failed"&&n.push(o.caseName);let i=[{type:"header",text:{type:"plain_text",text:"Assuremind Test Results",emoji:!0}},{type:"section",fields:[{type:"mrkdwn",text:`*Status:*
1502
+ `}async function Eb(r,e){let t=[];if(e.shadowPath){let a=e.frameSelector?`frameLocator('${ye(e.frameSelector)}').`:"",o=e.shadowPath.split(" >> ").map(c=>`locator('${ye(c.trim())}')`).join(".");return`${a}${o}`}let s=!!e.frameSelector,n=s?`frameLocator('${ye(e.frameSelector)}').`:"",i=s?r.frameLocator(e.frameSelector):r;try{let a=e.ariaRole||Ib(e.tag,e.type),o=e.ariaLabel||e.labelText||e.innerText||e.title||"",c=Pb(e.tag);e.testId&&t.push({name:"testid",locator:i.getByTestId(e.testId),pw:`${n}getByTestId('${ye(e.testId)}')`}),a&&o&&o.length<=60&&(c&&t.push({name:"role+name+level",locator:i.getByRole(a,{name:o,exact:!0,level:c}),pw:`${n}getByRole('${a}', { name: '${ye(o)}', level: ${c} })`}),t.push({name:"role+name-exact",locator:i.getByRole(a,{name:o,exact:!0}),pw:`${n}getByRole('${a}', { name: '${ye(o)}' })`}),t.push({name:"role+name-fuzzy",locator:i.getByRole(a,{name:o,exact:!1}),pw:`${n}getByRole('${a}', { name: '${ye(o)}' })`})),e.labelText&&(t.push({name:"label",locator:i.getByLabel(e.labelText,{exact:!0}),pw:`${n}getByLabel('${ye(e.labelText)}')`}),t.push({name:"label-fuzzy",locator:i.getByLabel(e.labelText,{exact:!1}),pw:`${n}getByLabel('${ye(e.labelText)}')`})),e.placeholder&&t.push({name:"placeholder",locator:i.getByPlaceholder(e.placeholder,{exact:!0}),pw:`${n}getByPlaceholder('${ye(e.placeholder)}')`}),e.innerText&&e.innerText.length<=60&&(t.push({name:"text-exact",locator:i.getByText(e.innerText,{exact:!0}),pw:`${n}getByText('${ye(e.innerText)}')`}),t.push({name:"text-fuzzy",locator:i.getByText(e.innerText,{exact:!1}),pw:`${n}getByText('${ye(e.innerText)}')`})),e.cssPath&&t.push({name:"css",locator:i.locator(e.cssPath),pw:`${n}locator('${ye(e.cssPath)}')`});for(let l of t)try{if(await l.locator.count()===1)return Le.debug({strategy:l.name,pw:l.pw,inIframe:s},"Locator resolved"),l.pw}catch{}return e.cssPath?`${n}locator('${ye(e.cssPath)}')`:e.id?`${n}locator('#${ye(e.id)}')`:`${n}locator('${ye(e.tag)}')`}catch(a){return Le.warn({err:a,meta:e.cssPath},"Locator resolution failed \u2014 using CSS fallback"),e.cssPath?`${n}locator('${ye(e.cssPath)}')`:`${n}locator('${ye(e.tag)}')`}}function Ib(r,e){if(r==="button"||r==="input"&&e==="submit")return"button";if(r==="a")return"link";if(r==="input"){if(e==="checkbox")return"checkbox";if(e==="radio")return"radio";if(["text","email","password","search","tel","url","number",""].includes(e))return"textbox"}return r==="textarea"?"textbox":r==="select"?"combobox":r==="img"?"img":["h1","h2","h3","h4","h5","h6"].includes(r)?"heading":null}function Pb(r){let e=r.match(/^h([1-6])$/);return e?parseInt(e[1],10):null}function ye(r){return r.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}var Pg,Le,Vi,Rg=b(()=>{"use strict";m();Pg=require("playwright");N();Le=E("recorder");Vi=class{browser=null;context=null;page=null;actions=[];actionCounter=0;running=!1;options;_setLastUserActionTime=null;constructor(e){this.options=e}get isRunning(){return this.running}get recordedActions(){return[...this.actions]}async start(){if(this.running)throw new Error("Recorder is already running");Le.info({url:this.options.startUrl},"Starting recorder"),this.actions=[],this.actionCounter=0,this.running=!0;try{this.browser=await Pg.chromium.launch({headless:!1,args:["--start-maximized"]}),this.context=await this.browser.newContext({viewport:this.options.viewport||{width:1280,height:720},ignoreHTTPSErrors:!0}),await this.context.exposeBinding("__amSend",(o,c)=>{this.handleRawAction(c)});let e=Cb();await this.context.addInitScript(e),this.page=await this.context.newPage(),this.page.on("pageerror",o=>{Le.warn({error:o.message},"Page error during recording")});let t=async o=>{try{await o.evaluate(e),Le.debug({url:o.url(),name:o.name()},"Capture script injected into frame")}catch(c){Le.debug({err:c,url:o.url()},"Could not inject into frame (likely cross-origin)")}},s=async o=>{await t(o.mainFrame());for(let c of o.frames())c!==o.mainFrame()&&await t(c)};this.page.on("load",()=>{!this.running||!this.page||setTimeout(()=>s(this.page),150)}),this.page.on("frameattached",o=>{this.running&&o.waitForLoadState("load").then(()=>{t(o)}).catch(()=>{})}),this.page.on("framenavigated",o=>{!this.running||!this.page||o!==this.page.mainFrame()&&setTimeout(()=>t(o),150)});let n="",i=0,a=3e3;this.page.on("framenavigated",o=>{if(!this.running||!this.page||o!==this.page.mainFrame())return;let c=o.url();if(c===n||c==="about:blank")return;n=c;let l=this.actionCounter===0;if(!l&&i>0){let d=Date.now()-i;if(d<a){Le.debug({url:c,elapsed:d},"Skipping redirect navigation after user action");return}}let u={id:`rec-${++this.actionCounter}`,order:this.actionCounter,action:"navigate",instruction:l?`Go to ${c}`:`Navigate to ${c}`,locator:"",url:c,timestamp:Date.now()};this.actions.push(u),this.options.onAction(u),Le.debug({action:u.instruction},"Recorded navigation")}),this._setLastUserActionTime=o=>{i=o},this.page.on("dialog",async o=>{if(!this.running)return;let c=o.type(),l=o.message();await o.accept().catch(()=>{});for(let u=this.actions.length-1;u>=0;u--){let d=this.actions[u];if(["click","fill","check","uncheck","select","press"].includes(d.action)){d.dialogHandler={type:"accept",dialogType:c,message:l};break}}Le.debug({dialogType:c,message:l},"Dialog auto-accepted and tagged on triggering action")}),this.page.on("close",()=>{this.running&&(Le.info("Browser closed by user \u2014 stopping recorder"),this.running=!1,this.options.onStop?.(this.actions))}),await this.page.goto(this.options.startUrl,{waitUntil:"load",timeout:3e4}),await s(this.page),Le.info("Recorder started \u2014 browser is open for interaction")}catch(e){throw Le.error({err:e},"Failed to start recorder"),await this.cleanup(),e}}async stop(){if(!this.running)return this.actions;Le.info({actionCount:this.actions.length},"Stopping recorder"),this.running=!1;let e=[...this.actions];return await this.cleanup(),this.options.onStop?.(e),e}async handleRawAction(e){if(!(!this.running||!this.page))try{let t=JSON.parse(e),s=t.meta,n="";if(s&&this.page)try{n=await Eb(this.page,s)}catch(o){Le.warn({err:o},"Locator resolution failed \u2014 using CSS fallback"),n=s.cssPath?`locator('${ye(s.cssPath)}')`:""}["click","fill","check","uncheck","select","press"].includes(t.action)&&this._setLastUserActionTime&&this._setLastUserActionTime(Date.now());let a={id:`rec-${++this.actionCounter}`,order:this.actionCounter,action:t.action,instruction:t.instruction,locator:n,value:t.value,url:t.url,timestamp:Date.now(),...t.soft?{soft:!0}:{},...s?.frameSelector?{frameSelector:s.frameSelector}:{},...s?.shadowPath?{shadowPath:s.shadowPath}:{}};this.actions.push(a),this.options.onAction(a),Le.debug({action:a.instruction,locator:n,strategy:"resolved"},"Recorded action")}catch(t){Le.warn({err:t,raw:e},"Failed to parse recorded action")}}async cleanup(){try{this.context&&await this.context.close().catch(()=>{}),this.browser&&await this.browser.close().catch(()=>{})}catch{}this.browser=null,this.context=null,this.page=null}}});async function Tg(r){let e=r.rootDir,t=r.wsManager;r.post("/recorder/start",async(s,n)=>{try{if(Ct?.isRunning)return n.status(409).send({error:"A recording session is already active. Stop it first."});let i=Tb.parse(s.body||{}),a=await G(e),o=i.url||a.baseUrl||"https://www.google.com";return Ct=new Vi({startUrl:o,viewport:i.viewport,onAction:c=>{t.broadcast("recorder:action",c)},onStop:c=>{t.broadcast("recorder:stopped",{actionCount:c.length}),Rb.info({actionCount:c.length},"Recording stopped (browser closed)")}}),await Ct.start(),n.send({status:"recording",url:o,message:"Browser launched \u2014 interact with your app. Actions are streamed in real time."})}catch(i){return Ct=null,w(n,500,"Failed to start recorder",i)}}),r.post("/recorder/stop",async(s,n)=>{try{if(!Ct?.isRunning)return n.status(404).send({error:"No active recording session."});let i=await Ct.stop();return Ct=null,t.broadcast("recorder:stopped",{actionCount:i.length}),n.send({status:"stopped",actions:i,actionCount:i.length})}catch(i){return Ct=null,w(n,500,"Failed to stop recorder",i)}}),r.get("/recorder/status",async(s,n)=>{let i=Ct?.isRunning??!1,a=Ct?.recordedActions.length??0;return n.send({recording:i,actionCount:a,actions:i?Ct.recordedActions:[]})})}var As,Rb,Tb,Ct,kg=b(()=>{"use strict";m();As=require("zod");Rg();Te();re();N();Rb=E("recorder-routes"),Tb=As.z.object({url:As.z.string().url().optional(),viewport:As.z.object({width:As.z.number().int().positive(),height:As.z.number().int().positive()}).optional()}),Ct=null});var Ag,$g=b(()=>{"use strict";m();no();Ag=async r=>{r.get("/faker/generators",async(e,t)=>{let s=ai();return t.send(s)})}});async function _g(r){let e=r.rootDir;r.get("/visual-regression/config",async(t,s)=>{try{let n=await sn(e);return s.send(n)}catch(n){return w(s,500,"Failed to read visual-regression config",n)}}),r.put("/visual-regression/config",async(t,s)=>{try{let n=t.body,i=await sn(e),a={enabled:typeof n.enabled=="boolean"?n.enabled:i.enabled,defaultThreshold:typeof n.defaultThreshold=="number"?n.defaultThreshold:i.defaultThreshold,fullPage:typeof n.fullPage=="boolean"?n.fullPage:i.fullPage,maskSelectors:Array.isArray(n.maskSelectors)?n.maskSelectors:i.maskSelectors};return await ip(e,a),s.send(a)}catch(n){return w(s,500,"Failed to save visual-regression config",n)}}),r.get("/visual-regression/baselines",async(t,s)=>{try{let n=await lp(e);return s.send(n)}catch(n){return w(s,500,"Failed to list baselines",n)}}),r.delete("/visual-regression/baselines",async(t,s)=>{try{let{path:n}=t.body;return n?(await up(e,n),s.send({ok:!0})):s.status(400).send({error:'Missing "path" in request body'})}catch(n){return w(s,500,"Failed to delete baseline",n)}}),r.post("/visual-regression/baselines/update",async(t,s)=>{try{let{actualPath:n,baselinePath:i}=t.body;return!n||!i?s.status(400).send({error:"Missing actualPath or baselinePath"}):await $s.default.pathExists(n)?(await $s.default.ensureDir(pn.default.dirname(i)),await $s.default.copy(n,i,{overwrite:!0}),s.send({ok:!0})):s.status(404).send({error:"Actual screenshot not found"})}catch(n){return w(s,500,"Failed to update baseline",n)}}),r.get("/visual-regression/diffs",async(t,s)=>{try{let n=await ap(e);return s.send(n)}catch(n){return w(s,500,"Failed to list diff runs",n)}}),r.get("/visual-regression/diffs/:runId",async(t,s)=>{try{let{runId:n}=t.params,i=await ui(e,n);return s.send(i)}catch(n){return w(s,500,"Failed to read diff summary",n)}}),r.patch("/visual-regression/diffs/:runId/:stepId",async(t,s)=>{try{let{runId:n,stepId:i}=t.params,{status:a}=t.body;if(!["approved","rejected"].includes(a))return s.status(400).send({error:'Status must be "approved" or "rejected"'});let o=await op(e,n,i,a);return s.send(o)}catch(n){return w(s,500,"Failed to update diff status",n)}}),r.post("/visual-regression/diffs/:runId/approve-all",async(t,s)=>{try{let{runId:n}=t.params,i=await cp(e,n);return s.send(i)}catch(n){return w(s,500,"Failed to approve all diffs",n)}}),r.get("/visual-regression/image/*",async(t,s)=>{try{let n=t.params["*"];if(!n)return s.status(400).send({error:"Missing image path"});let i=pn.default.resolve(e,n);if(!i.startsWith(pn.default.resolve(e)))return s.status(403).send({error:"Forbidden"});if(!await $s.default.pathExists(i))return s.status(404).send({error:"Image not found"});let a=pn.default.extname(i).toLowerCase(),c={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp"}[a]??"application/octet-stream",l=await $s.default.readFile(i);return s.type(c).send(l)}catch(n){return w(s,500,"Failed to serve image",n)}})}var $s,pn,Lg=b(()=>{"use strict";m();$s=x(require("fs-extra")),pn=x(require("path"));re();fo()});function Dg(r){return _s.default.join(r,".assuremind","ci-integration.json")}function Fg(r){return _s.default.join(r,"results","quality-gates")}function Ob(r,e){return _s.default.join(Fg(r),`${e}.json`)}async function qi(r){let e=Dg(r);if(!await tr.default.pathExists(e))return Gi.parse({});try{let t=await tr.default.readJson(e);return Gi.parse(t)}catch{return Gi.parse({})}}async function Ng(r,e){let t=Dg(r),s=Gi.parse(e);await tr.default.ensureDir(_s.default.dirname(t)),await K(t,s)}async function Mg(r){let e=Fg(r);if(!await tr.default.pathExists(e))return[];try{let s=(await tr.default.readdir(e)).filter(i=>i.endsWith(".json")).sort().reverse(),n=[];for(let i of s)try{let a=await tr.default.readJson(_s.default.join(e,i));n.push(Og.parse(a))}catch{}return n}catch{return[]}}async function jg(r,e){let t=Ob(r,e);if(!await tr.default.pathExists(t))return null;try{let s=await tr.default.readJson(t);return Og.parse(s)}catch{return null}}var _s,tr,O,zi,kb,Ab,$b,_b,Gi,Lb,Og,Bg=b(()=>{"use strict";m();_s=x(require("path")),tr=x(require("fs-extra")),O=require("zod");ze();zi=O.z.enum(["every-run","failure","healing"]),kb=O.z.object({enabled:O.z.boolean().default(!1),webhookUrl:O.z.string().default(""),on:O.z.array(zi).default(["failure"])}),Ab=O.z.object({enabled:O.z.boolean().default(!1),recipients:O.z.array(O.z.string()).default([]),on:O.z.array(zi).default(["failure"])}),$b=O.z.object({enabled:O.z.boolean().default(!1),webhookUrl:O.z.string().default(""),on:O.z.array(zi).default(["failure"])}),_b=O.z.object({enabled:O.z.boolean().default(!1),url:O.z.string().default(""),headers:O.z.record(O.z.string()).default({}),on:O.z.array(zi).default(["failure"])}),Gi=O.z.object({prComments:O.z.object({enabled:O.z.boolean().default(!1),provider:O.z.enum(["github","gitlab","azure-devops"]).default("github"),includeHealingSummary:O.z.boolean().default(!0),includeVisualDiffs:O.z.boolean().default(!1)}).default({}),qualityGate:O.z.object({enabled:O.z.boolean().default(!0),minPassRate:O.z.number().min(0).max(100).default(95),maxFlakyRate:O.z.number().min(0).max(100).default(10),maxDuration:O.z.number().min(0).default(0),requireTags:O.z.array(O.z.string()).default([])}).default({}),notifications:O.z.object({slack:kb.default({}),email:Ab.default({}),teams:$b.default({}),customWebhook:_b.default({})}).default({})}),Lb=O.z.object({name:O.z.string(),passed:O.z.boolean(),expected:O.z.string(),actual:O.z.string()}),Og=O.z.object({passed:O.z.boolean(),runId:O.z.string(),timestamp:O.z.string(),metrics:O.z.object({passRate:O.z.number(),totalTests:O.z.number(),passed:O.z.number(),failed:O.z.number(),skipped:O.z.number(),duration:O.z.number(),healingCount:O.z.number()}),gates:O.z.array(Lb),reason:O.z.string().optional()})});function Ug(r){let e=Math.floor(r/60),t=r%60;return e>0?`${e}m ${t}s`:`${t}s`}function Db(r){let e=r.passed+r.failed+r.skipped,t=e>0?(r.passed/e*100).toFixed(1):"0",s=r.failed>0?":x: Failed":":white_check_mark: Passed",n=[];if(r.suiteResults)for(let a of r.suiteResults)for(let o of a.cases)o.status==="failed"&&n.push(o.caseName);let i=[{type:"header",text:{type:"plain_text",text:"Assuremind Test Results",emoji:!0}},{type:"section",fields:[{type:"mrkdwn",text:`*Status:*
1449
1503
  ${s}`},{type:"mrkdwn",text:`*Pass Rate:*
1450
1504
  ${t}% (${r.passed}/${e})`},{type:"mrkdwn",text:`*Failed:*
1451
1505
  ${r.failed}`},{type:"mrkdwn",text:`*Duration:*
1452
- ${hg(r.duration)}`}]}];return n.length>0&&i.push({type:"section",text:{type:"mrkdwn",text:`*Failed Tests:*
1506
+ ${Ug(r.duration)}`}]}];return n.length>0&&i.push({type:"section",text:{type:"mrkdwn",text:`*Failed Tests:*
1453
1507
  ${n.map(a=>`\u2022 ${a}`).join(`
1454
- `)}`}}),i.push({type:"context",elements:[{type:"mrkdwn",text:":robot_face: Generated by Assuremind"}]}),{blocks:i}}function ib(r){let e=r.passed+r.failed+r.skipped,t=e>0?(r.passed/e*100).toFixed(1):"0",s=r.failed>0?"attention":"good",n=[{title:"Pass Rate",value:`${t}% (${r.passed}/${e})`},{title:"Failed",value:`${r.failed}`},{title:"Skipped",value:`${r.skipped}`},{title:"Duration",value:hg(r.duration)}];return{type:"message",attachments:[{contentType:"application/vnd.microsoft.card.adaptive",content:{$schema:"http://adaptivecards.io/schemas/adaptive-card.json",type:"AdaptiveCard",version:"1.4",body:[{type:"TextBlock",text:"Assuremind Test Results",weight:"bolder",size:"medium",color:s},{type:"FactSet",facts:n}]}}]}}async function ab(r,e){let t=nb(e);Qt.info("Sending Slack notification");let s=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(s.ok)Qt.info("Slack notification sent");else{let n=await s.text();Qt.error({status:s.status,text:n},"Failed to send Slack notification")}}async function ob(r,e){let t=ib(e);Qt.info("Sending Teams notification");let s=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(s.ok)Qt.info("Teams notification sent");else{let n=await s.text();Qt.error({status:s.status,text:n},"Failed to send Teams notification")}}async function cb(r,e,t){Qt.info({url:r},"Sending custom webhook notification");let s=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",...e},body:JSON.stringify({source:"assuremind",runId:t.runId,passed:t.passed,failed:t.failed,skipped:t.skipped,duration:t.duration,timestamp:new Date().toISOString()})});if(s.ok)Qt.info("Custom webhook notification sent");else{let n=await s.text();Qt.error({status:s.status,text:n},"Failed to send custom webhook notification")}}async function yg(r,e){let t={runId:"test-notification",passed:10,failed:1,skipped:2,duration:45,suiteResults:[{suiteId:"demo",suiteName:"Demo Suite",cases:[{caseId:"c1",caseName:"Test notification",status:"passed"},{caseId:"c2",caseName:"Example failed test",status:"failed",error:"This is a test notification"}]}]};try{switch(r){case"slack":{let{webhookUrl:s}=e.notifications.slack;return s?(await ab(s,t),{ok:!0}):{ok:!1,error:"Slack webhook URL not configured"}}case"teams":{let{webhookUrl:s}=e.notifications.teams;return s?(await ob(s,t),{ok:!0}):{ok:!1,error:"Teams webhook URL not configured"}}case"custom":{let{url:s,headers:n}=e.notifications.customWebhook;return s?(await cb(s,n,t),{ok:!0}):{ok:!1,error:"Custom webhook URL not configured"}}default:return{ok:!1,error:`Unsupported channel: ${r}`}}}catch(s){return{ok:!1,error:s instanceof Error?s.message:String(s)}}}var Qt,wg=w(()=>{"use strict";p();F();Qt=E("notifier")});async function bg(r){let e=r.rootDir;r.get("/ci-integration/config",async(t,s)=>{try{let n=await Fi(e);return s.send(n)}catch(n){return b(s,500,"Failed to read CI integration config",n)}}),r.put("/ci-integration/config",async(t,s)=>{try{let n=t.body;await pg(e,n);let i=await Fi(e);return s.send(i)}catch(n){return b(s,500,"Failed to save CI integration config",n)}}),r.get("/ci-integration/quality-gates",async(t,s)=>{try{let n=await mg(e);return s.send(n)}catch(n){return b(s,500,"Failed to list quality gate results",n)}}),r.get("/ci-integration/quality-gates/:runId",async(t,s)=>{try{let n=await gg(e,t.params.runId);return n?s.send(n):s.status(404).send({error:"Quality gate result not found"})}catch(n){return b(s,500,"Failed to read quality gate result",n)}}),r.post("/ci-integration/test-notification",async(t,s)=>{let n=lb.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid request",details:n.error.issues});try{let i=await Fi(e),a=await yg(n.data.channel,i);return s.send(a)}catch(i){return b(s,500,"Failed to send test notification",i)}})}var Go,lb,vg=w(()=>{"use strict";p();Go=require("zod");fg();wg();ae();lb=Go.z.object({channel:Go.z.enum(["slack","teams","custom"])})});var Pg={};Q(Pg,{startServer:()=>ub});async function ub(r){let{port:e,rootDir:t}=r,s=(0,Sg.default)({logger:!1}),n=new yn;return s.decorate("rootDir",t),s.decorate("wsManager",n),await s.register(Cg.default,{origin:!0,methods:["GET","POST","PUT","PATCH","DELETE","OPTIONS"]}),await s.register(Eg.default),s.get("/ws",{websocket:!0},i=>{n.add(i)}),await s.register(Tc,{prefix:"/api"}),await s.register(Dc,{prefix:"/api"}),await s.register(Bc,{prefix:"/api"}),await s.register(lu,{prefix:"/api"}),await s.register(xu,{prefix:"/api"}),await s.register(Cu,{prefix:"/api"}),await s.register(Fu,{prefix:"/api"}),await s.register(em,{prefix:"/api"}),await s.register(nm,{prefix:"/api"}),await s.register(am,{prefix:"/api"}),await s.register(mm,{prefix:"/api"}),await s.register(Im,{prefix:"/api"}),await s.register(Om,{prefix:"/api"}),await s.register(Nm,{prefix:"/api"}),await s.register(Bm,{prefix:"/api"}),await s.register(Hm,{prefix:"/api"}),await s.register(Gm,{prefix:"/api"}),await s.register(qm,{prefix:"/api"}),await s.register(Zm,{prefix:"/api"}),await s.register(sg,{prefix:"/api"}),await s.register(ig,{prefix:"/api"}),await s.register(og,{prefix:"/api"}),await s.register(bg,{prefix:"/api"}),await Pc(s,t),await s.listen({port:e,host:"127.0.0.1"}),xg.info({port:e,rootDir:t},`Assuremind Studio listening on http://127.0.0.1:${e}`),{async close(){await s.close(),xg.info("Server closed")}}}var Sg,Cg,Eg,xg,Ig=w(()=>{"use strict";p();Sg=x(require("fastify")),Cg=x(require("@fastify/cors")),Eg=x(require("@fastify/websocket"));Cc();Ec();Ic();kc();Nc();Uc();uu();Su();Eu();ju();tm();im();om();gm();Rm();Lm();Mm();Um();Vm();zm();Xm();eg();ng();ag();cg();vg();F();xg=E("server")});var Tg={};Q(Tg,{runStudio:()=>db});async function db(r={}){process.on("unhandledRejection",n=>{let i=n instanceof Error?n.message:String(n);W(`Unhandled rejection (non-fatal): ${i}`)}),process.stdout.write(`
1508
+ `)}`}}),i.push({type:"context",elements:[{type:"mrkdwn",text:":robot_face: Generated by Assuremind"}]}),{blocks:i}}function Fb(r){let e=r.passed+r.failed+r.skipped,t=e>0?(r.passed/e*100).toFixed(1):"0",s=r.failed>0?"attention":"good",n=[{title:"Pass Rate",value:`${t}% (${r.passed}/${e})`},{title:"Failed",value:`${r.failed}`},{title:"Skipped",value:`${r.skipped}`},{title:"Duration",value:Ug(r.duration)}];return{type:"message",attachments:[{contentType:"application/vnd.microsoft.card.adaptive",content:{$schema:"http://adaptivecards.io/schemas/adaptive-card.json",type:"AdaptiveCard",version:"1.4",body:[{type:"TextBlock",text:"Assuremind Test Results",weight:"bolder",size:"medium",color:s},{type:"FactSet",facts:n}]}}]}}async function Nb(r,e){let t=Db(e);rr.info("Sending Slack notification");let s=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(s.ok)rr.info("Slack notification sent");else{let n=await s.text();rr.error({status:s.status,text:n},"Failed to send Slack notification")}}async function Mb(r,e){let t=Fb(e);rr.info("Sending Teams notification");let s=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(s.ok)rr.info("Teams notification sent");else{let n=await s.text();rr.error({status:s.status,text:n},"Failed to send Teams notification")}}async function jb(r,e,t){rr.info({url:r},"Sending custom webhook notification");let s=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",...e},body:JSON.stringify({source:"assuremind",runId:t.runId,passed:t.passed,failed:t.failed,skipped:t.skipped,duration:t.duration,timestamp:new Date().toISOString()})});if(s.ok)rr.info("Custom webhook notification sent");else{let n=await s.text();rr.error({status:s.status,text:n},"Failed to send custom webhook notification")}}async function Hg(r,e){let t={runId:"test-notification",passed:10,failed:1,skipped:2,duration:45,suiteResults:[{suiteId:"demo",suiteName:"Demo Suite",cases:[{caseId:"c1",caseName:"Test notification",status:"passed"},{caseId:"c2",caseName:"Example failed test",status:"failed",error:"This is a test notification"}]}]};try{switch(r){case"slack":{let{webhookUrl:s}=e.notifications.slack;return s?(await Nb(s,t),{ok:!0}):{ok:!1,error:"Slack webhook URL not configured"}}case"teams":{let{webhookUrl:s}=e.notifications.teams;return s?(await Mb(s,t),{ok:!0}):{ok:!1,error:"Teams webhook URL not configured"}}case"custom":{let{url:s,headers:n}=e.notifications.customWebhook;return s?(await jb(s,n,t),{ok:!0}):{ok:!1,error:"Custom webhook URL not configured"}}default:return{ok:!1,error:`Unsupported channel: ${r}`}}}catch(s){return{ok:!1,error:s instanceof Error?s.message:String(s)}}}var rr,Vg=b(()=>{"use strict";m();N();rr=E("notifier")});async function Gg(r){let e=r.rootDir;r.get("/ci-integration/config",async(t,s)=>{try{let n=await qi(e);return s.send(n)}catch(n){return w(s,500,"Failed to read CI integration config",n)}}),r.put("/ci-integration/config",async(t,s)=>{try{let n=t.body;await Ng(e,n);let i=await qi(e);return s.send(i)}catch(n){return w(s,500,"Failed to save CI integration config",n)}}),r.get("/ci-integration/quality-gates",async(t,s)=>{try{let n=await Mg(e);return s.send(n)}catch(n){return w(s,500,"Failed to list quality gate results",n)}}),r.get("/ci-integration/quality-gates/:runId",async(t,s)=>{try{let n=await jg(e,t.params.runId);return n?s.send(n):s.status(404).send({error:"Quality gate result not found"})}catch(n){return w(s,500,"Failed to read quality gate result",n)}}),r.post("/ci-integration/test-notification",async(t,s)=>{let n=Bb.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid request",details:n.error.issues});try{let i=await qi(e),a=await Hg(n.data.channel,i);return s.send(a)}catch(i){return w(s,500,"Failed to send test notification",i)}})}var sc,Bb,zg=b(()=>{"use strict";m();sc=require("zod");Bg();Vg();re();Bb=sc.z.object({channel:sc.z.enum(["slack","teams","custom"])})});var Jg={};Q(Jg,{startServer:()=>Ub});async function Ub(r){let{port:e,rootDir:t}=r,s=(0,Xg.default)({logger:!1}),n=new Cn;return s.decorate("rootDir",t),s.decorate("wsManager",n),await s.register(Kg.default,{origin:!0,methods:["GET","POST","PUT","PATCH","DELETE","OPTIONS"]}),await s.register(Wg.default),s.get("/ws",{websocket:!0},i=>{n.add(i)}),await s.register(Uc,{prefix:"/api"}),await s.register(Kc,{prefix:"/api"}),await s.register(Zc,{prefix:"/api"}),await s.register(Ru,{prefix:"/api"}),await s.register(ju,{prefix:"/api"}),await s.register(Uu,{prefix:"/api"}),await s.register(rd,{prefix:"/api"}),await s.register(wm,{prefix:"/api"}),await s.register(Sm,{prefix:"/api"}),await s.register(Im,{prefix:"/api"}),await s.register(_m,{prefix:"/api"}),await s.register(zm,{prefix:"/api"}),await s.register(Qm,{prefix:"/api"}),await s.register(tg,{prefix:"/api"}),await s.register(ng,{prefix:"/api"}),await s.register(cg,{prefix:"/api"}),await s.register(mg,{prefix:"/api"}),await s.register(fg,{prefix:"/api"}),await s.register(yg,{prefix:"/api"}),await s.register(Eg,{prefix:"/api"}),await s.register(Tg,{prefix:"/api"}),await s.register(Ag,{prefix:"/api"}),await s.register(_g,{prefix:"/api"}),await s.register(Gg,{prefix:"/api"}),await Mc(s,t),await s.listen({port:e,host:"127.0.0.1"}),qg.info({port:e,rootDir:t},`Assuremind Studio listening on http://127.0.0.1:${e}`),{async close(){await s.close(),qg.info("Server closed")}}}var Xg,Kg,Wg,qg,Yg=b(()=>{"use strict";m();Xg=x(require("fastify")),Kg=x(require("@fastify/cors")),Wg=x(require("@fastify/websocket"));Fc();Nc();jc();Hc();Wc();el();Tu();Bu();Hu();sd();bm();Cm();Pm();Lm();qm();Zm();rg();ig();lg();gg();hg();wg();Ig();kg();$g();Lg();zg();N();qg=E("server")});var Zg={};Q(Zg,{runStudio:()=>Hb});async function Hb(r={}){process.on("unhandledRejection",n=>{let i=n instanceof Error?n.message:String(n);W(`Unhandled rejection (non-fatal): ${i}`)}),process.stdout.write(`
1455
1509
  `),V(`Starting Assuremind Studio\u2026
1456
- `),Ut()||He(`AI provider not configured. The Studio will start, but AI features
1510
+ `),Gt()||Ge(`AI provider not configured. The Studio will start, but AI features
1457
1511
  (test generation, code generation, self-healing) require a valid
1458
1512
  AI_PROVIDER and its API key in your .env file.
1459
1513
  See .env.example for details.
1460
- `);let t;try{let n=await J(process.cwd());t=r.port??n.studioPort}catch(n){W(`Config error: ${n instanceof Error?n.message:String(n)}`),process.exit(1)}let s=St("Starting server\u2026");s.start();try{let{startServer:n}=await Promise.resolve().then(()=>(Ig(),Pg)).catch(()=>{throw new ye(`Server module is not available yet.
1514
+ `);let t;try{let n=await G(process.cwd());t=r.port??n.studioPort}catch(n){W(`Config error: ${n instanceof Error?n.message:String(n)}`),process.exit(1)}let s=It("Starting server\u2026");s.start();try{let{startServer:n}=await Promise.resolve().then(()=>(Yg(),Jg)).catch(()=>{throw new fe(`Server module is not available yet.
1461
1515
  This is expected during development \u2014 Phase 5 implements the server.
1462
- Build the full package with "npm run build" first.`,"SERVER_NOT_AVAILABLE")}),i=await n({port:t,rootDir:process.cwd()});s.succeed(`Server running at http://localhost:${t}`);let a=`http://localhost:${t}`;jt(["\u{1F9EA} Assuremind Studio","",` URL: ${a}`,` Port: ${t}`,"","Press Ctrl+C to stop"]),r.noOpen||await(0,Rg.default)(a),await new Promise((o,c)=>{process.on("SIGINT",()=>{i.close().then(()=>{V(`
1516
+ Build the full package with "npm run build" first.`,"SERVER_NOT_AVAILABLE")}),i=await n({port:t,rootDir:process.cwd()});s.succeed(`Server running at http://localhost:${t}`);let a=`http://localhost:${t}`;Ht(["\u{1F9EA} Assuremind Studio","",` URL: ${a}`,` Port: ${t}`,"","Press Ctrl+C to stop"]),r.noOpen||await(0,Qg.default)(a),await new Promise((o,c)=>{process.on("SIGINT",()=>{i.close().then(()=>{V(`
1463
1517
  Studio stopped.`),process.exit(0)}).catch(c)}),process.on("SIGTERM",()=>{i.close().then(()=>process.exit(0)).catch(c)})})}catch(n){s.fail("Failed to start server");let i=n instanceof Error?n.message:String(n);i.includes("EADDRINUSE")?(W(`Port ${t} is already in use.`),V(`Fix: kill the process using the port, then try again:
1464
1518
  npx kill-port ${t}
1465
1519
  npx assuremind studio --port ${t}
1466
1520
 
1467
1521
  Or use a different port:
1468
1522
  npx assuremind studio --port ${t+1}
1469
- `)):W(i),process.exit(1)}}var Rg,kg=w(()=>{"use strict";p();Rg=x(require("open"));Bt();ar();_e();re()});var $g={};Q($g,{runRun:()=>yb});function pb(r){let e={};return r.all&&(e.all=!0),r.type&&(e.type=r.type),r.suite&&(e.suite=r.suite),r.tag&&(e.tag=r.tag),r.test&&(e.test=r.test),r.browser&&(e.browsers=r.browser),r.device&&(e.device=r.device),r.env&&(e.env=r.env),r.parallel!==void 0&&(e.parallel=r.parallel),r.headed&&(e.headed=!0),r.ci&&(e.ci=!0),r.reporter&&(e.reporter=r.reporter),r.noHealing&&(e.noHealing=!0),e}function mb(r){let e=[r.all,r.type,r.suite,r.tag,r.test].filter(Boolean);if(e.length===0)throw new ye(`Specify what to run: --all, --type <type>, --suite <name>, --tag <tag>, or --test <name>
1470
- Filters can be combined: e.g. --type audit --tag regression`,"RUN_NO_SELECTOR");if(r.all&&e.length>1)throw new ye("--all cannot be combined with other filters (--type, --suite, --tag, --test)","RUN_MULTIPLE_SELECTORS")}function zo(r){if(r<1e3)return`${r}ms`;if(r<6e4)return`${(r/1e3).toFixed(1)}s`;let e=Math.floor(r/6e4),t=Math.round(r%6e4/1e3);return`${e}m ${t}s`}function Ag(r){switch(r){case"passed":return O.success("\u2713");case"failed":return O.error("\u2717");case"skipped":return O.warn("\u2013");default:return O.dim("?")}}function gb(r,e){let t=Ag(r.status),s=O.dim(`(${zo(r.duration)})`);if(process.stdout.write(` ${t} ${r.caseName} ${s}
1471
- `),!e||r.status==="failed"){for(let n of r.steps)if(n.status==="failed"){if(process.stdout.write(` ${O.error("\u2717")} ${O.dim(n.instruction)}
1523
+ `)):W(i),process.exit(1)}}var Qg,ef=b(()=>{"use strict";m();Qg=x(require("open"));Vt();lr();Te();te()});var rf={};Q(rf,{runRun:()=>Kb});function Vb(r){let e={};return r.all&&(e.all=!0),r.type&&(e.type=r.type),r.suite&&(e.suite=r.suite),r.tag&&(e.tag=r.tag),r.test&&(e.test=r.test),r.browser&&(e.browsers=r.browser),r.device&&(e.device=r.device),r.env&&(e.env=r.env),r.parallel!==void 0&&(e.parallel=r.parallel),r.headed&&(e.headed=!0),r.ci&&(e.ci=!0),r.reporter&&(e.reporter=r.reporter),r.noHealing&&(e.noHealing=!0),e}function Gb(r){let e=[r.all,r.type,r.suite,r.tag,r.test].filter(Boolean);if(e.length===0)throw new fe(`Specify what to run: --all, --type <type>, --suite <name>, --tag <tag>, or --test <name>
1524
+ Filters can be combined: e.g. --type audit --tag regression`,"RUN_NO_SELECTOR");if(r.all&&e.length>1)throw new fe("--all cannot be combined with other filters (--type, --suite, --tag, --test)","RUN_MULTIPLE_SELECTORS")}function nc(r){if(r<1e3)return`${r}ms`;if(r<6e4)return`${(r/1e3).toFixed(1)}s`;let e=Math.floor(r/6e4),t=Math.round(r%6e4/1e3);return`${e}m ${t}s`}function tf(r){switch(r){case"passed":return L.success("\u2713");case"failed":return L.error("\u2717");case"skipped":return L.warn("\u2013");default:return L.dim("?")}}function zb(r,e){let t=tf(r.status),s=L.dim(`(${nc(r.duration)})`);if(process.stdout.write(` ${t} ${r.caseName} ${s}
1525
+ `),!e||r.status==="failed"){for(let n of r.steps)if(n.status==="failed"){if(process.stdout.write(` ${L.error("\u2717")} ${L.dim(n.instruction)}
1472
1526
  `),n.error){let i=n.error.split(`
1473
- `)[0]?.slice(0,120)??"";process.stdout.write(` ${O.dim(i)}
1474
- `)}n.healed&&process.stdout.write(` ${O.warn("\u2695")} ${O.dim("Self-healed \u2014 review in Studio")}
1475
- `)}}}function fb(r,e){let t=Ag(r.status),s=O.dim(`(${zo(r.duration)})`),n=O.dim(`[${r.browser}]`);process.stdout.write(`
1476
- ${t} ${O.bold(r.suiteName)} ${n} ${s}
1477
- `);for(let i of r.cases)gb(i,e)}function hb(r,e){let t=zo(r.duration),s=O.success(`${r.passed} passed`),n=r.failed>0?O.error(`${r.failed} failed`):O.dim("0 failed"),i=r.skipped>0?O.warn(`${r.skipped} skipped`):O.dim("0 skipped");if(!e){process.stdout.write(`
1478
- `);for(let o of r.suites)fb(o,e)}let a=[r.status==="passed"?"\u2705 All tests passed!":"\u274C Some tests failed","",` ${s} ${n} ${i}`,` Duration: ${t}`,` Run ID: ${r.runId}`,"",` Results saved to: results/runs/${r.runId}.json`];jt(a)}async function yb(r){process.stdout.write(`
1479
- `);try{mb(r)}catch(d){W(d instanceof Error?d.message:String(d)),process.exit(1)}try{Et()}catch(d){W(d instanceof Error?d.message:String(d)),process.exit(1)}let e=process.cwd(),t;try{t=await J(e)}catch(d){W(d instanceof Error?d.message:String(d)),process.exit(1)}let s=pb(r);s.browsers&&(t.browsers=s.browsers),s.parallel&&(t.parallel=s.parallel),s.headed&&(t.headless=!1),s.noHealing&&(t.healing.enabled=!1),s.device&&(t.device=s.device);let n=[];r.all&&n.push("all suites"),r.type&&n.push(`type "${r.type}"`),r.suite&&n.push(`suite "${r.suite}"`),r.tag&&n.push(`tag "${r.tag}"`),r.test&&n.push(`test "${r.test}"`);let i=n.join(" + ")||"all suites",a=t.device?` | device: ${t.device}`:"";V(`Running ${i} on [${t.browsers.join(", ")}]${a}`),r.ci||V(`Healing: ${t.healing.enabled?"enabled":"disabled"}`),process.stdout.write(`
1480
- `);let o=St("Loading test runner\u2026");o.start();let c;try{c=(await Promise.resolve().then(()=>(Io(),Zp))).runTests,o.succeed("Runner loaded")}catch{o.fail("Failed to load test runner"),W(`Test runner could not be loaded.
1481
- Make sure you have run "npm run build" or are running from source.`),process.exit(1)}let l=St("Running tests\u2026");r.ci||l.start();let u;try{u=await c(e,s,t)}catch(d){r.ci||l.fail("Run failed"),W(d instanceof Error?d.message:String(d)),process.exit(1)}r.ci||(u.status==="passed"?l.succeed("Run complete"):l.fail("Run complete with failures")),hb(u,r.ci??!1),u.failed>0&&(He(`${u.failed} test(s) failed. Check the report above for details.`),t.healing.enabled&&V('Self-healing events (if any) saved \u2014 run "npx assuremind apply-healing" to review.')),process.exit(u.status==="passed"?0:1)}var _g=w(()=>{"use strict";p();Bt();ar();_e();re()});var Og={};Q(Og,{runGenerate:()=>bb});async function wb(r){if(r.story)return r.story;if(r.storyFile){let e=Is.default.resolve(r.storyFile);if(!await qo.default.pathExists(e))throw new ye(`Story file not found: "${e}"`,"STORY_FILE_NOT_FOUND");return qo.default.readFile(e,"utf8")}throw new ye('Provide a story with --story "<text>" or --story-file <path>',"GENERATE_NO_STORY")}async function bb(r){process.stdout.write(`
1482
- `);try{Et()}catch(o){W(o instanceof Error?o.message:String(o)),process.exit(1)}let e;try{e=await wb(r)}catch(o){W(o instanceof Error?o.message:String(o)),process.exit(1)}let t=process.cwd(),s=r.output?Is.default.resolve(r.output):Is.default.join(t,"tests");V(`Story: ${O.dim(`${e.slice(0,80)}${e.length>80?"\u2026":""}`)}`),r.suite&&V(`Suite name: ${r.suite}`),V(`Output: ${s}`),process.stdout.write(`
1483
- `);let n=St("Loading AI layer\u2026");n.start();let i;try{i=(await Promise.resolve().then(()=>(dr(),au))).generateSuiteFromStory,n.succeed("AI layer ready")}catch{n.fail("Failed to load AI layer"),W(`AI layer could not be loaded.
1484
- Make sure you have run "npm run build" or are running from source.`),process.exit(1)}let a=St(`Generating test suite${r.suite?` "${r.suite}"`:""}\u2026`);a.start();try{await i(e,{rootDir:t,outputDir:s,suiteName:r.suite}),a.succeed("Suite generated");let o=r.output??Is.default.join(t,"tests");Ie(`Test suite created in: ${Is.default.relative(t,o)}`),V("Open Studio or use the Test Editor to review and generate Playwright code:"),process.stdout.write(` ${O.accent("npx assuremind studio")}
1485
-
1486
- `)}catch(o){a.fail("Generation failed"),W(o instanceof Error?o.message:String(o)),process.exit(1)}}var Is,qo,Lg=w(()=>{"use strict";p();Is=x(require("path")),qo=x(require("fs-extra"));Bt();ar();re()});var Dg={};Q(Dg,{runValidate:()=>Eb});async function vb(r,e){if(V("Checking configuration\u2026"),!await on.default.pathExists(Rs.default.join(r,"autotest.config.json"))&&!await on.default.pathExists(Rs.default.join(r,"autotest.config.ts"))){W(' autotest.config.ts not found \u2014 run "npx assuremind init" to create it'),e.errors++;return}try{let t=await J(r);Ie(` Config valid \u2014 baseUrl: ${O.accent(t.baseUrl)}, browsers: ${t.browsers.join(", ")}`),e.passed++}catch(t){W(` Config invalid: ${t instanceof Error?t.message:String(t)}`),e.errors++}}async function xb(r){if(V("Checking environment\u2026"),!await on.default.pathExists(".env")){He(" .env file not found \u2014 copy .env.example to .env and fill in your API key"),r.warnings++;return}let e=Ut();if(!e){W(" .env validation failed \u2014 check required variables for your AI provider"),r.errors++;return}Ie(` Provider: ${O.accent(String(e.AI_PROVIDER))}, tiered: ${e.AI_TIERED_ENABLED}`),r.passed++}async function Sb(r,e){V("Scanning test files\u2026");let t=Rs.default.join(r,"tests");if(!await on.default.pathExists(t)){He(" tests/ directory not found \u2014 no tests to validate"),e.warnings++;return}let s=await Tt(t);if(s.length===0){He(" No test suites found \u2014 create one in Studio"),e.warnings++;return}let n=0,i=0;for(let o of s){let c=await Ht(o);n+=c.length;for(let l of c)try{await se(l)}catch{W(` Invalid: ${Rs.default.relative(r,l)}`),i++,e.errors++}}let a=n-i;i===0?(Ie(` ${s.length} suite(s), ${n} test case(s) \u2014 all valid`),e.passed++):(He(` ${s.length} suite(s), ${a}/${n} cases valid`),e.warnings++)}async function Cb(r,e){V("Checking variable files\u2026");let t=await Xc(r);if(t.length===0){He(" No variable files found"),e.warnings++;return}let s=0;for(let n of t)try{await Yr(n)}catch{W(` Invalid: ${Rs.default.relative(r,n)}`),s++,e.errors++}s===0?(Ie(` ${t.length} variable file(s) \u2014 all valid`),e.passed++):e.warnings++}async function Eb(){let r=process.cwd();process.stdout.write(`
1487
- `);let e={passed:0,warnings:0,errors:0};await vb(r,e),process.stdout.write(`
1488
- `),await xb(e),process.stdout.write(`
1489
- `),await Sb(r,e),process.stdout.write(`
1490
- `),await Cb(r,e),process.stdout.write(`
1491
- `);let t=e.passed+e.warnings+e.errors,s=[e.passed>0?O.success(`${e.passed} passed`):null,e.warnings>0?O.warn(`${e.warnings} warnings`):null,e.errors>0?O.error(`${e.errors} errors`):null].filter(Boolean).join(O.dim(" | "));process.stdout.write(`Validation complete (${t} checks): ${s}
1492
-
1493
- `),e.errors>0&&process.exit(1)}var Rs,on,Ng=w(()=>{"use strict";p();Rs=x(require("path")),on=x(require("fs-extra"));Bt();_e();ze();dt();lr();ar()});var Mg={};Q(Mg,{runDoctor:()=>Ob});function fe(r,e,t){return{label:r,ok:e,detail:t}}function Ko(r){try{return(0,Xo.execSync)(r,{stdio:"pipe"}).toString().trim()}catch{return""}}async function Pb(){let r=process.version;return parseInt(r.slice(1).split(".")[0],10)>=18?fe("Node.js",!0,`${r} (>= 18 required)`):fe("Node.js",!1,`${r} is too old \u2014 upgrade to Node.js >= 18 from https://nodejs.org`)}async function Ib(){let r=Ko("npm --version");return r?fe("npm",!0,`v${r}`):fe("npm",!1,"npm not found \u2014 ensure Node.js is installed correctly")}async function Rb(){let r=Ko("npx playwright --version");if(!r)return fe("Playwright",!1,'Not found \u2014 run "npx assuremind init" to install');try{return(0,Xo.execSync)("npx playwright install --dry-run 2>&1",{stdio:"pipe"}),fe("Playwright",!0,`${r} \u2014 browsers installed`)}catch{return fe("Playwright",!1,`${r} installed but browsers may be missing \u2014 run "npx playwright install --with-deps"`)}}async function Tb(){if(!await ji.default.pathExists(".env"))return fe(".env file",!1,"Missing \u2014 copy .env.example to .env and fill in your API key");let r=Ut();return r?fe(".env file",!0,`Provider: ${String(r.AI_PROVIDER)}, tiered: ${r.AI_TIERED_ENABLED}`):fe(".env file",!1,"Present but invalid \u2014 check required variables for your AI provider")}async function kb(){try{let r=await J(process.cwd());return fe("Config",!0,`baseUrl: ${r.baseUrl}, port: ${r.studioPort}`)}catch(r){return fe("Config",!1,r instanceof Error?r.message:"Config validation failed")}}async function Ab(){if(!await ji.default.pathExists("package.json"))return fe("package.json",!1,'Not found \u2014 run "npm init -y" first');try{let r=await ji.default.readJson("package.json");return fe("package.json",!0,`${r.name??"unnamed"} v${r.version??"?"}`)}catch{return fe("package.json",!1,"Exists but is not valid JSON")}}async function $b(){let r=Ut();if(!r)return fe("AI connectivity",!1,"Cannot check \u2014 .env not configured");let e=String(r.AI_PROVIDER),s={anthropic:"https://api.anthropic.com",openai:"https://api.openai.com",google:"https://generativelanguage.googleapis.com",groq:"https://api.groq.com",deepseek:"https://api.deepseek.com",together:"https://api.together.xyz",perplexity:"https://api.perplexity.ai"}[e];if(!s)return fe("AI connectivity",!0,`${e} \u2014 skipped (local/custom provider)`);try{let n=Ko(`curl -s -o /dev/null -w "%{http_code}" --max-time 5 "${s}"`),i=parseInt(n,10);return i>0?fe("AI connectivity",!0,`${e} endpoint reachable (HTTP ${i})`):fe("AI connectivity",!1,`${e} endpoint unreachable \u2014 check your network or VPN`)}catch{return fe("AI connectivity",!1,`Could not reach ${e} endpoint`)}}function _b(r){r.ok?Ie(` ${O.bold(r.label)}: ${O.dim(r.detail)}`):W(` ${O.bold(r.label)}: ${r.detail}`)}async function Ob(){process.stdout.write(`
1527
+ `)[0]?.slice(0,120)??"";process.stdout.write(` ${L.dim(i)}
1528
+ `)}n.healed&&process.stdout.write(` ${L.warn("\u2695")} ${L.dim("Self-healed \u2014 review in Studio")}
1529
+ `)}}}function qb(r,e){let t=tf(r.status),s=L.dim(`(${nc(r.duration)})`),n=L.dim(`[${r.browser}]`);process.stdout.write(`
1530
+ ${t} ${L.bold(r.suiteName)} ${n} ${s}
1531
+ `);for(let i of r.cases)zb(i,e)}function Xb(r,e){let t=nc(r.duration),s=L.success(`${r.passed} passed`),n=r.failed>0?L.error(`${r.failed} failed`):L.dim("0 failed"),i=r.skipped>0?L.warn(`${r.skipped} skipped`):L.dim("0 skipped");if(!e){process.stdout.write(`
1532
+ `);for(let o of r.suites)qb(o,e)}let a=[r.status==="passed"?"\u2705 All tests passed!":"\u274C Some tests failed","",` ${s} ${n} ${i}`,` Duration: ${t}`,` Run ID: ${r.runId}`,"",` Results saved to: results/runs/${r.runId}.json`];Ht(a)}async function Kb(r){process.stdout.write(`
1533
+ `);try{Gb(r)}catch(d){W(d instanceof Error?d.message:String(d)),process.exit(1)}try{Rt()}catch(d){W(d instanceof Error?d.message:String(d)),process.exit(1)}let e=process.cwd(),t;try{t=await G(e)}catch(d){W(d instanceof Error?d.message:String(d)),process.exit(1)}let s=Vb(r);s.browsers&&(t.browsers=s.browsers),s.parallel&&(t.parallel=s.parallel),s.headed&&(t.headless=!1),s.noHealing&&(t.healing.enabled=!1),s.device&&(t.device=s.device);let n=[];r.all&&n.push("all suites"),r.type&&n.push(`type "${r.type}"`),r.suite&&n.push(`suite "${r.suite}"`),r.tag&&n.push(`tag "${r.tag}"`),r.test&&n.push(`test "${r.test}"`);let i=n.join(" + ")||"all suites",a=t.device?` | device: ${t.device}`:"";V(`Running ${i} on [${t.browsers.join(", ")}]${a}`),r.ci||V(`Healing: ${t.healing.enabled?"enabled":"disabled"}`),process.stdout.write(`
1534
+ `);let o=It("Loading test runner\u2026");o.start();let c;try{c=(await Promise.resolve().then(()=>(Do(),ym))).runTests,o.succeed("Runner loaded")}catch{o.fail("Failed to load test runner"),W(`Test runner could not be loaded.
1535
+ Make sure you have run "npm run build" or are running from source.`),process.exit(1)}let l=It("Running tests\u2026");r.ci||l.start();let u;try{u=await c(e,s,t)}catch(d){r.ci||l.fail("Run failed"),W(d instanceof Error?d.message:String(d)),process.exit(1)}r.ci||(u.status==="passed"?l.succeed("Run complete"):l.fail("Run complete with failures")),Xb(u,r.ci??!1),u.failed>0&&(Ge(`${u.failed} test(s) failed. Check the report above for details.`),t.healing.enabled&&V('Self-healing events (if any) saved \u2014 run "npx assuremind apply-healing" to review.')),process.exit(u.status==="passed"?0:1)}var sf=b(()=>{"use strict";m();Vt();lr();Te();te()});var nf={};Q(nf,{runGenerate:()=>Jb});async function Wb(r){if(r.story)return r.story;if(r.storyFile){let e=Ls.default.resolve(r.storyFile);if(!await ic.default.pathExists(e))throw new fe(`Story file not found: "${e}"`,"STORY_FILE_NOT_FOUND");return ic.default.readFile(e,"utf8")}throw new fe('Provide a story with --story "<text>" or --story-file <path>',"GENERATE_NO_STORY")}async function Jb(r){process.stdout.write(`
1536
+ `);try{Rt()}catch(o){W(o instanceof Error?o.message:String(o)),process.exit(1)}let e;try{e=await Wb(r)}catch(o){W(o instanceof Error?o.message:String(o)),process.exit(1)}let t=process.cwd(),s=r.output?Ls.default.resolve(r.output):Ls.default.join(t,"tests");V(`Story: ${L.dim(`${e.slice(0,80)}${e.length>80?"\u2026":""}`)}`),r.suite&&V(`Suite name: ${r.suite}`),V(`Output: ${s}`),process.stdout.write(`
1537
+ `);let n=It("Loading AI layer\u2026");n.start();let i;try{i=(await Promise.resolve().then(()=>(gr(),Eu))).generateSuiteFromStory,n.succeed("AI layer ready")}catch{n.fail("Failed to load AI layer"),W(`AI layer could not be loaded.
1538
+ Make sure you have run "npm run build" or are running from source.`),process.exit(1)}let a=It(`Generating test suite${r.suite?` "${r.suite}"`:""}\u2026`);a.start();try{await i(e,{rootDir:t,outputDir:s,suiteName:r.suite}),a.succeed("Suite generated");let o=r.output??Ls.default.join(t,"tests");Pe(`Test suite created in: ${Ls.default.relative(t,o)}`),V("Open Studio or use the Test Editor to review and generate Playwright code:"),process.stdout.write(` ${L.accent("npx assuremind studio")}
1539
+
1540
+ `)}catch(o){a.fail("Generation failed"),W(o instanceof Error?o.message:String(o)),process.exit(1)}}var Ls,ic,af=b(()=>{"use strict";m();Ls=x(require("path")),ic=x(require("fs-extra"));Vt();lr();te()});var of={};Q(of,{runValidate:()=>tv});async function Yb(r,e){if(V("Checking configuration\u2026"),!await mn.default.pathExists(Os.default.join(r,"autotest.config.json"))&&!await mn.default.pathExists(Os.default.join(r,"autotest.config.ts"))){W(' autotest.config.ts not found \u2014 run "npx assuremind init" to create it'),e.errors++;return}try{let t=await G(r);Pe(` Config valid \u2014 baseUrl: ${L.accent(t.baseUrl)}, browsers: ${t.browsers.join(", ")}`),e.passed++}catch(t){W(` Config invalid: ${t instanceof Error?t.message:String(t)}`),e.errors++}}async function Qb(r){if(V("Checking environment\u2026"),!await mn.default.pathExists(".env")){Ge(" .env file not found \u2014 copy .env.example to .env and fill in your API key"),r.warnings++;return}let e=Gt();if(!e){W(" .env validation failed \u2014 check required variables for your AI provider"),r.errors++;return}Pe(` Provider: ${L.accent(String(e.AI_PROVIDER))}, tiered: ${e.AI_TIERED_ENABLED}`),r.passed++}async function Zb(r,e){V("Scanning test files\u2026");let t=Os.default.join(r,"tests");if(!await mn.default.pathExists(t)){Ge(" tests/ directory not found \u2014 no tests to validate"),e.warnings++;return}let s=await $t(t);if(s.length===0){Ge(" No test suites found \u2014 create one in Studio"),e.warnings++;return}let n=0,i=0;for(let o of s){let c=await zt(o);n+=c.length;for(let l of c)try{await se(l)}catch{W(` Invalid: ${Os.default.relative(r,l)}`),i++,e.errors++}}let a=n-i;i===0?(Pe(` ${s.length} suite(s), ${n} test case(s) \u2014 all valid`),e.passed++):(Ge(` ${s.length} suite(s), ${a}/${n} cases valid`),e.warnings++)}async function ev(r,e){V("Checking variable files\u2026");let t=await al(r);if(t.length===0){Ge(" No variable files found"),e.warnings++;return}let s=0;for(let n of t)try{await rs(n)}catch{W(` Invalid: ${Os.default.relative(r,n)}`),s++,e.errors++}s===0?(Pe(` ${t.length} variable file(s) \u2014 all valid`),e.passed++):e.warnings++}async function tv(){let r=process.cwd();process.stdout.write(`
1541
+ `);let e={passed:0,warnings:0,errors:0};await Yb(r,e),process.stdout.write(`
1542
+ `),await Qb(e),process.stdout.write(`
1543
+ `),await Zb(r,e),process.stdout.write(`
1544
+ `),await ev(r,e),process.stdout.write(`
1545
+ `);let t=e.passed+e.warnings+e.errors,s=[e.passed>0?L.success(`${e.passed} passed`):null,e.warnings>0?L.warn(`${e.warnings} warnings`):null,e.errors>0?L.error(`${e.errors} errors`):null].filter(Boolean).join(L.dim(" | "));process.stdout.write(`Validation complete (${t} checks): ${s}
1546
+
1547
+ `),e.errors>0&&process.exit(1)}var Os,mn,cf=b(()=>{"use strict";m();Os=x(require("path")),mn=x(require("fs-extra"));Vt();Te();Xe();gt();pr();lr()});var lf={};Q(lf,{runDoctor:()=>uv});function ge(r,e,t){return{label:r,ok:e,detail:t}}function oc(r){try{return(0,ac.execSync)(r,{stdio:"pipe"}).toString().trim()}catch{return""}}async function rv(){let r=process.version;return parseInt(r.slice(1).split(".")[0],10)>=18?ge("Node.js",!0,`${r} (>= 18 required)`):ge("Node.js",!1,`${r} is too old \u2014 upgrade to Node.js >= 18 from https://nodejs.org`)}async function sv(){let r=oc("npm --version");return r?ge("npm",!0,`v${r}`):ge("npm",!1,"npm not found \u2014 ensure Node.js is installed correctly")}async function nv(){let r=oc("npx playwright --version");if(!r)return ge("Playwright",!1,'Not found \u2014 run "npx assuremind init" to install');try{return(0,ac.execSync)("npx playwright install --dry-run 2>&1",{stdio:"pipe"}),ge("Playwright",!0,`${r} \u2014 browsers installed`)}catch{return ge("Playwright",!1,`${r} installed but browsers may be missing \u2014 run "npx playwright install --with-deps"`)}}async function iv(){if(!await Xi.default.pathExists(".env"))return ge(".env file",!1,"Missing \u2014 copy .env.example to .env and fill in your API key");let r=Gt();return r?ge(".env file",!0,`Provider: ${String(r.AI_PROVIDER)}, tiered: ${r.AI_TIERED_ENABLED}`):ge(".env file",!1,"Present but invalid \u2014 check required variables for your AI provider")}async function av(){try{let r=await G(process.cwd());return ge("Config",!0,`baseUrl: ${r.baseUrl}, port: ${r.studioPort}`)}catch(r){return ge("Config",!1,r instanceof Error?r.message:"Config validation failed")}}async function ov(){if(!await Xi.default.pathExists("package.json"))return ge("package.json",!1,'Not found \u2014 run "npm init -y" first');try{let r=await Xi.default.readJson("package.json");return ge("package.json",!0,`${r.name??"unnamed"} v${r.version??"?"}`)}catch{return ge("package.json",!1,"Exists but is not valid JSON")}}async function cv(){let r=Gt();if(!r)return ge("AI connectivity",!1,"Cannot check \u2014 .env not configured");let e=String(r.AI_PROVIDER),s={anthropic:"https://api.anthropic.com",openai:"https://api.openai.com",google:"https://generativelanguage.googleapis.com",groq:"https://api.groq.com",deepseek:"https://api.deepseek.com",together:"https://api.together.xyz",perplexity:"https://api.perplexity.ai"}[e];if(!s)return ge("AI connectivity",!0,`${e} \u2014 skipped (local/custom provider)`);try{let n=oc(`curl -s -o /dev/null -w "%{http_code}" --max-time 5 "${s}"`),i=parseInt(n,10);return i>0?ge("AI connectivity",!0,`${e} endpoint reachable (HTTP ${i})`):ge("AI connectivity",!1,`${e} endpoint unreachable \u2014 check your network or VPN`)}catch{return ge("AI connectivity",!1,`Could not reach ${e} endpoint`)}}function lv(r){r.ok?Pe(` ${L.bold(r.label)}: ${L.dim(r.detail)}`):W(` ${L.bold(r.label)}: ${r.detail}`)}async function uv(){process.stdout.write(`
1494
1548
  `),V(`Running Assuremind system diagnostics\u2026
1495
- `);let r=await Promise.all([Pb(),Ib(),Ab(),Rb(),Tb(),kb(),$b()]);for(let s of r)_b(s);let e=r.filter(s=>!s.ok),t=r.filter(s=>s.ok);process.stdout.write(`
1496
- `),e.length===0?jt(["\u2705 All checks passed \u2014 Assuremind is ready!","","Run: npx assuremind studio"]):(jt([`\u26A0 ${t.length}/${r.length} checks passed`,"",'Fix the issues above, then run "npx assuremind doctor" again.']),process.exit(1))}var Xo,ji,Fg=w(()=>{"use strict";p();Xo=require("child_process"),ji=x(require("fs-extra"));Bt();ar();_e()});var Ug={};Q(Ug,{runApplyHealing:()=>Bb});async function Lb(r,e){let t=await Tt(r);for(let s of t){let n=await Ht(s);for(let i of n)try{if((await se(i)).id===e)return i}catch{}}return null}async function Db(r,e){let t=Ts.default.join(r,"tests"),s=await Lb(t,e.caseId);if(!s)throw new Error(`Test case "${e.caseId}" not found in ${t}. The file may have been deleted or renamed since the heal was recorded.`);let n=await se(s),i=n.steps.findIndex(a=>a.id===e.stepId);if(i===-1)throw new Error(`Step "${e.stepId}" not found in "${n.name}". The step may have been deleted since the heal was recorded.`);n.steps[i]={...n.steps[i],generatedCode:e.healedCode,lastHealed:new Date().toISOString()},n.updatedAt=new Date().toISOString(),await Fs(s,n),Ie(` Updated: ${Ts.default.relative(r,s)} \u203A step "${n.steps[i].instruction}"`)}function Nb(r,e){return new Promise(t=>r.question(e,t))}function Mb(r){process.stdout.write(`
1497
- ${O.bold("Step:")} ${r.stepInstruction}
1498
- ${O.bold("Case:")} ${r.caseId}
1499
- ${O.dim("Error:")} ${r.error}
1500
-
1501
- ${O.error("- "+r.failedCode)}
1502
- ${O.success("+ "+r.healedCode)}
1503
- `)}async function Fb(r,e,t){let s={accepted:0,rejected:0,skipped:0},n=jg.default.createInterface({input:process.stdin,output:process.stdout});try{for(let i=0;i<e.length;i++){let a=e[i];process.stdout.write(`
1504
- ${O.accent(`[${i+1}/${e.length}]`)} Healing event ${O.dim(a.id)}
1505
- `),Mb(a);let o;if(t?(o="y",process.stdout.write(` Accept? ${O.dim("(auto-accepting all)")} y
1506
- `)):o=(await Nb(n,` Accept? ${O.dim("(y)es / (n)o / (a)ll / (q)uit")} > `)).trim().toLowerCase(),o==="q"||o==="quit"){He(` Stopping \u2014 ${e.length-i} heals remaining`),s.skipped+=e.length-i;break}if((o==="a"||o==="all")&&(t=!0,o="y"),o==="y"||o==="yes")try{await Db(r,a),await qs(r,a.id),s.accepted++}catch(c){W(` Failed to apply: ${c instanceof Error?c.message:String(c)}`),s.skipped++}else await Nn(r,a.id),V(" Rejected \u2014 step will keep original code"),s.rejected++}}finally{n.close()}return s}async function jb(r,e){let t=process.env.GITHUB_TOKEN,s=process.env.GITHUB_REPO_OWNER,n=process.env.GITHUB_REPO_NAME,i=process.env.GITHUB_BASE_BRANCH||"main";if(!t||!s||!n){He("Auto PR skipped \u2014 missing GITHUB_TOKEN, GITHUB_REPO_OWNER, or GITHUB_REPO_NAME in .env");return}let a=new xs(r),c=`fix/self-heal-${Date.now()}`;try{V("Creating healing branch...");let l=a.git;await l.checkoutLocalBranch(c),V("Committing healed code...");let u=`fix: apply ${e} self-healed selector(s)
1549
+ `);let r=await Promise.all([rv(),sv(),ov(),nv(),iv(),av(),cv()]);for(let s of r)lv(s);let e=r.filter(s=>!s.ok),t=r.filter(s=>s.ok);process.stdout.write(`
1550
+ `),e.length===0?Ht(["\u2705 All checks passed \u2014 Assuremind is ready!","","Run: npx assuremind studio"]):(Ht([`\u26A0 ${t.length}/${r.length} checks passed`,"",'Fix the issues above, then run "npx assuremind doctor" again.']),process.exit(1))}var ac,Xi,uf=b(()=>{"use strict";m();ac=require("child_process"),Xi=x(require("fs-extra"));Vt();lr();Te()});var mf={};Q(mf,{runApplyHealing:()=>yv});async function dv(r,e){let t=await $t(r);for(let s of t){let n=await zt(s);for(let i of n)try{if((await se(i)).id===e)return i}catch{}}return null}async function pv(r,e){let t=Ds.default.join(r,"tests"),s=await dv(t,e.caseId);if(!s)throw new Error(`Test case "${e.caseId}" not found in ${t}. The file may have been deleted or renamed since the heal was recorded.`);let n=await se(s),i=n.steps.findIndex(a=>a.id===e.stepId);if(i===-1)throw new Error(`Step "${e.stepId}" not found in "${n.name}". The step may have been deleted since the heal was recorded.`);n.steps[i]={...n.steps[i],generatedCode:e.healedCode,lastHealed:new Date().toISOString()},n.updatedAt=new Date().toISOString(),await zs(s,n),Pe(` Updated: ${Ds.default.relative(r,s)} \u203A step "${n.steps[i].instruction}"`)}function mv(r,e){return new Promise(t=>r.question(e,t))}function gv(r){process.stdout.write(`
1551
+ ${L.bold("Step:")} ${r.stepInstruction}
1552
+ ${L.bold("Case:")} ${r.caseId}
1553
+ ${L.dim("Error:")} ${r.error}
1554
+
1555
+ ${L.error("- "+r.failedCode)}
1556
+ ${L.success("+ "+r.healedCode)}
1557
+ `)}async function fv(r,e,t){let s={accepted:0,rejected:0,skipped:0},n=df.default.createInterface({input:process.stdin,output:process.stdout});try{for(let i=0;i<e.length;i++){let a=e[i];process.stdout.write(`
1558
+ ${L.accent(`[${i+1}/${e.length}]`)} Healing event ${L.dim(a.id)}
1559
+ `),gv(a);let o;if(t?(o="y",process.stdout.write(` Accept? ${L.dim("(auto-accepting all)")} y
1560
+ `)):o=(await mv(n,` Accept? ${L.dim("(y)es / (n)o / (a)ll / (q)uit")} > `)).trim().toLowerCase(),o==="q"||o==="quit"){Ge(` Stopping \u2014 ${e.length-i} heals remaining`),s.skipped+=e.length-i;break}if((o==="a"||o==="all")&&(t=!0,o="y"),o==="y"||o==="yes")try{await pv(r,a),await Qs(r,a.id),s.accepted++}catch(c){W(` Failed to apply: ${c instanceof Error?c.message:String(c)}`),s.skipped++}else await Hn(r,a.id),V(" Rejected \u2014 step will keep original code"),s.rejected++}}finally{n.close()}return s}async function hv(r,e){let t=process.env.GITHUB_TOKEN,s=process.env.GITHUB_REPO_OWNER,n=process.env.GITHUB_REPO_NAME,i=process.env.GITHUB_BASE_BRANCH||"main";if(!t||!s||!n){Ge("Auto PR skipped \u2014 missing GITHUB_TOKEN, GITHUB_REPO_OWNER, or GITHUB_REPO_NAME in .env");return}let a=new Ts(r),c=`fix/self-heal-${Date.now()}`;try{V("Creating healing branch...");let l=a.git;await l.checkoutLocalBranch(c),V("Committing healed code...");let u=`fix: apply ${e} self-healed selector(s)
1507
1561
 
1508
1562
  Auto-generated by Assuremind self-healing engine.`;await a.commit(u),V("Pushing branch to remote..."),await l.push("origin",c,["--set-upstream"]),V("Creating pull request...");let d=await fetch(`https://api.github.com/repos/${s}/${n}/pulls`,{method:"POST",headers:{Authorization:`Bearer ${t}`,Accept:"application/vnd.github+json","Content-Type":"application/json","X-GitHub-Api-Version":"2022-11-28"},body:JSON.stringify({title:`fix: self-healed ${e} broken selector(s)`,body:`## Self-Healing Auto PR
1509
1563
 
@@ -1517,12 +1571,12 @@ Assuremind detected and fixed **${e}** broken test selector(s) during CI executi
1517
1571
  Review the changes and merge if the fixes look correct.
1518
1572
 
1519
1573
  ---
1520
- \u{1F916} *Auto-generated by Assuremind*`,head:c,base:i})});if(d.ok){let g=await d.json();Ie(`Pull request created: ${g.html_url}`)}else{let g=await d.json();W(`Failed to create PR: ${g.message||d.statusText}`)}await a.checkout(i)}catch(l){let u=l instanceof Error?l.message:String(l);W(`Auto PR failed: ${u}`);try{await a.checkout(i)}catch{}}}async function Bb(r){let e=process.cwd();(0,Bg.config)({path:Ts.default.join(e,".env")}),process.stdout.write(`
1521
- `);let t;if(r.from){let n=Ts.default.resolve(r.from);await Wo.default.pathExists(n)||(W(`Healing report not found: ${n}`),process.exit(1));try{let i=Ts.default.basename(n,".json").replace("healing-report-","");t=(await Dn(e,i)).events.filter(o=>o.status==="pending")}catch{let i=await Wo.default.readJson(n);t=Array.isArray(i)?i.filter(a=>a.status==="pending"):(i.events??[]).filter(a=>a.status==="pending")}}else t=(await rt(e)).filter(n=>n.status==="pending");if(t.length===0){V("No pending healing events found \u2014 nothing to apply.");return}V(`Found ${O.bold(String(t.length))} pending healing event(s).
1522
- `);let s=await Fb(e,t,r.yes??!1);if(process.stdout.write(`
1523
- `),V(`Done: ${O.success(String(s.accepted)+" accepted")}, ${O.error(String(s.rejected)+" rejected")}, ${O.dim(String(s.skipped)+" skipped")}`),process.stdout.write(`
1524
- `),s.accepted>0)try{(await J(e)).healing.autoPR&&(V(`Auto PR enabled \u2014 creating pull request with healed code...
1525
- `),await jb(e,s.accepted))}catch{}}var Ts,Wo,jg,Bg,Hg=w(()=>{"use strict";p();Ts=x(require("path")),Wo=x(require("fs-extra")),jg=x(require("readline")),Bg=require("dotenv");Mn();ze();dt();_e();Mo();Bt()});p();var Gg=require("commander"),zg=require("module");Bt();var Ub=(0,zg.createRequire)(__filename),Vg=Ub("../../package.json"),Zt=new Gg.Command;Zt.name("assuremind").description(Vg.description).version(Vg.version,"-v, --version","Print version number");Zt.command("init").description("Initialise Assuremind in the current project").option("--skip-playwright","Skip Playwright browser installation").action(async r=>{let{runInit:e}=await Promise.resolve().then(()=>(hc(),fc));await e({skipPlaywright:r.skipPlaywright}).catch(Ct)});Zt.command("studio").description("Open the Assuremind web UI").option("-p, --port <number>","Override studio port",parseInt).option("--no-open","Do not open browser automatically").action(async r=>{let{runStudio:e}=await Promise.resolve().then(()=>(kg(),Tg));await e({port:r.port,noOpen:r.open===!1}).catch(Ct)});Zt.command("run").description("Run tests from the command line").option("--all","Run all test suites").option("--type <type>","Filter suites by type: ui, api, audit, performance").option("--suite <name>","Run suite(s) matching name (case-insensitive partial match) or ID").option("--tag <tag>","Run all tests matching a tag").option("--test <name>","Run test(s) matching name (case-insensitive partial match) or ID").option("--browser <list...>","Browser(s) to use: chromium, firefox, webkit").option("--device <name>",'Emulate a device (e.g. "iPhone 15 Pro", "Pixel 7", "iPad Pro 11")').option("--env <name>","Environment to use (dev, staging, prod)").option("--parallel <n>","Number of parallel workers",parseInt).option("--headed","Run in headed (visible) mode").option("--ci","CI mode \u2014 no interactive prompts, exit code reflects pass/fail").option("--reporter <list...>","Reporter(s): allure, html, json").option("--no-healing","Disable self-healing for this run").addHelpText("after",`
1574
+ \u{1F916} *Auto-generated by Assuremind*`,head:c,base:i})});if(d.ok){let p=await d.json();Pe(`Pull request created: ${p.html_url}`)}else{let p=await d.json();W(`Failed to create PR: ${p.message||d.statusText}`)}await a.checkout(i)}catch(l){let u=l instanceof Error?l.message:String(l);W(`Auto PR failed: ${u}`);try{await a.checkout(i)}catch{}}}async function yv(r){let e=process.cwd();(0,pf.config)({path:Ds.default.join(e,".env")}),process.stdout.write(`
1575
+ `);let t;if(r.from){let n=Ds.default.resolve(r.from);await cc.default.pathExists(n)||(W(`Healing report not found: ${n}`),process.exit(1));try{let i=Ds.default.basename(n,".json").replace("healing-report-","");t=(await Un(e,i)).events.filter(o=>o.status==="pending")}catch{let i=await cc.default.readJson(n);t=Array.isArray(i)?i.filter(a=>a.status==="pending"):(i.events??[]).filter(a=>a.status==="pending")}}else t=(await nt(e)).filter(n=>n.status==="pending");if(t.length===0){V("No pending healing events found \u2014 nothing to apply.");return}V(`Found ${L.bold(String(t.length))} pending healing event(s).
1576
+ `);let s=await fv(e,t,r.yes??!1);if(process.stdout.write(`
1577
+ `),V(`Done: ${L.success(String(s.accepted)+" accepted")}, ${L.error(String(s.rejected)+" rejected")}, ${L.dim(String(s.skipped)+" skipped")}`),process.stdout.write(`
1578
+ `),s.accepted>0)try{(await G(e)).healing.autoPR&&(V(`Auto PR enabled \u2014 creating pull request with healed code...
1579
+ `),await hv(e,s.accepted))}catch{}}var Ds,cc,df,pf,gf=b(()=>{"use strict";m();Ds=x(require("path")),cc=x(require("fs-extra")),df=x(require("readline")),pf=require("dotenv");Vn();Xe();gt();Te();qo();Vt()});m();var hf=require("commander"),yf=require("module");Vt();var wv=(0,yf.createRequire)(__filename),ff=wv("../../package.json"),sr=new hf.Command;sr.name("assuremind").description(ff.description).version(ff.version,"-v, --version","Print version number");sr.command("init").description("Initialise Assuremind in the current project").option("--skip-playwright","Skip Playwright browser installation").action(async r=>{let{runInit:e}=await Promise.resolve().then(()=>(kc(),Tc));await e({skipPlaywright:r.skipPlaywright}).catch(Pt)});sr.command("studio").description("Open the Assuremind web UI").option("-p, --port <number>","Override studio port",parseInt).option("--no-open","Do not open browser automatically").action(async r=>{let{runStudio:e}=await Promise.resolve().then(()=>(ef(),Zg));await e({port:r.port,noOpen:r.open===!1}).catch(Pt)});sr.command("run").description("Run tests from the command line").option("--all","Run all test suites").option("--type <type>","Filter suites by type: ui, api, audit, performance").option("--suite <name>","Run suite(s) matching name (case-insensitive partial match) or ID").option("--tag <tag>","Run all tests matching a tag").option("--test <name>","Run test(s) matching name (case-insensitive partial match) or ID").option("--browser <list...>","Browser(s) to use: chromium, firefox, webkit").option("--device <name>",'Emulate a device (e.g. "iPhone 15 Pro", "Pixel 7", "iPad Pro 11")').option("--env <name>","Environment to use (dev, staging, prod)").option("--parallel <n>","Number of parallel workers",parseInt).option("--headed","Run in headed (visible) mode").option("--ci","CI mode \u2014 no interactive prompts, exit code reflects pass/fail").option("--reporter <list...>","Reporter(s): allure, html, json").option("--no-healing","Disable self-healing for this run").addHelpText("after",`
1526
1580
  Examples:
1527
1581
  assuremind run --all
1528
1582
  assuremind run --type ui
@@ -1540,7 +1594,7 @@ Examples:
1540
1594
 
1541
1595
  Filters are combinable (AND logic \u2014 all specified filters must match).
1542
1596
  Device names must match Playwright device descriptors exactly (case-sensitive).
1543
- `).action(async r=>{let{runRun:e}=await Promise.resolve().then(()=>(_g(),$g));await e({all:r.all,type:r.type,suite:r.suite,tag:r.tag,test:r.test,browser:r.browser,device:r.device,env:r.env,parallel:r.parallel,headed:r.headed,ci:r.ci,reporter:r.reporter,noHealing:r.noHealing}).catch(Ct)});Zt.command("generate").description("Generate test cases from a user story").option("--story <text>","User story text (plain English)").option("--story-file <path>","Path to a file containing the user story").option("--suite <name>","Name of the suite to create").option("--output <path>","Output directory (default: tests/)").action(async r=>{let{runGenerate:e}=await Promise.resolve().then(()=>(Lg(),Og));await e(r).catch(Ct)});Zt.command("validate").description("Validate config, environment, and test files").action(async()=>{let{runValidate:r}=await Promise.resolve().then(()=>(Ng(),Dg));await r().catch(Ct)});Zt.command("doctor").description("Check system requirements and configuration health").action(async()=>{let{runDoctor:r}=await Promise.resolve().then(()=>(Fg(),Mg));await r().catch(Ct)});Zt.command("apply-healing").description("Review and apply self-healing suggestions to test files").option("--from <path>","Path to a specific healing report JSON file").option("-y, --yes","Accept all pending heals without prompting").action(async r=>{let{runApplyHealing:e}=await Promise.resolve().then(()=>(Hg(),Ug));await e(r).catch(Ct)});Zt.parse(process.argv);
1597
+ `).action(async r=>{let{runRun:e}=await Promise.resolve().then(()=>(sf(),rf));await e({all:r.all,type:r.type,suite:r.suite,tag:r.tag,test:r.test,browser:r.browser,device:r.device,env:r.env,parallel:r.parallel,headed:r.headed,ci:r.ci,reporter:r.reporter,noHealing:r.noHealing}).catch(Pt)});sr.command("generate").description("Generate test cases from a user story").option("--story <text>","User story text (plain English)").option("--story-file <path>","Path to a file containing the user story").option("--suite <name>","Name of the suite to create").option("--output <path>","Output directory (default: tests/)").action(async r=>{let{runGenerate:e}=await Promise.resolve().then(()=>(af(),nf));await e(r).catch(Pt)});sr.command("validate").description("Validate config, environment, and test files").action(async()=>{let{runValidate:r}=await Promise.resolve().then(()=>(cf(),of));await r().catch(Pt)});sr.command("doctor").description("Check system requirements and configuration health").action(async()=>{let{runDoctor:r}=await Promise.resolve().then(()=>(uf(),lf));await r().catch(Pt)});sr.command("apply-healing").description("Review and apply self-healing suggestions to test files").option("--from <path>","Path to a specific healing report JSON file").option("-y, --yes","Accept all pending heals without prompting").action(async r=>{let{runApplyHealing:e}=await Promise.resolve().then(()=>(gf(),mf));await e(r).catch(Pt)});sr.parse(process.argv);
1544
1598
  /*! Bundled license information:
1545
1599
 
1546
1600
  lighthouse-logger/index.js: