assuremind 1.5.2 → 1.6.0

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 Rf=Object.create;var wn=Object.defineProperty;var Tf=Object.getOwnPropertyDescriptor;var kf=Object.getOwnPropertyNames;var Af=Object.getPrototypeOf,$f=Object.prototype.hasOwnProperty;var b=(r,e,t)=>()=>{if(t)throw t[0];try{return r&&(e=r(r=0)),e}catch(s){throw t=[s],s}};var Ct=(r,e)=>()=>{try{return e||r((e={exports:{}}).exports,e),e.exports}catch(t){throw e=0,t}},Q=(r,e)=>{for(var t in e)wn(r,t,{get:e[t],enumerable:!0})},wc=(r,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of kf(e))!$f.call(r,n)&&n!==t&&wn(r,n,{get:()=>e[n],enumerable:!(s=Tf(e,n))||s.enumerable});return r};var x=(r,e,t)=>(t=r!=null?Rf(Af(r)):{},wc(e||!r||!r.__esModule?wn(t,"default",{value:r,enumerable:!0}):t,r)),et=r=>wc(wn({},"__esModule",{value:!0}),r);var _f,y,m=b(()=>{"use strict";_f=()=>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=_f()});function Pe(r){process.stdout.write(`${O.success("\u2713")} ${r}
2
+ "use strict";var Mf=Object.create;var bn=Object.defineProperty;var jf=Object.getOwnPropertyDescriptor;var Bf=Object.getOwnPropertyNames;var Uf=Object.getPrototypeOf,Hf=Object.prototype.hasOwnProperty;var b=(r,e,t)=>()=>{if(t)throw t[0];try{return r&&(e=r(r=0)),e}catch(s){throw t=[s],s}};var It=(r,e)=>()=>{try{return e||r((e={exports:{}}).exports,e),e.exports}catch(t){throw e=0,t}},Q=(r,e)=>{for(var t in e)bn(r,t,{get:e[t],enumerable:!0})},Ec=(r,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Bf(e))!Hf.call(r,n)&&n!==t&&bn(r,n,{get:()=>e[n],enumerable:!(s=jf(e,n))||s.enumerable});return r};var x=(r,e,t)=>(t=r!=null?Mf(Uf(r)):{},Ec(e||!r||!r.__esModule?bn(t,"default",{value:r,enumerable:!0}):t,r)),et=r=>Ec(bn({},"__esModule",{value:!0}),r);var Vf,y,m=b(()=>{"use strict";Vf=()=>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=Vf()});function Pe(r){process.stdout.write(`${O.success("\u2713")} ${r}
3
3
  `)}function X(r){process.stderr.write(`${O.error("\u2717")} ${r}
4
4
  `)}function Ge(r){process.stdout.write(`${O.warn("\u26A0")} ${r}
5
5
  `)}function V(r){process.stdout.write(`${O.info("\u2139")} ${r}
6
- `)}function bn(r){process.stdout.write(`${O.dim("\u2013")} ${O.dim(r)}
7
- `)}function Ut(r){let e=Math.max(...r.map(s=>s.length))+4,t=O.accent("\u2500".repeat(e));process.stdout.write(`
6
+ `)}function vn(r){process.stdout.write(`${O.dim("\u2013")} ${O.dim(r)}
7
+ `)}function Ht(r){let e=Math.max(...r.map(s=>s.length))+4,t=O.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 It(r){return(0,bc.default)({text:r,color:"cyan"})}function Pt(r){let e=r instanceof Error?r.message:String(r);X(e),process.exit(1)}var ar,bc,O,Ht=b(()=>{"use strict";m();ar=x(require("chalk")),bc=x(require("ora")),O={success:ar.default.green,error:ar.default.red,warn:ar.default.yellow,info:ar.default.cyan,dim:ar.default.dim,bold:ar.default.bold,accent:ar.default.hex("#00adf7")}});var kc={};Q(kc,{AutotestConfigSchema:()=>Tr,BrowserNameSchema:()=>Zi,DEFAULT_CONFIG:()=>ta,EnvironmentProfileSchema:()=>Tc,EnvironmentSchema:()=>ea,EnvironmentUrlsSchema:()=>Cc,HealingConfigSchema:()=>Ic,PageLoadStrategySchema:()=>Ec,ReportingConfigSchema:()=>Pc,ScreenshotModeSchema:()=>vc,TraceModeSchema:()=>Sc,VideoModeSchema:()=>xc,ViewportSchema:()=>Rc});var A,vc,xc,Sc,Zi,Ec,ea,Cc,Ic,Pc,Rc,Tc,Tr,ta,vn=b(()=>{"use strict";m();A=require("zod"),vc=A.z.enum(["off","on","only-on-failure"]),xc=A.z.enum(["off","on","on-first-retry","retain-on-failure"]),Sc=A.z.enum(["off","on","on-first-retry","retain-on-failure"]),Zi=A.z.enum(["chromium","firefox","webkit"]),Ec=A.z.enum(["commit","domcontentloaded","load","networkidle"]),ea=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("")}),Ic=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)}),Pc=A.z.object({allure:A.z.boolean(),html:A.z.boolean(),json:A.z.boolean()}),Rc=A.z.object({width:A.z.number().int().positive(),height:A.z.number().int().positive()}),Tc=A.z.object({name:A.z.string().min(1),environment:ea,baseUrl:A.z.string().url(),browsers:A.z.array(Zi).min(1),headless:A.z.boolean().optional()}),Tr=A.z.object({baseUrl:A.z.string().url(),environment:ea.default("stage"),environmentUrls:Cc.default({dev:"",stage:"",test:"",prod:""}),browsers:A.z.array(Zi).min(1),headless:A.z.boolean(),viewport:Rc.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:Ec.default("domcontentloaded"),screenshot:vc,video:xc,trace:Sc,healing:Ic,reporting:Pc,studioPort:A.z.number().int().min(1024).max(65535),profiles:A.z.array(Tc).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})}),ta={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 $c={};Q($c,{runInit:()=>Ff});function Nf(){return xn.default.resolve(__dirname,"../../templates")}async function Ff(r={}){await pt.default.pathExists("package.json")||Pt(`No package.json found in the current directory.
12
+ `)}function Pt(r){return(0,Cc.default)({text:r,color:"cyan"})}function Rt(r){let e=r instanceof Error?r.message:String(r);X(e),process.exit(1)}var or,Cc,O,Vt=b(()=>{"use strict";m();or=x(require("chalk")),Cc=x(require("ora")),O={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 Lc={};Q(Lc,{AutotestConfigSchema:()=>kr,BrowserNameSchema:()=>ia,DEFAULT_CONFIG:()=>ca,DEFAULT_ENVIRONMENTS:()=>oa,EnvironmentProfileSchema:()=>Oc,EnvironmentSchema:()=>aa,EnvironmentUrlsSchema:()=>kc,HealingConfigSchema:()=>Ac,PageLoadStrategySchema:()=>Tc,ReportingConfigSchema:()=>$c,ScreenshotModeSchema:()=>Ic,TraceModeSchema:()=>Rc,VideoModeSchema:()=>Pc,ViewportSchema:()=>_c});var A,Ic,Pc,Rc,ia,Tc,aa,oa,kc,Ac,$c,_c,Oc,kr,ca,xn=b(()=>{"use strict";m();A=require("zod"),Ic=A.z.enum(["off","on","only-on-failure"]),Pc=A.z.enum(["off","on","on-first-retry","retain-on-failure"]),Rc=A.z.enum(["off","on","on-first-retry","retain-on-failure"]),ia=A.z.enum(["chromium","firefox","webkit"]),Tc=A.z.enum(["commit","domcontentloaded","load","networkidle"]),aa=A.z.string().min(1),oa=["DEV","TEST","STAGE","INT","PROD"],kc=A.z.record(A.z.string(),A.z.string()).default({}),Ac=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)}),$c=A.z.object({allure:A.z.boolean(),html:A.z.boolean(),json:A.z.boolean()}),_c=A.z.object({width:A.z.number().int().positive(),height:A.z.number().int().positive()}),Oc=A.z.object({name:A.z.string().min(1),environment:aa,baseUrl:A.z.string().url(),browsers:A.z.array(ia).min(1),headless:A.z.boolean().optional()}),kr=A.z.object({baseUrl:A.z.string().url(),environment:aa.default("DEV"),environments:A.z.array(A.z.string().min(1)).default([...oa]),environmentUrls:kc.default({DEV:"",TEST:"",STAGE:"",INT:"",PROD:""}),browsers:A.z.array(ia).min(1),headless:A.z.boolean(),viewport:_c.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:Tc.default("domcontentloaded"),screenshot:Ic,video:Pc,trace:Rc,healing:Ac,reporting:$c,studioPort:A.z.number().int().min(1024).max(65535),profiles:A.z.array(Oc).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})}),ca={baseUrl:"http://localhost:3000",environment:"DEV",environments:[...oa],environmentUrls:{DEV:"http://localhost:3000",TEST:"",STAGE:"",INT:"",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 Nc={};Q(Nc,{runInit:()=>Wf});function Kf(){return Sn.default.resolve(__dirname,"../../templates")}async function Wf(r={}){await pt.default.pathExists("package.json")||Rt(`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 Of)await pt.default.ensureDir(t),(await pt.default.readdir(t)).length===0&&await pt.default.writeFile(xn.default.join(t,".gitkeep"),""),Pe(` ${t}/`);process.stdout.write(`
15
- `),V("Creating config files\u2026");let e=Nf();for(let{dest:t,template:s}of Lf){if(await pt.default.pathExists(t)){bn(` ${t} (already exists)`);continue}let n=xn.default.join(e,s);await pt.default.copy(n,t),Pe(` ${t}`)}for(let t of Df){if(await pt.default.pathExists(t)){bn(` ${t} (already exists)`);continue}await pt.default.writeJson(t,{},{spaces:2}),Pe(` ${t}`)}if(await pt.default.pathExists("autotest.config.json"))bn(" autotest.config.json (already exists)");else{let{DEFAULT_CONFIG:t}=await Promise.resolve().then(()=>(vn(),kc));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,Ac.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 Gf)await pt.default.ensureDir(t),(await pt.default.readdir(t)).length===0&&await pt.default.writeFile(Sn.default.join(t,".gitkeep"),""),Pe(` ${t}/`);process.stdout.write(`
15
+ `),V("Creating config files\u2026");let e=Kf();for(let{dest:t,template:s}of zf){if(await pt.default.pathExists(t)){vn(` ${t} (already exists)`);continue}let n=Sn.default.join(e,s);await pt.default.copy(n,t),Pe(` ${t}`)}for(let t of qf){if(await pt.default.pathExists(t)){vn(` ${t} (already exists)`);continue}await pt.default.writeJson(t,{},{spaces:2}),Pe(` ${t}`)}if(await pt.default.pathExists("autotest.config.json"))vn(" autotest.config.json (already exists)");else{let{DEFAULT_CONFIG:t}=await Promise.resolve().then(()=>(xn(),Lc));await pt.default.writeJson("autotest.config.json",t,{spaces:2}),Pe(" autotest.config.json")}if(!r.skipPlaywright){process.stdout.write(`
16
+ `);let t=Pt("Installing Playwright browsers (Chromium, Firefox, WebKit)\u2026");t.start();try{(0,Dc.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
- `)}}Ut(["\u2705 AssureMind initialised!","","Defaults to local Ollama (free). To use it:"," \u2022 Install Ollama \u2192 https://ollama.com"," \u2022 ollama pull qwen2.5-coder:14b","","Or switch provider in .env, or via Studio \u2192 Settings \u2192 Environment.","","Next steps:"," 1. Run: npx assuremind studio"," 2. Start creating tests in the browser!","","Docs: https://assuremind.dev/docs"])}var xn,pt,Ac,Of,Lf,Df,_c=b(()=>{"use strict";m();xn=x(require("path")),pt=x(require("fs-extra")),Ac=require("child_process");Ht();Of=["tests","variables","results","results/screenshots","results/videos","results/traces","results/reports","results/healing","fixtures","fixtures/auth","fixtures/data","docs"],Lf=[{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"}],Df=["variables/dev.env.json","variables/staging.env.json","variables/prod.env.json"]});var or,B,fe,K,oe,re=b(()=>{"use strict";m();or=class extends Error{code;constructor(e,t){super(e),this.name="AssuremindError",this.code=t,Object.setPrototypeOf(this,new.target.prototype)}},B=class extends or{provider;constructor(e,t,s="PROVIDER_ERROR"){super(e,s),this.name="ProviderError",this.provider=t}},fe=class extends or{constructor(e,t="CONFIG_ERROR"){super(e,t),this.name="ConfigError"}},K=class extends or{field;constructor(e,t,s="VALIDATION_ERROR"){super(e,s),this.name="ValidationError",this.field=t}},oe=class extends or{path;constructor(e,t,s="STORAGE_ERROR"){super(e,s),this.name="StorageError",this.path=t}}});function cr(){if(Sn!==null)return Sn;let r=Mf.safeParse(process.env);if(!r.success){let i=r.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
18
+ `)}}Ht(["\u2705 AssureMind initialised!","","Defaults to local Ollama (free). To use it:"," \u2022 Install Ollama \u2192 https://ollama.com"," \u2022 ollama pull qwen2.5-coder:14b","","Or switch provider in .env, or via Studio \u2192 Settings \u2192 Environment.","","Next steps:"," 1. Run: npx assuremind studio"," 2. Start creating tests in the browser!","","Docs: https://assuremind.dev/docs"])}var Sn,pt,Dc,Gf,zf,qf,Fc=b(()=>{"use strict";m();Sn=x(require("path")),pt=x(require("fs-extra")),Dc=require("child_process");Vt();Gf=["tests","variables","results","results/screenshots","results/videos","results/traces","results/reports","results/healing","fixtures","fixtures/auth","fixtures/data","docs"],zf=[{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"}],qf=["variables/dev.env.json","variables/staging.env.json","variables/prod.env.json"]});var cr,B,fe,K,oe,re=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"}},K=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 lr(){if(En!==null)return En;let r=Xf.safeParse(process.env);if(!r.success){let i=r.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
19
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(`
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=ch[e].safeParse(process.env);if(!s.success){let i=s.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
23
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 Sn={...r.data,...s.data},Sn}function Vt(){try{return cr()}catch{return null}}var Lc,D,Oc,Mf,jf,Bf,Uf,Hf,Vf,Gf,zf,qf,Kf,Wf,Xf,Jf,Yf,Sn,lr=b(()=>{"use strict";m();Lc=require("dotenv"),D=require("zod");re();(0,Lc.config)();Oc=["anthropic","openai","google","azure-openai","bedrock","deepseek","groq","together","qwen","perplexity","ollama","custom"],Mf=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(Oc),AI_TIERED_ENABLED:D.z.string().transform(r=>r==="true").default("false"),AI_TIERED_FAST_PROVIDER:D.z.enum(Oc).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)}),jf=D.z.object({ANTHROPIC_API_KEY:D.z.string().min(1),ANTHROPIC_MODEL:D.z.string().default("claude-sonnet-4-20250514")}),Bf=D.z.object({OPENAI_API_KEY:D.z.string().min(1),OPENAI_MODEL:D.z.string().default("gpt-4o")}),Uf=D.z.object({GOOGLE_API_KEY:D.z.string().min(1),GOOGLE_MODEL:D.z.string().default("gemini-2.5-pro")}),Hf=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")}),Vf=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")}),Gf=D.z.object({DEEPSEEK_API_KEY:D.z.string().min(1),DEEPSEEK_MODEL:D.z.string().default("deepseek-chat")}),zf=D.z.object({GROQ_API_KEY:D.z.string().min(1),GROQ_MODEL:D.z.string().default("llama-3.3-70b-versatile")}),qf=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")}),Kf=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")}),Wf=D.z.object({PERPLEXITY_API_KEY:D.z.string().min(1),PERPLEXITY_MODEL:D.z.string().default("sonar-pro")}),Xf=D.z.object({OLLAMA_BASE_URL:D.z.string().url().default("http://localhost:11434"),OLLAMA_MODEL:D.z.string().default("llama3.3")}),Jf=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:jf,openai:Bf,google:Uf,"azure-openai":Hf,bedrock:Vf,deepseek:Gf,groq:zf,together:qf,qwen:Kf,perplexity:Wf,ollama:Xf,custom:Jf},Sn=null});function C(r){return Zf.child({component:r})}async function Nc(r,e){let t=na.default.join(r,"results","logs");await sa.default.ensureDir(t);let s=na.default.join(t,`run-${e}.log`),n=sa.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 En={...r.data,...s.data},En}function Gt(){try{return lr()}catch{return null}}var jc,D,Mc,Xf,Jf,Yf,Qf,Zf,eh,th,rh,sh,nh,ih,ah,oh,ch,En,ur=b(()=>{"use strict";m();jc=require("dotenv"),D=require("zod");re();(0,jc.config)();Mc=["anthropic","openai","google","azure-openai","bedrock","deepseek","groq","together","qwen","perplexity","ollama","custom"],Xf=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(Mc),AI_TIERED_ENABLED:D.z.string().transform(r=>r==="true").default("false"),AI_TIERED_FAST_PROVIDER:D.z.enum(Mc).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)}),Jf=D.z.object({ANTHROPIC_API_KEY:D.z.string().min(1),ANTHROPIC_MODEL:D.z.string().default("claude-sonnet-4-20250514")}),Yf=D.z.object({OPENAI_API_KEY:D.z.string().min(1),OPENAI_MODEL:D.z.string().default("gpt-4o")}),Qf=D.z.object({GOOGLE_API_KEY:D.z.string().min(1),GOOGLE_MODEL:D.z.string().default("gemini-2.5-pro")}),Zf=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")}),eh=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")}),th=D.z.object({DEEPSEEK_API_KEY:D.z.string().min(1),DEEPSEEK_MODEL:D.z.string().default("deepseek-chat")}),rh=D.z.object({GROQ_API_KEY:D.z.string().min(1),GROQ_MODEL:D.z.string().default("llama-3.3-70b-versatile")}),sh=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")}),nh=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")}),ih=D.z.object({PERPLEXITY_API_KEY:D.z.string().min(1),PERPLEXITY_MODEL:D.z.string().default("sonar-pro")}),ah=D.z.object({OLLAMA_BASE_URL:D.z.string().url().default("http://localhost:11434"),OLLAMA_MODEL:D.z.string().default("llama3.3")}),oh=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)}),ch={anthropic:Jf,openai:Yf,google:Qf,"azure-openai":Zf,bedrock:eh,deepseek:th,groq:rh,together:sh,qwen:nh,perplexity:ih,ollama:ah,custom:oh},En=null});function C(r){return uh.child({component:r})}async function Uc(r,e){let t=da.default.join(r,"results","logs");await ua.default.ensureDir(t);let s=da.default.join(t,`run-${e}.log`),n=ua.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 ra,sa,na,Qf,Dc,Zf,F=b(()=>{"use strict";m();ra=x(require("pino")),sa=x(require("fs-extra")),na=x(require("path")),Qf=process.env.NODE_ENV!=="production",Dc=Qf?{target:"pino-pretty",options:{colorize:!0,translateTime:"HH:MM:ss",ignore:"pid,hostname",messageFormat:"[assuremind] {msg}"}}:void 0,Zf=(0,ra.default)({level:process.env.LOG_LEVEL??"info",base:{name:"assuremind"}},Dc?ra.default.transport(Dc):void 0)});async function W(r,e){let t=ia.default.dirname(r);await Rt.default.ensureDir(t);let s=`${r}.${process.pid}.tmp`;try{await Rt.default.writeJson(s,e,{spaces:2}),await Rt.default.rename(s,r)}catch(n){throw await Rt.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 Rt.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 Fc(r,e){let t=ia.default.dirname(r);await Rt.default.ensureDir(t);let s=`${r}.${process.pid}.tmp`;try{await Rt.default.writeFile(s,e,"utf8"),await Rt.default.rename(s,r)}catch(n){throw await Rt.default.remove(s).catch(()=>{}),new oe(`Failed to write file "${r}": ${n instanceof Error?n.message:String(n)}`,r,"WRITE_FAILED")}}var ia,Rt,ze=b(()=>{"use strict";m();ia=x(require("path")),Rt=x(require("fs-extra"));re()});var ca={};Q(ca,{configExists:()=>th,readConfig:()=>G,updateConfig:()=>eh,validateConfig:()=>rh,writeConfig:()=>Cn});async function G(r){let e=Wr.default.join(r,oa);if(!await En.default.pathExists(e))return aa.debug({rootDir:r},"No autotest.config.json found \u2014 using defaults"),ta;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(`
34
+ `),n.end()}}}var la,ua,da,lh,Bc,uh,F=b(()=>{"use strict";m();la=x(require("pino")),ua=x(require("fs-extra")),da=x(require("path")),lh=process.env.NODE_ENV!=="production",Bc=lh?{target:"pino-pretty",options:{colorize:!0,translateTime:"HH:MM:ss",ignore:"pid,hostname",messageFormat:"[assuremind] {msg}"}}:void 0,uh=(0,la.default)({level:process.env.LOG_LEVEL??"info",base:{name:"assuremind"}},Bc?la.default.transport(Bc):void 0)});async function W(r,e){let t=pa.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 Hc(r,e){let t=pa.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 pa,Tt,ze=b(()=>{"use strict";m();pa=x(require("path")),Tt=x(require("fs-extra"));re()});var fa={};Q(fa,{configExists:()=>ph,readConfig:()=>G,updateConfig:()=>dh,validateConfig:()=>mh,writeConfig:()=>In});async function G(r){let e=Yr.default.join(r,ga);if(!await Cn.default.pathExists(e))return ma.debug({rootDir:r},"No autotest.config.json found \u2014 using defaults"),ca;let t=await ue(e),s=kr.safeParse(t);if(!s.success){let i=s.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
35
35
  `);throw new K(`Invalid autotest.config.json at "${e}":
36
- ${n}
36
+ ${i}
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 Cn(r,e){let t=Tr.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")}let n=s.data;if(t&&typeof t=="object"&&"environments"in t)n.environment&&!n.environments.includes(n.environment)&&(n.environments=[...n.environments,n.environment]);else{let i=new Set;for(let a of Object.keys(n.environmentUrls??{}))i.add(a);n.environment&&i.add(n.environment),i.size>0&&(n.environments=[...i])}return n}async function In(r,e){let t=kr.safeParse(e);if(!t.success){let i=t.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
39
39
  `);throw new K(`Cannot write invalid config:
40
- ${i}`,"config","INVALID_CONFIG")}let s=Wr.default.join(r,oa);await W(s,t.data);let n=Wr.default.join(r,Mc);await Fc(n,sh(t.data)),aa.info({rootDir:r},"Config saved")}async function eh(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 Cn(r,s),s}async function th(r){let e=Wr.default.join(r,oa),t=Wr.default.join(r,Mc);return await En.default.pathExists(e)||await En.default.pathExists(t)}async function rh(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");aa.debug({config:e},"Config validated successfully")}function sh(r){return`import { defineConfig } from 'assuremind';
40
+ ${i}`,"config","INVALID_CONFIG")}let s=Yr.default.join(r,ga);await W(s,t.data);let n=Yr.default.join(r,Vc);await Hc(n,gh(t.data)),ma.info({rootDir:r},"Config saved")}async function dh(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 In(r,s),s}async function ph(r){let e=Yr.default.join(r,ga),t=Yr.default.join(r,Vc);return await Cn.default.pathExists(e)||await Cn.default.pathExists(t)}async function mh(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");ma.debug({config:e},"Config validated successfully")}function gh(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 Wr,En,aa,oa,Mc,Te=b(()=>{"use strict";m();Wr=x(require("path")),En=x(require("fs-extra"));vn();re();F();ze();aa=C("config-store"),oa="autotest.config.json",Mc="autotest.config.ts"});var jc=b(()=>{"use strict";m()});var la,In,Bc=b(()=>{"use strict";m();F();la=C("websocket"),In=class{sockets=new Set;add(e){this.sockets.add(e),la.debug({total:this.sockets.size},"WS client connected"),e.on("close",()=>{this.sockets.delete(e),la.debug({total:this.sockets.size},"WS client disconnected")}),e.on("error",t=>{la.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 Uc(r,e){let{default:t}=await import("@fastify/static"),s=Hs.default.resolve(__dirname,"../../node_modules/playwright-core/lib/vite/traceViewer");await Xr.default.pathExists(s)?(await r.register(t,{root:s,prefix:"/trace/",decorateReply:!1}),Us.info({traceViewerDir:s},"Serving Playwright Trace Viewer at /trace/")):Us.warn({traceViewerDir:s},"Playwright Trace Viewer not found \u2014 skipping");let n=Hs.default.join(e,"results","allure-report");await Xr.default.ensureDir(n),Us.info({allureReportDir:n},"Per-run Allure reports will be served at /allure/<runId>");let i=Hs.default.resolve(__dirname,"../../ui/dist");await Xr.default.pathExists(i)?(await r.register(t,{root:i,prefix:"/",decorateReply:!0,index:"index.html"}),Us.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=Hs.default.join(e,"results","allure-report",p,"index.html");if(await Xr.default.pathExists(g)){let f=await Xr.default.readFile(g,"utf-8");return c.code(200).type("text/html").send(f)}}return c.code(200).type("text/html").send(`<!DOCTYPE html>
65
+ `}var Yr,Cn,ma,ga,Vc,Te=b(()=>{"use strict";m();Yr=x(require("path")),Cn=x(require("fs-extra"));xn();re();F();ze();ma=C("config-store"),ga="autotest.config.json",Vc="autotest.config.ts"});var Gc=b(()=>{"use strict";m()});var ha,Pn,zc=b(()=>{"use strict";m();F();ha=C("websocket"),Pn=class{sockets=new Set;add(e){this.sockets.add(e),ha.debug({total:this.sockets.size},"WS client connected"),e.on("close",()=>{this.sockets.delete(e),ha.debug({total:this.sockets.size},"WS client disconnected")}),e.on("error",t=>{ha.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 qc(r,e){let{default:t}=await import("@fastify/static"),s=Gs.default.resolve(__dirname,"../../node_modules/playwright-core/lib/vite/traceViewer");await Qr.default.pathExists(s)?(await r.register(t,{root:s,prefix:"/trace/",decorateReply:!1}),Vs.info({traceViewerDir:s},"Serving Playwright Trace Viewer at /trace/")):Vs.warn({traceViewerDir:s},"Playwright Trace Viewer not found \u2014 skipping");let n=Gs.default.join(e,"results","allure-report");await Qr.default.ensureDir(n),Vs.info({allureReportDir:n},"Per-run Allure reports will be served at /allure/<runId>");let i=Gs.default.resolve(__dirname,"../../ui/dist");await Qr.default.pathExists(i)?(await r.register(t,{root:i,prefix:"/",decorateReply:!0,index:"index.html"}),Vs.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=Gs.default.join(e,"results","allure-report",p,"index.html");if(await Qr.default.pathExists(g)){let f=await Qr.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,31 +88,31 @@ 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})})):(Us.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 Hs,Xr,Us,Hc=b(()=>{"use strict";m();Hs=x(require("path")),Xr=x(require("fs-extra"));F();Us=C("static")});function w(r,e,t,s){let n=s instanceof or?s.code:"INTERNAL_ERROR",i=s instanceof Error?s.message:s!==void 0?String(s):void 0,a=s instanceof fe||nh.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?Vc.error({err:s},t):Vc.debug({err:s},t),r.status(o).send({error:t,...i&&i!==t&&{detail:i},code:n,...u&&{featureHint:u}})}var Vc,nh,te=b(()=>{"use strict";m();re();F();Vc=C("server"),nh=new Set(["ENV_VALIDATION_FAILED","PROVIDER_ENV_MISSING","UNKNOWN_PROVIDER","CONFIG_ERROR"])});async function Gc(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=ih.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 Cn(e,a),s.send(a)}catch(i){return w(s,500,"Failed to update config",i)}}),r.get("/ai-provider",async(t,s)=>{let n=(process.env.AI_PROVIDER??"").trim()||"unknown",a={anthropic:{key:"ANTHROPIC_MODEL",fallback:"claude-sonnet-4-20250514"},openai:{key:"OPENAI_MODEL",fallback:"gpt-4o"},google:{key:"GOOGLE_MODEL",fallback:"gemini-2.5-pro"},"azure-openai":{key:"AZURE_OPENAI_DEPLOYMENT",fallback:"gpt-4o"},bedrock:{key:"BEDROCK_MODEL",fallback:"anthropic.claude-sonnet-4-20250514-v1:0"},deepseek:{key:"DEEPSEEK_MODEL",fallback:"deepseek-chat"},groq:{key:"GROQ_MODEL",fallback:"llama-3.3-70b-versatile"},together:{key:"TOGETHER_MODEL",fallback:"meta-llama/Llama-3.3-70B-Instruct-Turbo"},qwen:{key:"QWEN_MODEL",fallback:"qwen-max"},perplexity:{key:"PERPLEXITY_MODEL",fallback:"sonar-pro"},ollama:{key:"OLLAMA_MODEL",fallback:"qwen2.5-coder:14b"},custom:{key:"CUSTOM_MODEL",fallback:"custom"}}[n],o=a?(process.env[a.key]??"").trim()||a.fallback:"unknown";return s.send({provider:n,model:o})}),r.get("/config/status",async(t,s)=>{let n=Vt(),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 ih,zc=b(()=>{"use strict";m();Te();vn();lr();te();ih=Tr.partial()});function dh(r){let e=r.trim();return e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function ph(r){let e={};for(let t of r.split(/\r?\n/)){if(!t||t.trimStart().startsWith("#"))continue;let s=t.match(Xc);s&&(e[s[2]]=dh(s[3]??""))}return e}function qc(r){return r===""?"":/[\s#"'=]/.test(r)?`"${r.replace(/"/g,'\\"')}"`:r}function mh(r,e){let t=r.split(/\r?\n/),s=new Set,n=t.map(a=>{let o=a.match(Xc);if(o&&Object.prototype.hasOwnProperty.call(e,o[2])){let c=o[2];return s.add(c),`${o[1]??""}${c}=${qc(e[c])}`}return a}),i=Object.keys(e).filter(a=>!s.has(a)&&e[a]!=="");if(i.length>0){n.length>0&&n[n.length-1]!==""&&n.push(""),n.push("# \u2500\u2500 Added via AssureMind Studio \u2500\u2500");for(let a of i)n.push(`${a}=${qc(e[a])}`)}return n.join(`
92
- `)}async function Jc(r){let e=r.rootDir,t=Kc.default.join(e,".env");r.get("/env",async(s,n)=>{try{let i=await Jr.default.pathExists(t)?await Jr.default.readFile(t,"utf-8"):"",a=ph(i),o={},c={};for(let l of ua){let u=a[l.key]??"";l.type==="secret"?(o[l.key]="",c[l.key]=u.length>0):o[l.key]=u}return n.send({groups:Wc,values:o,secretSet:c,providerLabels:ch})}catch(i){return w(n,500,"Failed to read .env",i)}}),r.put("/env",async(s,n)=>{let i=gh.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid env payload",details:i.error.issues});try{let a={};for(let[l,u]of Object.entries(i.data.values))lh.get(l)&&(uh.has(l)&&u===""||(a[l]=u));if(Object.keys(a).length===0)return n.send({ok:!0,updated:0});let o=await Jr.default.pathExists(t)?await Jr.default.readFile(t,"utf-8"):"",c=mh(o,a);await Jr.default.writeFile(t,c,"utf-8");for(let[l,u]of Object.entries(a))process.env[l]=u;return ah.info({keys:Object.keys(a),path:t},".env updated from Studio"),n.send({ok:!0,updated:Object.keys(a).length,path:t})}catch(a){return w(n,500,"Failed to update .env",a)}})}var Kc,Jr,Vs,ah,oh,ch,Wc,ua,lh,uh,Xc,gh,Yc=b(()=>{"use strict";m();Kc=x(require("path")),Jr=x(require("fs-extra")),Vs=require("zod");te();F();ah=C("routes/env-config"),oh=["anthropic","openai","google","azure-openai","bedrock","deepseek","groq","together","qwen","perplexity","ollama","custom"],ch={anthropic:"Anthropic (Claude)",openai:"OpenAI (GPT)",google:"Google (Gemini)","azure-openai":"Azure OpenAI",bedrock:"AWS Bedrock",deepseek:"DeepSeek",groq:"Groq",together:"Together AI",qwen:"Qwen (Alibaba)",perplexity:"Perplexity",ollama:"Ollama (local)",custom:"Custom (OpenAI-compatible)"},Wc=[{id:"ai-core",title:"AI Provider",description:"Choose the AI provider used to generate test code.",fields:[{key:"AI_PROVIDER",label:"Provider",type:"select",options:["ollama","perplexity",...oh.filter(r=>r!=="ollama"&&r!=="perplexity")],default:"ollama",hint:"Which AI provider AssureMind uses."},{key:"AI_TIMEOUT",label:"Request timeout (s)",type:"number",placeholder:"e.g. 30 (use 120+ for Ollama)",default:"30",hint:"Use 120+ for local models (Ollama)."},{key:"AI_MAX_RETRIES",label:"Max retries",type:"number",placeholder:"e.g. 2 (0\u201310)",default:"2",hint:"Retries on a failed AI call (0\u201310)."}]},{id:"p-anthropic",title:"Anthropic",provider:"anthropic",fields:[{key:"ANTHROPIC_API_KEY",label:"API Key",type:"secret",provider:"anthropic",placeholder:"sk-ant-...",hint:"console.anthropic.com"},{key:"ANTHROPIC_MODEL",label:"Model",type:"text",provider:"anthropic",placeholder:"e.g. claude-sonnet-4-20250514",recommended:["claude-sonnet-4-20250514","claude-3-5-sonnet-20241022","claude-3-5-haiku-20241022"]}]},{id:"p-openai",title:"OpenAI",provider:"openai",fields:[{key:"OPENAI_API_KEY",label:"API Key",type:"secret",provider:"openai",placeholder:"sk-...",hint:"platform.openai.com"},{key:"OPENAI_MODEL",label:"Model",type:"text",provider:"openai",placeholder:"e.g. gpt-4o",recommended:["gpt-4o","gpt-4o-mini","gpt-4-turbo","o1-mini"]}]},{id:"p-google",title:"Google Gemini",provider:"google",fields:[{key:"GOOGLE_API_KEY",label:"API Key",type:"secret",provider:"google",placeholder:"AIza...",hint:"aistudio.google.com"},{key:"GOOGLE_MODEL",label:"Model",type:"text",provider:"google",placeholder:"e.g. gemini-2.5-pro",recommended:["gemini-2.5-pro","gemini-2.5-flash","gemini-1.5-pro"]}]},{id:"p-azure",title:"Azure OpenAI",provider:"azure-openai",fields:[{key:"AZURE_OPENAI_API_KEY",label:"API Key",type:"secret",provider:"azure-openai",placeholder:"your Azure resource key"},{key:"AZURE_OPENAI_ENDPOINT",label:"Endpoint",type:"text",provider:"azure-openai",placeholder:"https://<resource>.openai.azure.com"},{key:"AZURE_OPENAI_DEPLOYMENT",label:"Deployment",type:"text",provider:"azure-openai",placeholder:"e.g. gpt-4o"},{key:"AZURE_OPENAI_API_VERSION",label:"API version",type:"text",provider:"azure-openai",placeholder:"e.g. 2024-10-21",recommended:["2024-10-21","2024-08-01-preview","2024-06-01"]}]},{id:"p-bedrock",title:"AWS Bedrock",provider:"bedrock",fields:[{key:"AWS_ACCESS_KEY_ID",label:"Access Key ID",type:"secret",provider:"bedrock",placeholder:"AKIA..."},{key:"AWS_SECRET_ACCESS_KEY",label:"Secret Access Key",type:"secret",provider:"bedrock",placeholder:"your AWS secret access key"},{key:"AWS_SESSION_TOKEN",label:"Session Token (optional)",type:"secret",provider:"bedrock",placeholder:"only for temporary STS credentials"},{key:"AWS_REGION",label:"Region",type:"text",provider:"bedrock",placeholder:"e.g. us-east-1",recommended:["us-east-1","us-west-2","eu-west-1","ap-southeast-1"]},{key:"BEDROCK_MODEL",label:"Model",type:"text",provider:"bedrock",placeholder:"e.g. anthropic.claude-sonnet-4-20250514-v1:0",recommended:["anthropic.claude-sonnet-4-20250514-v1:0","anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0"]}]},{id:"p-deepseek",title:"DeepSeek",provider:"deepseek",fields:[{key:"DEEPSEEK_API_KEY",label:"API Key",type:"secret",provider:"deepseek",placeholder:"sk-... (platform.deepseek.com)"},{key:"DEEPSEEK_MODEL",label:"Model",type:"text",provider:"deepseek",placeholder:"e.g. deepseek-chat",recommended:["deepseek-chat","deepseek-reasoner"]}]},{id:"p-groq",title:"Groq",provider:"groq",fields:[{key:"GROQ_API_KEY",label:"API Key",type:"secret",provider:"groq",placeholder:"gsk_... (console.groq.com)"},{key:"GROQ_MODEL",label:"Model",type:"text",provider:"groq",placeholder:"e.g. llama-3.3-70b-versatile",recommended:["llama-3.3-70b-versatile","llama-3.1-8b-instant","mixtral-8x7b-32768"]}]},{id:"p-together",title:"Together AI",provider:"together",fields:[{key:"TOGETHER_API_KEY",label:"API Key",type:"secret",provider:"together",placeholder:"your Together API key"},{key:"TOGETHER_MODEL",label:"Model",type:"text",provider:"together",placeholder:"e.g. meta-llama/Llama-3.3-70B-Instruct-Turbo",recommended:["meta-llama/Llama-3.3-70B-Instruct-Turbo","meta-llama/Llama-3.1-8B-Instruct-Turbo","Qwen/Qwen2.5-Coder-32B-Instruct"]}]},{id:"p-qwen",title:"Qwen",provider:"qwen",fields:[{key:"QWEN_API_KEY",label:"API Key",type:"secret",provider:"qwen",placeholder:"sk-... (dashscope.aliyun.com)"},{key:"QWEN_BASE_URL",label:"Base URL",type:"text",provider:"qwen",placeholder:"https://dashscope-intl.aliyuncs.com/compatible-mode/v1"},{key:"QWEN_MODEL",label:"Model",type:"text",provider:"qwen",placeholder:"e.g. qwen-max",recommended:["qwen-max","qwen-plus","qwen-turbo","qwen2.5-coder-32b-instruct"]}]},{id:"p-perplexity",title:"Perplexity",provider:"perplexity",fields:[{key:"PERPLEXITY_API_KEY",label:"API Key",type:"secret",provider:"perplexity",placeholder:"pplx-..."},{key:"PERPLEXITY_MODEL",label:"Model",type:"text",provider:"perplexity",placeholder:"e.g. sonar-pro",recommended:["sonar-pro","sonar","sonar-reasoning"]}]},{id:"p-ollama",title:"Ollama (local)",provider:"ollama",fields:[{key:"OLLAMA_BASE_URL",label:"Base URL",type:"text",provider:"ollama",placeholder:"http://localhost:11434",default:"http://localhost:11434"},{key:"OLLAMA_MODEL",label:"Model",type:"text",provider:"ollama",placeholder:"e.g. qwen2.5-coder:14b",default:"qwen2.5-coder:14b",recommended:["qwen2.5-coder:14b","qwen2.5-coder:7b","qwen2.5-coder:3b","llama3.3","llama3.2","llama3.2:1b","codellama","mistral"]}]},{id:"p-custom",title:"Custom (OpenAI-compatible)",provider:"custom",fields:[{key:"CUSTOM_API_KEY",label:"API Key",type:"secret",provider:"custom",placeholder:"your API key"},{key:"CUSTOM_BASE_URL",label:"Base URL",type:"text",provider:"custom",placeholder:"https://your-endpoint/v1"},{key:"CUSTOM_MODEL",label:"Model",type:"text",provider:"custom",placeholder:"e.g. my-model"}]},{id:"jira",title:"Jira",description:"Generate tests from Jira issues.",fields:[{key:"JIRA_BASE_URL",label:"Base URL",type:"text",placeholder:"https://your-domain.atlassian.net"},{key:"JIRA_EMAIL",label:"Email",type:"text",placeholder:"you@company.com"},{key:"JIRA_API_TOKEN",label:"API Token",type:"secret",placeholder:"Atlassian API token",hint:"id.atlassian.com \u2192 API tokens"}]},{id:"xray",title:"Xray (Jira)",description:"Sync tests to Jira Xray. Requires Jira above.",fields:[{key:"XRAY_PROJECT_KEY",label:"Project Key",type:"text",placeholder:"e.g. PROJ"},{key:"XRAY_CLIENT_ID",label:"Client ID (Cloud)",type:"text",placeholder:"Xray Cloud client ID (blank for Server/DC)"},{key:"XRAY_CLIENT_SECRET",label:"Client Secret (Cloud)",type:"secret",placeholder:"Xray Cloud client secret"},{key:"XRAY_TEST_ISSUE_TYPE",label:"Test issue type",type:"text",placeholder:"e.g. Test"},{key:"XRAY_TEST_SET_ISSUE_TYPE",label:"Test Set issue type",type:"text",placeholder:"e.g. Test Set"}]},{id:"github",title:"GitHub",description:"Auto-PR on self-healing & PR comments.",fields:[{key:"GITHUB_TOKEN",label:"Personal Access Token",type:"secret",placeholder:"ghp_... (repo scope)",hint:"repo scope"},{key:"GITHUB_REPO_OWNER",label:"Repo Owner",type:"text",placeholder:"e.g. my-org"},{key:"GITHUB_REPO_NAME",label:"Repo Name",type:"text",placeholder:"e.g. my-repo"},{key:"GITHUB_BASE_BRANCH",label:"Base Branch",type:"text",placeholder:"e.g. main",recommended:["main","master","develop"]}]},{id:"advanced",title:"Advanced",description:"Framework runtime settings.",fields:[{key:"NODE_ENV",label:"Node env",type:"select",options:["development","production","test"]},{key:"LOG_LEVEL",label:"Log level",type:"select",options:["trace","debug","info","warn","error","fatal"]}]}],ua=Wc.flatMap(r=>r.fields),lh=new Map(ua.map(r=>[r.key,r])),uh=new Set(ua.filter(r=>r.type==="secret").map(r=>r.key)),Xc=/^(\s*)([A-Za-z_][A-Za-z0-9_]*)\s*=(.*)$/;gh=Vs.z.object({values:Vs.z.record(Vs.z.string(),Vs.z.string())})});var $,Gs,fh,Qc,hh,da,pa,Zc,ma,zs=b(()=>{"use strict";m();$=require("zod"),Gs=$.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()}),fh=$.z.object({type:$.z.enum(["inline","json-file","csv-file"]),path:$.z.string().optional(),data:$.z.array($.z.record($.z.string())).optional()}).optional(),Qc=$.z.object({id:$.z.string(),instruction:$.z.string(),generatedCode:$.z.string().default(""),order:$.z.number().int().default(0)}),hh=$.z.object({before:$.z.array(Qc).default([]),after:$.z.array(Qc).default([])}).default({before:[],after:[]}),da=$.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:fh,steps:$.z.array(Gs),caseHooks:hh,lighthouseCategories:$.z.array($.z.enum(["performance","accessibility","seo"])).default(["performance","accessibility","seo"]),createdAt:$.z.string().datetime(),updatedAt:$.z.string().datetime()}),pa=$.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()}),Zc=$.z.enum(["before_all","before_each","after_each","after_all"]),ma=$.z.object({before_all:$.z.array(Gs).default([]),before_each:$.z.array(Gs).default([]),after_each:$.z.array(Gs).default([]),after_all:$.z.array(Gs).default([])})});function Yr(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 Pn(r){let e=Yr(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 wh(r){for(let e of yh)if(e.test(r))throw new K(`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 el(r){let e=r.replace(bh,"").trim();return e.length>0?e:r}function vh(r){let e=r;return e=e.replace(/(getBy(?:Label|Placeholder)\(\s*)(['"`])([\s\S]*?)\2/g,(t,s,n,i)=>`${s}${n}${el(i)}${n}`),e=e.replace(/(name:\s*)(['"`])([\s\S]*?)\2/g,(t,s,n,i)=>`${s}${n}${el(i)}${n}`),e}function xh(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 Zr(r){let e=r;return e=xh(e),e=e.replace(/\.or\((?:[^()]*|\([^()]*\))*\)(?:\.(?:first|last)\(\))?/g,""),e=e.replace(/\.(?:first|last)\(\)(?=\.\w)/g,""),e=vh(e),e}function De(r){let e=Yr(r);if(!e)throw new K("AI returned an empty code response. Please try regenerating.","generatedCode","EMPTY_CODE");let t=Zr(e);return wh(t),t}function Tt(r){return r.toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}var yh,bh,kt=b(()=>{"use strict";m();re();yh=[/\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*\(/];bh=/\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 wa={};Q(wa,{createSuite:()=>qs,deleteSuite:()=>fa,findSuiteDirById:()=>de,listSuiteDirs:()=>At,listSuites:()=>kr,listSuitesWithCounts:()=>ya,moveSuiteType:()=>ha,readSuite:()=>ve,updateSuite:()=>Tn,writeSuite:()=>ga});async function ve(r){let e=Re.default.join(r,Rn);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=pa.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})})):(Vs.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 Gs,Qr,Vs,Kc=b(()=>{"use strict";m();Gs=x(require("path")),Qr=x(require("fs-extra"));F();Vs=C("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||fh.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?Wc.error({err:s},t):Wc.debug({err:s},t),r.status(o).send({error:t,...i&&i!==t&&{detail:i},code:n,...u&&{featureHint:u}})}var Wc,fh,te=b(()=>{"use strict";m();re();F();Wc=C("server"),fh=new Set(["ENV_VALIDATION_FAILED","PROVIDER_ENV_MISSING","UNKNOWN_PROVIDER","CONFIG_ERROR"])});async function Xc(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=hh.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=kr.parse({...i,...n.data});return await In(e,a),s.send(a)}catch(i){return w(s,500,"Failed to update config",i)}}),r.get("/ai-provider",async(t,s)=>{let n=(process.env.AI_PROVIDER??"").trim()||"unknown",a={anthropic:{key:"ANTHROPIC_MODEL",fallback:"claude-sonnet-4-20250514"},openai:{key:"OPENAI_MODEL",fallback:"gpt-4o"},google:{key:"GOOGLE_MODEL",fallback:"gemini-2.5-pro"},"azure-openai":{key:"AZURE_OPENAI_DEPLOYMENT",fallback:"gpt-4o"},bedrock:{key:"BEDROCK_MODEL",fallback:"anthropic.claude-sonnet-4-20250514-v1:0"},deepseek:{key:"DEEPSEEK_MODEL",fallback:"deepseek-chat"},groq:{key:"GROQ_MODEL",fallback:"llama-3.3-70b-versatile"},together:{key:"TOGETHER_MODEL",fallback:"meta-llama/Llama-3.3-70B-Instruct-Turbo"},qwen:{key:"QWEN_MODEL",fallback:"qwen-max"},perplexity:{key:"PERPLEXITY_MODEL",fallback:"sonar-pro"},ollama:{key:"OLLAMA_MODEL",fallback:"qwen2.5-coder:14b"},custom:{key:"CUSTOM_MODEL",fallback:"custom"}}[n],o=a?(process.env[a.key]??"").trim()||a.fallback:"unknown";return s.send({provider:n,model:o})}),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 hh,Jc=b(()=>{"use strict";m();Te();xn();ur();te();hh=kr.partial()});function Sh(r){let e=r.trim();return e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function Eh(r){let e={};for(let t of r.split(/\r?\n/)){if(!t||t.trimStart().startsWith("#"))continue;let s=t.match(el);s&&(e[s[2]]=Sh(s[3]??""))}return e}function Yc(r){return r===""?"":/[\s#"'=]/.test(r)?`"${r.replace(/"/g,'\\"')}"`:r}function Ch(r,e){let t=r.split(/\r?\n/),s=new Set,n=t.map(a=>{let o=a.match(el);if(o&&Object.prototype.hasOwnProperty.call(e,o[2])){let c=o[2];return s.add(c),`${o[1]??""}${c}=${Yc(e[c])}`}return a}),i=Object.keys(e).filter(a=>!s.has(a)&&e[a]!=="");if(i.length>0){n.length>0&&n[n.length-1]!==""&&n.push(""),n.push("# \u2500\u2500 Added via AssureMind Studio \u2500\u2500");for(let a of i)n.push(`${a}=${Yc(e[a])}`)}return n.join(`
92
+ `)}async function tl(r){let e=r.rootDir,t=Qc.default.join(e,".env");r.get("/env",async(s,n)=>{try{let i=await Zr.default.pathExists(t)?await Zr.default.readFile(t,"utf-8"):"",a=Eh(i),o={},c={};for(let l of ya){let u=a[l.key]??"";l.type==="secret"?(o[l.key]="",c[l.key]=u.length>0):o[l.key]=u}return n.send({groups:Zc,values:o,secretSet:c,providerLabels:bh})}catch(i){return w(n,500,"Failed to read .env",i)}}),r.put("/env",async(s,n)=>{let i=Ih.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid env payload",details:i.error.issues});try{let a={};for(let[l,u]of Object.entries(i.data.values))vh.get(l)&&(xh.has(l)&&u===""||(a[l]=u));if(Object.keys(a).length===0)return n.send({ok:!0,updated:0});let o=await Zr.default.pathExists(t)?await Zr.default.readFile(t,"utf-8"):"",c=Ch(o,a);await Zr.default.writeFile(t,c,"utf-8");for(let[l,u]of Object.entries(a))process.env[l]=u;return yh.info({keys:Object.keys(a),path:t},".env updated from Studio"),n.send({ok:!0,updated:Object.keys(a).length,path:t})}catch(a){return w(n,500,"Failed to update .env",a)}})}var Qc,Zr,zs,yh,wh,bh,Zc,ya,vh,xh,el,Ih,rl=b(()=>{"use strict";m();Qc=x(require("path")),Zr=x(require("fs-extra")),zs=require("zod");te();F();yh=C("routes/env-config"),wh=["anthropic","openai","google","azure-openai","bedrock","deepseek","groq","together","qwen","perplexity","ollama","custom"],bh={anthropic:"Anthropic (Claude)",openai:"OpenAI (GPT)",google:"Google (Gemini)","azure-openai":"Azure OpenAI",bedrock:"AWS Bedrock",deepseek:"DeepSeek",groq:"Groq",together:"Together AI",qwen:"Qwen (Alibaba)",perplexity:"Perplexity",ollama:"Ollama (local)",custom:"Custom (OpenAI-compatible)"},Zc=[{id:"ai-core",title:"AI Provider",description:"Choose the AI provider used to generate test code.",fields:[{key:"AI_PROVIDER",label:"Provider",type:"select",options:["ollama","perplexity",...wh.filter(r=>r!=="ollama"&&r!=="perplexity")],default:"ollama",hint:"Which AI provider AssureMind uses."},{key:"AI_TIMEOUT",label:"Request timeout (s)",type:"number",placeholder:"e.g. 30 (use 120+ for Ollama)",default:"30",hint:"Use 120+ for local models (Ollama)."},{key:"AI_MAX_RETRIES",label:"Max retries",type:"number",placeholder:"e.g. 2 (0\u201310)",default:"2",hint:"Retries on a failed AI call (0\u201310)."}]},{id:"p-anthropic",title:"Anthropic",provider:"anthropic",fields:[{key:"ANTHROPIC_API_KEY",label:"API Key",type:"secret",provider:"anthropic",placeholder:"sk-ant-...",hint:"console.anthropic.com"},{key:"ANTHROPIC_MODEL",label:"Model",type:"text",provider:"anthropic",placeholder:"e.g. claude-sonnet-4-20250514",recommended:["claude-sonnet-4-20250514","claude-3-5-sonnet-20241022","claude-3-5-haiku-20241022"]}]},{id:"p-openai",title:"OpenAI",provider:"openai",fields:[{key:"OPENAI_API_KEY",label:"API Key",type:"secret",provider:"openai",placeholder:"sk-...",hint:"platform.openai.com"},{key:"OPENAI_MODEL",label:"Model",type:"text",provider:"openai",placeholder:"e.g. gpt-4o",recommended:["gpt-4o","gpt-4o-mini","gpt-4-turbo","o1-mini"]}]},{id:"p-google",title:"Google Gemini",provider:"google",fields:[{key:"GOOGLE_API_KEY",label:"API Key",type:"secret",provider:"google",placeholder:"AIza...",hint:"aistudio.google.com"},{key:"GOOGLE_MODEL",label:"Model",type:"text",provider:"google",placeholder:"e.g. gemini-2.5-pro",recommended:["gemini-2.5-pro","gemini-2.5-flash","gemini-1.5-pro"]}]},{id:"p-azure",title:"Azure OpenAI",provider:"azure-openai",fields:[{key:"AZURE_OPENAI_API_KEY",label:"API Key",type:"secret",provider:"azure-openai",placeholder:"your Azure resource key"},{key:"AZURE_OPENAI_ENDPOINT",label:"Endpoint",type:"text",provider:"azure-openai",placeholder:"https://<resource>.openai.azure.com"},{key:"AZURE_OPENAI_DEPLOYMENT",label:"Deployment",type:"text",provider:"azure-openai",placeholder:"e.g. gpt-4o"},{key:"AZURE_OPENAI_API_VERSION",label:"API version",type:"text",provider:"azure-openai",placeholder:"e.g. 2024-10-21",recommended:["2024-10-21","2024-08-01-preview","2024-06-01"]}]},{id:"p-bedrock",title:"AWS Bedrock",provider:"bedrock",fields:[{key:"AWS_ACCESS_KEY_ID",label:"Access Key ID",type:"secret",provider:"bedrock",placeholder:"AKIA..."},{key:"AWS_SECRET_ACCESS_KEY",label:"Secret Access Key",type:"secret",provider:"bedrock",placeholder:"your AWS secret access key"},{key:"AWS_SESSION_TOKEN",label:"Session Token (optional)",type:"secret",provider:"bedrock",placeholder:"only for temporary STS credentials"},{key:"AWS_REGION",label:"Region",type:"text",provider:"bedrock",placeholder:"e.g. us-east-1",recommended:["us-east-1","us-west-2","eu-west-1","ap-southeast-1"]},{key:"BEDROCK_MODEL",label:"Model",type:"text",provider:"bedrock",placeholder:"e.g. anthropic.claude-sonnet-4-20250514-v1:0",recommended:["anthropic.claude-sonnet-4-20250514-v1:0","anthropic.claude-3-5-sonnet-20241022-v2:0","anthropic.claude-3-5-haiku-20241022-v1:0"]}]},{id:"p-deepseek",title:"DeepSeek",provider:"deepseek",fields:[{key:"DEEPSEEK_API_KEY",label:"API Key",type:"secret",provider:"deepseek",placeholder:"sk-... (platform.deepseek.com)"},{key:"DEEPSEEK_MODEL",label:"Model",type:"text",provider:"deepseek",placeholder:"e.g. deepseek-chat",recommended:["deepseek-chat","deepseek-reasoner"]}]},{id:"p-groq",title:"Groq",provider:"groq",fields:[{key:"GROQ_API_KEY",label:"API Key",type:"secret",provider:"groq",placeholder:"gsk_... (console.groq.com)"},{key:"GROQ_MODEL",label:"Model",type:"text",provider:"groq",placeholder:"e.g. llama-3.3-70b-versatile",recommended:["llama-3.3-70b-versatile","llama-3.1-8b-instant","mixtral-8x7b-32768"]}]},{id:"p-together",title:"Together AI",provider:"together",fields:[{key:"TOGETHER_API_KEY",label:"API Key",type:"secret",provider:"together",placeholder:"your Together API key"},{key:"TOGETHER_MODEL",label:"Model",type:"text",provider:"together",placeholder:"e.g. meta-llama/Llama-3.3-70B-Instruct-Turbo",recommended:["meta-llama/Llama-3.3-70B-Instruct-Turbo","meta-llama/Llama-3.1-8B-Instruct-Turbo","Qwen/Qwen2.5-Coder-32B-Instruct"]}]},{id:"p-qwen",title:"Qwen",provider:"qwen",fields:[{key:"QWEN_API_KEY",label:"API Key",type:"secret",provider:"qwen",placeholder:"sk-... (dashscope.aliyun.com)"},{key:"QWEN_BASE_URL",label:"Base URL",type:"text",provider:"qwen",placeholder:"https://dashscope-intl.aliyuncs.com/compatible-mode/v1"},{key:"QWEN_MODEL",label:"Model",type:"text",provider:"qwen",placeholder:"e.g. qwen-max",recommended:["qwen-max","qwen-plus","qwen-turbo","qwen2.5-coder-32b-instruct"]}]},{id:"p-perplexity",title:"Perplexity",provider:"perplexity",fields:[{key:"PERPLEXITY_API_KEY",label:"API Key",type:"secret",provider:"perplexity",placeholder:"pplx-..."},{key:"PERPLEXITY_MODEL",label:"Model",type:"text",provider:"perplexity",placeholder:"e.g. sonar-pro",recommended:["sonar-pro","sonar","sonar-reasoning"]}]},{id:"p-ollama",title:"Ollama (local)",provider:"ollama",fields:[{key:"OLLAMA_BASE_URL",label:"Base URL",type:"text",provider:"ollama",placeholder:"http://localhost:11434",default:"http://localhost:11434"},{key:"OLLAMA_MODEL",label:"Model",type:"text",provider:"ollama",placeholder:"e.g. qwen2.5-coder:14b",default:"qwen2.5-coder:14b",recommended:["qwen2.5-coder:14b","qwen2.5-coder:7b","qwen2.5-coder:3b","llama3.3","llama3.2","llama3.2:1b","codellama","mistral"]}]},{id:"p-custom",title:"Custom (OpenAI-compatible)",provider:"custom",fields:[{key:"CUSTOM_API_KEY",label:"API Key",type:"secret",provider:"custom",placeholder:"your API key"},{key:"CUSTOM_BASE_URL",label:"Base URL",type:"text",provider:"custom",placeholder:"https://your-endpoint/v1"},{key:"CUSTOM_MODEL",label:"Model",type:"text",provider:"custom",placeholder:"e.g. my-model"}]},{id:"jira",title:"Jira",description:"Generate tests from Jira issues.",fields:[{key:"JIRA_BASE_URL",label:"Base URL",type:"text",placeholder:"https://your-domain.atlassian.net"},{key:"JIRA_EMAIL",label:"Email",type:"text",placeholder:"you@company.com"},{key:"JIRA_API_TOKEN",label:"API Token",type:"secret",placeholder:"Atlassian API token",hint:"id.atlassian.com \u2192 API tokens"}]},{id:"xray",title:"Xray (Jira)",description:"Sync tests to Jira Xray. Requires Jira above.",fields:[{key:"XRAY_PROJECT_KEY",label:"Project Key",type:"text",placeholder:"e.g. PROJ"},{key:"XRAY_CLIENT_ID",label:"Client ID (Cloud)",type:"text",placeholder:"Xray Cloud client ID (blank for Server/DC)"},{key:"XRAY_CLIENT_SECRET",label:"Client Secret (Cloud)",type:"secret",placeholder:"Xray Cloud client secret"},{key:"XRAY_TEST_ISSUE_TYPE",label:"Test issue type",type:"text",placeholder:"e.g. Test"},{key:"XRAY_TEST_SET_ISSUE_TYPE",label:"Test Set issue type",type:"text",placeholder:"e.g. Test Set"}]},{id:"github",title:"GitHub",description:"Auto-PR on self-healing & PR comments.",fields:[{key:"GITHUB_TOKEN",label:"Personal Access Token",type:"secret",placeholder:"ghp_... (repo scope)",hint:"repo scope"},{key:"GITHUB_REPO_OWNER",label:"Repo Owner",type:"text",placeholder:"e.g. my-org"},{key:"GITHUB_REPO_NAME",label:"Repo Name",type:"text",placeholder:"e.g. my-repo"},{key:"GITHUB_BASE_BRANCH",label:"Base Branch",type:"text",placeholder:"e.g. main",recommended:["main","master","develop"]}]},{id:"advanced",title:"Advanced",description:"Framework runtime settings.",fields:[{key:"NODE_ENV",label:"Node env",type:"select",options:["development","production","test"]},{key:"LOG_LEVEL",label:"Log level",type:"select",options:["trace","debug","info","warn","error","fatal"]}]}],ya=Zc.flatMap(r=>r.fields),vh=new Map(ya.map(r=>[r.key,r])),xh=new Set(ya.filter(r=>r.type==="secret").map(r=>r.key)),el=/^(\s*)([A-Za-z_][A-Za-z0-9_]*)\s*=(.*)$/;Ih=zs.z.object({values:zs.z.record(zs.z.string(),zs.z.string())})});var $,qs,Ph,sl,Rh,wa,ba,nl,va,Ks=b(()=>{"use strict";m();$=require("zod"),qs=$.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()}),Ph=$.z.object({type:$.z.enum(["inline","json-file","csv-file"]),path:$.z.string().optional(),data:$.z.array($.z.record($.z.string())).optional()}).optional(),sl=$.z.object({id:$.z.string(),instruction:$.z.string(),generatedCode:$.z.string().default(""),order:$.z.number().int().default(0)}),Rh=$.z.object({before:$.z.array(sl).default([]),after:$.z.array(sl).default([])}).default({before:[],after:[]}),wa=$.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:Ph,steps:$.z.array(qs),caseHooks:Rh,lighthouseCategories:$.z.array($.z.enum(["performance","accessibility","seo"])).default(["performance","accessibility","seo"]),createdAt:$.z.string().datetime(),updatedAt:$.z.string().datetime()}),ba=$.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()}),nl=$.z.enum(["before_all","before_each","after_each","after_all"]),va=$.z.object({before_all:$.z.array(qs).default([]),before_each:$.z.array(qs).default([]),after_each:$.z.array(qs).default([]),after_all:$.z.array(qs).default([])})});function es(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 Rn(r){let e=es(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 kh(r){for(let e of Th)if(e.test(r))throw new K(`Generated code contains forbidden pattern: ${e.source}. This may be a prompt injection attempt. Please regenerate the step.`,"generatedCode","UNSAFE_CODE")}function ts(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 il(r){let e=r.replace(Ah,"").trim();return e.length>0?e:r}function $h(r){let e=r;return e=e.replace(/(getBy(?:Label|Placeholder)\(\s*)(['"`])([\s\S]*?)\2/g,(t,s,n,i)=>`${s}${n}${il(i)}${n}`),e=e.replace(/(name:\s*)(['"`])([\s\S]*?)\2/g,(t,s,n,i)=>`${s}${n}${il(i)}${n}`),e}function _h(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 rs(r){let e=r;return e=_h(e),e=e.replace(/\.or\((?:[^()]*|\([^()]*\))*\)(?:\.(?:first|last)\(\))?/g,""),e=e.replace(/\.(?:first|last)\(\)(?=\.\w)/g,""),e=$h(e),e}function De(r){let e=es(r);if(!e)throw new K("AI returned an empty code response. Please try regenerating.","generatedCode","EMPTY_CODE");let t=rs(e);return kh(t),t}function kt(r){return r.toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}var Th,Ah,At=b(()=>{"use strict";m();re();Th=[/\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*\(/];Ah=/\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 Ia={};Q(Ia,{createSuite:()=>Ws,deleteSuite:()=>Sa,findSuiteDirById:()=>de,listSuiteDirs:()=>$t,listSuites:()=>Ar,listSuitesWithCounts:()=>Ca,moveSuiteType:()=>Ea,readSuite:()=>ve,updateSuite:()=>kn,writeSuite:()=>xa});async function ve(r){let e=Re.default.join(r,Tn);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=ba.safeParse(t);if(!s.success){let i=s.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
93
93
  `);throw new K(`Invalid suite.json at "${e}":
94
- ${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 ga(r,e){await qe.default.ensureDir(r);let t=Re.default.join(r,Rn),s=pa.safeParse(e);if(!s.success){let n=s.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
94
+ ${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 xa(r,e){await qe.default.ensureDir(r);let t=Re.default.join(r,Tn),s=ba.safeParse(e);if(!s.success){let n=s.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
95
95
  `);throw new K(`Cannot write invalid suite to "${t}":
96
- ${n}`,"suite","INVALID_SUITE")}await W(t,s.data),es.debug({suiteId:e.id,path:t},"Suite written")}async function qs(r,e){let t=new Date().toISOString(),s=e.type??"ui",n={...e,type:s,id:(0,tl.v4)(),createdAt:t,updatedAt:t},i=Re.default.join(r,s),a=Re.default.join(i,Tt(n.name));if(await qe.default.pathExists(Re.default.join(a,Rn)))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 ga(a,n),es.info({suiteId:n.id,path:a},"Suite created"),{suiteDir:a,suiteId:n.id}}async function Tn(r,e){let t=await ve(r),s={...t,...e,id:t.id,createdAt:t.createdAt,updatedAt:new Date().toISOString()};return await ga(r,s),s}async function fa(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),es.info({path:r},"Suite deleted")}async function At(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,Rn);await qe.default.pathExists(a)&&e.push(Re.default.join(s,i.name))}}return e}async function ha(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 Tn(a,{type:t}),es.info({suiteId:s.id,from:e,to:a},"Suite moved"),a}async function de(r,e){let t=await At(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 At(r),t=[];for(let s of e)try{t.push(await ve(s))}catch(n){es.warn({path:s,err:n},"Failed to read suite \u2014 skipping")}return t}async function ya(r){let e=await At(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){es.warn({path:s,err:n},"Failed to read suite \u2014 skipping")}return t}var Re,qe,tl,es,Rn,Ke=b(()=>{"use strict";m();Re=x(require("path")),qe=x(require("fs-extra")),tl=require("uuid");zs();re();F();kt();ze();es=C("suite-store"),Rn="suite.json"});async function sl(r){let e=rl.default.join(r.rootDir,"tests");r.get("/suites",async(t,s)=>{try{let n=await ya(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=Sh.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid suite data",details:n.error.issues});try{let{suiteDir:i}=await qs(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=Eh.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 ha(e,i,n.data.type));let a=await Tn(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 fa(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 rl,je,Sh,Eh,nl=b(()=>{"use strict";m();rl=x(require("path")),je=require("zod");Ke();te();Sh=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")}),Eh=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 Ch.some(e=>e.test(r))?"api":"ui"}var Ch,Ar=b(()=>{"use strict";m();Ch=[/\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 al={};Q(al,{createCase:()=>rs,deleteCase:()=>Ws,findCasePathById:()=>mt,getCasePath:()=>Ih,listCasePaths:()=>Gt,listCases:()=>We,readCase:()=>se,updateCase:()=>Be,writeCase:()=>Ks});async function se(r){if(!await ts.default.pathExists(r))throw new oe(`Test case file not found at "${r}".`,r,"CASE_NOT_FOUND");let e=await ue(r),t=da.safeParse(e);if(!t.success){let s=t.error.issues.map(n=>` \u2022 ${n.path.join(".")}: ${n.message}`).join(`
96
+ ${n}`,"suite","INVALID_SUITE")}await W(t,s.data),ss.debug({suiteId:e.id,path:t},"Suite written")}async function Ws(r,e){let t=new Date().toISOString(),s=e.type??"ui",n={...e,type:s,id:(0,al.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,Tn)))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 xa(a,n),ss.info({suiteId:n.id,path:a},"Suite created"),{suiteDir:a,suiteId:n.id}}async function kn(r,e){let t=await ve(r),s={...t,...e,id:t.id,createdAt:t.createdAt,updatedAt:new Date().toISOString()};return await xa(r,s),s}async function Sa(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),ss.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,Tn);await qe.default.pathExists(a)&&e.push(Re.default.join(s,i.name))}}return e}async function Ea(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 kn(a,{type:t}),ss.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 Ar(r){let e=await $t(r),t=[];for(let s of e)try{t.push(await ve(s))}catch(n){ss.warn({path:s,err:n},"Failed to read suite \u2014 skipping")}return t}async function Ca(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){ss.warn({path:s,err:n},"Failed to read suite \u2014 skipping")}return t}var Re,qe,al,ss,Tn,Ke=b(()=>{"use strict";m();Re=x(require("path")),qe=x(require("fs-extra")),al=require("uuid");Ks();re();F();At();ze();ss=C("suite-store"),Tn="suite.json"});async function cl(r){let e=ol.default.join(r.rootDir,"tests");r.get("/suites",async(t,s)=>{try{let n=await Ca(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=Oh.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid suite data",details:n.error.issues});try{let{suiteDir:i}=await Ws(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=Lh.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 Ea(e,i,n.data.type));let a=await kn(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 Sa(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 ol,je,Oh,Lh,ll=b(()=>{"use strict";m();ol=x(require("path")),je=require("zod");Ke();te();Oh=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")}),Lh=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 Dh.some(e=>e.test(r))?"api":"ui"}var Dh,$r=b(()=>{"use strict";m();Dh=[/\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 dl={};Q(dl,{createCase:()=>is,deleteCase:()=>Js,findCasePathById:()=>mt,getCasePath:()=>Nh,listCasePaths:()=>zt,listCases:()=>We,readCase:()=>se,updateCase:()=>Be,writeCase:()=>Xs});async function se(r){if(!await ns.default.pathExists(r))throw new oe(`Test case file not found at "${r}".`,r,"CASE_NOT_FOUND");let e=await ue(r),t=wa.safeParse(e);if(!t.success){let s=t.error.issues.map(n=>` \u2022 ${n.path.join(".")}: ${n.message}`).join(`
97
97
  `);throw new K(`Invalid test case file at "${r}":
98
- ${s}`,"case","INVALID_CASE")}return t.data}async function Ks(r,e){let t=da.safeParse(e);if(!t.success){let s=t.error.issues.map(n=>` \u2022 ${n.path.join(".")}: ${n.message}`).join(`
98
+ ${s}`,"case","INVALID_CASE")}return t.data}async function Xs(r,e){let t=wa.safeParse(e);if(!t.success){let s=t.error.issues.map(n=>` \u2022 ${n.path.join(".")}: ${n.message}`).join(`
99
99
  `);throw new K(`Cannot write invalid test case to "${r}":
100
- ${s}`,"case","INVALID_CASE")}await W(r,t.data),An.debug({caseId:e.id,path:r},"Test case written")}async function rs(r,e){let t=new Date().toISOString(),s={...e,id:(0,il.v4)(),createdAt:t,updatedAt:t},n=kn.default.join(r,`${Tt(s.name)}${ba}`);return await Ks(n,s),An.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 Ks(r,s),s}async function Ws(r){if(!await ts.default.pathExists(r))throw new oe(`Test case file not found at "${r}".`,r,"CASE_NOT_FOUND");await ts.default.remove(r),An.info({path:r},"Test case deleted")}async function Gt(r){return await ts.default.pathExists(r)?(await ts.default.readdir(r,{withFileTypes:!0})).filter(t=>t.isFile()&&t.name.endsWith(ba)).map(t=>kn.default.join(r,t.name)):[]}async function We(r){let e=await Gt(r),t=[];for(let s of e)try{t.push(await se(s))}catch(n){An.warn({path:s,err:n},"Failed to read test case \u2014 skipping")}return t.sort((s,n)=>s.name.localeCompare(n.name))}function Ih(r,e){return kn.default.join(r,`${Tt(e)}${ba}`)}async function mt(r,e){let t=await Gt(r);for(let s of t)try{if((await se(s)).id===e)return s}catch{}return null}var kn,ts,il,An,ba,gt=b(()=>{"use strict";m();kn=x(require("path")),ts=x(require("fs-extra")),il=require("uuid");zs();re();F();kt();ze();An=C("case-store"),ba=".test.json"});async function cl(r){let e=ol.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=kh.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 Ws(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=Ah.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 rs(o,d),await Ws(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 We(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=Ph.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 rs(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=Th.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 Ws(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 ol,z,Ph,Rh,Th,kh,Ah,ll=b(()=>{"use strict";m();ol=x(require("path")),z=require("zod");Ar();gt();Ke();te();Ph=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([])}),Rh=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(),Th=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:Rh,lighthouseCategories:z.z.array(z.z.enum(["performance","accessibility","seo"])).optional()}),kh=z.z.object({ids:z.z.array(z.z.string().min(1)).min(1)}),Ah=z.z.object({ids:z.z.array(z.z.string().min(1)).min(1),targetSuiteId:z.z.string().min(1)})});function Oh(r){return typeof r=="object"&&r.secret===!0}function ul(r){return Oh(r)?r.value:r}var ur,$h,_h,va,dl=b(()=>{"use strict";m();ur=require("zod"),$h=ur.z.object({value:ur.z.string(),secret:ur.z.literal(!0)}),_h=ur.z.union([ur.z.string(),$h]),va=ur.z.record(ur.z.string(),_h)});function Dh(r){return`${r}.env.json`}async function ss(r){if(!await Xs.default.pathExists(r))return{};let e=await ue(r),t=va.safeParse(e);if(!t.success){let s=t.error.issues.map(n=>` \u2022 ${n.path.join(".")}: ${n.message}`).join(`
100
+ ${s}`,"case","INVALID_CASE")}await W(r,t.data),$n.debug({caseId:e.id,path:r},"Test case written")}async function is(r,e){let t=new Date().toISOString(),s={...e,id:(0,ul.v4)(),createdAt:t,updatedAt:t},n=An.default.join(r,`${kt(s.name)}${Pa}`);return await Xs(n,s),$n.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 Xs(r,s),s}async function Js(r){if(!await ns.default.pathExists(r))throw new oe(`Test case file not found at "${r}".`,r,"CASE_NOT_FOUND");await ns.default.remove(r),$n.info({path:r},"Test case deleted")}async function zt(r){return await ns.default.pathExists(r)?(await ns.default.readdir(r,{withFileTypes:!0})).filter(t=>t.isFile()&&t.name.endsWith(Pa)).map(t=>An.default.join(r,t.name)):[]}async function We(r){let e=await zt(r),t=[];for(let s of e)try{t.push(await se(s))}catch(n){$n.warn({path:s,err:n},"Failed to read test case \u2014 skipping")}return t.sort((s,n)=>s.name.localeCompare(n.name))}function Nh(r,e){return An.default.join(r,`${kt(e)}${Pa}`)}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 An,ns,ul,$n,Pa,gt=b(()=>{"use strict";m();An=x(require("path")),ns=x(require("fs-extra")),ul=require("uuid");Ks();re();F();At();ze();$n=C("case-store"),Pa=".test.json"});async function ml(r){let e=pl.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=Bh.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 Js(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=Uh.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 is(o,d),await Js(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 We(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=Fh.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 is(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=jh.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 Js(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 pl,z,Fh,Mh,jh,Bh,Uh,gl=b(()=>{"use strict";m();pl=x(require("path")),z=require("zod");$r();gt();Ke();te();Fh=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([])}),Mh=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(),jh=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:Mh,lighthouseCategories:z.z.array(z.z.enum(["performance","accessibility","seo"])).optional()}),Bh=z.z.object({ids:z.z.array(z.z.string().min(1)).min(1)}),Uh=z.z.object({ids:z.z.array(z.z.string().min(1)).min(1),targetSuiteId:z.z.string().min(1)})});function Gh(r){return typeof r=="object"&&r.secret===!0}function fl(r){return Gh(r)?r.value:r}var dr,Hh,Vh,Ra,hl=b(()=>{"use strict";m();dr=require("zod"),Hh=dr.z.object({value:dr.z.string(),secret:dr.z.literal(!0)}),Vh=dr.z.union([dr.z.string(),Hh]),Ra=dr.z.record(dr.z.string(),Vh)});function yl(r){return`${r}.env.json`}async function pr(r){if(!await _r.default.pathExists(r))return{};let e=await ue(r),t=Ra.safeParse(e);if(!t.success){let s=t.error.issues.map(n=>` \u2022 ${n.path.join(".")}: ${n.message}`).join(`
101
101
  `);throw new K(`Invalid variables file at "${r}":
102
- ${s}`,"variables","INVALID_VARIABLES")}return t.data}async function pl(r,e){let t=va.safeParse(e);if(!t.success){let s=t.error.issues.map(n=>` \u2022 ${n.path.join(".")}: ${n.message}`).join(`
102
+ ${s}`,"variables","INVALID_VARIABLES")}return t.data}async function Ln(r,e){let t=Ra.safeParse(e);if(!t.success){let s=t.error.issues.map(n=>` \u2022 ${n.path.join(".")}: ${n.message}`).join(`
103
103
  `);throw new K(`Cannot write invalid variables to "${r}":
104
- ${s}`,"variables","INVALID_VARIABLES")}await W(r,t.data),Lh.debug({path:r},"Variables written")}async function Sa(r){let e=dr.default.join(r,Js,xa);return ss(e)}async function Ea(r,e){let t=dr.default.join(r,Js,Dh(e));return ss(t)}async function rt(r,e){let t=await Sa(r),s=e?await Ea(r,e):{},n={...t,...s},i={};for(let[a,o]of Object.entries(n))i[a]=ul(o);return i}async function ml(r,e,t){let s=dr.default.join(r,Js,xa);await Xs.default.ensureDir(dr.default.dirname(s));let n=await ss(s);n[e]=t,await pl(s,n)}async function gl(r,e){let t=dr.default.join(r,Js,xa),s=await ss(t);if(!(e in s))throw new oe(`Variable "${e}" not found in global variables.`,t,"VARIABLE_NOT_FOUND");delete s[e],await pl(t,s)}async function fl(r){let e=dr.default.join(r,Js);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,Lh,Js,xa,pr=b(()=>{"use strict";m();dr=x(require("path")),Xs=x(require("fs-extra"));dl();re();F();ze();Lh=C("variable-store"),Js="variables",xa="global.json"});function Nh(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 Ca(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 Ia(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(`
105
- `)}function hl(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(`
106
- `)}var yl,$n,wl=b(()=>{"use strict";m();yl=[{regex:/^(?:go to|navigate to|open|visit)\s+(.+)$/i,gen:r=>`await page.goto('${Nh(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=>hl((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=>hl((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 ${Ca(r[2]??"")}.fill('${r[1]}');`},{regex:/^clear\s+(?:the\s+)?(.+?)(?:\s+field)?$/i,gen:r=>`await ${Ca(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=>Ia(r[1]??"",r[2]??"",r[3]??"")},{regex:/^upload\s+(?:the\s+)?(?:file\s+)?["']?(.+?)["']?\s+(?:to|into|in|on)\s+(?:the\s+)?(.+)$/i,gen:r=>Ia(r[1]??"",r[2]??"","")},{regex:/^upload\s+(?:the\s+)?(?:file\s+)?["']?(.+?)["']?$/i,gen:r=>Ia(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]}');
107
- 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 ${Ca(r[1]??"")}.focus();`}],$n=class{tryMatch(e){for(let t of yl){let s=e.match(t.regex);if(s!==null)return t.gen(s)}return null}get patternCount(){return yl.length}}});function Fh(r){return(0,bl.createHash)("sha256").update(r,"utf8").digest("hex")}function Mh(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 vl(r,e){let t=r.toLowerCase().replace(/\s+/g," ").trim(),s=Mh(e);return Fh(`${t}|${s}`).slice(0,16)}var bl,xl=b(()=>{"use strict";m();bl=require("crypto")});var Sl,Pa,ns,jh,Bh,is,Ra=b(()=>{"use strict";m();Sl=x(require("path")),Pa=x(require("fs-extra"));xl();F();ze();ns=C("code-cache"),jh=Sl.default.join("results",".code-cache.json"),Bh=3e4,is=class{constructor(e=jh){this.persistPath=e}persistPath;cache=new Map;dirty=!1;persistTimer=null;generateKey(e,t){return vl(e,t)}get(e){let t=this.cache.get(e);return t?t.failCount>=2?(this.cache.delete(e),this.dirty=!0,ns.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),ns.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 W(this.persistPath,e),this.dirty=!1,ns.debug({entries:this.cache.size,path:this.persistPath},"Cache persisted")}catch(e){ns.warn({err:e},"Failed to persist code cache")}}async load(){if(await Pa.default.pathExists(this.persistPath))try{let e=await Pa.default.readJson(this.persistPath);this.cache.clear();for(let[t,s]of Object.entries(e))this.cache.set(t,s);ns.debug({entries:this.cache.size,path:this.persistPath},"Cache loaded")}catch(e){ns.warn({err:e},"Failed to load code cache \u2014 starting fresh")}}startAutoSave(){if(this.persistTimer)return;this.persistTimer=setInterval(()=>{this.persist()},Bh),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 Uh,_n,El=b(()=>{"use strict";m();Uh=[/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],_n=class{classify(e){let t=Uh.filter(s=>s.test(e)).length;return t>=2?"complex":t===1?"medium":"simple"}}});var Ta,On,Cl=b(()=>{"use strict";m();kt();F();Ta=C("batch-processor"),On=class{constructor(e,t){this.templateEngine=e;this.cache=t}templateEngine;cache;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(Ta.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){Ta.warn({instruction:c.instruction},"AI returned empty code for step");continue}let u;try{u=De(l)}catch(p){Ta.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 Hh(r){return r.includes("'")?`"${r.replace(/"/g,'\\"')}"`:`'${r.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}'`}function Il(r){return r.split("||").map(e=>e.trim()).filter(Boolean).map(e=>`frameLocator(${Hh(e)})`).join(".")+"."}function Vh(r){let e=new Map;for(let t of r.split(`
108
- `)){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 Pl(r,e){if(!e)return null;let t=r.get(e.trim().toLowerCase());return!t||t.ambiguous||!t.frame?null:t.frame}function Rl(r,e){if(!r||!e||!e.includes("frame=")||!r.includes("page.getBy"))return r;let t=Vh(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=Pl(t,i?.[2]);return a?n.replace(/^page\./,`page.${Il(a)}`):n}),s=s.replace(/\bpage\.getBy(?:Text|Label|Placeholder)\((['"])([^'"]+)\1/g,(n,i,a)=>{let o=Pl(t,a);return o?n.replace(/^page\./,`page.${Il(o)}`):n}),s}var Tl=b(()=>{"use strict";m()});function qh(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 Ln(r){if(!r||!r.trim())return{title:"",interactiveElements:"",accessibilityTree:""};let e=r.split(`
109
- `),t="",s=[],n=[];for(let l of e){let u=l.trim();if(!u||u==="-")continue;let d=qh(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=Gh.has(f),v=zh.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(`
110
- `),accessibilityTree:r.slice(0,8e3)}}var Gh,zh,ka=b(()=>{"use strict";m();Gh=new Set(["button","link","textbox","checkbox","radio","combobox","listbox","menuitem","menuitemcheckbox","menuitemradio","option","searchbox","slider","spinbutton","switch","tab","treeitem"]),zh=new Set(["heading","img","navigation","dialog","alert","alertdialog","status","progressbar","table","row","cell","columnheader","rowheader"])});function kl(r,e){let t=`Current page accessibility snapshot:
104
+ ${s}`,"variables","INVALID_VARIABLES")}await W(r,t.data),zh.debug({path:r},"Variables written")}async function Dn(r){let e=ft.default.join(r,Or,On);return pr(e)}async function Nn(r,e){let t=ft.default.join(r,Or,yl(e));return pr(t)}async function rt(r,e){let t=await Dn(r),s=e?await Nn(r,e):{},n={...t,...s},i={};for(let[a,o]of Object.entries(n)){let c=process.env[a];i[a]=c!==void 0&&c!==""?c:fl(o)}return i}async function Ta(r,e,t){let s=ft.default.join(r,Or,On);await _r.default.ensureDir(ft.default.dirname(s));let n=await pr(s);n[e]=t,await Ln(s,n)}async function wl(r,e){let t=ft.default.join(r,Or,On),s=await pr(t);if(!(e in s))throw new oe(`Variable "${e}" not found in global variables.`,t,"VARIABLE_NOT_FOUND");delete s[e],await Ln(t,s)}function vl(r){return!r||r.toUpperCase()===bl}function xl(r,e){return ft.default.join(r,Or,yl(e))}function _n(r){return typeof r=="string"?{value:r,secret:!1}:{value:r.value,secret:!0}}async function Sl(r,e){let t=await Dn(r),s={};for(let a of e)s[a]=await Nn(r,a);let n=new Set(Object.keys(t));for(let a of e)for(let o of Object.keys(s[a]))n.add(o);let i=[];for(let a of[...n].sort()){let o=!1,c=t[a]!==void 0?_n(t[a]):{value:"",secret:!1};c.secret&&(o=!0);let l={};for(let u of e){let d=s[u][a];if(d!==void 0){let p=_n(d);l[u]=p.value,p.secret&&(o=!0)}else l[u]=""}i.push({key:a,secret:o,global:c.value,values:l})}return i}async function El(r,e,t,s){if(vl(e)){if(_n(s).value===""){await Ys(r,e,t).catch(()=>{});return}return Ta(r,t,s)}let n=xl(r,e);await _r.default.ensureDir(ft.default.dirname(n));let i=await pr(n);_n(s).value===""?delete i[t]:i[t]=s,await Ln(n,i)}async function Ys(r,e,t){let s=vl(e)?ft.default.join(r,Or,On):xl(r,e);if(!await _r.default.pathExists(s))return;let n=await pr(s);t in n&&(delete n[t],await Ln(s,n))}async function Cl(r,e,t){await Ys(r,bl,e);for(let s of t)await Ys(r,s,e)}async function Il(r){let e=ft.default.join(r,Or);return await _r.default.pathExists(e)?(await _r.default.readdir(e,{withFileTypes:!0})).filter(s=>s.isFile()&&s.name.endsWith(".json")).map(s=>ft.default.join(e,s.name)):[]}var ft,_r,zh,Or,On,bl,mr=b(()=>{"use strict";m();ft=x(require("path")),_r=x(require("fs-extra"));hl();re();F();ze();zh=C("variable-store"),Or="variables",On="global.json";bl="GLOBAL"});function qh(r){let e=r.trim();return/^https?:\/\//i.test(e)?e:e.startsWith("/")?`{{BASE_URL}}${e}`:/^[\w-]+\.[\w.-]+/.test(e)?`https://${e}`:e}function Lr(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 ka(r){let e=Lr(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 Aa(r,e,t){let s=Lr(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(`
105
+ `)}function Pl(r,e){let t=Lr(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(`
106
+ `)}var Rl,Fn,Tl=b(()=>{"use strict";m();Rl=[{regex:/^(?:go to|navigate to|open|visit)\s+(.+)$/i,gen:r=>`await page.goto('${qh(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=>Pl((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=>Pl((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: '${Lr(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 ${ka(r[2]??"")}.fill('${r[1]}');`},{regex:/^clear\s+(?:the\s+)?(.+?)(?:\s+field)?$/i,gen:r=>`await ${ka(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=>Aa(r[1]??"",r[2]??"",r[3]??"")},{regex:/^upload\s+(?:the\s+)?(?:file\s+)?["']?(.+?)["']?\s+(?:to|into|in|on)\s+(?:the\s+)?(.+)$/i,gen:r=>Aa(r[1]??"",r[2]??"","")},{regex:/^upload\s+(?:the\s+)?(?:file\s+)?["']?(.+?)["']?$/i,gen:r=>Aa(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]}');
107
+ await page.keyboard.press('Enter');`},{regex:/^select\s+["'](.+?)["']\s+from\s+(?:the\s+)?(.+)$/i,gen:r=>`await page.getByRole('combobox', { name: '${Lr(r[2]??"")}' }).selectOption('${r[1]}');`},{regex:/^check\s+(?:the\s+)?["']?(.+?)["']?(?:\s+checkbox)?$/i,gen:r=>`await page.getByRole('checkbox', { name: '${Lr(r[1]??"")}' }).check();`},{regex:/^uncheck\s+(?:the\s+)?["']?(.+?)["']?(?:\s+checkbox)?$/i,gen:r=>`await page.getByRole('checkbox', { name: '${Lr(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 ${ka(r[1]??"")}.focus();`}],Fn=class{tryMatch(e){for(let t of Rl){let s=e.match(t.regex);if(s!==null)return t.gen(s)}return null}get patternCount(){return Rl.length}}});function Kh(r){return(0,kl.createHash)("sha256").update(r,"utf8").digest("hex")}function Wh(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 Al(r,e){let t=r.toLowerCase().replace(/\s+/g," ").trim(),s=Wh(e);return Kh(`${t}|${s}`).slice(0,16)}var kl,$l=b(()=>{"use strict";m();kl=require("crypto")});var _l,$a,as,Xh,Jh,os,_a=b(()=>{"use strict";m();_l=x(require("path")),$a=x(require("fs-extra"));$l();F();ze();as=C("code-cache"),Xh=_l.default.join("results",".code-cache.json"),Jh=3e4,os=class{constructor(e=Xh){this.persistPath=e}persistPath;cache=new Map;dirty=!1;persistTimer=null;generateKey(e,t){return Al(e,t)}get(e){let t=this.cache.get(e);return t?t.failCount>=2?(this.cache.delete(e),this.dirty=!0,as.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),as.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 W(this.persistPath,e),this.dirty=!1,as.debug({entries:this.cache.size,path:this.persistPath},"Cache persisted")}catch(e){as.warn({err:e},"Failed to persist code cache")}}async load(){if(await $a.default.pathExists(this.persistPath))try{let e=await $a.default.readJson(this.persistPath);this.cache.clear();for(let[t,s]of Object.entries(e))this.cache.set(t,s);as.debug({entries:this.cache.size,path:this.persistPath},"Cache loaded")}catch(e){as.warn({err:e},"Failed to load code cache \u2014 starting fresh")}}startAutoSave(){if(this.persistTimer)return;this.persistTimer=setInterval(()=>{this.persist()},Jh),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 Yh,Mn,Ol=b(()=>{"use strict";m();Yh=[/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],Mn=class{classify(e){let t=Yh.filter(s=>s.test(e)).length;return t>=2?"complex":t===1?"medium":"simple"}}});var Oa,jn,Ll=b(()=>{"use strict";m();At();F();Oa=C("batch-processor"),jn=class{constructor(e,t){this.templateEngine=e;this.cache=t}templateEngine;cache;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(Oa.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){Oa.warn({instruction:c.instruction},"AI returned empty code for step");continue}let u;try{u=De(l)}catch(p){Oa.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 Qh(r){return r.includes("'")?`"${r.replace(/"/g,'\\"')}"`:`'${r.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}'`}function Dl(r){return r.split("||").map(e=>e.trim()).filter(Boolean).map(e=>`frameLocator(${Qh(e)})`).join(".")+"."}function Zh(r){let e=new Map;for(let t of r.split(`
108
+ `)){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 Nl(r,e){if(!e)return null;let t=r.get(e.trim().toLowerCase());return!t||t.ambiguous||!t.frame?null:t.frame}function Fl(r,e){if(!r||!e||!e.includes("frame=")||!r.includes("page.getBy"))return r;let t=Zh(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=Nl(t,i?.[2]);return a?n.replace(/^page\./,`page.${Dl(a)}`):n}),s=s.replace(/\bpage\.getBy(?:Text|Label|Placeholder)\((['"])([^'"]+)\1/g,(n,i,a)=>{let o=Nl(t,a);return o?n.replace(/^page\./,`page.${Dl(o)}`):n}),s}var Ml=b(()=>{"use strict";m()});function ry(r){return(r.match(/^(\s*)/)?.[1]??"").replace(/\t/g," ").length}function sy(r,e){if(r)return`iframe[name='${r}']`;let t=e.match(/title=([^\s\]]+)/i);return t?`iframe[title='${t[1]}']`:"iframe"}function Bn(r){if(!r||!r.trim())return{title:"",interactiveElements:"",accessibilityTree:""};let e=r.split(`
109
+ `),t="",s=[],n=[];for(let l of e){let u=l.trim();if(!u||u==="-")continue;let d=ry(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=sy(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=ey.has(f),v=ty.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(`
110
+ `),accessibilityTree:r.slice(0,8e3)}}var ey,ty,La=b(()=>{"use strict";m();ey=new Set(["button","link","textbox","checkbox","radio","combobox","listbox","menuitem","menuitemcheckbox","menuitemradio","option","searchbox","slider","spinbutton","switch","tab","treeitem"]),ty=new Set(["heading","img","navigation","dialog","alert","alertdialog","status","progressbar","table","row","cell","columnheader","rowheader"])});function jl(r,e){let t=`Current page accessibility snapshot:
111
111
  ${e.slice(0,6e3)}
112
112
 
113
113
  Step to execute: "${r}"
114
114
 
115
- Plan the MCP browser actions needed. Return JSON with the "actions" array.`;return{system:Wh,user:t}}var Wh,Al=b(()=>{"use strict";m();Wh=`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.
115
+ Plan the MCP browser actions needed. Return JSON with the "actions" array.`;return{system:ny,user:t}}var ny,Bl=b(()=>{"use strict";m();ny=`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.
116
116
 
117
117
  \u2501\u2501\u2501 OUTPUT FORMAT \u2501\u2501\u2501
118
118
  Return ONLY valid JSON \u2014 no markdown, no explanations.
@@ -151,10 +151,10 @@ Match elements from the snapshot by their role and name:
151
151
  - "Click Login button" \u2192 find button with name containing "Login"
152
152
  - "Select country" \u2192 find combobox/listbox with name containing "country"
153
153
 
154
- Always use the ref value from the snapshot (e.g., "s1e4") \u2014 this is the unique element identifier.`});async function $l(r,e,t){try{let{system:s,user:n}=kl(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 Aa.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 Aa.info({instruction:e,actionCount:l.length},"MCP action plan created"),l}catch(s){let n=s instanceof Error?s.message:String(s);return Aa.warn({err:n,instruction:e},"Failed to plan MCP actions"),[]}}var Aa,_l=b(()=>{"use strict";m();Al();F();Aa=C("action-mapper")});function Ll(r){let e=[];for(let t of r){let s=Xh(t);s&&e.push(s)}return e.length===0?(Ol.warn("No actions could be converted to script"),""):e.join(`
155
- `)}function Xh(r){let e=r.args??{};switch(r.tool){case"browser_navigate":{let t=String(e.url??"");return t?`await page.goto('${zt(t)}', { waitUntil: 'networkidle' });`:null}case"browser_click":{let t=Dn(e);return t?`await ${t}.click();`:null}case"browser_type":{let t=Dn(e),s=String(e.text??"");return!t||!s?null:`await ${t}.fill('${zt(s)}');`}case"browser_select_option":{let t=Dn(e),s=e.values;if(!t||!s?.length)return null;let n=s.map(i=>`'${zt(i)}'`).join(", ");return`await ${t}.selectOption([${n}]);`}case"browser_hover":{let t=Dn(e);return t?`await ${t}.hover();`:null}case"browser_press_key":{let t=String(e.key??"");return t?`await page.keyboard.press('${zt(t)}');`:null}case"browser_wait":return`await page.waitForTimeout(${Number(e.time??1e3)});`;default:return Ol.debug({tool:r.tool},"Unknown MCP action \u2014 skipping"),null}}function Dn(r){let e=String(r.element??"");if(!e)return null;let t=typeof r.frame=="string"?r.frame.trim():"",s=`page.${Jh(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('${zt(o)}')`;let l=c[a];if(l&&o)return`${s}getByRole('${l}', { name: '${zt(o)}' })`;if((a==="textbox"||a==="searchbox")&&o)return`${s}getByLabel('${zt(o)}')`}let i=e.match(/['"]([^'"]+)['"]/);return i?`${s}getByText('${zt(i[1])}')`:null}function Jh(r){return r?r.split("||").map(e=>e.trim()).filter(Boolean).map(e=>`frameLocator(${Yh(e)})`).join(".")+".":""}function Yh(r){return r.includes("'")?`"${r.replace(/"/g,'\\"')}"`:`'${zt(r)}'`}function zt(r){return r.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}var Ol,Dl=b(()=>{"use strict";m();F();Ol=C("action-to-script")});var ke,Nn,Nl=b(()=>{"use strict";m();wl();Ra();El();Cl();kt();Tl();F();Ar();ka();_l();Dl();ke=C("smart-router"),Nn=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 is,this.templateEngine=new $n,this.classifier=new _n,this.batchProcessor=new On(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:Zr(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:Qr(e,Zr(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=Qr(e,Zr(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=Rl(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=Ln(n);return ke.info({elements:i.interactiveElements.split(`
156
- `).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 $l(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=Ll(i);if(!a)return null;let o=Zr(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 Fl,Ml,Fn,Mn,jl=b(()=>{"use strict";m();Fl=require("@modelcontextprotocol/sdk/client/index.js"),Ml=require("@modelcontextprotocol/sdk/client/stdio.js");F();Fn=C("mcp-client"),Mn=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 Ml.StdioClientTransport({command:"npx",args:e}),this.client=new Fl.Client({name:"assuremind-studio",version:"1.0.0"},{capabilities:{}}),await this.client.connect(this.transport),this._connected=!0,Fn.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,Fn.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 Fn.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(`
157
- `)||null}catch(s){let n=s instanceof Error?s.message:String(s);return Fn.warn({tool:e,error:n},"MCP tool call failed"),null}}}});var Bl,ft,Ys=b(()=>{"use strict";m();jl();F();Bl=C("mcp-session"),ft=class{client;idleTimeout;idleTimer=null;mutex=Promise.resolve();_currentUrl=null;constructor(e={}){this.client=new Mn(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 Bl.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()=>{Bl.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,Ul,Qh,Hl,Zh,Vl,ey,Gl,zl,ql,$a=b(()=>{"use strict";m();H=require("zod"),Ul=H.z.object({instruction:H.z.string().min(1)}),Qh=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(Ul)}),Hl=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(Qh)}),Zh=H.z.object({index:H.z.number().int().min(0),code:H.z.string()}),Vl=H.z.object({results:H.z.array(Zh)}),ey=H.z.object({name:H.z.string().min(1),description:H.z.string().default(""),tags:H.z.array(H.z.string()).default([])}),Gl=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(ey)}),zl=H.z.object({steps:H.z.array(Ul)}),ql=H.z.object({x:H.z.number(),y:H.z.number(),action:H.z.string()})});function Kl(r,e){let t=e.previousSteps.length>0?e.previousSteps.slice(-5).map((g,f)=>` ${f+1}. "${g.instruction}"
154
+ Always use the ref value from the snapshot (e.g., "s1e4") \u2014 this is the unique element identifier.`});async function Ul(r,e,t){try{let{system:s,user:n}=jl(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 Da.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 Da.info({instruction:e,actionCount:l.length},"MCP action plan created"),l}catch(s){let n=s instanceof Error?s.message:String(s);return Da.warn({err:n,instruction:e},"Failed to plan MCP actions"),[]}}var Da,Hl=b(()=>{"use strict";m();Bl();F();Da=C("action-mapper")});function Gl(r){let e=[];for(let t of r){let s=iy(t);s&&e.push(s)}return e.length===0?(Vl.warn("No actions could be converted to script"),""):e.join(`
155
+ `)}function iy(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=Un(e);return t?`await ${t}.click();`:null}case"browser_type":{let t=Un(e),s=String(e.text??"");return!t||!s?null:`await ${t}.fill('${qt(s)}');`}case"browser_select_option":{let t=Un(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=Un(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 Vl.debug({tool:r.tool},"Unknown MCP action \u2014 skipping"),null}}function Un(r){let e=String(r.element??"");if(!e)return null;let t=typeof r.frame=="string"?r.frame.trim():"",s=`page.${ay(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 ay(r){return r?r.split("||").map(e=>e.trim()).filter(Boolean).map(e=>`frameLocator(${oy(e)})`).join(".")+".":""}function oy(r){return r.includes("'")?`"${r.replace(/"/g,'\\"')}"`:`'${qt(r)}'`}function qt(r){return r.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}var Vl,zl=b(()=>{"use strict";m();F();Vl=C("action-to-script")});var ke,Hn,ql=b(()=>{"use strict";m();Tl();_a();Ol();Ll();At();Ml();F();$r();La();Hl();zl();ke=C("smart-router"),Hn=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 os,this.templateEngine=new Fn,this.classifier=new Mn,this.batchProcessor=new jn(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:rs(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:ts(e,rs(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=ts(e,rs(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=Fl(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=Bn(n);return ke.info({elements:i.interactiveElements.split(`
156
+ `).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 Ul(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=Gl(i);if(!a)return null;let o=rs(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 Kl,Wl,Vn,Gn,Xl=b(()=>{"use strict";m();Kl=require("@modelcontextprotocol/sdk/client/index.js"),Wl=require("@modelcontextprotocol/sdk/client/stdio.js");F();Vn=C("mcp-client"),Gn=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 Wl.StdioClientTransport({command:"npx",args:e}),this.client=new Kl.Client({name:"assuremind-studio",version:"1.0.0"},{capabilities:{}}),await this.client.connect(this.transport),this._connected=!0,Vn.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,Vn.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 Vn.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(`
157
+ `)||null}catch(s){let n=s instanceof Error?s.message:String(s);return Vn.warn({tool:e,error:n},"MCP tool call failed"),null}}}});var Jl,ht,Qs=b(()=>{"use strict";m();Xl();F();Jl=C("mcp-session"),ht=class{client;idleTimeout;idleTimer=null;mutex=Promise.resolve();_currentUrl=null;constructor(e={}){this.client=new Gn(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 Jl.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()=>{Jl.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,Yl,cy,Ql,ly,Zl,uy,eu,tu,ru,Na=b(()=>{"use strict";m();H=require("zod"),Yl=H.z.object({instruction:H.z.string().min(1)}),cy=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(Yl)}),Ql=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(cy)}),ly=H.z.object({index:H.z.number().int().min(0),code:H.z.string()}),Zl=H.z.object({results:H.z.array(ly)}),uy=H.z.object({name:H.z.string().min(1),description:H.z.string().default(""),tags:H.z.array(H.z.string()).default([])}),eu=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(uy)}),tu=H.z.object({steps:H.z.array(Yl)}),ru=H.z.object({x:H.z.number(),y:H.z.number(),action:H.z.string()})});function su(r,e){let t=e.previousSteps.length>0?e.previousSteps.slice(-5).map((g,f)=>` ${f+1}. "${g.instruction}"
158
158
  ${g.code}`).join(`
159
159
  `):" None",s=Object.keys(e.variables).length>0?Object.entries(e.variables).map(([g,f])=>` {{${g}}} = ${f}`).join(`
160
160
  `):" None",i=!!(e.interactiveElements&&e.accessibilityTree)?`Interactive elements on page (LIVE from actual page \u2014 use exact roles/names):
@@ -184,7 +184,7 @@ ${t}
184
184
  Runtime variables:
185
185
  ${s}
186
186
 
187
- Step to implement: "${r}"${u}${d}`;return{system:ty,user:p}}var ty,Wl=b(()=>{"use strict";m();ty=`You are a Playwright test automation expert. Convert plain English test steps into executable Playwright TypeScript code.
187
+ Step to implement: "${r}"${u}${d}`;return{system:dy,user:p}}var dy,nu=b(()=>{"use strict";m();dy=`You are a Playwright test automation expert. Convert plain English test steps into executable Playwright TypeScript code.
188
188
 
189
189
  \u2501\u2501\u2501 OUTPUT RULES \u2501\u2501\u2501
190
190
  1. Return ONLY raw executable code \u2014 no markdown, no \`\`\`, no explanations
@@ -418,13 +418,13 @@ For keyboard-specific steps (press key, keyboard shortcut, type text):
418
418
  await page.getByLabel('Search').press('Enter');
419
419
  await page.getByRole('textbox').press('Control+A');
420
420
 
421
- Use page.keyboard.press() for single keys or shortcuts, page.keyboard.type() when the step says "type using keyboard".`});function Xl(r){return{system:ry,user:`User story:
421
+ Use page.keyboard.press() for single keys or shortcuts, page.keyboard.type() when the step says "type using keyboard".`});function iu(r){return{system:py,user:`User story:
422
422
  ${r}
423
423
 
424
424
  Generate the suite outline (no steps) following this schema:
425
- ${sy}
425
+ ${my}
426
426
 
427
- Return only the JSON object.`}}function Jl(r,e,t,s){return{system:ny,user:`Suite: "${r}"
427
+ Return only the JSON object.`}}function au(r,e,t,s){return{system:gy,user:`Suite: "${r}"
428
428
  Test case: "${e}"
429
429
  Description: "${t}"
430
430
 
@@ -432,17 +432,17 @@ Context (original user story):
432
432
  ${s}
433
433
 
434
434
  Generate the steps for this test case following this schema:
435
- ${iy}
435
+ ${fy}
436
436
 
437
- Return only the JSON object.`}}function Yl(r){let e=`User story:
437
+ Return only the JSON object.`}}function ou(r){let e=`User story:
438
438
  ${r}
439
439
 
440
440
  Generate a JSON test suite following this exact schema:
441
- ${oy}
441
+ ${yy}
442
442
 
443
- Important: return only the JSON object, nothing else.`;return{system:ay,user:e}}var ry,sy,ny,iy,ay,oy,Ql=b(()=>{"use strict";m();ry=`You are a QA test planning expert.
443
+ Important: return only the JSON object, nothing else.`;return{system:hy,user:e}}var py,my,gy,fy,hy,yy,cu=b(()=>{"use strict";m();py=`You are a QA test planning expert.
444
444
  Given a user story, produce a test suite outline \u2014 the suite metadata and a list of test cases.
445
- Do NOT include steps yet. Return ONLY valid JSON, no markdown, no code fences.`,sy=`{
445
+ Do NOT include steps yet. Return ONLY valid JSON, no markdown, no code fences.`,my=`{
446
446
  "name": "Suite name (e.g. Authentication)",
447
447
  "description": "What this suite covers",
448
448
  "tags": ["smoke", "regression"],
@@ -453,13 +453,13 @@ Do NOT include steps yet. Return ONLY valid JSON, no markdown, no code fences.`,
453
453
  "tags": ["smoke"]
454
454
  }
455
455
  ]
456
- }`;ny=`You are a QA test automation expert.
456
+ }`;gy=`You are a QA test automation expert.
457
457
  Given a test case name and description, write the detailed plain-English steps needed to execute it.
458
458
  Rules:
459
459
  1. Return ONLY valid JSON \u2014 no markdown, no code fences
460
460
  2. Each step must be a single atomic action or assertion
461
461
  3. Be concrete \u2014 reference actual UI elements by their visible labels or text
462
- 4. Use {{VARIABLE}} tokens for sensitive values (e.g. {{PASSWORD}}, {{USERNAME}})`,iy=`{
462
+ 4. Use {{VARIABLE}} tokens for sensitive values (e.g. {{PASSWORD}}, {{USERNAME}})`,fy=`{
463
463
  "steps": [
464
464
  { "instruction": "Navigate to the login page" },
465
465
  { "instruction": "Enter 'admin' in the Username field" },
@@ -467,7 +467,7 @@ Rules:
467
467
  { "instruction": "Click the 'Login' button" },
468
468
  { "instruction": "Verify the Dashboard heading is visible" }
469
469
  ]
470
- }`;ay=`You are a QA test planning expert. Convert user stories into structured test suites.
470
+ }`;hy=`You are a QA test planning expert. Convert user stories into structured test suites.
471
471
 
472
472
  RULES:
473
473
  1. Return ONLY valid JSON \u2014 no markdown, no explanations, no code fences
@@ -475,7 +475,7 @@ RULES:
475
475
  3. Steps must be atomic \u2014 one action or assertion per step
476
476
  4. Cover the happy path, then common edge cases and negative scenarios
477
477
  5. Test case names must be descriptive and start with a verb (e.g. "Login with valid credentials")
478
- 6. Steps should be concrete \u2014 reference actual UI elements by their labels or text`,oy=`{
478
+ 6. Steps should be concrete \u2014 reference actual UI elements by their labels or text`,yy=`{
479
479
  "name": "Suite name (e.g. Authentication)",
480
480
  "description": "What this suite covers",
481
481
  "tags": ["smoke", "regression"],
@@ -493,7 +493,7 @@ RULES:
493
493
  ]
494
494
  }
495
495
  ]
496
- }`});function Zl(r,e,t,s,n){let a=!!(s.interactiveElements&&s.accessibilityTree)?`Current interactive elements (LIVE from page snapshot \u2014 use exact names):
496
+ }`});function lu(r,e,t,s,n){let a=!!(s.interactiveElements&&s.accessibilityTree)?`Current interactive elements (LIVE from page snapshot \u2014 use exact names):
497
497
  ${s.interactiveElements}`:`Current interactive elements:
498
498
  ${s.interactiveElements||" None captured"}`,o=s.accessibilityTree?`
499
499
  Accessibility tree:
@@ -520,7 +520,7 @@ ${a}
520
520
  HTML snapshot (partial):
521
521
  ${s.htmlSnapshot.slice(0,3e3)}${o}${c}
522
522
 
523
- Generate new Playwright code that achieves: "${r}"`;return{system:cy,user:l}}var cy,eu=b(()=>{"use strict";m();cy=`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.
523
+ Generate new Playwright code that achieves: "${r}"`;return{system:wy,user:l}}var wy,uu=b(()=>{"use strict";m();wy=`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.
524
524
 
525
525
  RULES:
526
526
  1. Return ONLY raw executable code \u2014 no markdown, no explanations, no code fences
@@ -538,7 +538,7 @@ RULES:
538
538
  expect(page.frameLocator('#wrong').getByText('Docs')).toBeVisible()), fix ONLY the
539
539
  structural/locator path \u2014 the frame selector or container. PRESERVE the matcher
540
540
  (toBeVisible/toHaveText/...) AND the content being matched (e.g. keep getByText('Docs')
541
- verbatim). Never swap 'Docs' for another element to force a pass.`});function tu(r,e){let t=r.map(c=>` ${c.index}. "${c.instruction}"`).join(`
541
+ verbatim). Never swap 'Docs' for another element to force a pass.`});function du(r,e){let t=r.map(c=>` ${c.index}. "${c.instruction}"`).join(`
542
542
  `),s=Object.keys(e.variables).length>0?Object.entries(e.variables).map(([c,l])=>` {{${c}}} = ${l}`).join(`
543
543
  `):" None",i=!!(e.interactiveElements&&e.accessibilityTree)?`Interactive elements on page (LIVE from actual page \u2014 use exact roles/names):
544
544
  ${e.interactiveElements}
@@ -569,7 +569,7 @@ Return JSON:
569
569
  ]
570
570
  }
571
571
 
572
- Return one result per step. Include ALL ${r.length} steps.`;return{system:ly,user:o}}var ly,ru=b(()=>{"use strict";m();ly=`You are a Playwright test automation expert. Generate executable Playwright code for multiple test steps in a single JSON response.
572
+ Return one result per step. Include ALL ${r.length} steps.`;return{system:by,user:o}}var by,pu=b(()=>{"use strict";m();by=`You are a Playwright test automation expert. Generate executable Playwright code for multiple test steps in a single JSON response.
573
573
 
574
574
  \u2501\u2501\u2501 OUTPUT FORMAT \u2501\u2501\u2501
575
575
  1. Return ONLY valid JSON \u2014 no markdown, no \`\`\`, no explanations
@@ -654,7 +654,7 @@ Not visible: await expect(page.getByText('Error')).not.toBeVisible()
654
654
  \u2501\u2501\u2501 SOFT ASSERTIONS (test continues on failure) \u2501\u2501\u2501
655
655
  When instruction starts with "Soft verify/assert/check", use expect.soft():
656
656
  await expect.soft(page.getByText('Welcome')).toBeVisible()
657
- await expect.soft(page).toHaveURL(/dashboard/)`});async function uy(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 Qs(r){let e=Yr(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();$a();Wl();Ql();eu();ru();kt();re();$a();kt();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}=Kl(e,t),i=await this.chatWithRetry([{role:"system",content:s},{role:"user",content:n}]),a=De(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=Xl(e),s=await this.chatWithRetry([{role:"system",content:t.system},{role:"user",content:t.user}]),n=Pn(s),i=Qs(n)??n,a=Gl.safeParse(JSON.parse(i));if(!a.success)throw new K("Outline parse failed","outline","INVALID_OUTLINE");let o=a.data,c=await uy(o.cases.map(l=>async()=>{let u=Jl(o.name,l.name,l.description,e),d=await this.chatWithRetry([{role:"system",content:u.system},{role:"user",content:u.user}]),p=Pn(d),g=Qs(p)??p,f=zl.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}=Yl(e),n=[{role:"system",content:t},{role:"user",content:s}],i=await this.chatWithRetry(n);for(let a=0;a<2;a++){let o=Qs(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(Qs(i)??i)}async healSelector(e,t,s,n){let{system:i,user:a}=Zl(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}=tu(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 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
+ await expect.soft(page).toHaveURL(/dashboard/)`});async function vy(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 Zs(r){let e=es(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,gr=b(()=>{"use strict";m();Na();nu();cu();uu();pu();At();re();Na();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}=su(e,t),i=await this.chatWithRetry([{role:"system",content:s},{role:"user",content:n}]),a=De(i);return ts(e,a)}async generateTestSuite(e){try{return await this.generateTestSuiteTwoPass(e)}catch{return await this.generateTestSuiteSinglePass(e)}}async generateTestSuiteTwoPass(e){let t=iu(e),s=await this.chatWithRetry([{role:"system",content:t.system},{role:"user",content:t.user}]),n=Rn(s),i=Zs(n)??n,a=eu.safeParse(JSON.parse(i));if(!a.success)throw new K("Outline parse failed","outline","INVALID_OUTLINE");let o=a.data,c=await vy(o.cases.map(l=>async()=>{let u=au(o.name,l.name,l.description,e),d=await this.chatWithRetry([{role:"system",content:u.system},{role:"user",content:u.user}]),p=Rn(d),g=Zs(p)??p,f=tu.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}=ou(e),n=[{role:"system",content:t},{role:"user",content:s}],i=await this.chatWithRetry(n);for(let a=0;a<2;a++){let o=Zs(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(Zs(i)??i)}async healSelector(e,t,s,n){let{system:i,user:a}=lu(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}=du(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)=>ts(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}"
658
658
  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.
659
659
 
660
660
  Each interactive element on the page has been highlighted with a colored numbered box.
@@ -678,25 +678,25 @@ Rules:
678
678
  Examples:
679
679
  await page.getByRole('link', { name: 'Admin' }).click()
680
680
  await page.getByPlaceholder('Username').fill('Admin')
681
- 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=Pn(e),s=Qs(t)??t,n;try{n=JSON.parse(s)}catch{throw new K(`Provider "${this.name}" returned invalid JSON for test suite generation. Raw response: ${t.slice(0,200)}`,"generatedSuite","INVALID_SUITE_JSON")}let i=Hl.safeParse(n);if(!i.success){let a=i.error.issues.map(o=>` \u2022 ${o.path.join(".")}: ${o.message}`).join(`
681
+ 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=Rn(e),s=Zs(t)??t,n;try{n=JSON.parse(s)}catch{throw new K(`Provider "${this.name}" returned invalid JSON for test suite generation. Raw response: ${t.slice(0,200)}`,"generatedSuite","INVALID_SUITE_JSON")}let i=Ql.safeParse(n);if(!i.success){let a=i.error.issues.map(o=>` \u2022 ${o.path.join(".")}: ${o.message}`).join(`
682
682
  `);throw new K(`AI-generated suite has invalid structure:
683
- ${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=Yr(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=Vl.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=Yr(e);try{let s=JSON.parse(t),n=ql.safeParse(s);if(n.success)return n.data}catch{}throw new K(`Could not parse screenshot analysis response: ${t.slice(0,200)}`,"screenshotAnalysis","INVALID_SCREENSHOT_ANALYSIS")}}});var nu={};Q(nu,{AnthropicProvider:()=>_a});var su,_a,iu=b(()=>{"use strict";m();su=x(require("@anthropic-ai/sdk"));mr();re();_a=class extends Ae{name="anthropic";model;supportsVision=!0;client;constructor(e){super(e),this.model=e.model,this.client=new su.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 ou={};Q(ou,{OpenAIProvider:()=>Oa});var au,Oa,cu=b(()=>{"use strict";m();au=x(require("openai"));mr();re();Oa=class extends Ae{name="openai";model;supportsVision=!0;client;constructor(e){super(e),this.model=e.model,this.client=new au.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 uu={};Q(uu,{GoogleProvider:()=>La});var lu,La,du=b(()=>{"use strict";m();lu=require("@google/generative-ai");mr();re();La=class extends Ae{name="google";model;supportsVision=!0;genAI;constructor(e){super(e),this.model=e.model,this.genAI=new lu.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 mu={};Q(mu,{AzureOpenAIProvider:()=>Da});var pu,Da,gu=b(()=>{"use strict";m();pu=x(require("openai"));mr();re();Da=class extends Ae{name="azure-openai";model;supportsVision=!0;client;constructor(e){super(e),this.model=e.deployment,this.client=new pu.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 fu={};Q(fu,{BedrockProvider:()=>Na});var jn,Na,hu=b(()=>{"use strict";m();jn=require("@aws-sdk/client-bedrock-runtime");mr();re();Na=class extends Ae{name="bedrock";model;supportsVision=!1;client;constructor(e){super(e),this.model=e.model,this.client=new jn.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 jn.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 yu,Ue,_r=b(()=>{"use strict";m();yu=x(require("openai"));mr();re();Ue=class extends Ae{name;model;supportsVision=!1;client;constructor(e,t){super(t),this.name=e,this.model=t.model,this.client=new yu.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 wu={};Q(wu,{DeepSeekProvider:()=>Fa});var Fa,bu=b(()=>{"use strict";m();_r();Fa=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 vu={};Q(vu,{GroqProvider:()=>Ma});var Ma,xu=b(()=>{"use strict";m();_r();Ma=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 Su={};Q(Su,{TogetherProvider:()=>ja});var ja,Eu=b(()=>{"use strict";m();_r();ja=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 Cu={};Q(Cu,{QwenProvider:()=>Ba});var Ba,Iu=b(()=>{"use strict";m();_r();Ba=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 Pu={};Q(Pu,{PerplexityProvider:()=>Ua});var Ua,Ru=b(()=>{"use strict";m();_r();Ua=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 ku={};Q(ku,{OllamaProvider:()=>Ha});var Tu,Ha,Au=b(()=>{"use strict";m();Tu=x(require("openai"));mr();re();Ha=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 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 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 $u={};Q($u,{CustomProvider:()=>Va});var Va,_u=b(()=>{"use strict";m();_r();Va=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 Ou={};Q(Ou,{createProvider:()=>Or,createSmartRouter:()=>st,generateSuiteFromStory:()=>Zs,generateSuitesFromStories:()=>za});function Or(r,e){let t=cr(),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}=(iu(),et(nu));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}=(cu(),et(ou));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}=(du(),et(uu));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}=(gu(),et(mu));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}=(hu(),et(fu));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}=(bu(),et(wu));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}=(xu(),et(vu));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}=(Eu(),et(Su));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}=(Iu(),et(Cu));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}=(Ru(),et(Pu));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}=(Au(),et(ku));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}=(_u(),et($u));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=cr(),i=Or(),a;if(n.AI_TIERED_ENABLED){let l=n.AI_TIERED_FAST_PROVIDER;if(l)try{a=Or(l),Ne.info({fast:l,primary:String(n.AI_PROVIDER)},"Tiered mode active")}catch(u){Ne.warn({err:u},"Failed to create fast provider \u2014 tiered mode disabled")}}let o=r?Bn.default.join(r,"results",".code-cache.json"):void 0,c=new is(o);return new Nn({primaryProvider:i,fastProvider:a,cache:c,mcpSession:e,actThenScript:t,ragManager:s})}async function Zs(r,e){let t=Or();Ne.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 qs(e.outputDir,{name:n,description:s.description,tags:s.tags,type:e.type??"ui"});Ne.info({suiteDir:i,suiteId:a,cases:s.cases.length},"Suite directory created");for(let l of s.cases)await rs(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}))});Ne.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}),Ne.info({headless:l.mcp.headless},"MCP session created for suite generation"));let d=st(e.rootDir,o,l.mcp?.actThenScript),p=await Gt(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}),Ne.info({caseName:f.name,generated:k,total:f.steps.length},"Code generated for case"))}await d.getCache().persist(),Ne.info({suiteId:a},"Auto code generation complete")}catch(l){Ne.warn({err:l,suiteId:a},"Auto code generation failed \u2014 steps saved without code")}finally{o&&(o.release(),Ne.debug("MCP session released after suite generation"))}let c=Bn.default.join(e.rootDir,"results",`generated-suite-${Tt(n)}.json`);return await Ga.default.ensureDir(Bn.default.dirname(c)),await Ga.default.writeJson(c,{story:r,generated:s,suiteDir:i,suiteId:a},{spaces:2}),Ne.info({reportPath:c,suiteId:a},"Generation complete"),{suiteId:a,suiteName:n}}async function za(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}),Ne.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 Zs(I.story,{rootDir:e.rootDir,outputDir:e.outputDir,suiteName:I.suiteName}),o++,Ne.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}),Ne.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),Ne.info({jobId:i,completed:o,failed:c,total:a},"Bulk story generation finished"),f}var Bn,Ga,Ne,gr=b(()=>{"use strict";m();Bn=x(require("path")),Ga=x(require("fs-extra"));lr();re();F();Nl();Ra();Ys();gt();Ke();Te();pr();kt();Ar();Ne=C("router")});async function Nu(r){let e=r.rootDir,t=Lu.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=dy.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,Du.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=py.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=my.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 Lu,Du,ne,dy,py,my,Fu=b(()=>{"use strict";m();Lu=x(require("path")),Du=require("crypto"),ne=require("zod");gt();Ke();pr();Te();gr();Ys();te();dy=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()}),py=ne.z.object({stepIds:ne.z.array(ne.z.string().min(1))}),my=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=qa.default.join(r,Uu);if(!await Ka.default.pathExists(e))return{...Mu};let t=await ue(e),s=ma.safeParse(t);return s.success?s.data:(Bu.warn({path:e,errors:s.error.issues},"Invalid hooks.json \u2014 returning defaults"),{...Mu})}async function Lr(r,e){await Ka.default.ensureDir(r);let t=qa.default.join(r,Uu),s=ma.safeParse(e);if(!s.success){let n=s.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
683
+ ${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=es(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=Zl.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=es(e);try{let s=JSON.parse(t),n=ru.safeParse(s);if(n.success)return n.data}catch{}throw new K(`Could not parse screenshot analysis response: ${t.slice(0,200)}`,"screenshotAnalysis","INVALID_SCREENSHOT_ANALYSIS")}}});var gu={};Q(gu,{AnthropicProvider:()=>Fa});var mu,Fa,fu=b(()=>{"use strict";m();mu=x(require("@anthropic-ai/sdk"));gr();re();Fa=class extends Ae{name="anthropic";model;supportsVision=!0;client;constructor(e){super(e),this.model=e.model,this.client=new mu.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 yu={};Q(yu,{OpenAIProvider:()=>Ma});var hu,Ma,wu=b(()=>{"use strict";m();hu=x(require("openai"));gr();re();Ma=class extends Ae{name="openai";model;supportsVision=!0;client;constructor(e){super(e),this.model=e.model,this.client=new hu.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 vu={};Q(vu,{GoogleProvider:()=>ja});var bu,ja,xu=b(()=>{"use strict";m();bu=require("@google/generative-ai");gr();re();ja=class extends Ae{name="google";model;supportsVision=!0;genAI;constructor(e){super(e),this.model=e.model,this.genAI=new bu.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 Eu={};Q(Eu,{AzureOpenAIProvider:()=>Ba});var Su,Ba,Cu=b(()=>{"use strict";m();Su=x(require("openai"));gr();re();Ba=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 Iu={};Q(Iu,{BedrockProvider:()=>Ua});var zn,Ua,Pu=b(()=>{"use strict";m();zn=require("@aws-sdk/client-bedrock-runtime");gr();re();Ua=class extends Ae{name="bedrock";model;supportsVision=!1;client;constructor(e){super(e),this.model=e.model,this.client=new zn.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 zn.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 Ru,Ue,Dr=b(()=>{"use strict";m();Ru=x(require("openai"));gr();re();Ue=class extends Ae{name;model;supportsVision=!1;client;constructor(e,t){super(t),this.name=e,this.model=t.model,this.client=new Ru.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 Tu={};Q(Tu,{DeepSeekProvider:()=>Ha});var Ha,ku=b(()=>{"use strict";m();Dr();Ha=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 Au={};Q(Au,{GroqProvider:()=>Va});var Va,$u=b(()=>{"use strict";m();Dr();Va=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 _u={};Q(_u,{TogetherProvider:()=>Ga});var Ga,Ou=b(()=>{"use strict";m();Dr();Ga=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 Lu={};Q(Lu,{QwenProvider:()=>za});var za,Du=b(()=>{"use strict";m();Dr();za=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 Nu={};Q(Nu,{PerplexityProvider:()=>qa});var qa,Fu=b(()=>{"use strict";m();Dr();qa=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 ju={};Q(ju,{OllamaProvider:()=>Ka});var Mu,Ka,Bu=b(()=>{"use strict";m();Mu=x(require("openai"));gr();re();Ka=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 Mu.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 Uu={};Q(Uu,{CustomProvider:()=>Wa});var Wa,Hu=b(()=>{"use strict";m();Dr();Wa=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 Vu={};Q(Vu,{createProvider:()=>Nr,createSmartRouter:()=>st,generateSuiteFromStory:()=>en,generateSuitesFromStories:()=>Ja});function Nr(r,e){let t=lr(),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}=(fu(),et(gu));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}=(wu(),et(yu));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}=(xu(),et(vu));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}=(Cu(),et(Eu));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}=(Pu(),et(Iu));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}=(ku(),et(Tu));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}=($u(),et(Au));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}=(Ou(),et(_u));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}=(Du(),et(Lu));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}=(Fu(),et(Nu));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}=(Bu(),et(ju));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}=(Hu(),et(Uu));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=lr(),i=Nr(),a;if(n.AI_TIERED_ENABLED){let l=n.AI_TIERED_FAST_PROVIDER;if(l)try{a=Nr(l),Ne.info({fast:l,primary:String(n.AI_PROVIDER)},"Tiered mode active")}catch(u){Ne.warn({err:u},"Failed to create fast provider \u2014 tiered mode disabled")}}let o=r?qn.default.join(r,"results",".code-cache.json"):void 0,c=new os(o);return new Hn({primaryProvider:i,fastProvider:a,cache:c,mcpSession:e,actThenScript:t,ragManager:s})}async function en(r,e){let t=Nr();Ne.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 Ws(e.outputDir,{name:n,description:s.description,tags:s.tags,type:e.type??"ui"});Ne.info({suiteDir:i,suiteId:a,cases:s.cases.length},"Suite directory created");for(let l of s.cases)await is(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}))});Ne.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 ht({headless:l.mcp.headless,actionTimeout:l.mcp.actionTimeout,idleTimeout:l.mcp.idleTimeout}),Ne.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}),Ne.info({caseName:f.name,generated:k,total:f.steps.length},"Code generated for case"))}await d.getCache().persist(),Ne.info({suiteId:a},"Auto code generation complete")}catch(l){Ne.warn({err:l,suiteId:a},"Auto code generation failed \u2014 steps saved without code")}finally{o&&(o.release(),Ne.debug("MCP session released after suite generation"))}let c=qn.default.join(e.rootDir,"results",`generated-suite-${kt(n)}.json`);return await Xa.default.ensureDir(qn.default.dirname(c)),await Xa.default.writeJson(c,{story:r,generated:s,suiteDir:i,suiteId:a},{spaces:2}),Ne.info({reportPath:c,suiteId:a},"Generation complete"),{suiteId:a,suiteName:n}}async function Ja(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}),Ne.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 en(I.story,{rootDir:e.rootDir,outputDir:e.outputDir,suiteName:I.suiteName}),o++,Ne.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}),Ne.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),Ne.info({jobId:i,completed:o,failed:c,total:a},"Bulk story generation finished"),f}var qn,Xa,Ne,fr=b(()=>{"use strict";m();qn=x(require("path")),Xa=x(require("fs-extra"));ur();re();F();ql();_a();Qs();gt();Ke();Te();mr();At();$r();Ne=C("router")});async function qu(r){let e=r.rootDir,t=Gu.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=xy.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,zu.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 ht({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 ht({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=Sy.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=Ey.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 Gu,zu,ne,xy,Sy,Ey,Ku=b(()=>{"use strict";m();Gu=x(require("path")),zu=require("crypto"),ne=require("zod");gt();Ke();mr();Te();fr();Qs();te();xy=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()}),Sy=ne.z.object({stepIds:ne.z.array(ne.z.string().min(1))}),Ey=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 hr(r){let e=Ya.default.join(r,Yu);if(!await Qa.default.pathExists(e))return{...Wu};let t=await ue(e),s=va.safeParse(t);return s.success?s.data:(Ju.warn({path:e,errors:s.error.issues},"Invalid hooks.json \u2014 returning defaults"),{...Wu})}async function Fr(r,e){await Qa.default.ensureDir(r);let t=Ya.default.join(r,Yu),s=va.safeParse(e);if(!s.success){let n=s.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
684
684
  `);throw new K(`Cannot write invalid hooks to "${t}":
685
- ${n}`,"hooks","INVALID_HOOKS")}await W(t,s.data),Bu.debug({path:t},"Hooks written")}async function Hu(r,e,t,s){let n=await fr(r),i=n[e],a=s??i.length+1,o={id:`step-${(0,ju.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 Lr(r,n),n}async function Vu(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 Lr(r,s),s}async function Gu(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 Lr(r,s),s}async function zu(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 Lr(r,n),n}var qa,Ka,ju,Bu,Uu,Mu,qu=b(()=>{"use strict";m();qa=x(require("path")),Ka=x(require("fs-extra")),ju=require("crypto");zs();re();F();ze();Bu=C("hooks-store"),Uu="hooks.json",Mu={before_all:[],before_each:[],after_each:[],after_all:[]}});function as(r){let e=Zc.safeParse(r);return e.success?e.data:null}async function Wu(r){let e=r.rootDir,t=Ku.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=as(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});let o=gy.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 Hu(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=as(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(),ca)).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 Lr(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=as(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});let o=fy.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 Gu(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=as(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 Vu(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=as(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});let o=hy.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 zu(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=as(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(),ca)).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 Lr(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 Ku,$t,gy,fy,hy,Xu=b(()=>{"use strict";m();Ku=x(require("path")),$t=require("zod");Ke();qu();pr();gr();te();zs();gy=$t.z.object({instruction:$t.z.string().min(1),order:$t.z.number().int().positive().optional()}),fy=$t.z.object({stepIds:$t.z.array($t.z.string().min(1))}),hy=$t.z.object({instruction:$t.z.string().min(1).optional(),timeout:$t.z.number().int().positive().optional().nullable()})});async function Ju(r){let e=r.rootDir;r.get("/variables",async(t,s)=>{try{let n=await Sa(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 Ea(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=yy.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid variable value",details:n.error.issues});try{return await ml(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 gl(e,t.params.key),s.status(204).send()}catch(n){return w(s,500,"Failed to delete variable",n)}})}var Dr,yy,Yu=b(()=>{"use strict";m();Dr=require("zod");pr();Te();te();yy=Dr.z.object({value:Dr.z.union([Dr.z.string(),Dr.z.object({value:Dr.z.string(),secret:Dr.z.literal(!0)})])})});var ee,wy,by,Un,Wa,Qu=b(()=>{"use strict";m();ee=require("zod"),wy=ee.z.enum(["pending","accepted","rejected"]),by=ee.z.enum(["retry","regenerate","multi-selector","visual","decompose","manual"]),Un=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:by,level:ee.z.number().int().min(1).max(6),status:wy,pageUrl:ee.z.string(),timestamp:ee.z.string().datetime(),acceptedAt:ee.z.string().datetime().optional(),rejectedAt:ee.z.string().datetime().optional()}),Wa=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(Un)})});function td(r,e){return Fe.default.join(r,`${Hn}${e}.json`)}function Fr(r){return Fe.default.join(r,vy)}async function rd(r,e){let t=Wa.safeParse(e);if(!t.success){let i=t.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
685
+ ${n}`,"hooks","INVALID_HOOKS")}await W(t,s.data),Ju.debug({path:t},"Hooks written")}async function Qu(r,e,t,s){let n=await hr(r),i=n[e],a=s??i.length+1,o={id:`step-${(0,Xu.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 Fr(r,n),n}async function Zu(r,e,t){let s=await hr(r);return s[e]=s[e].filter(n=>n.id!==t).map((n,i)=>({...n,order:i+1})),await Fr(r,s),s}async function ed(r,e,t){let s=await hr(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 Fr(r,s),s}async function td(r,e,t,s){let n=await hr(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 Fr(r,n),n}var Ya,Qa,Xu,Ju,Yu,Wu,rd=b(()=>{"use strict";m();Ya=x(require("path")),Qa=x(require("fs-extra")),Xu=require("crypto");Ks();re();F();ze();Ju=C("hooks-store"),Yu="hooks.json",Wu={before_all:[],before_each:[],after_each:[],after_all:[]}});function cs(r){let e=nl.safeParse(r);return e.success?e.data:null}async function nd(r){let e=r.rootDir,t=sd.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 hr(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=cs(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});let o=Cy.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 Qu(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=cs(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 hr(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(),fa)).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 Fr(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=cs(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});let o=Iy.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 ed(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=cs(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 Zu(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=cs(n.params.hookType);if(!a)return i.status(400).send({error:`Invalid hook type: ${n.params.hookType}`});let o=Py.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 td(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=cs(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 hr(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(),fa)).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 Fr(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 sd,_t,Cy,Iy,Py,id=b(()=>{"use strict";m();sd=x(require("path")),_t=require("zod");Ke();rd();mr();fr();te();Ks();Cy=_t.z.object({instruction:_t.z.string().min(1),order:_t.z.number().int().positive().optional()}),Iy=_t.z.object({stepIds:_t.z.array(_t.z.string().min(1))}),Py=_t.z.object({instruction:_t.z.string().min(1).optional(),timeout:_t.z.number().int().positive().optional().nullable()})});async function od(r){let e=r.rootDir;r.get("/variables",async(t,s)=>{try{let n=await Dn(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/matrix",async(t,s)=>{try{let i=(await G(e)).environments??[],a=await Sl(e,i);return s.send({environments:i,entries:a})}catch(n){return w(s,500,"Failed to read variable matrix",n)}}),r.put("/variables/:key/scope/:scope",async(t,s)=>{if(t.params.key==="BASE_URL")return s.status(400).send({error:"BASE_URL is managed in Settings \u2192 Environment."});let n=ad.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid variable value",details:n.error.issues});try{return await El(e,t.params.scope,t.params.key,n.data.value),s.send({key:t.params.key,scope:t.params.scope,value:n.data.value})}catch(i){return w(s,500,"Failed to set variable",i)}}),r.delete("/variables/:key/scope/:scope",async(t,s)=>{try{return await Ys(e,t.params.scope,t.params.key),s.status(204).send()}catch(n){return w(s,500,"Failed to delete variable value",n)}}),r.delete("/variables/:key/everywhere",async(t,s)=>{if(t.params.key==="BASE_URL")return s.status(400).send({error:"BASE_URL is managed in Settings \u2192 Environment."});try{let n=await G(e);return await Cl(e,t.params.key,n.environments??[]),s.status(204).send()}catch(n){return w(s,500,"Failed to delete variable",n)}}),r.get("/variables/env/:env",async(t,s)=>{try{let n=await Nn(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=ad.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid variable value",details:n.error.issues});try{return await Ta(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 wl(e,t.params.key),s.status(204).send()}catch(n){return w(s,500,"Failed to delete variable",n)}})}var Mr,ad,cd=b(()=>{"use strict";m();Mr=require("zod");mr();Te();te();ad=Mr.z.object({value:Mr.z.union([Mr.z.string(),Mr.z.object({value:Mr.z.string(),secret:Mr.z.literal(!0)})])})});var ee,Ry,Ty,Kn,Za,ld=b(()=>{"use strict";m();ee=require("zod"),Ry=ee.z.enum(["pending","accepted","rejected"]),Ty=ee.z.enum(["retry","regenerate","multi-selector","visual","decompose","manual"]),Kn=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:Ry,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(Kn)})});function pd(r,e){return Fe.default.join(r,`${Wn}${e}.json`)}function Br(r){return Fe.default.join(r,ky)}async function md(r,e){let t=Za.safeParse(e);if(!t.success){let i=t.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
686
686
  `);throw new K(`Cannot write invalid healing report:
687
- ${i}`,"healingReport","INVALID_HEALING_REPORT")}let s=Fe.default.join(r,_t),n=td(s,e.runId);await W(n,t.data),hr.info({runId:e.runId,totalHeals:e.totalHeals},"Healing report saved")}async function Vn(r,e){let t=Fe.default.join(r,_t),s=td(t,e);if(!await Nr.default.pathExists(s))throw new oe(`Healing report not found for runId "${e}".`,s,"HEALING_REPORT_NOT_FOUND");let n=await ue(s),i=Wa.safeParse(n);if(!i.success){let a=i.error.issues.map(o=>` \u2022 ${o.path.join(".")}: ${o.message}`).join(`
687
+ ${i}`,"healingReport","INVALID_HEALING_REPORT")}let s=Fe.default.join(r,Ot),n=pd(s,e.runId);await W(n,t.data),yr.info({runId:e.runId,totalHeals:e.totalHeals},"Healing report saved")}async function Xn(r,e){let t=Fe.default.join(r,Ot),s=pd(t,e);if(!await jr.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(`
688
688
  `);throw new K(`Invalid healing report at "${s}":
689
- ${a}`,"healingReport","INVALID_HEALING_REPORT")}return i.data}async function nt(r){let e=Fe.default.join(r,_t),t=Fr(e);if(!await Nr.default.pathExists(t))return[];let s=await ue(t),n=Un.array().safeParse(s);return n.success?n.data:(hr.warn({path:t},"Pending healing file is malformed \u2014 resetting"),[])}function xy(r){if(r.length<=Zu)return r;let e=[...r].sort((n,i)=>{let a=ed.indexOf(n.status),o=ed.indexOf(i.status);return a!==o?a-o:n.timestamp<i.timestamp?-1:1}),t=r.length-Zu,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 sd(r,e){let t=Un.safeParse(e);if(!t.success)throw new K(`Invalid healing event: ${t.error.message}`,"healingEvent","INVALID_HEALING_EVENT");let s=Fe.default.join(r,_t);await Nr.default.ensureDir(s);let n=await nt(r);n.push(t.data),await W(Fr(s),xy(n))}async function en(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=Fe.default.join(r,_t);return await W(Fr(n),t),hr.info({eventId:e},"Healing event accepted"),t[s]}async function Gn(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=Fe.default.join(r,_t);return await W(Fr(n),t),hr.info({eventId:e},"Healing event rejected"),t[s]}async function nd(r,e){let s=(await nt(r)).filter(i=>i.id!==e),n=Fe.default.join(r,_t);await W(Fr(n),s),hr.info({eventId:e},"Healing event deleted")}async function id(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=Fe.default.join(r,_t);return await W(Fr(a),n),hr.info({count:i},"Healing events bulk-deleted"),i}async function ad(r){let t=(await nt(r)).length,s=Fe.default.join(r,_t);return await W(Fr(s),[]),hr.info({count:t},"All healing events cleared"),t}async function od(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 cd(r){let e=Fe.default.join(r,_t);if(!await Nr.default.pathExists(e))return[];let s=(await Nr.default.readdir(e,{withFileTypes:!0})).filter(i=>i.isFile()&&i.name.startsWith(Hn)&&i.name.endsWith(".json")).map(i=>i.name.slice(Hn.length,-5));return(await Promise.all(s.map(async i=>{let a=await Nr.default.stat(Fe.default.join(e,`${Hn}${i}.json`));return{id:i,mtime:a.mtimeMs}}))).sort((i,a)=>a.mtime-i.mtime).map(i=>i.id)}var Fe,Nr,hr,_t,vy,Hn,Zu,ed,zn=b(()=>{"use strict";m();Fe=x(require("path")),Nr=x(require("fs-extra"));Qu();re();F();ze();hr=C("healing-store"),_t=Fe.default.join("results","healing"),vy="pending.json",Hn="healing-report-";Zu=50,ed=["pending","rejected","accepted"]});async function dd(r){let e=r.rootDir,t=ud.default.join(e,"tests");r.get("/healing",async(s,n)=>{try{let i=await cd(e),a=[];for(let o of i){let c=await Vn(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 od(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 en(e,s.params.id);return await Xa(t,i.caseId,i.stepId,i.healedCode),ld.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 Gn(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 en(e,o.id),await Xa(t,o.caseId,o.stepId,o.healedCode),a.push({id:o.id,status:"accepted"}),ld.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 ad(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=Ey.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid request",details:i.error.issues});try{let a=await id(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 nd(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=Sy.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 Xa(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 Xa(r,e,t,s){let n=await Cy(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 Cy(r,e){let{default:t}=await import("fs-extra"),{listSuiteDirs:s}=await Promise.resolve().then(()=>(Ke(),wa)),n=await s(r);for(let i of n){let a=await mt(i,e);if(a)return a}return null}var ud,os,ld,Sy,Ey,pd=b(()=>{"use strict";m();ud=x(require("path")),os=require("zod");zn();gt();te();F();ld=C("routes/healing"),Sy=os.z.object({reportPath:os.z.string().min(1)}),Ey=os.z.object({ids:os.z.array(os.z.string().min(1)).min(1)})});var R,qn,Iy,Py,ht,md,Ry,Ty,ky,Ay,Ja,gd=b(()=>{"use strict";m();R=require("zod"),qn=R.z.enum(["pending","running","passed","failed","skipped"]),Iy=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(),Py=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),md=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()}),Ry=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(md).optional(),seoAudits:R.z.array(md).optional(),lighthouseError:R.z.string().optional()}),Ty=R.z.object({stepId:R.z.string(),instruction:R.z.string(),status:qn,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:Iy,apiResponse:Py,navigatedToUrl:R.z.string().optional(),auditUrl:R.z.string().optional()}),ky=R.z.object({caseId:R.z.string(),caseName:R.z.string(),status:qn,steps:R.z.array(Ty),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(Ry).default([])}),Ay=R.z.object({suiteId:R.z.string(),suiteName:R.z.string(),suiteType:R.z.enum(["ui","api","audit","performance"]).optional(),status:qn,cases:R.z.array(ky),duration:R.z.number(),browser:R.z.string(),startedAt:R.z.string().datetime(),finishedAt:R.z.string().datetime()}),Ja=R.z.object({runId:R.z.string(),status:qn,environment:R.z.string().optional(),suites:R.z.array(Ay),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 Qa(r,e){return jr.default.join(r,fd,`${e}.json`)}async function hd(r,e){let t=Ja.safeParse(e);if(!t.success){let n=t.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
689
+ ${a}`,"healingReport","INVALID_HEALING_REPORT")}return i.data}async function nt(r){let e=Fe.default.join(r,Ot),t=Br(e);if(!await jr.default.pathExists(t))return[];let s=await ue(t),n=Kn.array().safeParse(s);return n.success?n.data:(yr.warn({path:t},"Pending healing file is malformed \u2014 resetting"),[])}function Ay(r){if(r.length<=ud)return r;let e=[...r].sort((n,i)=>{let a=dd.indexOf(n.status),o=dd.indexOf(i.status);return a!==o?a-o:n.timestamp<i.timestamp?-1:1}),t=r.length-ud,s=new Set(e.slice(0,t).map(n=>n.id));return yr.info({excess:t,deleted:s.size},"Auto-pruning healing events to enforce cap"),r.filter(n=>!s.has(n.id))}async function gd(r,e){let t=Kn.safeParse(e);if(!t.success)throw new K(`Invalid healing event: ${t.error.message}`,"healingEvent","INVALID_HEALING_EVENT");let s=Fe.default.join(r,Ot);await jr.default.ensureDir(s);let n=await nt(r);n.push(t.data),await W(Br(s),Ay(n))}async function tn(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=Fe.default.join(r,Ot);return await W(Br(n),t),yr.info({eventId:e},"Healing event accepted"),t[s]}async function Jn(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=Fe.default.join(r,Ot);return await W(Br(n),t),yr.info({eventId:e},"Healing event rejected"),t[s]}async function fd(r,e){let s=(await nt(r)).filter(i=>i.id!==e),n=Fe.default.join(r,Ot);await W(Br(n),s),yr.info({eventId:e},"Healing event deleted")}async function hd(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=Fe.default.join(r,Ot);return await W(Br(a),n),yr.info({count:i},"Healing events bulk-deleted"),i}async function yd(r){let t=(await nt(r)).length,s=Fe.default.join(r,Ot);return await W(Br(s),[]),yr.info({count:t},"All healing events cleared"),t}async function wd(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 bd(r){let e=Fe.default.join(r,Ot);if(!await jr.default.pathExists(e))return[];let s=(await jr.default.readdir(e,{withFileTypes:!0})).filter(i=>i.isFile()&&i.name.startsWith(Wn)&&i.name.endsWith(".json")).map(i=>i.name.slice(Wn.length,-5));return(await Promise.all(s.map(async i=>{let a=await jr.default.stat(Fe.default.join(e,`${Wn}${i}.json`));return{id:i,mtime:a.mtimeMs}}))).sort((i,a)=>a.mtime-i.mtime).map(i=>i.id)}var Fe,jr,yr,Ot,ky,Wn,ud,dd,Yn=b(()=>{"use strict";m();Fe=x(require("path")),jr=x(require("fs-extra"));ld();re();F();ze();yr=C("healing-store"),Ot=Fe.default.join("results","healing"),ky="pending.json",Wn="healing-report-";ud=50,dd=["pending","rejected","accepted"]});async function Sd(r){let e=r.rootDir,t=xd.default.join(e,"tests");r.get("/healing",async(s,n)=>{try{let i=await bd(e),a=[];for(let o of i){let c=await Xn(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 wd(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 tn(e,s.params.id);return await eo(t,i.caseId,i.stepId,i.healedCode),vd.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 Jn(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 tn(e,o.id),await eo(t,o.caseId,o.stepId,o.healedCode),a.push({id:o.id,status:"accepted"}),vd.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 yd(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=_y.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid request",details:i.error.issues});try{let a=await hd(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 fd(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=$y.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 eo(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 eo(r,e,t,s){let n=await Oy(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 Oy(r,e){let{default:t}=await import("fs-extra"),{listSuiteDirs:s}=await Promise.resolve().then(()=>(Ke(),Ia)),n=await s(r);for(let i of n){let a=await mt(i,e);if(a)return a}return null}var xd,ls,vd,$y,_y,Ed=b(()=>{"use strict";m();xd=x(require("path")),ls=require("zod");Yn();gt();te();F();vd=C("routes/healing"),$y=ls.z.object({reportPath:ls.z.string().min(1)}),_y=ls.z.object({ids:ls.z.array(ls.z.string().min(1)).min(1)})});var R,Qn,Ly,Dy,yt,Cd,Ny,Fy,My,jy,to,Id=b(()=>{"use strict";m();R=require("zod"),Qn=R.z.enum(["pending","running","passed","failed","skipped"]),Ly=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(),Dy=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(),yt=R.z.number().nullish().transform(r=>r??void 0),Cd=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()}),Ny=R.z.object({url:R.z.string(),stepIndex:R.z.number().int(),stepInstruction:R.z.string(),score:yt,a11yScore:yt,seoScore:yt,fcp:yt,lcp:yt,cls:yt,ttfb:yt,tbt:yt,si:yt,tti:yt,inp:yt,a11yAudits:R.z.array(Cd).optional(),seoAudits:R.z.array(Cd).optional(),lighthouseError:R.z.string().optional()}),Fy=R.z.object({stepId:R.z.string(),instruction:R.z.string(),status:Qn,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:Ly,apiResponse:Dy,navigatedToUrl:R.z.string().optional(),auditUrl:R.z.string().optional()}),My=R.z.object({caseId:R.z.string(),caseName:R.z.string(),status:Qn,steps:R.z.array(Fy),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(Ny).default([])}),jy=R.z.object({suiteId:R.z.string(),suiteName:R.z.string(),suiteType:R.z.enum(["ui","api","audit","performance"]).optional(),status:Qn,cases:R.z.array(My),duration:R.z.number(),browser:R.z.string(),startedAt:R.z.string().datetime(),finishedAt:R.z.string().datetime()}),to=R.z.object({runId:R.z.string(),status:Qn,environment:R.z.string().optional(),suites:R.z.array(jy),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 so(r,e){return Hr.default.join(r,Pd,`${e}.json`)}async function Rd(r,e){let t=to.safeParse(e);if(!t.success){let n=t.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
690
690
  `);throw new K(`Cannot write invalid run result:
691
- ${n}`,"result","INVALID_RESULT")}let s=Qa(jr.default.join(r,Kn),e.runId);await W(s,t.data),Ya.info({runId:e.runId,status:e.status},"Run result saved")}async function Br(r,e){let t=Qa(jr.default.join(r,Kn),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=Ja.safeParse(s);if(!n.success){let i=n.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
691
+ ${n}`,"result","INVALID_RESULT")}let s=so(Hr.default.join(r,Zn),e.runId);await W(s,t.data),ro.info({runId:e.runId,status:e.status},"Run result saved")}async function Vr(r,e){let t=so(Hr.default.join(r,Zn),e);if(!await Ur.default.pathExists(t))throw new oe(`Run result not found for runId "${e}".`,t,"RESULT_NOT_FOUND");let s=await ue(t),n=to.safeParse(s);if(!n.success){let i=n.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
692
692
  `);throw new K(`Invalid run result at "${t}":
693
- ${i}`,"result","INVALID_RESULT")}return n.data}async function Za(r){let e=jr.default.join(r,Kn,fd);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 Wn(r,e=20){let t=await Za(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){Ya.warn({runId:n,err:i},"Failed to read run result \u2014 skipping")}return s}async function yd(r,e){let t=Qa(jr.default.join(r,Kn),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),Ya.info({runId:e},"Run result deleted")}var jr,Mr,Ya,Kn,fd,tn=b(()=>{"use strict";m();jr=x(require("path")),Mr=x(require("fs-extra"));gd();re();F();ze();Ya=C("result-store"),Kn="results",fd="runs"});function wd(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&&!$y.has(n)),s=[...t];for(let n=0;n<t.length-1;n++)s.push(`${t[n]}_${t[n+1]}`);return s}function _y(r){return(0,bd.createHash)("md5").update(r).digest().readUInt32LE(0)%eo}var bd,Jn,eo,$y,Xn,vd=b(()=>{"use strict";m();bd=require("crypto"),Jn=require("fs-extra"),eo=256,$y=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}vocabPath;vocab={docCount:0,termDocFreq:{}};dirty=!1;async load(){try{this.vocab=await(0,Jn.readJson)(this.vocabPath)}catch{this.vocab={docCount:0,termDocFreq:{}}}}async save(){this.dirty&&(await(0,Jn.outputJson)(this.vocabPath,this.vocab,{spaces:0}),this.dirty=!1)}addDocument(e){let t=new Set(wd(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=wd(e);if(t.length===0)return new Array(eo).fill(0);let s={};for(let o of t)s[o]=(s[o]??0)+1;let n=new Array(eo).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=_y(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 xd(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 Sd=b(()=>{"use strict";m()});var ls,cs,Ed=b(()=>{"use strict";m();ls=require("fs-extra");Sd();cs=class{constructor(e,t=500){this.filePath=e;this.maxEntries=t}filePath;maxEntries;documents=[];dirty=!1;async load(){if(await(0,ls.pathExists)(this.filePath))try{let e=await(0,ls.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,ls.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=xd(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 Ly(r,e){let t=`${r.toLowerCase().trim()}|${to(e)}`;return(0,Cd.createHash)("sha256").update(t).digest("hex").slice(0,16)}function to(r){if(!r)return"";try{let e=new URL(r),t=e.pathname.replace(/\/\d+/g,"/*");return`${e.hostname}${t}`}catch{return r}}function Dy(r,e,t){let s=e+t;if(s===0)return r;let n=e/s;return r*(1+.05*n)}function Ny(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 Cd,Oy,Yn,Id=b(()=>{"use strict";m();Cd=require("crypto"),Oy=2,Yn=class{constructor(e,t){this.store=e;this.embedder=t}store;embedder;ingest(e,t,s){let n=Ly(e,s),i=to(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=to(t),a=`${e} ${i}`,o=this.embedder.embed(a),l=this.store.search(o,s*2,n).map(u=>({...u,score:Dy(u.score,u.metadata.successCount,u.metadata.failCount)}));return l.sort((u,d)=>d.score-u.score),l.slice(0,s).map(Ny)}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>=Oy){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 Fy(r,e){let t=`${r.toLowerCase().trim()}|${Qn(e)}`;return(0,Pd.createHash)("sha256").update(t).digest("hex").slice(0,16)}function Qn(r){return r.replace(/\d+ms/g,"Nms").replace(/\d+/g,"N").replace(/["'][^"']*["']/g,"'...'").replace(/\s+/g," ").trim().slice(0,200)}function My(r){if(!r)return"";try{let e=new URL(r);return`${e.hostname}${e.pathname.replace(/\/\d+/g,"/*")}`}catch{return r}}function jy(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 Pd,Zn,Rd=b(()=>{"use strict";m();Pd=require("crypto"),Zn=class{constructor(e,t){this.store=e;this.embedder=t}store;embedder;ingest(e){let t=Fy(e.instruction,e.error),s=My(e.url),n=`${e.instruction} ${Qn(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:Qn(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} ${Qn(t)}`,a=this.embedder.embed(i);return this.store.search(a,s,n).map(jy)}get size(){return this.store.size}}});function By(r,e){let t=`${r}|${e}`;return(0,kd.createHash)("sha256").update(t).digest("hex").slice(0,16)}function Uy(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 Hy(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 kd,ei,Ad=b(()=>{"use strict";m();kd=require("crypto"),ei=class{constructor(e,t){this.store=e;this.embedder=t}store;embedder;record(e,t,s){let n=Uy(e),i=Td(t),a=By(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(Hy)}get size(){return this.store.size}}});var us,$d,ro,ti,_d=b(()=>{"use strict";m();us=require("path"),$d=require("fs-extra");vd();Ed();Id();Rd();Ad();F();ro=C("rag"),ti=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 Yn(t,e),this.healingCorpus=new Zn(s,e),this.errorCatalog=new ei(n,e)}static async create(e,t){let s=(0,us.join)(e,"results",".rag");await(0,$d.ensureDir)(s),ro.info({ragDir:s},"Initializing RAG manager");let n=new Xn((0,us.join)(s,"idf-vocab.json"));await n.load();let i=new cs((0,us.join)(s,"code-corpus.json"),t.codeCorpus.maxEntries),a=new cs((0,us.join)(s,"healing-corpus.json"),t.healingCorpus.maxEntries),o=new cs((0,us.join)(s,"error-catalog.json"),t.errorCatalog.maxEntries);return await Promise.all([i.load(),a.load(),o.load()]),ro.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()]),ro.debug("RAG corpora persisted")}getStats(){return{codeCorpus:this.codeStore.size,healingCorpus:this.healingStore.size,errorCatalog:this.errorStore.size,idfVocab:this.embedder.documentCount}}}});function Gy(r){let e=[];for(let t of Vy){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 zy(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=qy(s,c[1].toLowerCase());l>i&&(i=l,a=o)}}if(i>.3)return a}}}function qy(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 Ld(r,e,t){let s=Gy(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 Od.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=Ln(n).interactiveElements.split(`
694
- `).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=zy(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 Od.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 Od,Vy,Dd=b(()=>{"use strict";m();ka();F();Od=C("proactive-checker"),Vy=[{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 ri.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 ri.default.pathExists(i))return i}return r}var yr,ri,yt,qt,si,Nd=b(()=>{"use strict";m();yr=x(require("path")),ri=x(require("fs-extra")),yt=require("playwright");F();qt=C("browser-manager");si=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),qt.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&&qt.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 ri.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),qt.info({file:yr.default.basename(p)},"Download captured")}catch(u){qt.debug({err:u},"Failed to capture download")}})();this.pendingDownloads.get(o)?.push(l)})),await o.addInitScript(()=>{let c=`
693
+ ${i}`,"result","INVALID_RESULT")}return n.data}async function no(r){let e=Hr.default.join(r,Zn,Pd);if(!await Ur.default.pathExists(e))return[];let s=(await Ur.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 Ur.default.stat(Hr.default.join(e,`${i}.json`));return{id:i,mtime:a.mtimeMs}}))).sort((i,a)=>a.mtime-i.mtime).map(i=>i.id)}async function ei(r,e=20){let t=await no(r),s=[];for(let n of t.slice(0,e))try{let i=await Vr(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){ro.warn({runId:n,err:i},"Failed to read run result \u2014 skipping")}return s}async function Td(r,e){let t=so(Hr.default.join(r,Zn),e);if(!await Ur.default.pathExists(t))throw new oe(`Run result not found for runId "${e}".`,t,"RESULT_NOT_FOUND");await Ur.default.remove(t),ro.info({runId:e},"Run result deleted")}var Hr,Ur,ro,Zn,Pd,rn=b(()=>{"use strict";m();Hr=x(require("path")),Ur=x(require("fs-extra"));Id();re();F();ze();ro=C("result-store"),Zn="results",Pd="runs"});function kd(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&&!By.has(n)),s=[...t];for(let n=0;n<t.length-1;n++)s.push(`${t[n]}_${t[n+1]}`);return s}function Uy(r){return(0,Ad.createHash)("md5").update(r).digest().readUInt32LE(0)%io}var Ad,ri,io,By,ti,$d=b(()=>{"use strict";m();Ad=require("crypto"),ri=require("fs-extra"),io=256,By=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"]);ti=class{constructor(e){this.vocabPath=e}vocabPath;vocab={docCount:0,termDocFreq:{}};dirty=!1;async load(){try{this.vocab=await(0,ri.readJson)(this.vocabPath)}catch{this.vocab={docCount:0,termDocFreq:{}}}}async save(){this.dirty&&(await(0,ri.outputJson)(this.vocabPath,this.vocab,{spaces:0}),this.dirty=!1)}addDocument(e){let t=new Set(kd(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=kd(e);if(t.length===0)return new Array(io).fill(0);let s={};for(let o of t)s[o]=(s[o]??0)+1;let n=new Array(io).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=Uy(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 _d(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 Od=b(()=>{"use strict";m()});var ds,us,Ld=b(()=>{"use strict";m();ds=require("fs-extra");Od();us=class{constructor(e,t=500){this.filePath=e;this.maxEntries=t}filePath;maxEntries;documents=[];dirty=!1;async load(){if(await(0,ds.pathExists)(this.filePath))try{let e=await(0,ds.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,ds.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=_d(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 Vy(r,e){let t=`${r.toLowerCase().trim()}|${ao(e)}`;return(0,Dd.createHash)("sha256").update(t).digest("hex").slice(0,16)}function ao(r){if(!r)return"";try{let e=new URL(r),t=e.pathname.replace(/\/\d+/g,"/*");return`${e.hostname}${t}`}catch{return r}}function Gy(r,e,t){let s=e+t;if(s===0)return r;let n=e/s;return r*(1+.05*n)}function zy(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 Dd,Hy,si,Nd=b(()=>{"use strict";m();Dd=require("crypto"),Hy=2,si=class{constructor(e,t){this.store=e;this.embedder=t}store;embedder;ingest(e,t,s){let n=Vy(e,s),i=ao(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=ao(t),a=`${e} ${i}`,o=this.embedder.embed(a),l=this.store.search(o,s*2,n).map(u=>({...u,score:Gy(u.score,u.metadata.successCount,u.metadata.failCount)}));return l.sort((u,d)=>d.score-u.score),l.slice(0,s).map(zy)}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>=Hy){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 qy(r,e){let t=`${r.toLowerCase().trim()}|${ni(e)}`;return(0,Fd.createHash)("sha256").update(t).digest("hex").slice(0,16)}function ni(r){return r.replace(/\d+ms/g,"Nms").replace(/\d+/g,"N").replace(/["'][^"']*["']/g,"'...'").replace(/\s+/g," ").trim().slice(0,200)}function Ky(r){if(!r)return"";try{let e=new URL(r);return`${e.hostname}${e.pathname.replace(/\/\d+/g,"/*")}`}catch{return r}}function Wy(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 Fd,ii,Md=b(()=>{"use strict";m();Fd=require("crypto"),ii=class{constructor(e,t){this.store=e;this.embedder=t}store;embedder;ingest(e){let t=qy(e.instruction,e.error),s=Ky(e.url),n=`${e.instruction} ${ni(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:ni(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} ${ni(t)}`,a=this.embedder.embed(i);return this.store.search(a,s,n).map(Wy)}get size(){return this.store.size}}});function Xy(r,e){let t=`${r}|${e}`;return(0,Bd.createHash)("sha256").update(t).digest("hex").slice(0,16)}function Jy(r){return r.replace(/\d+ms/g,"Nms").replace(/\d+/g,"N").replace(/["'][^"']*["']/g,"'...'").replace(/\s+/g," ").trim().slice(0,200)}function jd(r){if(!r)return"";try{let e=new URL(r);return`${e.hostname}${e.pathname.replace(/\/\d+/g,"/*")}`}catch{return r}}function Yy(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 Bd,ai,Ud=b(()=>{"use strict";m();Bd=require("crypto"),ai=class{constructor(e,t){this.store=e;this.embedder=t}store;embedder;record(e,t,s){let n=Jy(e),i=jd(t),a=Xy(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=jd(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(Yy)}get size(){return this.store.size}}});var ps,Hd,oo,oi,Vd=b(()=>{"use strict";m();ps=require("path"),Hd=require("fs-extra");$d();Ld();Nd();Md();Ud();F();oo=C("rag"),oi=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 si(t,e),this.healingCorpus=new ii(s,e),this.errorCatalog=new ai(n,e)}static async create(e,t){let s=(0,ps.join)(e,"results",".rag");await(0,Hd.ensureDir)(s),oo.info({ragDir:s},"Initializing RAG manager");let n=new ti((0,ps.join)(s,"idf-vocab.json"));await n.load();let i=new us((0,ps.join)(s,"code-corpus.json"),t.codeCorpus.maxEntries),a=new us((0,ps.join)(s,"healing-corpus.json"),t.healingCorpus.maxEntries),o=new us((0,ps.join)(s,"error-catalog.json"),t.errorCatalog.maxEntries);return await Promise.all([i.load(),a.load(),o.load()]),oo.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()]),oo.debug("RAG corpora persisted")}getStats(){return{codeCorpus:this.codeStore.size,healingCorpus:this.healingStore.size,errorCatalog:this.errorStore.size,idfVocab:this.embedder.documentCount}}}});function Zy(r){let e=[];for(let t of Qy){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 ew(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=tw(s,c[1].toLowerCase());l>i&&(i=l,a=o)}}if(i>.3)return a}}}function tw(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 zd(r,e,t){let s=Zy(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 Gd.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=Bn(n).interactiveElements.split(`
694
+ `).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=ew(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 Gd.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 Gd,Qy,qd=b(()=>{"use strict";m();La();F();Gd=C("proactive-checker"),Qy=[{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 rw(r){if(!await ci.default.pathExists(r))return r;let e=wr.default.dirname(r),t=wr.default.extname(r),s=wr.default.basename(r,t);for(let n=1;n<1e3;n++){let i=wr.default.join(e,`${s} (${n})${t}`);if(!await ci.default.pathExists(i))return i}return r}var wr,ci,wt,Kt,li,Kd=b(()=>{"use strict";m();wr=x(require("path")),ci=x(require("fs-extra")),wt=require("playwright");F();Kt=C("browser-manager");li=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"?wt.firefox:e==="webkit"?wt.webkit:wt.chromium).launch({headless:t.headless});return this.browsers.set(e,i),Kt.info({browser:e,headless:t.headless},"Browser launched"),i}async newContext(e,t,s,n){let i=t.device&&wt.devices[t.device]?wt.devices[t.device]:null;t.device&&!i&&Kt.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 ci.default.ensureDir(n);let u=c.suggestedFilename()||"download",d=wr.default.basename(u).replace(/[^a-zA-Z0-9._-]+/g,"_")||"download",p=await rw(wr.default.join(n,d));await c.saveAs(p),this.capturedDownloads.get(o)?.push(p),Kt.info({file:wr.default.basename(p)},"Download captured")}catch(u){Kt.debug({err:u},"Failed to capture download")}})();this.pendingDownloads.get(o)?.push(l)})),await o.addInitScript(()=>{let c=`
695
695
  outline: 3px solid #3b82f6 !important;
696
696
  outline-offset: 3px !important;
697
697
  box-shadow: 0 0 0 6px rgba(59,130,246,0.20) !important;
698
698
  transition: outline 0.08s ease, box-shadow 0.08s ease !important;
699
- `,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 qt.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){qt.debug({err:i},"Tracing stop failed \u2014 ignoring")}await e.close().catch(i=>{qt.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(),qt.debug({browser:e},"Browser closed")}catch(s){qt.warn({err:s,browser:e},"Error closing browser")}this.browsers.clear()}get openBrowserCount(){return this.browsers.size}}});var Fd,Wy,ni,Md=b(()=>{"use strict";m();F();Fd=C("healing-budget"),Wy=[/timeout/i,/ECONNREFUSED/i,/ENOTFOUND/i,/ETIMEDOUT/i,/net::ERR/i,/ERR_NAME_NOT_RESOLVED/i,/DNS/i,/socket hang up/i],ni=class{constructor(e){this.dailyBudget=e}dailyBudget;spent=0;healFailures=new Map;pageFailures=new Map;shouldHeal(e){if(this.spent>=this.dailyBudget)return Fd.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,Fd.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 Wy.some(t=>t.test(e))}}});var jd,ii,ai,Bd=b(()=>{"use strict";m();jd=require("crypto");zn();F();ii=C("healing-report"),ai=class{events=[];record(e){let t={id:(0,jd.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),ii.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 rd(e,s),ii.info({runId:t,count:this.events.length},"Healing report written")}catch(n){ii.error({err:n,runId:t},"Failed to write healing report")}for(let n of this.events)try{await sd(e,n)}catch(i){ii.warn({err:i,eventId:n.id},"Failed to append pending healing event")}}}});function Xy(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 Ud(r){switch(r){case"passed":return"passed";case"failed":return"failed";case"skipped":return"skipped";default:return"broken"}}function Jy(r){return r==null?"\u2014":r<1e3?`${Math.round(r)}ms`:`${(r/1e3).toFixed(2)}s`}function Hd(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 Yy(r){return r==null?"#94a3b8":r>=90?"#10b981":r>=50?"#f59e0b":"#ef4444"}function no(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):Jy(d),a=(u,d)=>{let p=Yy(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
+ `,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 wt.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 Kt.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){Kt.debug({err:i},"Tracing stop failed \u2014 ignoring")}await e.close().catch(i=>{Kt.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(),Kt.debug({browser:e},"Browser closed")}catch(s){Kt.warn({err:s,browser:e},"Error closing browser")}this.browsers.clear()}get openBrowserCount(){return this.browsers.size}}});var Wd,sw,ui,Xd=b(()=>{"use strict";m();F();Wd=C("healing-budget"),sw=[/timeout/i,/ECONNREFUSED/i,/ENOTFOUND/i,/ETIMEDOUT/i,/net::ERR/i,/ERR_NAME_NOT_RESOLVED/i,/DNS/i,/socket hang up/i],ui=class{constructor(e){this.dailyBudget=e}dailyBudget;spent=0;healFailures=new Map;pageFailures=new Map;shouldHeal(e){if(this.spent>=this.dailyBudget)return Wd.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,Wd.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 sw.some(t=>t.test(e))}}});var Jd,di,pi,Yd=b(()=>{"use strict";m();Jd=require("crypto");Yn();F();di=C("healing-report"),pi=class{events=[];record(e){let t={id:(0,Jd.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),di.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 md(e,s),di.info({runId:t,count:this.events.length},"Healing report written")}catch(n){di.error({err:n,runId:t},"Failed to write healing report")}for(let n of this.events)try{await gd(e,n)}catch(i){di.warn({err:i,eventId:n.id},"Failed to append pending healing event")}}}});function nw(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 Qd(r){switch(r){case"passed":return"passed";case"failed":return"failed";case"skipped":return"skipped";default:return"broken"}}function iw(r){return r==null?"\u2014":r<1e3?`${Math.round(r)}ms`:`${(r/1e3).toFixed(2)}s`}function Zd(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 aw(r){return r==null?"#94a3b8":r>=90?"#10b981":r>=50?"#f59e0b":"#ef4444"}function lo(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):iw(d),a=(u,d)=>{let p=aw(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`
700
700
  <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;">
701
701
  <div style="position:relative;width:58px;height:58px;">
702
702
  <svg width="58" height="58" viewBox="0 0 60 60" style="transform:rotate(-90deg)">
@@ -708,12 +708,12 @@ ${i}`,"result","INVALID_RESULT")}return n.data}async function Za(r){let e=jr.def
708
708
  </div>
709
709
  <div style="font-size:9px;font-weight:700;color:${p};margin-top:4px;">${h}</div>
710
710
  <div style="font-size:9px;color:#64748b;margin-top:1px;text-align:center;">${d}</div>
711
- </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=Hd(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>`},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=Zd(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;">
712
712
  <div style="font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:${j};opacity:.8;margin-bottom:3px;">${k}</div>
713
713
  <div style="font-size:14px;font-weight:800;color:${j};font-variant-numeric:tabular-nums;">${i(v,u[v])}</div>
714
714
  </div>`}).join(""),g=u.lighthouseError?"":`
715
715
  <div style="border-top:1px solid #f1f5f9;padding:10px 16px;display:grid;grid-template-columns:1fr 1fr;gap:3px 24px;">
716
- ${n.map(({key:v,abbr:k,label:T})=>{let P=Hd(v,u[v]);return`<div style="display:flex;align-items:center;gap:5px;font-size:9px;color:#64748b;padding:1px 0;">
716
+ ${n.map(({key:v,abbr:k,label:T})=>{let P=Zd(v,u[v]);return`<div style="display:flex;align-items:center;gap:5px;font-size:9px;color:#64748b;padding:1px 0;">
717
717
  <span style="color:${P==="good"?"#10b981":P==="average"?"#f59e0b":P==="poor"?"#ef4444":"#94a3b8"};font-size:11px;line-height:1;flex-shrink:0;">\u25CF</span>
718
718
  <span style="font-weight:700;color:#475569;">${k}</span>
719
719
  <span style="opacity:.7;">${T}</span>
@@ -786,17 +786,17 @@ ${i}`,"result","INVALID_RESULT")}return n.data}async function Za(r){let e=jr.def
786
786
  <p style="font-size:9px;color:#cbd5e1;text-align:center;margin-top:16px;">Powered by Google Lighthouse \xB7 Desktop preset \xB7 Assuremind Studio</p>
787
787
  </div>
788
788
  </body>
789
- </html>`}var Me,Vd,wr,so,oi,Gd=b(()=>{"use strict";m();Me=x(require("path")),Vd=require("crypto"),wr=x(require("fs-extra"));F();so=C("allure-reporter"),oi=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(`
790
- `);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(()=>{}),so.debug({logFile:s},"Log file copied to Allure results")}catch{so.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++;so.info({dir:this.resultsDir,written:n},"Allure results written")}async writeTestResult(e,t,s){let n=(0,Vd.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:Xy(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=no(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=no(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=no(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:Ud(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:Ud(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 Zy(){try{let e=(0,Kd.createRequire)(y??__filename).resolve("allure-commandline/package.json"),t=ds.default.dirname(e);return ds.default.join(t,"dist","bin",ao?"allure.bat":"allure")}catch{return ds.default.resolve(__dirname,ao?"../node_modules/allure-commandline/dist/bin/allure.bat":"../node_modules/.bin/allure")}}async function Wd(r,e){let t=ds.default.join(r,"results","allure-results",e),s=ds.default.join(r,"results","allure-report",e);if(!await io.default.pathExists(t))return rn.debug({resultsDir:t},"No allure-results dir for run \u2014 skipping report generation"),!1;if((await io.default.readdir(t)).length===0)return rn.debug({runId:e},"allure-results is empty \u2014 skipping report generation"),!1;try{return await Qy(ew,["generate",t,"--output",s,"--clean","--single-file"],ao?{shell:!0}:{}),rn.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")?rn.warn("Allure report generation skipped \u2014 Java is not installed. Install Java (https://adoptium.net) to enable Allure HTML reports."):rn.warn({err:a,runId:e},"Allure report generation failed"),!1}}var ds,io,zd,qd,Kd,Qy,rn,ao,ew,Xd=b(()=>{"use strict";m();ds=x(require("path")),io=x(require("fs-extra")),zd=require("child_process"),qd=require("util"),Kd=require("module");F();Qy=(0,qd.promisify)(zd.execFile),rn=C("allure-generator"),ao=process.platform==="win32";ew=Zy()});function ci(){return[{category:"person",methods:[{name:"fullName",example:E.faker.person.fullName()},{name:"firstName",example:E.faker.person.firstName()},{name:"lastName",example:E.faker.person.lastName()},{name:"middleName",example:E.faker.person.middleName()},{name:"sex",example:E.faker.person.sex()},{name:"prefix",example:E.faker.person.prefix()},{name:"suffix",example:E.faker.person.suffix()},{name:"jobTitle",example:E.faker.person.jobTitle()},{name:"jobArea",example:E.faker.person.jobArea()},{name:"jobType",example:E.faker.person.jobType()},{name:"bio",example:E.faker.person.bio()}]},{category:"internet",methods:[{name:"email",example:E.faker.internet.email()},{name:"userName",example:E.faker.internet.username()},{name:"password",example:E.faker.internet.password()},{name:"url",example:E.faker.internet.url()},{name:"domainName",example:E.faker.internet.domainName()},{name:"domainWord",example:E.faker.internet.domainWord()},{name:"ip",example:E.faker.internet.ip()},{name:"ipv6",example:E.faker.internet.ipv6()},{name:"mac",example:E.faker.internet.mac()},{name:"userAgent",example:E.faker.internet.userAgent()},{name:"emoji",example:E.faker.internet.emoji()}]},{category:"phone",methods:[{name:"number",example:E.faker.phone.number()},{name:"imei",example:E.faker.phone.imei()}]},{category:"location",methods:[{name:"streetAddress",example:E.faker.location.streetAddress()},{name:"street",example:E.faker.location.street()},{name:"city",example:E.faker.location.city()},{name:"state",example:E.faker.location.state()},{name:"zipCode",example:E.faker.location.zipCode()},{name:"country",example:E.faker.location.country()},{name:"countryCode",example:E.faker.location.countryCode()},{name:"county",example:E.faker.location.county()},{name:"latitude",example:String(E.faker.location.latitude())},{name:"longitude",example:String(E.faker.location.longitude())},{name:"timeZone",example:E.faker.location.timeZone()},{name:"buildingNumber",example:E.faker.location.buildingNumber()}]},{category:"company",methods:[{name:"name",example:E.faker.company.name()},{name:"catchPhrase",example:E.faker.company.catchPhrase()},{name:"buzzPhrase",example:E.faker.company.buzzPhrase()},{name:"buzzNoun",example:E.faker.company.buzzNoun()},{name:"buzzVerb",example:E.faker.company.buzzVerb()},{name:"buzzAdjective",example:E.faker.company.buzzAdjective()}]},{category:"finance",methods:[{name:"accountNumber",example:E.faker.finance.accountNumber()},{name:"accountName",example:E.faker.finance.accountName()},{name:"creditCardNumber",example:E.faker.finance.creditCardNumber()},{name:"creditCardCVV",example:E.faker.finance.creditCardCVV()},{name:"currencyCode",example:E.faker.finance.currencyCode()},{name:"currencyName",example:E.faker.finance.currencyName()},{name:"amount",example:E.faker.finance.amount()},{name:"iban",example:E.faker.finance.iban()},{name:"bic",example:E.faker.finance.bic()},{name:"bitcoinAddress",example:E.faker.finance.bitcoinAddress()},{name:"transactionType",example:E.faker.finance.transactionType()}]},{category:"date",methods:[{name:"past",example:E.faker.date.past().toISOString()},{name:"future",example:E.faker.date.future().toISOString()},{name:"recent",example:E.faker.date.recent().toISOString()},{name:"soon",example:E.faker.date.soon().toISOString()},{name:"birthdate",example:E.faker.date.birthdate().toISOString()},{name:"month",example:E.faker.date.month()},{name:"weekday",example:E.faker.date.weekday()}]},{category:"lorem",methods:[{name:"word",example:E.faker.lorem.word()},{name:"words",example:E.faker.lorem.words()},{name:"sentence",example:E.faker.lorem.sentence()},{name:"sentences",example:E.faker.lorem.sentences()},{name:"paragraph",example:E.faker.lorem.paragraph()},{name:"slug",example:E.faker.lorem.slug()},{name:"lines",example:E.faker.lorem.lines(1)}]},{category:"string",methods:[{name:"uuid",example:E.faker.string.uuid()},{name:"alphanumeric",example:E.faker.string.alphanumeric(10)},{name:"numeric",example:E.faker.string.numeric(6)},{name:"alpha",example:E.faker.string.alpha(8)},{name:"nanoid",example:E.faker.string.nanoid()},{name:"hexadecimal",example:E.faker.string.hexadecimal({length:8})},{name:"sample",example:E.faker.string.sample(12)}]},{category:"number",methods:[{name:"int",example:String(E.faker.number.int({max:9999}))},{name:"float",example:String(E.faker.number.float({max:100,fractionDigits:2}))}]},{category:"datatype",methods:[{name:"boolean",example:String(E.faker.datatype.boolean())}]},{category:"image",methods:[{name:"avatar",example:E.faker.image.avatar()},{name:"url",example:E.faker.image.url()}]},{category:"color",methods:[{name:"human",example:E.faker.color.human()},{name:"rgb",example:E.faker.color.rgb()},{name:"hex",example:E.faker.color.rgb({format:"hex"})}]},{category:"commerce",methods:[{name:"productName",example:E.faker.commerce.productName()},{name:"price",example:E.faker.commerce.price()},{name:"department",example:E.faker.commerce.department()},{name:"productDescription",example:E.faker.commerce.productDescription().slice(0,60)+"..."},{name:"isbn",example:E.faker.commerce.isbn()}]},{category:"vehicle",methods:[{name:"vehicle",example:E.faker.vehicle.vehicle()},{name:"manufacturer",example:E.faker.vehicle.manufacturer()},{name:"model",example:E.faker.vehicle.model()},{name:"vin",example:E.faker.vehicle.vin()},{name:"vrm",example:E.faker.vehicle.vrm()}]},{category:"system",methods:[{name:"fileName",example:E.faker.system.fileName()},{name:"mimeType",example:E.faker.system.mimeType()},{name:"fileExt",example:E.faker.system.fileExt()},{name:"filePath",example:E.faker.system.filePath()},{name:"semver",example:E.faker.system.semver()}]}]}function Ur(r,e){let t=E.faker[r],s=tw[`${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 E,tw,oo=b(()=>{"use strict";m();E=require("@faker-js/faker");tw={"internet.userName":"username"}});function Yd(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=Jd[t];if(s)return Ur(s[0],s[1])}return null}var Jd,Qd=b(()=>{"use strict";m();oo();Jd={};for(let r of ci())for(let e of r.methods){let t=`${r.category}_${e.name}`.toUpperCase();Jd[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(rw,"g"),(n,i)=>{if(i==="BASE_URL")return t;let a=Yd(i);return a!==null?a:e[i]??`{{${i}}}`}),s}var rw,co=b(()=>{"use strict";m();Qd();rw="\\{\\{([A-Z0-9_]+)\\}\\}"});async function wt(r,e,t,s="domcontentloaded",n){t&&(e.setDefaultTimeout(t),e.setDefaultNavigationTimeout(t));let i=t?lo.expect.configure({timeout:t}):lo.expect,a=n??{setVariable:()=>{},getVariable:()=>{}},c=new sw("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 lo,sw,li=b(()=>{"use strict";m();lo=require("@playwright/test"),sw=Object.getPrototypeOf(async function(){}).constructor});async function nw(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 sn(r,e,t){let s=r.url(),n=await r.title().catch(()=>""),i={maxElements:120,maxTextLen:80},a=await r.evaluate(Zd,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 nw(d,c);if(p===null)continue;let g=await d.evaluate(Zd,i).catch(()=>[])??[];for(let f of g)o.push(`${f} frame="${p}"`)}catch{}}let l=[...a,...o].slice(0,120).join(`
791
- `),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 Zd,ep=b(()=>{"use strict";m();Zd=({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 iw(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 po(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")??"":"",Ce=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:Ce,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=iw(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:uo});let s=await r.screenshot({type:"png",fullPage:!1});await r.evaluate(i=>document.getElementById(i)?.remove(),uo);let n=t.map(i=>i.description).join(`
792
- `);return{screenshot:s,elements:t,elementMap:n}}async function mo(r){await r.evaluate(e=>document.getElementById(e)?.remove(),uo).catch(()=>{})}var uo,tp=b(()=>{"use strict";m();uo="__testassuremind_som__"});function rp(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(`
793
- `).map(t=>t.trim()).filter(t=>t.length>0&&t.startsWith("await"))}var $e,ui,sp=b(()=>{"use strict";m();ep();tp();kt();co();F();li();Ar();$e=C("self-healing"),ui=class{constructor(e,t,s,n=!1){this.provider=e;this.maxLevel=t;this.ragManager=s;this.healAssertionLocators=n}provider;maxLevel;ragManager;healAssertionLocators;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 po(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 mo(n)}let o=await sn(n,s,i),c="";if(this.ragManager)try{let d=this.ragManager.healingCorpus.retrieve(e.instruction,t.error,2);d.length>0&&(c=`
789
+ </html>`}var Me,ep,br,co,mi,tp=b(()=>{"use strict";m();Me=x(require("path")),ep=require("crypto"),br=x(require("fs-extra"));F();co=C("allure-reporter"),mi=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 br.default.ensureDir(this.resultsDir);let t=[`Environment=${this.environment.toUpperCase()}`,"Framework=Assuremind"].join(`
790
+ `);await br.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(()=>{}),co.debug({logFile:s},"Log file copied to Allure results")}catch{co.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++;co.info({dir:this.resultsDir,written:n},"Allure results written")}async writeTestResult(e,t,s){let n=(0,ep.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:nw(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=lo(t.caseName,l,"performance"),S=`${n}-perf.html`;await br.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=lo(t.caseName,l,"accessibility"),S=`${n}-a11y.html`;await br.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=lo(t.caseName,l,"seo"),S=`${n}-seo.html`;await br.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:Qd(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 br.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:Qd(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 br.default.copy(e,t,{overwrite:!0})}}});function cw(){try{let e=(0,np.createRequire)(y??__filename).resolve("allure-commandline/package.json"),t=ms.default.dirname(e);return ms.default.join(t,"dist","bin",po?"allure.bat":"allure")}catch{return ms.default.resolve(__dirname,po?"../node_modules/allure-commandline/dist/bin/allure.bat":"../node_modules/.bin/allure")}}async function ip(r,e){let t=ms.default.join(r,"results","allure-results",e),s=ms.default.join(r,"results","allure-report",e);if(!await uo.default.pathExists(t))return sn.debug({resultsDir:t},"No allure-results dir for run \u2014 skipping report generation"),!1;if((await uo.default.readdir(t)).length===0)return sn.debug({runId:e},"allure-results is empty \u2014 skipping report generation"),!1;try{return await ow(lw,["generate",t,"--output",s,"--clean","--single-file"],po?{shell:!0}:{}),sn.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")?sn.warn("Allure report generation skipped \u2014 Java is not installed. Install Java (https://adoptium.net) to enable Allure HTML reports."):sn.warn({err:a,runId:e},"Allure report generation failed"),!1}}var ms,uo,rp,sp,np,ow,sn,po,lw,ap=b(()=>{"use strict";m();ms=x(require("path")),uo=x(require("fs-extra")),rp=require("child_process"),sp=require("util"),np=require("module");F();ow=(0,sp.promisify)(rp.execFile),sn=C("allure-generator"),po=process.platform==="win32";lw=cw()});function gi(){return[{category:"person",methods:[{name:"fullName",example:E.faker.person.fullName()},{name:"firstName",example:E.faker.person.firstName()},{name:"lastName",example:E.faker.person.lastName()},{name:"middleName",example:E.faker.person.middleName()},{name:"sex",example:E.faker.person.sex()},{name:"prefix",example:E.faker.person.prefix()},{name:"suffix",example:E.faker.person.suffix()},{name:"jobTitle",example:E.faker.person.jobTitle()},{name:"jobArea",example:E.faker.person.jobArea()},{name:"jobType",example:E.faker.person.jobType()},{name:"bio",example:E.faker.person.bio()}]},{category:"internet",methods:[{name:"email",example:E.faker.internet.email()},{name:"userName",example:E.faker.internet.username()},{name:"password",example:E.faker.internet.password()},{name:"url",example:E.faker.internet.url()},{name:"domainName",example:E.faker.internet.domainName()},{name:"domainWord",example:E.faker.internet.domainWord()},{name:"ip",example:E.faker.internet.ip()},{name:"ipv6",example:E.faker.internet.ipv6()},{name:"mac",example:E.faker.internet.mac()},{name:"userAgent",example:E.faker.internet.userAgent()},{name:"emoji",example:E.faker.internet.emoji()}]},{category:"phone",methods:[{name:"number",example:E.faker.phone.number()},{name:"imei",example:E.faker.phone.imei()}]},{category:"location",methods:[{name:"streetAddress",example:E.faker.location.streetAddress()},{name:"street",example:E.faker.location.street()},{name:"city",example:E.faker.location.city()},{name:"state",example:E.faker.location.state()},{name:"zipCode",example:E.faker.location.zipCode()},{name:"country",example:E.faker.location.country()},{name:"countryCode",example:E.faker.location.countryCode()},{name:"county",example:E.faker.location.county()},{name:"latitude",example:String(E.faker.location.latitude())},{name:"longitude",example:String(E.faker.location.longitude())},{name:"timeZone",example:E.faker.location.timeZone()},{name:"buildingNumber",example:E.faker.location.buildingNumber()}]},{category:"company",methods:[{name:"name",example:E.faker.company.name()},{name:"catchPhrase",example:E.faker.company.catchPhrase()},{name:"buzzPhrase",example:E.faker.company.buzzPhrase()},{name:"buzzNoun",example:E.faker.company.buzzNoun()},{name:"buzzVerb",example:E.faker.company.buzzVerb()},{name:"buzzAdjective",example:E.faker.company.buzzAdjective()}]},{category:"finance",methods:[{name:"accountNumber",example:E.faker.finance.accountNumber()},{name:"accountName",example:E.faker.finance.accountName()},{name:"creditCardNumber",example:E.faker.finance.creditCardNumber()},{name:"creditCardCVV",example:E.faker.finance.creditCardCVV()},{name:"currencyCode",example:E.faker.finance.currencyCode()},{name:"currencyName",example:E.faker.finance.currencyName()},{name:"amount",example:E.faker.finance.amount()},{name:"iban",example:E.faker.finance.iban()},{name:"bic",example:E.faker.finance.bic()},{name:"bitcoinAddress",example:E.faker.finance.bitcoinAddress()},{name:"transactionType",example:E.faker.finance.transactionType()}]},{category:"date",methods:[{name:"past",example:E.faker.date.past().toISOString()},{name:"future",example:E.faker.date.future().toISOString()},{name:"recent",example:E.faker.date.recent().toISOString()},{name:"soon",example:E.faker.date.soon().toISOString()},{name:"birthdate",example:E.faker.date.birthdate().toISOString()},{name:"month",example:E.faker.date.month()},{name:"weekday",example:E.faker.date.weekday()}]},{category:"lorem",methods:[{name:"word",example:E.faker.lorem.word()},{name:"words",example:E.faker.lorem.words()},{name:"sentence",example:E.faker.lorem.sentence()},{name:"sentences",example:E.faker.lorem.sentences()},{name:"paragraph",example:E.faker.lorem.paragraph()},{name:"slug",example:E.faker.lorem.slug()},{name:"lines",example:E.faker.lorem.lines(1)}]},{category:"string",methods:[{name:"uuid",example:E.faker.string.uuid()},{name:"alphanumeric",example:E.faker.string.alphanumeric(10)},{name:"numeric",example:E.faker.string.numeric(6)},{name:"alpha",example:E.faker.string.alpha(8)},{name:"nanoid",example:E.faker.string.nanoid()},{name:"hexadecimal",example:E.faker.string.hexadecimal({length:8})},{name:"sample",example:E.faker.string.sample(12)}]},{category:"number",methods:[{name:"int",example:String(E.faker.number.int({max:9999}))},{name:"float",example:String(E.faker.number.float({max:100,fractionDigits:2}))}]},{category:"datatype",methods:[{name:"boolean",example:String(E.faker.datatype.boolean())}]},{category:"image",methods:[{name:"avatar",example:E.faker.image.avatar()},{name:"url",example:E.faker.image.url()}]},{category:"color",methods:[{name:"human",example:E.faker.color.human()},{name:"rgb",example:E.faker.color.rgb()},{name:"hex",example:E.faker.color.rgb({format:"hex"})}]},{category:"commerce",methods:[{name:"productName",example:E.faker.commerce.productName()},{name:"price",example:E.faker.commerce.price()},{name:"department",example:E.faker.commerce.department()},{name:"productDescription",example:E.faker.commerce.productDescription().slice(0,60)+"..."},{name:"isbn",example:E.faker.commerce.isbn()}]},{category:"vehicle",methods:[{name:"vehicle",example:E.faker.vehicle.vehicle()},{name:"manufacturer",example:E.faker.vehicle.manufacturer()},{name:"model",example:E.faker.vehicle.model()},{name:"vin",example:E.faker.vehicle.vin()},{name:"vrm",example:E.faker.vehicle.vrm()}]},{category:"system",methods:[{name:"fileName",example:E.faker.system.fileName()},{name:"mimeType",example:E.faker.system.mimeType()},{name:"fileExt",example:E.faker.system.fileExt()},{name:"filePath",example:E.faker.system.filePath()},{name:"semver",example:E.faker.system.semver()}]}]}function Gr(r,e){let t=E.faker[r],s=uw[`${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 E,uw,mo=b(()=>{"use strict";m();E=require("@faker-js/faker");uw={"internet.userName":"username"}});function cp(r){switch(r){case"FAKE_FIRST_NAME":return Gr("person","firstName");case"FAKE_LAST_NAME":return Gr("person","lastName");case"FAKE_AGE":return String(Math.floor(Math.random()*63)+18);case"FAKE_EMAIL":return Gr("internet","email");case"FAKE_PHONE":return Gr("phone","number");case"FAKE_PASSWORD":return Gr("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=op[t];if(s)return Gr(s[0],s[1])}return null}var op,lp=b(()=>{"use strict";m();mo();op={};for(let r of gi())for(let e of r.methods){let t=`${r.category}_${e.name}`.toUpperCase();op[t]=[r.category,e.name]}});function Wt(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(dw,"g"),(n,i)=>{if(i==="BASE_URL")return t;let a=cp(i);return a!==null?a:e[i]??`{{${i}}}`}),s}var dw,go=b(()=>{"use strict";m();lp();dw="\\{\\{([A-Z0-9_]+)\\}\\}"});async function bt(r,e,t,s="domcontentloaded",n){t&&(e.setDefaultTimeout(t),e.setDefaultNavigationTimeout(t));let i=t?fo.expect.configure({timeout:t}):fo.expect,a=n??{setVariable:()=>{},getVariable:()=>{}},c=new pw("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 fo,pw,fi=b(()=>{"use strict";m();fo=require("@playwright/test"),pw=Object.getPrototypeOf(async function(){}).constructor});async function mw(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 nn(r,e,t){let s=r.url(),n=await r.title().catch(()=>""),i={maxElements:120,maxTextLen:80},a=await r.evaluate(up,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 mw(d,c);if(p===null)continue;let g=await d.evaluate(up,i).catch(()=>[])??[];for(let f of g)o.push(`${f} frame="${p}"`)}catch{}}let l=[...a,...o].slice(0,120).join(`
791
+ `),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 up,dp=b(()=>{"use strict";m();up=({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 gw(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 yo(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")??"":"",Ce=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:Ce,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=gw(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:ho});let s=await r.screenshot({type:"png",fullPage:!1});await r.evaluate(i=>document.getElementById(i)?.remove(),ho);let n=t.map(i=>i.description).join(`
792
+ `);return{screenshot:s,elements:t,elementMap:n}}async function wo(r){await r.evaluate(e=>document.getElementById(e)?.remove(),ho).catch(()=>{})}var ho,pp=b(()=>{"use strict";m();ho="__testassuremind_som__"});function mp(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(`
793
+ `).map(t=>t.trim()).filter(t=>t.length>0&&t.startsWith("await"))}var $e,hi,gp=b(()=>{"use strict";m();dp();pp();At();go();F();fi();$r();$e=C("self-healing"),hi=class{constructor(e,t,s,n=!1){this.provider=e;this.maxLevel=t;this.ragManager=s;this.healAssertionLocators=n}provider;maxLevel;ragManager;healAssertionLocators;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 bt(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 yo(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=Wt(De(p),i,a);return await bt(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 wo(n)}let o=await nn(n,s,i),c="";if(this.ragManager)try{let d=this.ragManager.healingCorpus.retrieve(e.instruction,t.error,2);d.length>0&&(c=`
794
794
 
795
795
  Similar past fixes that worked:
796
796
  `+d.map((p,g)=>` ${g+1}. Error: ${p.error}
797
797
  Fix: ${p.healedCode}`).join(`
798
- `),$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 sn(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 sn(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=rp(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 po(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 mo(t),$e.debug({stepId:e.id,err:i},"Level 4 SoM failed"),null}}async level5Decompose(e,t,s,n,i,a){let o=await sn(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=rp(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(`
799
- `),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 lw(r){for(let e of aw)if(e.test(r)){for(let t of cw)if(t.test(r))return"assertion-locator-missing";return"assertion"}for(let e of ow)if(e.test(r))return"infra";return"assertion"}async function fo(r,e,t){let s=Date.now(),n={...t.variables,...Object.fromEntries(t.sharedVariables)},i=r.generatedCode.includes("{{");i&&Xe.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&&Xe.warn({stepId:r.id,before:r.generatedCode,after:a},"Variable interpolation result"),!a.trim()&&r.stepType!=="mock")return Xe.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),Xe.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 uw(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 np(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){Xe.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);Xe.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 np(e,t,r.id,"fail"));let S=lw(g);if(S==="assertion")return Xe.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 Xe.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{}Xe.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 Xe.info({stepId:r.id,reason:v.reason},"Healing skipped"),{...bt(r,"failed",a,Date.now()-s,g,h),...f?{auditUrl:f}:{}};let k=new ui(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 Xe.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);Xe.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 np(r,e,t,s){try{await r.waitForLoadState("load",{timeout:5e3}).catch(()=>{});let n=go.default.join(e.rootDir,"results","screenshots"),i=`${e.runId}_${e.caseId}_${t}_${s}.png`,a=go.default.join(n,i);return await r.screenshot({path:a,fullPage:!0}),a}catch(n){Xe.debug({err:n},"Screenshot capture failed");return}}function uw(r,e){return Promise.race([r,new Promise((t,s)=>setTimeout(()=>s(new Error(`Step timed out after ${e}ms`)),e))])}var go,Xe,aw,ow,cw,ip=b(()=>{"use strict";m();go=x(require("path"));co();li();sp();Ar();F();li();Xe=C("executor"),aw=[/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],ow=[/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],cw=[/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 ap(r){await r.addInitScript(dw)}var dw,op=b(()=>{"use strict";m();dw=`(function () {
798
+ `),$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=Wt(De(l),i,a);return await bt(u,n),{code:u,level:2,strategy:"regenerate"}}async level2ApiRegenerate(e,t,s,n,i){let a=await nn(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=Wt(De(c),n,i);return await bt(l,s),{code:l,level:2,strategy:"regenerate"}}async level3MultiSelector(e,t,s,n,i,a){let o=await nn(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=mp(l);for(let d of u)try{let p=Wt(De(d),i,a);return await bt(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 yo(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=Wt(De(a),s,n);return await bt(o,t),{code:o,level:4,strategy:"visual"}}catch(i){return await wo(t),$e.debug({stepId:e.id,err:i},"Level 4 SoM failed"),null}}async level5Decompose(e,t,s,n,i,a){let o=await nn(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=mp(l),d=[];for(let p of u){let g=Wt(De(p),i,a);await bt(g,n),d.push(g)}return{code:d.join(`
799
+ `),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 ww(r){for(let e of fw)if(e.test(r)){for(let t of yw)if(t.test(r))return"assertion-locator-missing";return"assertion"}for(let e of hw)if(e.test(r))return"infra";return"assertion"}async function vo(r,e,t){let s=Date.now(),n={...t.variables,...Object.fromEntries(t.sharedVariables)},i=r.generatedCode.includes("{{");i&&Xe.warn({stepId:r.id,variableKeys:Object.keys(n),variableCount:Object.keys(n).length},"Interpolating variables into step code");let a=Wt(r.generatedCode,n,t.config.baseUrl);if(i&&Xe.warn({stepId:r.id,before:r.generatedCode,after:a},"Variable interpolation result"),!a.trim()&&r.stepType!=="mock")return Xe.warn({stepId:r.id},"Step has no generated code \u2014 skipping"),vt(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=vt(r,"passed",a,Date.now()-s);return await e.unrouteAll().catch(()=>{}),g}catch(g){let f=g instanceof Error?g.message:String(g);return vt(r,"failed",a,Date.now()-s,f)}let o={setVariable:(g,f)=>{t.sharedVariables.set(g,f),Xe.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 bw(bt(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 fp(e,t,r.id,"pass");return{...vt(r,"passed",a,Date.now()-s,void 0,S),navigatedToUrl:f,auditUrl:h}}return{...vt(r,"passed",a,Date.now()-s),navigatedToUrl:f,auditUrl:h}}catch(f){if(d=f,g<c){Xe.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);Xe.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 fp(e,t,r.id,"fail"));let S=ww(g);if(S==="assertion")return Xe.info({stepId:r.id,error:g},"Assertion failure detected \u2014 NOT healing (possible application bug)"),{...vt(r,"failed",a,Date.now()-s,g,h),...f?{auditUrl:f}:{}};if(S==="assertion-locator-missing"&&!t.config.healing.healAssertionLocators)return Xe.info({stepId:r.id,error:g},"Assertion locator not found \u2014 healing disabled (enable healing.healAssertionLocators to fix locators inside assertions)"),{...vt(r,"failed",a,Date.now()-s,g,h),...f?{auditUrl:f}:{}};if(!t.config.healing.enabled)return{...vt(r,"failed",a,Date.now()-s,g,h),...f?{auditUrl:f}:{}};if(t.ragManager)try{t.ragManager.errorCatalog.record(g,e.url())}catch{}Xe.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 Xe.info({stepId:r.id,reason:v.reason},"Healing skipped"),{...vt(r,"failed",a,Date.now()-s,g,h),...f?{auditUrl:f}:{}};let k=new hi(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 Xe.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)"),vt(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);Xe.warn({stepId:r.id,error:P},"Healing threw an error"),t.budget.recordHealFailure(r.id)}return{...vt(r,"failed",a,Date.now()-s,g,h),...f?{auditUrl:f}:{}}}}function vt(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 fp(r,e,t,s){try{await r.waitForLoadState("load",{timeout:5e3}).catch(()=>{});let n=bo.default.join(e.rootDir,"results","screenshots"),i=`${e.runId}_${e.caseId}_${t}_${s}.png`,a=bo.default.join(n,i);return await r.screenshot({path:a,fullPage:!0}),a}catch(n){Xe.debug({err:n},"Screenshot capture failed");return}}function bw(r,e){return Promise.race([r,new Promise((t,s)=>setTimeout(()=>s(new Error(`Step timed out after ${e}ms`)),e))])}var bo,Xe,fw,hw,yw,hp=b(()=>{"use strict";m();bo=x(require("path"));go();fi();gp();$r();F();fi();Xe=C("executor"),fw=[/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],hw=[/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],yw=[/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 yp(r){await r.addInitScript(vw)}var vw,wp=b(()=>{"use strict";m();vw=`(function () {
800
800
  if (window.__tm_highlighter_installed__) return;
801
801
  window.__tm_highlighter_installed__ = true;
802
802
 
@@ -938,13 +938,13 @@ Similar past fixes that worked:
938
938
  }
939
939
  }, { capture: true, passive: true });
940
940
 
941
- })();`});async function lp(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=ho.default.resolve(r,e.path);if(!await nn.default.pathExists(t))throw new Error(`Data file not found: ${t}`);let s=await nn.default.readJson(t);if(!Array.isArray(s))throw new Error("JSON data file must contain an array of objects");return cp.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=ho.default.resolve(r,e.path);if(!await nn.default.pathExists(t))throw new Error(`Data file not found: ${t}`);let n=(await nn.default.readFile(t,"utf8")).trim().split(`
942
- `).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 cp.info({path:t,rows:a.length},"Loaded CSV data rows"),a}default:return[]}}var ho,nn,cp,up=b(()=>{"use strict";m();ho=x(require("path")),nn=x(require("fs-extra"));F();cp=C("data-loader")});function dp(r){return Ot.default.join(r,".assuremind","visual-regression.json")}function pp(r,e){return Ot.default.join(r,"results","visual-diffs",e,"summary.json")}function pw(r){return Ot.default.join(r,"results","visual-diffs")}function mp(r){return Ot.default.join(r,"baselines")}async function an(r){let e=dp(r);if(!await Wt.default.pathExists(e))return{...yo};try{let t=await ue(e);return{...yo,...t}}catch{return{...yo}}}async function gp(r,e){await W(dp(r),e)}async function di(r,e){await W(pp(r,e.runId),e)}async function pi(r,e){return await ue(pp(r,e))}async function fp(r){let e=pw(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 hp(r,e,t,s){let n=await pi(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 di(r,n),n}async function yp(r,e){let t=await pi(r,e);for(let s of t.diffs)(s.status==="failed"||s.status==="new")&&(s.status="approved");return await di(r,t),t}async function wp(r){let e=mp(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 bp(r,e){let t=mp(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,yo,wo=b(()=>{"use strict";m();Ot=x(require("path")),Wt=x(require("fs-extra"));ze();yo={enabled:!1,defaultThreshold:.5,fullPage:!0,maskSelectors:[]}});async function vp(r){let e=await it.default.readFile(r);return new Promise((t,s)=>{new mi.PNG().parse(e,(i,a)=>{i?s(i):t(a)})})}function mw(r){return mi.PNG.sync.write(r)}async function Sp(r,e,t,s={}){let{threshold:n=.1,diffThreshold:i=.5}=s;if(!await it.default.pathExists(r))return await it.default.ensureDir(ps.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([vp(r),vp(e)]);if(o.width!==c.width||o.height!==c.height){await it.default.ensureDir(ps.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 mi.PNG({width:l,height:u}),p=(0,xp.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(ps.default.dirname(t));let S=mw(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 Ep(r,e,t,s,n,i){return ps.default.join(r,"baselines",e,t,`${s}-${n}-${i.width}x${i.height}.png`)}function Cp(r,e,t,s,n){return ps.default.join(r,"results","visual-diffs",e,`${t}-${s}-${n.width}x${n.height}-diff.png`)}var xp,mi,it,ps,Ip=b(()=>{"use strict";m();xp=x(require("pixelmatch")),mi=require("pngjs"),it=x(require("fs-extra")),ps=x(require("path"))});var Rp=Ct((JI,Pp)=>{"use strict";m();Pp.exports=r=>{if(typeof r!="string")throw new TypeError("Expected a string");return r.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}});var kp=Ct((QI,Tp)=>{"use strict";m();var ms=1e3,gs=ms*60,fs=gs*60,Hr=fs*24,gw=Hr*7,fw=Hr*365.25;Tp.exports=function(r,e){e=e||{};var t=typeof r;if(t==="string"&&r.length>0)return hw(r);if(t==="number"&&isFinite(r))return e.long?ww(r):yw(r);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(r))};function hw(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*fw;case"weeks":case"week":case"w":return t*gw;case"days":case"day":case"d":return t*Hr;case"hours":case"hour":case"hrs":case"hr":case"h":return t*fs;case"minutes":case"minute":case"mins":case"min":case"m":return t*gs;case"seconds":case"second":case"secs":case"sec":case"s":return t*ms;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return t;default:return}}}}function yw(r){var e=Math.abs(r);return e>=Hr?Math.round(r/Hr)+"d":e>=fs?Math.round(r/fs)+"h":e>=gs?Math.round(r/gs)+"m":e>=ms?Math.round(r/ms)+"s":r+"ms"}function ww(r){var e=Math.abs(r);return e>=Hr?gi(r,e,Hr,"day"):e>=fs?gi(r,e,fs,"hour"):e>=gs?gi(r,e,gs,"minute"):e>=ms?gi(r,e,ms,"second"):r+" ms"}function gi(r,e,t,s){var n=e>=t*1.5;return Math.round(r/t)+" "+s+(n?"s":"")}});var bo=Ct((eP,Ap)=>{"use strict";m();function bw(r){t.debug=t,t.default=t,t.coerce=c,t.disable=a,t.enable=n,t.enabled=o,t.humanize=kp(),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 Ce=S[T];j=M.call(I,Ce),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}Ap.exports=bw});var $p=Ct((He,fi)=>{"use strict";m();He.formatArgs=xw;He.save=Sw;He.load=Ew;He.useColors=vw;He.storage=Cw();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 vw(){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 xw(r){if(r[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+r[0]+(this.useColors?"%c ":" ")+"+"+fi.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 Sw(r){try{r?He.storage.setItem("debug",r):He.storage.removeItem("debug")}catch{}}function Ew(){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 Cw(){try{return localStorage}catch{}}fi.exports=bo()(He);var{formatters:Iw}=fi.exports;Iw.j=function(r){try{return JSON.stringify(r)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}}});var Op=Ct((sP,_p)=>{"use strict";m();_p.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 Np=Ct((iP,Dp)=>{"use strict";m();var Pw=require("os"),Lp=require("tty"),at=Op(),{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 vo(r){return r===0?!1:{level:r,hasBasic:!0,has256:r>=2,has16m:r>=3}}function xo(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=Pw.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 Rw(r){let e=xo(r,r&&r.isTTY);return vo(e)}Dp.exports={supportsColor:Rw,stdout:vo(xo(!0,Lp.isatty(1))),stderr:vo(xo(!0,Lp.isatty(2)))}});var Mp=Ct((Se,yi)=>{"use strict";m();var Tw=require("tty"),hi=require("util");Se.init=Dw;Se.log=_w;Se.formatArgs=Aw;Se.save=Ow;Se.load=Lw;Se.useColors=kw;Se.destroy=hi.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=Np();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 kw(){return"colors"in Se.inspectOpts?!!Se.inspectOpts.colors:Tw.isatty(process.stderr.fd)}function Aw(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(`
941
+ })();`});async function vp(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=xo.default.resolve(r,e.path);if(!await an.default.pathExists(t))throw new Error(`Data file not found: ${t}`);let s=await an.default.readJson(t);if(!Array.isArray(s))throw new Error("JSON data file must contain an array of objects");return bp.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=xo.default.resolve(r,e.path);if(!await an.default.pathExists(t))throw new Error(`Data file not found: ${t}`);let n=(await an.default.readFile(t,"utf8")).trim().split(`
942
+ `).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 bp.info({path:t,rows:a.length},"Loaded CSV data rows"),a}default:return[]}}var xo,an,bp,xp=b(()=>{"use strict";m();xo=x(require("path")),an=x(require("fs-extra"));F();bp=C("data-loader")});function Sp(r){return Lt.default.join(r,".assuremind","visual-regression.json")}function Ep(r,e){return Lt.default.join(r,"results","visual-diffs",e,"summary.json")}function xw(r){return Lt.default.join(r,"results","visual-diffs")}function Cp(r){return Lt.default.join(r,"baselines")}async function on(r){let e=Sp(r);if(!await Xt.default.pathExists(e))return{...So};try{let t=await ue(e);return{...So,...t}}catch{return{...So}}}async function Ip(r,e){await W(Sp(r),e)}async function yi(r,e){await W(Ep(r,e.runId),e)}async function wi(r,e){return await ue(Ep(r,e))}async function Pp(r){let e=xw(r);if(!await Xt.default.pathExists(e))return[];let t=await Xt.default.readdir(e,{withFileTypes:!0}),s=[];for(let n of t){if(!n.isDirectory())continue;let i=Lt.default.join(e,n.name,"summary.json");if(await Xt.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 Rp(r,e,t,s){let n=await wi(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 yi(r,n),n}async function Tp(r,e){let t=await wi(r,e);for(let s of t.diffs)(s.status==="failed"||s.status==="new")&&(s.status="approved");return await yi(r,t),t}async function kp(r){let e=Cp(r);if(!await Xt.default.pathExists(e))return[];let t=[];async function s(n){let i=await Xt.default.readdir(n,{withFileTypes:!0});for(let a of i){let o=Lt.default.join(n,a.name);if(a.isDirectory())await s(o);else if(a.name.endsWith(".png")){let c=Lt.default.relative(e,o).replace(/\\/g,"/"),l=c.split("/"),u=await Xt.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 Ap(r,e){let t=Cp(r),s=Lt.default.resolve(e);if(!s.startsWith(Lt.default.resolve(t)))throw new Error("Path is outside baselines directory");await Xt.default.remove(s)}var Lt,Xt,So,Eo=b(()=>{"use strict";m();Lt=x(require("path")),Xt=x(require("fs-extra"));ze();So={enabled:!1,defaultThreshold:.5,fullPage:!0,maskSelectors:[]}});async function $p(r){let e=await it.default.readFile(r);return new Promise((t,s)=>{new bi.PNG().parse(e,(i,a)=>{i?s(i):t(a)})})}function Sw(r){return bi.PNG.sync.write(r)}async function Op(r,e,t,s={}){let{threshold:n=.1,diffThreshold:i=.5}=s;if(!await it.default.pathExists(r))return await it.default.ensureDir(gs.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([$p(r),$p(e)]);if(o.width!==c.width||o.height!==c.height){await it.default.ensureDir(gs.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 bi.PNG({width:l,height:u}),p=(0,_p.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(gs.default.dirname(t));let S=Sw(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 Lp(r,e,t,s,n,i){return gs.default.join(r,"baselines",e,t,`${s}-${n}-${i.width}x${i.height}.png`)}function Dp(r,e,t,s,n){return gs.default.join(r,"results","visual-diffs",e,`${t}-${s}-${n.width}x${n.height}-diff.png`)}var _p,bi,it,gs,Np=b(()=>{"use strict";m();_p=x(require("pixelmatch")),bi=require("pngjs"),it=x(require("fs-extra")),gs=x(require("path"))});var Mp=It((iP,Fp)=>{"use strict";m();Fp.exports=r=>{if(typeof r!="string")throw new TypeError("Expected a string");return r.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}});var Bp=It((oP,jp)=>{"use strict";m();var fs=1e3,hs=fs*60,ys=hs*60,zr=ys*24,Ew=zr*7,Cw=zr*365.25;jp.exports=function(r,e){e=e||{};var t=typeof r;if(t==="string"&&r.length>0)return Iw(r);if(t==="number"&&isFinite(r))return e.long?Rw(r):Pw(r);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(r))};function Iw(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*Cw;case"weeks":case"week":case"w":return t*Ew;case"days":case"day":case"d":return t*zr;case"hours":case"hour":case"hrs":case"hr":case"h":return t*ys;case"minutes":case"minute":case"mins":case"min":case"m":return t*hs;case"seconds":case"second":case"secs":case"sec":case"s":return t*fs;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return t;default:return}}}}function Pw(r){var e=Math.abs(r);return e>=zr?Math.round(r/zr)+"d":e>=ys?Math.round(r/ys)+"h":e>=hs?Math.round(r/hs)+"m":e>=fs?Math.round(r/fs)+"s":r+"ms"}function Rw(r){var e=Math.abs(r);return e>=zr?vi(r,e,zr,"day"):e>=ys?vi(r,e,ys,"hour"):e>=hs?vi(r,e,hs,"minute"):e>=fs?vi(r,e,fs,"second"):r+" ms"}function vi(r,e,t,s){var n=e>=t*1.5;return Math.round(r/t)+" "+s+(n?"s":"")}});var Co=It((lP,Up)=>{"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=Bp(),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 Ce=S[T];j=M.call(I,Ce),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}Up.exports=Tw});var Hp=It((He,xi)=>{"use strict";m();He.formatArgs=Aw;He.save=$w;He.load=_w;He.useColors=kw;He.storage=Ow();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 kw(){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 Aw(r){if(r[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+r[0]+(this.useColors?"%c ":" ")+"+"+xi.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 $w(r){try{r?He.storage.setItem("debug",r):He.storage.removeItem("debug")}catch{}}function _w(){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 Ow(){try{return localStorage}catch{}}xi.exports=Co()(He);var{formatters:Lw}=xi.exports;Lw.j=function(r){try{return JSON.stringify(r)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}}});var Gp=It((pP,Vp)=>{"use strict";m();Vp.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 Kp=It((gP,qp)=>{"use strict";m();var Dw=require("os"),zp=require("tty"),at=Gp(),{env:xe}=process,vr;at("no-color")||at("no-colors")||at("color=false")||at("color=never")?vr=0:(at("color")||at("colors")||at("color=true")||at("color=always"))&&(vr=1);"FORCE_COLOR"in xe&&(xe.FORCE_COLOR==="true"?vr=1:xe.FORCE_COLOR==="false"?vr=0:vr=xe.FORCE_COLOR.length===0?1:Math.min(parseInt(xe.FORCE_COLOR,10),3));function Io(r){return r===0?!1:{level:r,hasBasic:!0,has256:r>=2,has16m:r>=3}}function Po(r,e){if(vr===0)return 0;if(at("color=16m")||at("color=full")||at("color=truecolor"))return 3;if(at("color=256"))return 2;if(r&&!e&&vr===void 0)return 0;let t=vr||0;if(xe.TERM==="dumb")return t;if(process.platform==="win32"){let s=Dw.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 Nw(r){let e=Po(r,r&&r.isTTY);return Io(e)}qp.exports={supportsColor:Nw,stdout:Io(Po(!0,zp.isatty(1))),stderr:Io(Po(!0,zp.isatty(2)))}});var Xp=It((Se,Ei)=>{"use strict";m();var Fw=require("tty"),Si=require("util");Se.init=Gw;Se.log=Uw;Se.formatArgs=jw;Se.save=Hw;Se.load=Vw;Se.useColors=Mw;Se.destroy=Si.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=Kp();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 Mw(){return"colors"in Se.inspectOpts?!!Se.inspectOpts.colors:Fw.isatty(process.stderr.fd)}function jw(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(`
943
943
  `).join(`
944
- `+i),r.push(n+"m+"+yi.exports.humanize(this.diff)+"\x1B[0m")}else r[0]=$w()+e+" "+r[0]}function $w(){return Se.inspectOpts.hideDate?"":new Date().toISOString()+" "}function _w(...r){return process.stderr.write(hi.formatWithOptions(Se.inspectOpts,...r)+`
945
- `)}function Ow(r){r?process.env.DEBUG=r:delete process.env.DEBUG}function Lw(){return process.env.DEBUG}function Dw(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]]}yi.exports=bo()(Se);var{formatters:Fp}=yi.exports;Fp.o=function(r){return this.inspectOpts.colors=this.useColors,hi.inspect(r,this.inspectOpts).split(`
946
- `).map(e=>e.trim()).join(" ")};Fp.O=function(r){return this.inspectOpts.colors=this.useColors,hi.inspect(r,this.inspectOpts)}});var jp=Ct((cP,So)=>{"use strict";m();typeof process>"u"||process.type==="renderer"||process.browser===!0||process.__nwjs?So.exports=$p():So.exports=Mp()});function wi(r){if(!r)throw new Error("name must be non-empty")}function Nw(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 Ee,Vp,Bp,Eo,Up,Hp,xi,Si,on,Ei,bi,vi,Gp=b(()=>{"use strict";m();Ee=typeof performance<"u"&&performance;Bp=process.hrtime,Eo=function(){var r=Bp();return r[0]*1e9+r[1]},Up=Eo(),Vp=function(){return(Eo()-Up)/1e6};Hp=Ee&&Ee.now?function(){return Ee.now()}:Vp;Ee&&Ee.mark&&Ee.measure&&Ee.getEntriesByName&&Ee.getEntriesByType&&Ee.clearMarks&&Ee.clearMeasures&&Ee.clearResourceTimings?(xi=function(r){wi(r),Ee.mark("start "+r)},Si=function(r){wi(r),Ee.mark("end "+r);var e=Ee.measure(r,"start "+r,"end "+r);if(e)return e;var t=Ee.getEntriesByName(r);return t[t.length-1]},on=function(){return Ee.getEntriesByType("measure")},Ei=function(){Ee.clearMarks(),Ee.clearMeasures()}):(bi={},vi=[],xi=function(r){wi(r);var e=Hp();bi["$"+r]=e},Si=function(r){wi(r);var e=Hp(),t=bi["$"+r];if(!t)throw new Error("no known mark: "+r);var s={startTime:t,name:r,duration:e-t,entryType:"measure"};return Nw(vi,s),s},on=function(){return vi},Ei=function(){bi={},vi=[]})});var ws,Kp,xr,vr,hs,ys,Co,zp,Mw,qp,bs,ce,Io=b(()=>{"use strict";m();ws=x(require("process"),1),Kp=require("events"),xr=x(jp(),1);Gp();vr=ws.default.platform==="win32",hs=ws.default.browser,ys={red:hs?"crimson":1,yellow:hs?"gold":3,cyan:hs?"darkturquoise":6,green:hs?"forestgreen":2,blue:hs?"steelblue":4,magenta:hs?"palevioletred":5};xr.default.colors=[ys.cyan,ys.green,ys.blue,ys.magenta];Co=class extends Kp.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])}},zp={},Mw=25,bs=class r{static _logToStdErr(e,t){r.loggerfn(e)(...t)}static loggerfn(e){e=`LH:${e}`;let t=zp[e];return t||(t=(0,xr.default)(e),zp[e]=t,e.endsWith("error")?t.color=ys.red:e.endsWith("warn")&&(t.color=ys.yellow)),t}static setLevel(e){switch(qp=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=!ws.default||ws.default.browser?1/0:ws.default.stdout.columns,i=t.method||"?????",a=n-i.length-e.length-Mw,o=t.params&&i!=="IO.read"?JSON.stringify(t.params).substr(0,a):"";r._logToStdErr(`${e}:${s||""}`,[i,o])}static isVerbose(){return qp==="verbose"}static time({msg:e,id:t,args:s=[]},n="log"){xi(t),r[n]("status",e,...s)}static timeEnd({msg:e,id:t,args:s=[]},n="verbose"){r[n]("statusEnd",e,...s),Si(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"}};bs.events=new Co;bs.takeTimeEntries=()=>{let r=on();return Ei(),r};bs.getTimeEntries=()=>on();ce=bs});var Jp=Ct((mP,Xp)=>{"use strict";m();var Wp=require("fs"),Po;function jw(){try{return Wp.statSync("/.dockerenv"),!0}catch{return!1}}function Bw(){try{return Wp.readFileSync("/proc/self/cgroup","utf8").includes("docker")}catch{return!1}}Xp.exports=()=>(Po===void 0&&(Po=jw()||Bw()),Po)});var Zp=Ct((fP,Ro)=>{"use strict";m();var Uw=require("os"),Hw=require("fs"),Yp=Jp(),Qp=()=>{if(process.platform!=="linux")return!1;if(Uw.release().toLowerCase().includes("microsoft"))return!Yp();try{return Hw.readFileSync("/proc/version","utf8").toLowerCase().includes("microsoft")?!Yp():!1}catch{return!1}};process.env.__IS_WSL_TEST__?Ro.exports=Qp:Ro.exports=Qp()});function vt(r,e){return typeof r>"u"?e:r}async function sm(r){return new Promise(e=>setTimeout(e,r))}function Lt(){return rm.default?"wsl":process.platform}function nm(){switch(Lt()){case"darwin":case"linux":return zw();case"wsl":process.env.TEMP=To(`${process.env.PATH}`);case"win32":return qw();default:throw new cn}}function Vw(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 im(r=""){if(/[a-z]:\\/iu.test(r))return r;try{return Pi.default.execFileSync("wslpath",["-w",r]).toString().trim()}catch{return Vw(r)}}function Ri(r,e){try{return Pi.default.execFileSync("wslpath",["-u",r]).toString().trim()}catch{return e}}function Gw(r){let t=/\/mnt\/([a-z])\/Users\/([^\/:]+)\/AppData\//.exec(r)||[];return`/mnt/${t[1]}/Users/${t[2]}/AppData/Local`}function To(r){let t=/\/([a-z])\/Users\/([^\/:]+)\/AppData\//.exec(r)||[];return Ri(`${t[1]}:\\Users\\${t[2]}\\AppData\\Local`,Gw(r))}function zw(){return Pi.default.execSync("mktemp -d -t lighthouse.XXXXXXX").toString().trim()}function qw(){let r=process.env.TEMP||process.env.TMP||(process.env.SystemRoot||process.env.windir)+"\\temp",e=Math.floor(Math.random()*9e7+1e7),t=(0,em.join)(r,"lighthouse."+e);return(0,tm.mkdirSync)(t,{recursive:!0}),t}var em,Pi,tm,rm,vs,Ci,Ii,cn,ln,ko=b(()=>{"use strict";m();em=require("path"),Pi=x(require("child_process"),1),tm=require("fs"),rm=x(Zp(),1);vs=class extends Error{constructor(e="Unexpected error",t){return super(),this.message=e,this.code=t,this.stack=new Error().stack,this}},Ci=class extends vs{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"}},Ii=class extends vs{constructor(){super(...arguments),this.message="userDataDir must be false or a path.",this.code="ERR_LAUNCHER_INVALID_USER_DATA_DIRECTORY"}},cn=class extends vs{constructor(){super(...arguments),this.message=`Platform ${Lt()} is not supported.`,this.code="ERR_LAUNCHER_UNSUPPORTED_PLATFORM"}},ln=class extends vs{constructor(){super(...arguments),this.message="No Chrome installations found.",this.code="ERR_LAUNCHER_NOT_INSTALLED"}}});var Ti={};Q(Ti,{darwin:()=>om,darwinFast:()=>_o,linux:()=>Kw,win32:()=>cm,wsl:()=>Ww});function _o(){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 om()[0]}function om(){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=Oo();s&&t.push(s),(0,Ss.execSync)(`${e} -dump | grep -i 'google chrome\\( canary\\)\\?\\.app' | awk '{$1=""; print $0}'`).toString().split($o).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,xs.default)(process.env.HOME||(0,Ao.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,xs.default)(process.env.LIGHTHOUSE_CHROMIUM_PATH)),weight:150}),process.env.CHROME_PATH&&i.unshift({regex:new RegExp((0,xs.default)(process.env.CHROME_PATH)),weight:151}),lm(t,i)}function Oo(){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=Oo();if(e&&r.push(e),[ot.default.join((0,Ao.homedir)(),".local/share/applications/"),"/usr/share/applications/"].forEach(i=>{r=r.concat(Jw(i))}),["google-chrome-stable","google-chrome","chromium-browser","chromium"].forEach(i=>{try{let a=(0,Ss.execFileSync)("which",[i],{stdio:"pipe"}).toString().split($o)[0];Sr(a)&&r.push(a)}catch{}}),!r.length)throw new Ci;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,xs.default)(process.env.LIGHTHOUSE_CHROMIUM_PATH)),weight:100}),process.env.CHROME_PATH&&n.unshift({regex:new RegExp((0,xs.default)(process.env.CHROME_PATH)),weight:101}),lm(Xw(r.filter(Boolean)),n)}function Ww(){return process.env.LOCALAPPDATA=To(`${process.env.PATH}`),process.env.PROGRAMFILES=Ri("C:/Program Files","/mnt/c/Program Files"),process.env["PROGRAMFILES(X86)"]=Ri("C:/Program Files (x86)","/mnt/c/Program Files (x86)"),cm()}function cm(){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=Oo();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 lm(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 am.default.accessSync(r),!0}catch{return!1}}function Xw(r){return Array.from(new Set(r))}function Jw(r){let e=/(^[^ ]+).*/,t="^Exec=/.*/(google-chrome|chrome|chromium)-.*",s=[];if(Sr(r)){let n;try{n=(0,Ss.execSync)(`grep -ER "${t}" ${r} | awk -F '=' '{print $2}'`,{stdio:"pipe"})}catch{n=(0,Ss.execSync)(`grep -Er "${t}" ${r} | awk -F '=' '{print $2}'`,{stdio:"pipe"})}n=n.toString().split($o).map(i=>i.replace(e,"$1")),n.forEach(i=>Sr(i)&&s.push(i))}return s}var am,ot,Ao,Ss,xs,$o,um=b(()=>{"use strict";m();am=x(require("fs"),1),ot=x(require("path"),1),Ao=require("os"),Ss=require("child_process"),xs=x(Rp(),1);Io();ko();$o=/\r?\n/});function pm(){return new Promise((r,e)=>{let t=(0,dm.createServer)();t.listen(0),t.once("listening",()=>{let{port:s}=t.address();t.close(()=>r(s))}),t.once("error",e)})}var dm,mm=b(()=>{"use strict";m();dm=require("http");});var Lo,gm=b(()=>{"use strict";m();Lo=["--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 rb(r={}){r.handleSIGINT=vt(r.handleSIGINT,!0);let e=new un(r);r.handleSIGINT&&Es.size===0&&process.on(fm,hm),Es.add(e),await e.launch();let t=()=>{Es.delete(e),Es.size===0&&process.removeListener(fm,hm),e.kill()};return{pid:e.pid,port:e.port,process:e.chromeProcess,remoteDebuggingPipes:e.remoteDebuggingPipes,kill:t}}function sb(){let r=un.getFirstInstallation();if(!r)throw new ln;return r}function wm(){let r=[];for(let e of Es)try{e.kill(),Es.delete(e)}catch(t){r.push(t)}return r}var Yw,ym,ki,Qw,Zw,fm,eb,tb,Es,hm,un,bm=b(()=>{"use strict";m();Yw=x(require("fs"),1),ym=x(require("net"),1);um();mm();gm();ko();ki=require("child_process");Io();Qw=Lt()==="wsl",Zw=Lt()==="win32",fm="SIGINT",eb=130,tb=new Set(["darwin","linux","win32","wsl"]),Es=new Set,hm=()=>{wm(),process.exit(eb)};un=class r{constructor(e={},t={}){if(this.opts=e,this.tmpDirandPidFileReady=!1,this.remoteDebuggingPipes=null,this.fs=t.fs||Yw,this.spawn=t.spawn||ki.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 Ii;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?[]:Lo.slice();return this.port&&e.push(`--remote-debugging-port=${this.port}`),!this.ignoreDefaultFlags&&Lt()==="linux"&&e.push("--disable-setuid-sandbox"),this.useDefaultProfile||e.push(`--user-data-dir=${Qw?im(this.userDataDir):this.userDataDir}`),process.env.HEADLESS&&e.push("--headless"),e.push(...this.chromeFlags),e.push(this.startingUrl),e}static defaultFlags(){return Lo.slice()}static getFirstInstallation(){return Lt()==="darwin"?_o():Ti[Lt()]()[0]}static getInstallations(){return Ti[Lt()]()}makeTmpDir(){return nm()}prepare(){let e=Lt();if(!tb.has(e))throw new cn;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 ln;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 pm()),ce.verbose("ChromeLauncher",`Launching with command:
947
- "${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=ym.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)}sm(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(Zw){let e=(0,ki.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 vm={};Q(vm,{Launcher:()=>un,getChromePath:()=>sb,killAll:()=>wm,launch:()=>rb});var xm=b(()=>{"use strict";m();bm()});var Pm={};Q(Pm,{getActiveRunId:()=>nb,runTests:()=>Fo,stopActiveRun:()=>No});function Cm(r){return r.steps.length===0?!1:r.steps.every(e=>(e.stepType??tt(e.instruction))==="api")}function Im(r){return r.type==="api"}function Ai(r){return r.type==="audit"||r.type==="performance"}function No(){$i&&$i()}function nb(){return Do}async function Fo(r,e,t,s){let n=(0,Em.randomUUID)(),i=new Date().toISOString(),a=Xt.default.join(r,"tests"),o=!1;Do=n,$i=()=>{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 Nc(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 si,g=new ai,f=new oi(r,n,c),h=await an(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 ab(a,e);I.length===0&&le.warn({runConfig:e},"No tests matched the run config");let v=await ob(r,e.env),k=new Map,T=[];for(let _ of I){if(_.testCase.dataSource)try{let Z=await lp(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 Ld(_,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 ti.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 ni(t.healing.dailyBudget),Ce=t.browsers,lt=[],Ve=T.length>0&&T.every(({suite:_,testCase:Z})=>(Im(_)||Cm(Z))&&!Ai(_));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 Ce)Ye.set(_,null);else{let _=await Promise.all(Ce.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 Ce){let Z=Ye.get(_)??null;for(let ie of T)Fs.push({browserName:_,browser:Z,...ie})}let sr=(await cb(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:Ce.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 ib(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(Ce.length>1)for(let _ of Ce){let Z=sr.filter(we=>we.browserName===_),ie=Sm(Z,_);lt.push(...ie)}else{let _=Sm(sr);lt.push(..._)}let Ms=new Date().toISOString(),Ie=lb(n,i,Ms,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 hd(r,Ie),t.reporting.allure&&(await f.writeResults(Ie),Wd(r,n).catch(_=>{le.warn({err:_ instanceof Error?_.message:String(_),runId:n},"Allure report generation failed")})),t.reporting.json){let _=Xt.default.join(r,"results",`run-${n}.json`);await Er.default.ensureDir(Xt.default.dirname(_)),await Er.default.writeJson(_,Ie,{spaces:2})}if(h.enabled&&S.length>0&&(await di(r,{runId:n,timestamp:Ms,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{$i=null,Do=null,await p.closeAll(),o&&s?.broadcast("run:stopped",{runId:n})}}async function ib(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=Im(t)||Cm(s),M=Ai(t)?{...a,screenshot:"off",video:"off",trace:"off"}:a,Ce=!J&&M.trace!=="off"?Xt.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,Xt.default.join(r,"results","videos"),Xt.default.join(r,"results","downloads",e)),Ve=await p.newPage(lt),await ap(Ve)}let Ye="passed",Fs=!1,Ft=[],sr,Ms=[],Ie=async be=>{let U=s.timeout??t.timeout??M.timeout,ut=U!==M.timeout?{...M,timeout:U}:M;try{await fo({...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 fo(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 Le=await Ve.screenshot({type:"jpeg",quality:60});g.broadcast("run:screenshot",{runId:e,caseId:k,stepId:Y.stepId,image:Le.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},Le=Tt(t.name),Mt=Tt(s.name),Ir=Ep(r,Le,Mt,U.id,n,ae),js=Cp(r,e,U.id,n,ae),Ze=await Sp(Ir,Y.screenshotPath,js,{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??js}),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:Ai(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(()=>(xm(),vm)),Le=ae.launch??ae.default?.launch,{chromium:Mt}=await import("playwright"),Ir=Mt.executablePath(),js=Xt.default.join(r,"results",".lh-profiles");await Er.default.ensureDir(js);for(let Ze=0;Ze<Qe.length;Ze++){let{s:Pr,idx:pc}=Qe[Ze],zr=Pr.auditUrl??Pr.navigatedToUrl;f?.("info",` Auditing: ${zr}`);let Ji=null,Yi=Xt.default.join(js,`audit-${Date.now()}-${Ze}`);try{await Er.default.ensureDir(Yi),Ji=await Le({chromePath:Ir,chromeFlags:["--headless","--no-sandbox","--disable-gpu"],userDataDir:Yi,logLevel:"silent"});let qr=(await Promise.race([q(zr,{port:Ji.port,output:"json",logLevel:"silent",onlyCategories:Y,disableStorageReset:!0,screenEmulation:{disabled:!0},throttlingMethod:"simulate",formFactor:"desktop"}),new Promise((Kr,Bt)=>setTimeout(()=>Bt(new Error("Lighthouse audit timed out after 60s")),6e4))]))?.lhr,mc=qr?.audits??{},gc=qr?.categories??{},nr=Kr=>{let Bt=mc[Kr]?.numericValue;return Bt!=null&&isFinite(Bt)?Bt:void 0},Qi=Kr=>{let Bt=gc[Kr]?.score;return Bt!=null?Math.round(Bt*100):void 0},fc=Kr=>(gc[Kr]?.auditRefs??[]).filter(Rr=>(Rr.weight??0)>0).map(Rr=>{let yn=mc[Rr.id],ir=yn?.score??null,Bs=ir!==null&&ir>0&&ir<1;return{id:Rr.id,title:yn?.title??Rr.id,passed:ir===1,partial:Bs||void 0,na:ir===null||void 0}}).sort((Rr,yn)=>{let ir=Bs=>Bs.na?3:Bs.passed?4:Bs.partial?1:0;return ir(Rr)-ir(yn)}),jt=Y.includes("performance"),hc=Y.includes("accessibility"),yc=Y.includes("seo"),dt={url:zr,stepIndex:pc,stepInstruction:Pr.instruction,score:jt?Qi("performance"):void 0,a11yScore:hc?Qi("accessibility"):void 0,seoScore:yc?Qi("seo"):void 0,fcp:jt?nr("first-contentful-paint"):void 0,lcp:jt?nr("largest-contentful-paint"):void 0,cls:jt?nr("cumulative-layout-shift"):void 0,ttfb:jt?nr("server-response-time"):void 0,tbt:jt?nr("total-blocking-time"):void 0,si:jt?nr("speed-index"):void 0,tti:jt?nr("interactive"):void 0,inp:jt?nr("interaction-to-next-paint"):void 0,a11yAudits:hc?fc("accessibility"):void 0,seoAudits:yc?fc("seo"):void 0};Ft.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(hn){let qr=hn instanceof Error?hn.message:String(hn);le.warn({url:zr,err:qr},"Lighthouse audit failed for URL"),f?.("warn",` Lighthouse failed for ${zr}: ${qr}`),Ft.push({url:zr,stepIndex:pc,stepInstruction:Pr.instruction,lighthouseError:qr})}finally{try{await Ji?.kill()}catch{}try{await Er.default.remove(Yi)}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 Le=new Set(Ft.map(Mt=>Mt.stepIndex));for(let{s:Mt,idx:Ir}of Qe)Le.has(Ir)||Ft.push({url:Mt.auditUrl??Mt.navigatedToUrl,stepIndex:Ir,stepInstruction:Mt.instruction,lighthouseError:`Lighthouse unavailable: ${ae}`})}f?.("info","------------------------------------")}Ai(t)&&Ft.length>0&&Ye==="passed"&&Ft.some(Le=>!Le.lighthouseError&&(Le.score!=null&&Le.score<50||Le.a11yScore!=null&&Le.a11yScore<50||Le.seoScore!=null&&Le.seoScore<50))&&(Ye="failed",f?.("warn"," Case FAILED: one or more Lighthouse scores below 50 (Poor threshold)"))}else!J&&n!=="chromium"&&(Ft=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||(sr=await Ve.video()?.path().catch(()=>{}))}finally{J||lt&&(await p.closeContext(lt,M,Ce),Ms=p.takeDownloads(lt),(M.video==="retain-on-failure"||M.video==="on-first-retry")&&Ye==="passed"&&sr&&await Er.default.remove(sr).catch(()=>{}),(M.trace==="retain-on-failure"||M.trace==="on-first-retry")&&Ye==="passed"&&Ce&&await Er.default.remove(Ce).catch(()=>{}))}let _,Z;if(!J){let be=M.video==="retain-on-failure"||M.video==="on-first-retry";_=M.video!=="off"&&sr?be&&Ye==="passed"?void 0:sr:void 0;let U=M.trace==="retain-on-failure"||M.trace==="on-first-retry";Z=M.trace==="off"||U&&Ye==="passed"?void 0:Ce}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:Ms,pageLoads:Ft}}}async function ab(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 We(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 ob(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 cb(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 Sm(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 lb(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 Xt,Em,Er,le,$i,Do,Mo=b(()=>{"use strict";m();Xt=x(require("path")),Em=require("crypto"),Er=x(require("fs-extra"));Ke();gt();pr();tn();gr();Ys();_d();Dd();Nd();Md();Bd();Gd();Xd();ip();op();up();Ar();wo();Ip();kt();F();le=C("runner");$i=null,Do=null});async function Rm(r){let e=r.rootDir;r.post("/run",async(t,s)=>{let n=mb.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 jo.info({runConfig:a},"Run requested via API"),Fo(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}),jo.info({runId:u.runId,status:u.status},"API-triggered run complete")}).catch(u=>{jo.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)=>(No(),s.status(202).send({status:"stopping"}))),r.get("/run",async(t,s)=>{let n=gb.safeParse(t.query);if(!n.success)return s.status(400).send({error:"Invalid query",details:n.error.issues});try{let i=await Wn(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,jo,ub,db,pb,mb,gb,Tm=b(()=>{"use strict";m();pe=require("zod");Mo();Te();tn();te();F();jo=C("routes/run"),ub=pe.z.enum(["off","on","only-on-failure"]),db=pe.z.enum(["off","on","on-first-retry","retain-on-failure"]),pb=pe.z.enum(["off","on","on-first-retry","retain-on-failure"]),mb=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:ub.optional(),video:db.optional(),trace:pb.optional(),device:pe.z.string().optional()}),gb=pe.z.object({limit:pe.z.coerce.number().int().positive().max(100).default(20)})});async function Bo(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),dn.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{dn.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):_i.default.load(d),e&&(e.openapi||e.swagger||e.paths)){a=!0,dn.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=_i.default.load(d);if(f&&typeof f=="object"&&(f.openapi||f.swagger||f.paths)){e=f,a=!0,dn.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.
944
+ `+i),r.push(n+"m+"+Ei.exports.humanize(this.diff)+"\x1B[0m")}else r[0]=Bw()+e+" "+r[0]}function Bw(){return Se.inspectOpts.hideDate?"":new Date().toISOString()+" "}function Uw(...r){return process.stderr.write(Si.formatWithOptions(Se.inspectOpts,...r)+`
945
+ `)}function Hw(r){r?process.env.DEBUG=r:delete process.env.DEBUG}function Vw(){return process.env.DEBUG}function Gw(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]]}Ei.exports=Co()(Se);var{formatters:Wp}=Ei.exports;Wp.o=function(r){return this.inspectOpts.colors=this.useColors,Si.inspect(r,this.inspectOpts).split(`
946
+ `).map(e=>e.trim()).join(" ")};Wp.O=function(r){return this.inspectOpts.colors=this.useColors,Si.inspect(r,this.inspectOpts)}});var Jp=It((yP,Ro)=>{"use strict";m();typeof process>"u"||process.type==="renderer"||process.browser===!0||process.__nwjs?Ro.exports=Hp():Ro.exports=Xp()});function Ci(r){if(!r)throw new Error("name must be non-empty")}function zw(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 Ee,em,Yp,To,Qp,Zp,Ri,Ti,cn,ki,Ii,Pi,tm=b(()=>{"use strict";m();Ee=typeof performance<"u"&&performance;Yp=process.hrtime,To=function(){var r=Yp();return r[0]*1e9+r[1]},Qp=To(),em=function(){return(To()-Qp)/1e6};Zp=Ee&&Ee.now?function(){return Ee.now()}:em;Ee&&Ee.mark&&Ee.measure&&Ee.getEntriesByName&&Ee.getEntriesByType&&Ee.clearMarks&&Ee.clearMeasures&&Ee.clearResourceTimings?(Ri=function(r){Ci(r),Ee.mark("start "+r)},Ti=function(r){Ci(r),Ee.mark("end "+r);var e=Ee.measure(r,"start "+r,"end "+r);if(e)return e;var t=Ee.getEntriesByName(r);return t[t.length-1]},cn=function(){return Ee.getEntriesByType("measure")},ki=function(){Ee.clearMarks(),Ee.clearMeasures()}):(Ii={},Pi=[],Ri=function(r){Ci(r);var e=Zp();Ii["$"+r]=e},Ti=function(r){Ci(r);var e=Zp(),t=Ii["$"+r];if(!t)throw new Error("no known mark: "+r);var s={startTime:t,name:r,duration:e-t,entryType:"measure"};return zw(Pi,s),s},cn=function(){return Pi},ki=function(){Ii={},Pi=[]})});var vs,nm,Sr,xr,ws,bs,ko,rm,Kw,sm,xs,ce,Ao=b(()=>{"use strict";m();vs=x(require("process"),1),nm=require("events"),Sr=x(Jp(),1);tm();xr=vs.default.platform==="win32",ws=vs.default.browser,bs={red:ws?"crimson":1,yellow:ws?"gold":3,cyan:ws?"darkturquoise":6,green:ws?"forestgreen":2,blue:ws?"steelblue":4,magenta:ws?"palevioletred":5};Sr.default.colors=[bs.cyan,bs.green,bs.blue,bs.magenta];ko=class extends nm.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])}},rm={},Kw=25,xs=class r{static _logToStdErr(e,t){r.loggerfn(e)(...t)}static loggerfn(e){e=`LH:${e}`;let t=rm[e];return t||(t=(0,Sr.default)(e),rm[e]=t,e.endsWith("error")?t.color=bs.red:e.endsWith("warn")&&(t.color=bs.yellow)),t}static setLevel(e){switch(sm=e,e){case"silent":Sr.default.enable("-LH:*");break;case"verbose":Sr.default.enable("LH:*");break;case"warn":Sr.default.enable("-LH:*, LH:*:warn, LH:*:error");break;case"error":Sr.default.enable("-LH:*, LH:*:error");break;default:Sr.default.enable("LH:*, -LH:*:verbose")}}static formatProtocol(e,t,s){let n=!vs.default||vs.default.browser?1/0:vs.default.stdout.columns,i=t.method||"?????",a=n-i.length-e.length-Kw,o=t.params&&i!=="IO.read"?JSON.stringify(t.params).substr(0,a):"";r._logToStdErr(`${e}:${s||""}`,[i,o])}static isVerbose(){return sm==="verbose"}static time({msg:e,id:t,args:s=[]},n="log"){Ri(t),r[n]("status",e,...s)}static timeEnd({msg:e,id:t,args:s=[]},n="verbose"){r[n]("statusEnd",e,...s),Ti(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 xr?"\u221A":"\u2713"}static get cross(){return xr?"\xD7":"\u2718"}static get whiteSmallSquare(){return xr?"\u0387":"\u25AB"}static get heavyHorizontal(){return xr?"\u2500":"\u2501"}static get heavyVertical(){return xr?"\u2502 ":"\u2503 "}static get heavyUpAndRight(){return xr?"\u2514":"\u2517"}static get heavyVerticalAndRight(){return xr?"\u251C":"\u2523"}static get heavyDownAndHorizontal(){return xr?"\u252C":"\u2533"}static get doubleLightHorizontal(){return"\u2500\u2500"}};xs.events=new ko;xs.takeTimeEntries=()=>{let r=cn();return ki(),r};xs.getTimeEntries=()=>cn();ce=xs});var om=It((SP,am)=>{"use strict";m();var im=require("fs"),$o;function Ww(){try{return im.statSync("/.dockerenv"),!0}catch{return!1}}function Xw(){try{return im.readFileSync("/proc/self/cgroup","utf8").includes("docker")}catch{return!1}}am.exports=()=>($o===void 0&&($o=Ww()||Xw()),$o)});var um=It((CP,_o)=>{"use strict";m();var Jw=require("os"),Yw=require("fs"),cm=om(),lm=()=>{if(process.platform!=="linux")return!1;if(Jw.release().toLowerCase().includes("microsoft"))return!cm();try{return Yw.readFileSync("/proc/version","utf8").toLowerCase().includes("microsoft")?!cm():!1}catch{return!1}};process.env.__IS_WSL_TEST__?_o.exports=lm:_o.exports=lm()});function xt(r,e){return typeof r>"u"?e:r}async function gm(r){return new Promise(e=>setTimeout(e,r))}function Dt(){return mm.default?"wsl":process.platform}function fm(){switch(Dt()){case"darwin":case"linux":return eb();case"wsl":process.env.TEMP=Oo(`${process.env.PATH}`);case"win32":return tb();default:throw new ln}}function Qw(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 hm(r=""){if(/[a-z]:\\/iu.test(r))return r;try{return _i.default.execFileSync("wslpath",["-w",r]).toString().trim()}catch{return Qw(r)}}function Oi(r,e){try{return _i.default.execFileSync("wslpath",["-u",r]).toString().trim()}catch{return e}}function Zw(r){let t=/\/mnt\/([a-z])\/Users\/([^\/:]+)\/AppData\//.exec(r)||[];return`/mnt/${t[1]}/Users/${t[2]}/AppData/Local`}function Oo(r){let t=/\/([a-z])\/Users\/([^\/:]+)\/AppData\//.exec(r)||[];return Oi(`${t[1]}:\\Users\\${t[2]}\\AppData\\Local`,Zw(r))}function eb(){return _i.default.execSync("mktemp -d -t lighthouse.XXXXXXX").toString().trim()}function tb(){let r=process.env.TEMP||process.env.TMP||(process.env.SystemRoot||process.env.windir)+"\\temp",e=Math.floor(Math.random()*9e7+1e7),t=(0,dm.join)(r,"lighthouse."+e);return(0,pm.mkdirSync)(t,{recursive:!0}),t}var dm,_i,pm,mm,Ss,Ai,$i,ln,un,Lo=b(()=>{"use strict";m();dm=require("path"),_i=x(require("child_process"),1),pm=require("fs"),mm=x(um(),1);Ss=class extends Error{constructor(e="Unexpected error",t){return super(),this.message=e,this.code=t,this.stack=new Error().stack,this}},Ai=class extends Ss{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"}},$i=class extends Ss{constructor(){super(...arguments),this.message="userDataDir must be false or a path.",this.code="ERR_LAUNCHER_INVALID_USER_DATA_DIRECTORY"}},ln=class extends Ss{constructor(){super(...arguments),this.message=`Platform ${Dt()} is not supported.`,this.code="ERR_LAUNCHER_UNSUPPORTED_PLATFORM"}},un=class extends Ss{constructor(){super(...arguments),this.message="No Chrome installations found.",this.code="ERR_LAUNCHER_NOT_INSTALLED"}}});var Li={};Q(Li,{darwin:()=>wm,darwinFast:()=>Fo,linux:()=>rb,win32:()=>bm,wsl:()=>sb});function Fo(){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&&Er(e))return e;return wm()[0]}function wm(){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=Mo();s&&t.push(s),(0,Cs.execSync)(`${e} -dump | grep -i 'google chrome\\( canary\\)\\?\\.app' | awk '{$1=""; print $0}'`).toString().split(No).forEach(a=>{r.forEach(o=>{let c=ot.default.join(a.substring(0,a.indexOf(".app")+4).trim(),o);Er(c)&&t.indexOf(c)===-1&&t.push(c)})});let n=(0,Es.default)(process.env.HOME||(0,Do.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,Es.default)(process.env.LIGHTHOUSE_CHROMIUM_PATH)),weight:150}),process.env.CHROME_PATH&&i.unshift({regex:new RegExp((0,Es.default)(process.env.CHROME_PATH)),weight:151}),vm(t,i)}function Mo(){if(Er(process.env.CHROME_PATH))return process.env.CHROME_PATH;if(Er(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 rb(){let r=[],e=Mo();if(e&&r.push(e),[ot.default.join((0,Do.homedir)(),".local/share/applications/"),"/usr/share/applications/"].forEach(i=>{r=r.concat(ib(i))}),["google-chrome-stable","google-chrome","chromium-browser","chromium"].forEach(i=>{try{let a=(0,Cs.execFileSync)("which",[i],{stdio:"pipe"}).toString().split(No)[0];Er(a)&&r.push(a)}catch{}}),!r.length)throw new Ai;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,Es.default)(process.env.LIGHTHOUSE_CHROMIUM_PATH)),weight:100}),process.env.CHROME_PATH&&n.unshift({regex:new RegExp((0,Es.default)(process.env.CHROME_PATH)),weight:101}),vm(nb(r.filter(Boolean)),n)}function sb(){return process.env.LOCALAPPDATA=Oo(`${process.env.PATH}`),process.env.PROGRAMFILES=Oi("C:/Program Files","/mnt/c/Program Files"),process.env["PROGRAMFILES(X86)"]=Oi("C:/Program Files (x86)","/mnt/c/Program Files (x86)"),bm()}function bm(){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=Mo();return s&&r.push(s),t.forEach(n=>e.forEach(i=>{let a=ot.default.join(n,i);Er(a)&&r.push(a)})),r}function vm(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 Er(r){if(!r)return!1;try{return ym.default.accessSync(r),!0}catch{return!1}}function nb(r){return Array.from(new Set(r))}function ib(r){let e=/(^[^ ]+).*/,t="^Exec=/.*/(google-chrome|chrome|chromium)-.*",s=[];if(Er(r)){let n;try{n=(0,Cs.execSync)(`grep -ER "${t}" ${r} | awk -F '=' '{print $2}'`,{stdio:"pipe"})}catch{n=(0,Cs.execSync)(`grep -Er "${t}" ${r} | awk -F '=' '{print $2}'`,{stdio:"pipe"})}n=n.toString().split(No).map(i=>i.replace(e,"$1")),n.forEach(i=>Er(i)&&s.push(i))}return s}var ym,ot,Do,Cs,Es,No,xm=b(()=>{"use strict";m();ym=x(require("fs"),1),ot=x(require("path"),1),Do=require("os"),Cs=require("child_process"),Es=x(Mp(),1);Ao();Lo();No=/\r?\n/});function Em(){return new Promise((r,e)=>{let t=(0,Sm.createServer)();t.listen(0),t.once("listening",()=>{let{port:s}=t.address();t.close(()=>r(s))}),t.once("error",e)})}var Sm,Cm=b(()=>{"use strict";m();Sm=require("http");});var jo,Im=b(()=>{"use strict";m();jo=["--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 db(r={}){r.handleSIGINT=xt(r.handleSIGINT,!0);let e=new dn(r);r.handleSIGINT&&Is.size===0&&process.on(Pm,Rm),Is.add(e),await e.launch();let t=()=>{Is.delete(e),Is.size===0&&process.removeListener(Pm,Rm),e.kill()};return{pid:e.pid,port:e.port,process:e.chromeProcess,remoteDebuggingPipes:e.remoteDebuggingPipes,kill:t}}function pb(){let r=dn.getFirstInstallation();if(!r)throw new un;return r}function km(){let r=[];for(let e of Is)try{e.kill(),Is.delete(e)}catch(t){r.push(t)}return r}var ab,Tm,Di,ob,cb,Pm,lb,ub,Is,Rm,dn,Am=b(()=>{"use strict";m();ab=x(require("fs"),1),Tm=x(require("net"),1);xm();Cm();Im();Lo();Di=require("child_process");Ao();ob=Dt()==="wsl",cb=Dt()==="win32",Pm="SIGINT",lb=130,ub=new Set(["darwin","linux","win32","wsl"]),Is=new Set,Rm=()=>{km(),process.exit(lb)};dn=class r{constructor(e={},t={}){if(this.opts=e,this.tmpDirandPidFileReady=!1,this.remoteDebuggingPipes=null,this.fs=t.fs||ab,this.spawn=t.spawn||Di.spawn,ce.setLevel(xt(this.opts.logLevel,"silent")),this.startingUrl=xt(this.opts.startingUrl,"about:blank"),this.chromeFlags=xt(this.opts.chromeFlags,[]),this.prefs=xt(this.opts.prefs,{}),this.requestedPort=xt(this.opts.port,0),this.portStrictMode=e.portStrictMode,this.chromePath=this.opts.chromePath,this.ignoreDefaultFlags=xt(this.opts.ignoreDefaultFlags,!1),this.connectionPollInterval=xt(this.opts.connectionPollInterval,500),this.maxConnectionRetries=xt(this.opts.maxConnectionRetries,50),this.envVars=xt(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 $i;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?[]:jo.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=${ob?hm(this.userDataDir):this.userDataDir}`),process.env.HEADLESS&&e.push("--headless"),e.push(...this.chromeFlags),e.push(this.startingUrl),e}static defaultFlags(){return jo.slice()}static getFirstInstallation(){return Dt()==="darwin"?Fo():Li[Dt()]()[0]}static getInstallations(){return Li[Dt()]()}makeTmpDir(){return fm()}prepare(){let e=Dt();if(!ub.has(e))throw new ln;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 un;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 Em()),ce.verbose("ChromeLauncher",`Launching with command:
947
+ "${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=Tm.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)}gm(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(cb){let e=(0,Di.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 $m={};Q($m,{Launcher:()=>dn,getChromePath:()=>pb,killAll:()=>km,launch:()=>db});var _m=b(()=>{"use strict";m();Am()});var Fm={};Q(Fm,{getActiveRunId:()=>mb,runTests:()=>Ho,stopActiveRun:()=>Uo});function Dm(r){return r.steps.length===0?!1:r.steps.every(e=>(e.stepType??tt(e.instruction))==="api")}function Nm(r){return r.type==="api"}function Ni(r){return r.type==="audit"||r.type==="performance"}function Uo(){Fi&&Fi()}function mb(){return Bo}async function Ho(r,e,t,s){let n=(0,Lm.randomUUID)(),i=new Date().toISOString(),a=Jt.default.join(r,"tests"),o=!1;Bo=n,Fi=()=>{o=!0,le.info({runId:n},"Run stop requested")};let c=e.env??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 Uc(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 li,g=new pi,f=new mi(r,n,c),h=await on(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 fb(a,e);I.length===0&&le.warn({runConfig:e},"No tests matched the run config");let v=await hb(r,c),k=new Map,T=[];for(let _ of I){if(_.testCase.dataSource)try{let Z=await vp(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 ht({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 zd(_,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 oi.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 ui(t.healing.dailyBudget),Ce=t.browsers,lt=[],Ve=T.length>0&&T.every(({suite:_,testCase:Z})=>(Nm(_)||Dm(Z))&&!Ni(_));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 Ce)Ye.set(_,null);else{let _=await Promise.all(Ce.map(async Z=>({name:Z,instance:await p.launchBrowser(Z,t)})));for(let{name:Z,instance:ie}of _)Ye.set(Z,ie)}let js=[];for(let _ of Ce){let Z=Ye.get(_)??null;for(let ie of T)js.push({browserName:_,browser:Z,...ie})}let nr=(await yb(js,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:Ce.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 gb(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(Ce.length>1)for(let _ of Ce){let Z=nr.filter(we=>we.browserName===_),ie=Om(Z,_);lt.push(...ie)}else{let _=Om(nr);lt.push(..._)}let Bs=new Date().toISOString(),Ie=wb(n,i,Bs,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 Rd(r,Ie),t.reporting.allure&&(await f.writeResults(Ie),ip(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 yi(r,{runId:n,timestamp:Bs,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{Fi=null,Bo=null,await p.closeAll(),o&&s?.broadcast("run:stopped",{runId:n})}}async function gb(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=Nm(t)||Dm(s),M=Ni(t)?{...a,screenshot:"off",video:"off",trace:"off"}:a,Ce=!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 yp(Ve)}let Ye="passed",js=!1,Mt=[],nr,Bs=[],Ie=async be=>{let U=s.timeout??t.timeout??M.timeout,ut=U!==M.timeout?{...M,timeout:U}:M;try{await vo({...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(js){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 vo(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 Le=await Ve.screenshot({type:"jpeg",quality:60});g.broadcast("run:screenshot",{runId:e,caseId:k,stepId:Y.stepId,image:Le.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},Le=kt(t.name),jt=kt(s.name),Pr=Lp(r,Le,jt,U.id,n,ae),Us=Dp(r,e,U.id,n,ae),Ze=await Op(Pr,Y.screenshotPath,Us,{threshold:.1,diffThreshold:I.defaultThreshold}),Rr=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:Rr,baselinePath:Ze.baselinePath,actualPath:Ze.actualPath,diffPath:Ze.diffImagePath??Us}),f?.("info",` Visual: ${U.id} \u2014 ${Rr} (diff: ${Ze.diffPercentage}%)`,{baseline:Pr})}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",js=!0)}let be=(()=>{let U=s.lighthouseCategories;return U&&U.length>0?U:Ni(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(()=>(_m(),$m)),Le=ae.launch??ae.default?.launch,{chromium:jt}=await import("playwright"),Pr=jt.executablePath(),Us=Jt.default.join(r,"results",".lh-profiles");await Cr.default.ensureDir(Us);for(let Ze=0;Ze<Qe.length;Ze++){let{s:Rr,idx:yc}=Qe[Ze],Wr=Rr.auditUrl??Rr.navigatedToUrl;f?.("info",` Auditing: ${Wr}`);let ra=null,sa=Jt.default.join(Us,`audit-${Date.now()}-${Ze}`);try{await Cr.default.ensureDir(sa),ra=await Le({chromePath:Pr,chromeFlags:["--headless","--no-sandbox","--disable-gpu"],userDataDir:sa,logLevel:"silent"});let Xr=(await Promise.race([q(Wr,{port:ra.port,output:"json",logLevel:"silent",onlyCategories:Y,disableStorageReset:!0,screenEmulation:{disabled:!0},throttlingMethod:"simulate",formFactor:"desktop"}),new Promise((Jr,Ut)=>setTimeout(()=>Ut(new Error("Lighthouse audit timed out after 60s")),6e4))]))?.lhr,wc=Xr?.audits??{},bc=Xr?.categories??{},ir=Jr=>{let Ut=wc[Jr]?.numericValue;return Ut!=null&&isFinite(Ut)?Ut:void 0},na=Jr=>{let Ut=bc[Jr]?.score;return Ut!=null?Math.round(Ut*100):void 0},vc=Jr=>(bc[Jr]?.auditRefs??[]).filter(Tr=>(Tr.weight??0)>0).map(Tr=>{let wn=wc[Tr.id],ar=wn?.score??null,Hs=ar!==null&&ar>0&&ar<1;return{id:Tr.id,title:wn?.title??Tr.id,passed:ar===1,partial:Hs||void 0,na:ar===null||void 0}}).sort((Tr,wn)=>{let ar=Hs=>Hs.na?3:Hs.passed?4:Hs.partial?1:0;return ar(Tr)-ar(wn)}),Bt=Y.includes("performance"),xc=Y.includes("accessibility"),Sc=Y.includes("seo"),dt={url:Wr,stepIndex:yc,stepInstruction:Rr.instruction,score:Bt?na("performance"):void 0,a11yScore:xc?na("accessibility"):void 0,seoScore:Sc?na("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:xc?vc("accessibility"):void 0,seoAudits:Sc?vc("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(yn){let Xr=yn instanceof Error?yn.message:String(yn);le.warn({url:Wr,err:Xr},"Lighthouse audit failed for URL"),f?.("warn",` Lighthouse failed for ${Wr}: ${Xr}`),Mt.push({url:Wr,stepIndex:yc,stepInstruction:Rr.instruction,lighthouseError:Xr})}finally{try{await ra?.kill()}catch{}try{await Cr.default.remove(sa)}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 Le=new Set(Mt.map(jt=>jt.stepIndex));for(let{s:jt,idx:Pr}of Qe)Le.has(Pr)||Mt.push({url:jt.auditUrl??jt.navigatedToUrl,stepIndex:Pr,stepInstruction:jt.instruction,lighthouseError:`Lighthouse unavailable: ${ae}`})}f?.("info","------------------------------------")}Ni(t)&&Mt.length>0&&Ye==="passed"&&Mt.some(Le=>!Le.lighthouseError&&(Le.score!=null&&Le.score<50||Le.a11yScore!=null&&Le.a11yScore<50||Le.seoScore!=null&&Le.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,Ce),Bs=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"&&Ce&&await Cr.default.remove(Ce).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:Ce}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:Bs,pageLoads:Mt}}}async function fb(r,e){let t=await Ar(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 We(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 hb(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 yb(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 Om(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 wb(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,Lm,Cr,le,Fi,Bo,Vo=b(()=>{"use strict";m();Jt=x(require("path")),Lm=require("crypto"),Cr=x(require("fs-extra"));Ke();gt();mr();rn();fr();Qs();Vd();qd();Kd();Xd();Yd();tp();ap();hp();wp();xp();$r();Eo();Np();At();F();le=C("runner");Fi=null,Bo=null});async function Mm(r){let e=r.rootDir;r.post("/run",async(t,s)=>{let n=Sb.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 Go.info({runConfig:a},"Run requested via API"),Ho(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}),Go.info({runId:u.runId,status:u.status},"API-triggered run complete")}).catch(u=>{Go.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)=>(Uo(),s.status(202).send({status:"stopping"}))),r.get("/run",async(t,s)=>{let n=Eb.safeParse(t.query);if(!n.success)return s.status(400).send({error:"Invalid query",details:n.error.issues});try{let i=await ei(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 Vr(e,t.params.runId);return s.send(n)}catch{return s.status(404).send({error:`Run "${t.params.runId}" not found`})}})}var pe,Go,bb,vb,xb,Sb,Eb,jm=b(()=>{"use strict";m();pe=require("zod");Vo();Te();rn();te();F();Go=C("routes/run"),bb=pe.z.enum(["off","on","only-on-failure"]),vb=pe.z.enum(["off","on","on-first-retry","retain-on-failure"]),xb=pe.z.enum(["off","on","on-first-retry","retain-on-failure"]),Sb=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:bb.optional(),video:vb.optional(),trace:xb.optional(),device:pe.z.string().optional()}),Eb=pe.z.object({limit:pe.z.coerce.number().int().positive().max(100).default(20)})});async function zo(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),pn.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{pn.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):Mi.default.load(d),e&&(e.openapi||e.swagger||e.paths)){a=!0,pn.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=Mi.default.load(d);if(f&&typeof f=="object"&&(f.openapi||f.swagger||f.paths)){e=f,a=!0,pn.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.
948
948
  This may be a developer portal that loads the spec dynamically.
949
949
 
950
950
  Try one of these instead:
@@ -954,8 +954,8 @@ Try one of these instead:
954
954
 
955
955
  Details:
956
956
  ${o.map(c=>` \u2022 ${c}`).join(`
957
- `)}`)}else try{e=JSON.parse(r)}catch{e=_i.default.load(r)}return fb(e)}function fb(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 dn.info({title:t,endpointCount:i.length},"Parsed OpenAPI spec"),{title:t,baseUrl:s,endpoints:i}}var _i,dn,km=b(()=>{"use strict";m();_i=x(require("js-yaml"));F();dn=C("swagger-parser")});function Uo(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 hb(){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 Li(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=>Li(n)),s=new Set(["paragraph","heading","bulletList","orderedList","listItem","blockquote","codeBlock","rule"]);return typeof e.type=="string"&&s.has(e.type)?t.join("")+`
958
- `:t.join("")}return""}async function Ho(r){let e=hb();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`;Jt.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=Li(a.description).trim());let c="",l=a.customfield_10020;if(typeof l=="string"?c=l:l&&typeof l=="object"&&(c=Li(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?Li(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 Am(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(`
957
+ `)}`)}else try{e=JSON.parse(r)}catch{e=Mi.default.load(r)}return Cb(e)}function Cb(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 pn.info({title:t,endpointCount:i.length},"Parsed OpenAPI spec"),{title:t,baseUrl:s,endpoints:i}}var Mi,pn,Bm=b(()=>{"use strict";m();Mi=x(require("js-yaml"));F();pn=C("swagger-parser")});function qo(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 Ib(){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 Bi(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=>Bi(n)),s=new Set(["paragraph","heading","bulletList","orderedList","listItem","blockquote","codeBlock","rule"]);return typeof e.type=="string"&&s.has(e.type)?t.join("")+`
958
+ `:t.join("")}return""}async function Ko(r){let e=Ib();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=Bi(a.description).trim());let c="",l=a.customfield_10020;if(typeof l=="string"?c=l:l&&typeof l=="object"&&(c=Bi(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?Bi(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 Um(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(`
959
959
  ### Description
960
960
  ${r.description}`),r.acceptanceCriteria&&t.push(`
961
961
  ### Acceptance Criteria
@@ -963,9 +963,9 @@ ${r.acceptanceCriteria}`),r.comments.length>0&&(t.push(`
963
963
  ### Relevant Comments`),r.comments.forEach((s,n)=>t.push(`${n+1}. ${s}`))),e&&e.trim()&&t.push(`
964
964
  ### Additional Context (User Input)
965
965
  ${e.trim()}`),t.join(`
966
- `)}async function $m(r){let e=r.rootDir;r.post("/story/fetch-jira",async(i,a)=>{let o=wb.safeParse(i.body);if(!o.success)return a.status(400).send({error:"Invalid request",details:o.error.issues});let c=Uo(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 Ho(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=yb.safeParse(i.body);if(!o.success)return a.status(400).send({error:"Invalid request",details:o.error.issues});try{let c=Oi.default.join(e,"tests"),l=o.data.story;if(o.data.jiraUrl){let p=Uo(o.data.jiraUrl);if(p)try{let g=await Ho(p);l=Am(g,o.data.story||void 0),Jt.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);Jt.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."});Jt.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 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=Oi.default.join(e,"tests"),d=r.wsManager;Jt.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=Uo(g.jiraUrl);if(!f)return{story:g.story,suiteName:g.suiteName};try{let h=await Ho(f);return{story:Am(h,g.story),suiteName:g.suiteName??h.summary}}catch{return Jt.warn({issueKey:f},"Failed to fetch Jira issue for bulk item \u2014 using raw story"),{story:g.story,suiteName:g.suiteName}}}));return za(p,{rootDir:e,outputDir:u},d,l).catch(g=>{Jt.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 Bo(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 Bo(o.data.specUrl);Jt.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&&(Jt.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(`
967
- `),f=o.data.suiteName??`${c.title} API Tests`,h=Oi.default.join(e,"tests"),{suiteId:S}=await Zs(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 Oi,me,Jt,yb,wb,_m=b(()=>{"use strict";m();Oi=x(require("path")),me=require("zod");gr();km();te();F();Jt=C("routes/story");yb=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"]}),wb=me.z.object({jiraUrl:me.z.string().min(1,"Jira URL is required")})});function Om(r,e){let t=Is.default.basename(e);return t!==e?null:Is.default.join(r,"results","downloads",t)}async function Lm(r){let e=r.rootDir;r.get("/report",async(t,s)=>{let n=vb.safeParse(t.query);if(!n.success)return s.status(400).send({error:"Invalid query",details:n.error.issues});try{let i=await Wn(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=Om(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(Is.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=Om(e,t.params.runId),i=Is.default.basename(t.params.file);if(!n||i!==t.params.file)return s.status(400).send({error:"Invalid path"});let a=Is.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 yd(e,t.params.runId),bb.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 Is,Cs,Vo,bb,vb,Dm=b(()=>{"use strict";m();Is=x(require("path")),Cs=x(require("fs-extra")),Vo=require("zod");tn();te();F();bb=C("routes/report");vb=Vo.z.object({limit:Vo.z.coerce.number().int().positive().max(100).default(20)})});function Nm(r){return Go.default.join(r,"results","baselines")}function Fm(r,e){return Go.default.join(Nm(r),`${e}.png`)}async function Mm(r,e,t){let s=Nm(r);await Di.default.ensureDir(s),await Di.default.copy(t,Fm(r,e),{overwrite:!0})}async function jm(r,e){return Di.default.pathExists(Fm(r,e))}var Go,Di,Bm=b(()=>{"use strict";m();Go=x(require("path")),Di=x(require("fs-extra"))});async function Um(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 Ps.default.pathExists(a))return t.status(404).send({error:`File not found: ${i}`});let o=Vr.default.extname(i).toLowerCase(),c=xb[o]??"application/octet-stream";o===".zip"&&t.header("Content-Disposition",`attachment; filename="${i}"`);let l=await Ps.default.stat(a);return t.header("Content-Length",l.size),t.type(c).send(Ps.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 Ps.default.pathExists(n)?(await Mm(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 jm(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 Ps.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,Ps,xb,Hm=b(()=>{"use strict";m();Vr=x(require("path")),Ps=x(require("fs-extra"));Bm();te();xb={".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 Ni(r){return{type:"doc",version:1,content:r.split(`
968
- `).map(t=>({type:"paragraph",content:t.trim()?[{type:"text",text:t}]:[]}))}}var N,Fi,Vm=b(()=>{"use strict";m();F();N=C("xray-client");Fi=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(g=>`{ action: ${JSON.stringify(g.instruction)}, data: ${JSON.stringify(g.generatedCode?`Strategy: ${g.strategy}`:"")}, result: "Step completes successfully" }`).join(`,
966
+ `)}async function Hm(r){let e=r.rootDir;r.post("/story/fetch-jira",async(i,a)=>{let o=Rb.safeParse(i.body);if(!o.success)return a.status(400).send({error:"Invalid request",details:o.error.issues});let c=qo(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 Ko(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=Pb.safeParse(i.body);if(!o.success)return a.status(400).send({error:"Invalid request",details:o.error.issues});try{let c=ji.default.join(e,"tests"),l=o.data.story;if(o.data.jiraUrl){let p=qo(o.data.jiraUrl);if(p)try{let g=await Ko(p);l=Um(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 en(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=ji.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=qo(g.jiraUrl);if(!f)return{story:g.story,suiteName:g.suiteName};try{let h=await Ko(f);return{story:Um(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 Ja(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 zo(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 zo(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(`
967
+ `),f=o.data.suiteName??`${c.title} API Tests`,h=ji.default.join(e,"tests"),{suiteId:S}=await en(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 ji,me,Yt,Pb,Rb,Vm=b(()=>{"use strict";m();ji=x(require("path")),me=require("zod");fr();Bm();te();F();Yt=C("routes/story");Pb=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"]}),Rb=me.z.object({jiraUrl:me.z.string().min(1,"Jira URL is required")})});function Gm(r,e){let t=Rs.default.basename(e);return t!==e?null:Rs.default.join(r,"results","downloads",t)}async function zm(r){let e=r.rootDir;r.get("/report",async(t,s)=>{let n=kb.safeParse(t.query);if(!n.success)return s.status(400).send({error:"Invalid query",details:n.error.issues});try{let i=await ei(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 Vr(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=Gm(e,t.params.runId);if(!n||!await Ps.default.pathExists(n))return s.send([]);let i=await Ps.default.readdir(n,{withFileTypes:!0}),a=await Promise.all(i.filter(o=>o.isFile()).map(async o=>{let c=await Ps.default.stat(Rs.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=Gm(e,t.params.runId),i=Rs.default.basename(t.params.file);if(!n||i!==t.params.file)return s.status(400).send({error:"Invalid path"});let a=Rs.default.join(n,i);return await Ps.default.pathExists(a)?(s.header("Content-Disposition",`attachment; filename="${i}"`),s.type("application/octet-stream"),s.send(Ps.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 Td(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 Rs,Ps,Wo,Tb,kb,qm=b(()=>{"use strict";m();Rs=x(require("path")),Ps=x(require("fs-extra")),Wo=require("zod");rn();te();F();Tb=C("routes/report");kb=Wo.z.object({limit:Wo.z.coerce.number().int().positive().max(100).default(20)})});function Km(r){return Xo.default.join(r,"results","baselines")}function Wm(r,e){return Xo.default.join(Km(r),`${e}.png`)}async function Xm(r,e,t){let s=Km(r);await Ui.default.ensureDir(s),await Ui.default.copy(t,Wm(r,e),{overwrite:!0})}async function Jm(r,e){return Ui.default.pathExists(Wm(r,e))}var Xo,Ui,Ym=b(()=>{"use strict";m();Xo=x(require("path")),Ui=x(require("fs-extra"))});async function Qm(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=qr.default.basename(n),a=qr.default.join(r.rootDir,"results",s,i);if(!await Ts.default.pathExists(a))return t.status(404).send({error:`File not found: ${i}`});let o=qr.default.extname(i).toLowerCase(),c=Ab[o]??"application/octet-stream";o===".zip"&&t.header("Content-Disposition",`attachment; filename="${i}"`);let l=await Ts.default.stat(a);return t.header("Content-Length",l.size),t.type(c).send(Ts.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=qr.default.isAbsolute(s.screenshotPath)?s.screenshotPath:qr.default.join(r.rootDir,s.screenshotPath);return await Ts.default.pathExists(n)?(await Xm(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 Jm(r.rootDir,e.params.stepId))return t.send({hasBaseline:!1});let n=qr.default.join(r.rootDir,"results","baselines",`${e.params.stepId}.png`),i=await Ts.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 qr,Ts,Ab,Zm=b(()=>{"use strict";m();qr=x(require("path")),Ts=x(require("fs-extra"));Ym();te();Ab={".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 Hi(r){return{type:"doc",version:1,content:r.split(`
968
+ `).map(t=>({type:"paragraph",content:t.trim()?[{type:"text",text:t}]:[]}))}}var N,Vi,eg=b(()=>{"use strict";m();F();N=C("xray-client");Vi=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(g=>`{ action: ${JSON.stringify(g.instruction)}, data: ${JSON.stringify(g.generatedCode?`Strategy: ${g.strategy}`:"")}, result: "Step completes successfully" }`).join(`,
969
969
  `)}],`:"",c=`mutation {
970
970
  createTest(
971
971
  testType: { name: "Manual" },
@@ -985,7 +985,7 @@ ${e.trim()}`),t.join(`
985
985
  }
986
986
  warnings
987
987
  }
988
- }`;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??"",p=l.createTest.warnings;return p&&p.length>0&&N.warn({warnings:p,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:Ni(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:Ni(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 {
988
+ }`;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??"",p=l.createTest.warnings;return p&&p.length>0&&N.warn({warnings:p,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:Hi(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:Hi(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 {
989
989
  createTestSet(
990
990
  ${t&&t.length>0?`testIssueIds: [${t.map(l=>`"${l}"`).join(", ")}],`:""}
991
991
  jira: {
@@ -1002,7 +1002,7 @@ ${e.trim()}`),t.join(`
1002
1002
  }
1003
1003
  warnings
1004
1004
  }
1005
- }`;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:Ni(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:Ni(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 {
1005
+ }`;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:Hi(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:Hi(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 {
1006
1006
  addTestStep(
1007
1007
  issueId: "${e}",
1008
1008
  step: {
@@ -1049,23 +1049,23 @@ ${e.trim()}`),t.join(`
1049
1049
  jira(fields: ["key", "summary"])
1050
1050
  }
1051
1051
  }
1052
- }`;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 he,_R,Sb,Eb,Gm,zm=b(()=>{"use strict";m();he=require("zod"),_R=he.z.enum(["not-created","created","synced","update-pending"]),Sb=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()}),Eb=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(Sb).default([])}),Gm=he.z.object({projectKey:he.z.string().min(1),suites:he.z.array(Eb).default([]),updatedAt:he.z.string().datetime()})});function Km(r){return zo.default.join(r,"assuremind-data",Cb)}async function Wm(r){let e=Km(r);if(!await qo.default.pathExists(e))return{projectKey:"",suites:[],updatedAt:new Date().toISOString()};let t=await ue(e),s=Gm.safeParse(t);return s.success?s.data:(qm.warn({path:e,errors:s.error.issues},"Invalid xray-mapping.json \u2014 returning empty"),{projectKey:"",suites:[],updatedAt:new Date().toISOString()})}async function Yt(r,e){let t=Km(r);await qo.default.ensureDir(zo.default.dirname(t));let s={...e,updatedAt:new Date().toISOString()};await W(t,s),qm.debug({path:t},"Xray mapping written")}function Qt(r,e){return r.suites.find(t=>t.suiteId===e)}function Mi(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 Zt(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 pn(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 zo,qo,qm,Cb,Xm=b(()=>{"use strict";m();zo=x(require("path")),qo=x(require("fs-extra"));zm();ze();F();qm=C("xray-store"),Cb="xray-mapping.json"});function Ym(r){return Jm.default.createHash("sha256").update(JSON.stringify(r)).digest("hex").slice(0,16)}function Rs(r){return Ym({name:r.name,description:r.description,tags:r.tags})}function mn(r){return Ym({name:r.name,description:r.description,tags:r.tags,priority:r.priority,steps:r.steps.map(e=>({instruction:e.instruction,code:e.generatedCode}))})}var Jm,xt,ji,Qm=b(()=>{"use strict";m();Jm=x(require("crypto"));Vm();Xm();Ke();gt();F();xt=C("xray-service");ji=class{client;rootDir;testsDir;projectKey;constructor(e,t){this.rootDir=e,this.testsDir=`${e}/tests`,this.projectKey=t.projectKey.trim().toUpperCase(),this.client=new Fi(t)}async readMapping(){let e=await Wm(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=Qt(t,e.id),n=await de(this.testsDir,e.id),i=n?await We(n):[],a="not-created";s&&(a=Rs(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=mn(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 We(s),a=[],o=Qt(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=Mi(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:mn(p)};o||(o={suiteId:e,xrayTestSetId:"",xrayTestSetIssueId:"",lastSyncedAt:h,lastSyncHash:Rs(n),cases:[]}),o=pn(o,S),t=Zt(t,o),await Yt(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=Qt(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(!Qt(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:Rs(n)},t=Zt(t,o),await Yt(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 We(n)).find(d=>d.id===t);if(!o)return this.summarizeResults([{success:!1,caseId:t,action:"failed",error:"Test case not found"}]);let c=Qt(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:Rs(i),cases:[]},s=Zt(s,c),await Yt(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=Mi(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:mn(t)},d=pn(i,u),p=Zt(n,d);return await Yt(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 We(s),a=[],o=Qt(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:Rs(n)},t=Zt(t,o),await Yt(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=Rs(n);if(o.xrayTestSetId&&c!==o.lastSyncHash)try{await this.client.updateTestSet(o.xrayTestSetId,n),o={...o,lastSyncedAt:new Date().toISOString(),lastSyncHash:c},t=Zt(t,o),await Yt(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=Qt(t,e)??o,g.result.xrayKey&&l.push(g.result.xrayKey);continue}let p=mn(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=pn(o,g);t=Zt(t,f),o=f,await Yt(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=Qt(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 We(n)).find(u=>u.id===t);if(!o)return this.summarizeResults([{success:!1,caseId:t,action:"failed",error:"Test case not found"}]);let c=Mi(s,t);if(!c)return this.createSingleCase(e,t);let l=mn(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=pn(c.suiteMapping,u),p=Zt(s,d);return await Yt(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 Zm(){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 eg(r){let e=r.rootDir;function t(){let n=Zm();return n?new ji(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=Zm();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{Bi.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{Bi.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{Bi.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{Bi.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 Bi,tg=b(()=>{"use strict";m();Qm();te();F();Bi=C("xray-routes")});var rg,Ko,Wo,Ts,ks,Xo=b(()=>{"use strict";m();rg=x(require("simple-git")),Ko=x(require("fs-extra")),Wo=x(require("path"));F();Ts=C("git-service"),ks=class{git;rootDir;wsManager;constructor(e,t){this.rootDir=e,this.wsManager=t,this.git=(0,rg.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),Ts.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"),Ts.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"),Ts.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"),Ts.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"),Ts.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(`
1053
- `)}async getConflictedFiles(){return(await this.git.status()).conflicted}async getFileConflictContent(e){let t=Wo.default.join(this.rootDir,e),s=await Ko.default.readFile(t,"utf-8"),n="",i="",a="none";for(let o of s.split(`
1052
+ }`;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 he,UR,$b,_b,tg,rg=b(()=>{"use strict";m();he=require("zod"),UR=he.z.enum(["not-created","created","synced","update-pending"]),$b=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()}),_b=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($b).default([])}),tg=he.z.object({projectKey:he.z.string().min(1),suites:he.z.array(_b).default([]),updatedAt:he.z.string().datetime()})});function ng(r){return Jo.default.join(r,"assuremind-data",Ob)}async function ig(r){let e=ng(r);if(!await Yo.default.pathExists(e))return{projectKey:"",suites:[],updatedAt:new Date().toISOString()};let t=await ue(e),s=tg.safeParse(t);return s.success?s.data:(sg.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=ng(r);await Yo.default.ensureDir(Jo.default.dirname(t));let s={...e,updatedAt:new Date().toISOString()};await W(t,s),sg.debug({path:t},"Xray mapping written")}function Zt(r,e){return r.suites.find(t=>t.suiteId===e)}function Gi(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 mn(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 Jo,Yo,sg,Ob,ag=b(()=>{"use strict";m();Jo=x(require("path")),Yo=x(require("fs-extra"));rg();ze();F();sg=C("xray-store"),Ob="xray-mapping.json"});function cg(r){return og.default.createHash("sha256").update(JSON.stringify(r)).digest("hex").slice(0,16)}function ks(r){return cg({name:r.name,description:r.description,tags:r.tags})}function gn(r){return cg({name:r.name,description:r.description,tags:r.tags,priority:r.priority,steps:r.steps.map(e=>({instruction:e.instruction,code:e.generatedCode}))})}var og,St,zi,lg=b(()=>{"use strict";m();og=x(require("crypto"));eg();ag();Ke();gt();F();St=C("xray-service");zi=class{client;rootDir;testsDir;projectKey;constructor(e,t){this.rootDir=e,this.testsDir=`${e}/tests`,this.projectKey=t.projectKey.trim().toUpperCase(),this.client=new Vi(t)}async readMapping(){let e=await ig(this.rootDir);return e.projectKey||(e.projectKey=this.projectKey),e}async getAllStatuses(){let e=await this.readMapping(),t=await Ar(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 We(n):[],a="not-created";s&&(a=ks(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=gn(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 Ar(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 We(s),a=[],o=Zt(t,e);if(o)return St.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=Gi(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:gn(p)};o||(o={suiteId:e,xrayTestSetId:"",xrayTestSetIssueId:"",lastSyncedAt:h,lastSyncHash:ks(n),cases:[]}),o=mn(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"}),St.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),St.info({folderPath:c,testCount:u.length},"Tests organized into folder")}catch(p){St.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:ks(n)},t=er(t,o),await Qt(this.rootDir,t),a.push({success:!0,suiteId:e,xrayKey:p.key,action:"created"}),St.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 We(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:ks(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){St.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){St.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=Gi(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:gn(t)},d=mn(i,u),p=er(n,d);return await Qt(this.rootDir,p),St.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 Ar(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 We(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:ks(n)},t=er(t,o),await Qt(this.rootDir,t),a.push({success:!0,suiteId:e,xrayKey:d.key,action:"created"}),St.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=ks(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=gn(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=mn(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){St.warn({err:p instanceof Error?p.message:String(p)},"Folder organization failed for synced tests (non-fatal)")}}}catch(u){St.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 We(n)).find(u=>u.id===t);if(!o)return this.summarizeResults([{success:!1,caseId:t,action:"failed",error:"Test case not found"}]);let c=Gi(s,t);if(!c)return this.createSingleCase(e,t);let l=gn(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=mn(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 ug(){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 dg(r){let e=r.rootDir;function t(){let n=ug();return n?new zi(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=ug();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{qi.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{qi.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{qi.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{qi.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 qi,pg=b(()=>{"use strict";m();lg();te();F();qi=C("xray-routes")});var mg,Qo,Zo,As,$s,ec=b(()=>{"use strict";m();mg=x(require("simple-git")),Qo=x(require("fs-extra")),Zo=x(require("path"));F();As=C("git-service"),$s=class{git;rootDir;wsManager;constructor(e,t){this.rootDir=e,this.wsManager=t,this.git=(0,mg.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),As.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"),As.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"),As.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"),As.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"),As.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(`
1053
+ `)}async getConflictedFiles(){return(await this.git.status()).conflicted}async getFileConflictContent(e){let t=Zo.default.join(this.rootDir,e),s=await Qo.default.readFile(t,"utf-8"),n="",i="",a="none";for(let o of s.split(`
1054
1054
  `)){if(o.startsWith("<<<<<<<")){a="ours";continue}if(o.startsWith("=======")){a="theirs";continue}if(o.startsWith(">>>>>>>")){a="none";continue}a==="ours"?n+=o+`
1055
1055
  `:a==="theirs"&&(i+=o+`
1056
- `)}return{ours:n.trimEnd(),theirs:i.trimEnd()}}async resolveConflict(e,t){let s=Wo.default.join(this.rootDir,e);await Ko.default.writeFile(s,t,"utf-8"),await this.git.add(e),Ts.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 sg(r){return{url:"git://local",title:"Git Operations",interactiveElements:"",htmlSnapshot:r,previousSteps:[],variables:{}}}async function ng(r){if(!r.trim())return"chore: update files";let e=8e3,t=r.length>e?r.slice(0,e)+`
1056
+ `)}return{ours:n.trimEnd(),theirs:i.trimEnd()}}async resolveConflict(e,t){let s=Zo.default.join(this.rootDir,e);await Qo.default.writeFile(s,t,"utf-8"),await this.git.add(e),As.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 gg(r){return{url:"git://local",title:"Git Operations",interactiveElements:"",htmlSnapshot:r,previousSteps:[],variables:{}}}async function fg(r){if(!r.trim())return"chore: update files";let e=8e3,t=r.length>e?r.slice(0,e)+`
1057
1057
  ... (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(`
1058
- `);try{let a=(await Or(void 0,{temperature:.4}).generateCode(s,sg(t))).trim();return a=a.replace(/^["'`]+|["'`]+$/g,""),a=a.replace(/^(commit message:?\s*)/i,""),a=a.split(`
1059
- `)[0].trim(),Ui.info({messageLength:a.length},"AI commit message generated"),a||"chore: update files"}catch(n){return Ui.warn({err:n instanceof Error?n.message:String(n)},"AI commit message generation failed"),"chore: update files"}}async function ig(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(`
1060
- `),n=sg(`Conflict in: ${t}
1058
+ `);try{let a=(await Nr(void 0,{temperature:.4}).generateCode(s,gg(t))).trim();return a=a.replace(/^["'`]+|["'`]+$/g,""),a=a.replace(/^(commit message:?\s*)/i,""),a=a.split(`
1059
+ `)[0].trim(),Ki.info({messageLength:a.length},"AI commit message generated"),a||"chore: update files"}catch(n){return Ki.warn({err:n instanceof Error?n.message:String(n)},"AI commit message generation failed"),"chore: update files"}}async function hg(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(`
1060
+ `),n=gg(`Conflict in: ${t}
1061
1061
 
1062
1062
  Ours:
1063
1063
  ${r}
1064
1064
 
1065
1065
  Theirs:
1066
- ${e}`);try{let a=await Or(void 0,{temperature:.4}).generateCode(s,n);return a=a.replace(/^```[\w]*\n?/,"").replace(/\n?```$/,""),Ui.info({filePath:t,resultLength:a.length},"AI conflict resolution generated"),a}catch(i){throw Ui.warn({filePath:t,err:i instanceof Error?i.message:String(i)},"AI conflict resolution failed"),i}}var Ui,ag=b(()=>{"use strict";m();gr();F();Ui=C("git-ai")});async function og(r){let e=r.rootDir,t=r.wsManager,s=new ks(e,t),n=null,i=async()=>{if(n!==null)return n;try{await s.getStatus(),n=!0}catch{n=!1,Ib.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=Pb.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=Rb.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=Tb.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=kb.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=Ab.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 ng(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=$b.safeParse(o.body);if(!l.success)return c.status(400).send({error:"Invalid body",details:l.error.issues});try{let u=await ig(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(`
1067
- `).filter(Boolean),{listSuiteDirs:p,readSuite:g}=await Promise.resolve().then(()=>(Ke(),wa)),{listCases:f}=await Promise.resolve().then(()=>(gt(),al)),h=Hi.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=Hi.default.basename(J).toLowerCase(),Ce=Hi.default.dirname(J).toLowerCase();if(j.includes(M)||j.includes(Ce)){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 Hi,_e,Ib,Pb,Rb,Tb,kb,Ab,$b,cg=b(()=>{"use strict";m();Hi=x(require("path")),_e=require("zod");Xo();ag();te();F();Ib=C("git-routes"),Pb=_e.z.object({branch:_e.z.string().min(1)}),Rb=_e.z.object({message:_e.z.string().min(1)}),Tb=_e.z.object({rebase:_e.z.boolean().optional()}),kb=_e.z.object({message:_e.z.string().min(1)}),Ab=_e.z.object({filePath:_e.z.string().min(1),content:_e.z.string()}),$b=_e.z.object({filePath:_e.z.string().min(1),ours:_e.z.string(),theirs:_e.z.string()})});function lg(r){let e=r.trim().split(`
1068
- `).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 ug(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()&&Yo.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=lg(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(!Yo.includes(c))return n.status(400).send({error:`Only ${Yo.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=lg(o).length;else{let p=JSON.parse(o);d=Array.isArray(p)?p.length:0}}catch{}return Jo.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"),Jo.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),Jo.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,Jo,Yo,dg=b(()=>{"use strict";m();St=x(require("path")),ct=x(require("fs-extra"));te();F();Jo=C("routes/data-files"),Yo=[".json",".csv"]});function pg(r){return Gr.default.basename(r).replace(/[^a-zA-Z0-9._-]+/g,"_").replace(/^\.+/,"")||"file"}async function mg(r){let e=r.rootDir,t=Gr.default.join(e,Qo);r.post("/files/upload",{bodyLimit:Zo+8*1024*1024},async(s,n)=>{let i=Ob.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid upload",details:i.error.issues});try{let a=pg(i.data.name),o=Buffer.from(i.data.dataBase64,"base64");if(o.length>Zo)return n.status(413).send({error:`File exceeds ${Zo/(1024*1024)} MB limit`});await Cr.default.ensureDir(t);let c=Gr.default.join(t,a);await Cr.default.writeFile(c,o),_b.info({name:a,size:o.length},"Fixture file uploaded");let l=`${Qo.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 Cr.default.pathExists(t))return n.send([]);let i=await Cr.default.readdir(t,{withFileTypes:!0}),a=await Promise.all(i.filter(o=>o.isFile()).map(async o=>{let c=await Cr.default.stat(Gr.default.join(t,o.name));return{name:o.name,path:`${Qo.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=pg(s.params.name),a=Gr.default.join(t,i);return await Cr.default.pathExists(a)?(await Cr.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,Cr,Vi,_b,Qo,Zo,Ob,gg=b(()=>{"use strict";m();Gr=x(require("path")),Cr=x(require("fs-extra")),Vi=require("zod");te();F();_b=C("routes/files"),Qo=Gr.default.join("fixtures","uploads"),Zo=25*1024*1024,Ob=Vi.z.object({name:Vi.z.string().min(1).max(255),dataBase64:Vi.z.string().min(1)})});function fg(r){switch(r){case"name":return 0;case"description":return 1;case"tag":return 2;case"instruction":return 3}}async function yg(r){let e=hg.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 At(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 We(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)=>fg(c.matchedOn)-fg(l.matchedOn)),s.send(o.slice(0,20))}catch(i){return w(s,500,"Search failed",i)}})}var hg,wg=b(()=>{"use strict";m();hg=x(require("path"));Ke();gt();te()});function rc(r,e,t){let s=["--all",`--browser ${r.join(" ")}`,`--parallel ${e}`,"--ci"];return t&&s.push(`--device "${t}"`),s.join(" ")}function Lb(r,e,t){let s=rc(r,e,t);return`name: Assuremind Tests
1066
+ ${e}`);try{let a=await Nr(void 0,{temperature:.4}).generateCode(s,n);return a=a.replace(/^```[\w]*\n?/,"").replace(/\n?```$/,""),Ki.info({filePath:t,resultLength:a.length},"AI conflict resolution generated"),a}catch(i){throw Ki.warn({filePath:t,err:i instanceof Error?i.message:String(i)},"AI conflict resolution failed"),i}}var Ki,yg=b(()=>{"use strict";m();fr();F();Ki=C("git-ai")});async function wg(r){let e=r.rootDir,t=r.wsManager,s=new $s(e,t),n=null,i=async()=>{if(n!==null)return n;try{await s.getStatus(),n=!0}catch{n=!1,Lb.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=Db.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=Nb.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=Fb.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=Mb.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=jb.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 fg(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=Bb.safeParse(o.body);if(!l.success)return c.status(400).send({error:"Invalid body",details:l.error.issues});try{let u=await hg(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(`
1067
+ `).filter(Boolean),{listSuiteDirs:p,readSuite:g}=await Promise.resolve().then(()=>(Ke(),Ia)),{listCases:f}=await Promise.resolve().then(()=>(gt(),dl)),h=Wi.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=Wi.default.basename(J).toLowerCase(),Ce=Wi.default.dirname(J).toLowerCase();if(j.includes(M)||j.includes(Ce)){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 Wi,_e,Lb,Db,Nb,Fb,Mb,jb,Bb,bg=b(()=>{"use strict";m();Wi=x(require("path")),_e=require("zod");ec();yg();te();F();Lb=C("git-routes"),Db=_e.z.object({branch:_e.z.string().min(1)}),Nb=_e.z.object({message:_e.z.string().min(1)}),Fb=_e.z.object({rebase:_e.z.boolean().optional()}),Mb=_e.z.object({message:_e.z.string().min(1)}),jb=_e.z.object({filePath:_e.z.string().min(1),content:_e.z.string()}),Bb=_e.z.object({filePath:_e.z.string().min(1),ours:_e.z.string(),theirs:_e.z.string()})});function vg(r){let e=r.trim().split(`
1068
+ `).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 xg(r){let e=r.rootDir,t=Et.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()&&rc.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=Et.default.basename(s.params.filename),a=Et.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=vg(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=Et.default.extname(a).toLowerCase();if(!rc.includes(c))return n.status(400).send({error:`Only ${rc.join(", ")} files are allowed`});let l=Et.default.basename(a),u=Et.default.join(t,l);await ct.default.ensureDir(t),await ct.default.writeFile(u,o,"utf8");let d=0;try{if(c===".csv")d=vg(o).length;else{let p=JSON.parse(o);d=Array.isArray(p)?p.length:0}}catch{}return tc.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=Et.default.basename(s.params.filename),a=Et.default.join(t,i),o=s.body,c=String(o.content??"");return await ct.default.ensureDir(t),await ct.default.writeFile(a,c,"utf8"),tc.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=Et.default.basename(s.params.filename),a=Et.default.join(t,i);return await ct.default.pathExists(a)?(await ct.default.remove(a),tc.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 Et,ct,tc,rc,Sg=b(()=>{"use strict";m();Et=x(require("path")),ct=x(require("fs-extra"));te();F();tc=C("routes/data-files"),rc=[".json",".csv"]});function Eg(r){return Kr.default.basename(r).replace(/[^a-zA-Z0-9._-]+/g,"_").replace(/^\.+/,"")||"file"}async function Cg(r){let e=r.rootDir,t=Kr.default.join(e,sc);r.post("/files/upload",{bodyLimit:nc+8*1024*1024},async(s,n)=>{let i=Hb.safeParse(s.body);if(!i.success)return n.status(400).send({error:"Invalid upload",details:i.error.issues});try{let a=Eg(i.data.name),o=Buffer.from(i.data.dataBase64,"base64");if(o.length>nc)return n.status(413).send({error:`File exceeds ${nc/(1024*1024)} MB limit`});await Ir.default.ensureDir(t);let c=Kr.default.join(t,a);await Ir.default.writeFile(c,o),Ub.info({name:a,size:o.length},"Fixture file uploaded");let l=`${sc.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 Ir.default.pathExists(t))return n.send([]);let i=await Ir.default.readdir(t,{withFileTypes:!0}),a=await Promise.all(i.filter(o=>o.isFile()).map(async o=>{let c=await Ir.default.stat(Kr.default.join(t,o.name));return{name:o.name,path:`${sc.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=Eg(s.params.name),a=Kr.default.join(t,i);return await Ir.default.pathExists(a)?(await Ir.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 Kr,Ir,Xi,Ub,sc,nc,Hb,Ig=b(()=>{"use strict";m();Kr=x(require("path")),Ir=x(require("fs-extra")),Xi=require("zod");te();F();Ub=C("routes/files"),sc=Kr.default.join("fixtures","uploads"),nc=25*1024*1024,Hb=Xi.z.object({name:Xi.z.string().min(1).max(255),dataBase64:Xi.z.string().min(1)})});function Pg(r){switch(r){case"name":return 0;case"description":return 1;case"tag":return 2;case"instruction":return 3}}async function Tg(r){let e=Rg.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 We(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)=>Pg(c.matchedOn)-Pg(l.matchedOn)),s.send(o.slice(0,20))}catch(i){return w(s,500,"Search failed",i)}})}var Rg,kg=b(()=>{"use strict";m();Rg=x(require("path"));Ke();gt();te()});function oc(r,e,t){let s=["--all",`--browser ${r.join(" ")}`,`--parallel ${e}`,"--ci"];return t&&s.push(`--device "${t}"`),s.join(" ")}function Vb(r,e,t){let s=oc(r,e,t);return`name: Assuremind Tests
1069
1069
  on:
1070
1070
  push:
1071
1071
  branches: [main]
@@ -1088,7 +1088,7 @@ jobs:
1088
1088
  with:
1089
1089
  name: assuremind-results
1090
1090
  path: results/
1091
- `}function Db(r,e,t){let s=rc(r,e,t);return`stages: [test]
1091
+ `}function Gb(r,e,t){let s=oc(r,e,t);return`stages: [test]
1092
1092
  test:
1093
1093
  stage: test
1094
1094
  image: mcr.microsoft.com/playwright:v1.40.0-jammy${t?`
@@ -1100,7 +1100,7 @@ test:
1100
1100
  when: always
1101
1101
  paths: [results/]
1102
1102
  expire_in: 7 days
1103
- `}function Nb(r,e,t){let s=rc(r,e,t);return`pipeline {
1103
+ `}function zb(r,e,t){let s=oc(r,e,t);return`pipeline {
1104
1104
  agent any
1105
1105
  stages {
1106
1106
  stage('Install') { steps { sh 'npm ci' } }
@@ -1111,7 +1111,7 @@ test:
1111
1111
  }
1112
1112
  post { always { archiveArtifacts artifacts: 'results/**', allowEmptyArchive: true } }
1113
1113
  }
1114
- `}function xg(r,e,t,s){return r==="github"?Lb(e,t,s):r==="gitlab"?Db(e,t,s):Nb(e,t,s)}async function Sg(r){let e=r.rootDir;r.post("/ci-config",async(t,s)=>{let n=bg.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=xg(i,a,o,c);return s.send({yaml:l,filename:vg[i]})}catch(i){return w(s,500,"Failed to generate CI config",i)}}),r.post("/ci-config/write",async(t,s)=>{let n=bg.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:xg(a,o,c,l),d=vg[a],p=ec.default.join(e,d);return await tc.default.ensureDir(ec.default.dirname(p)),await tc.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 ec,tc,Dt,bg,vg,Eg=b(()=>{"use strict";m();ec=x(require("path")),tc=x(require("fs-extra")),Dt=require("zod");te();Te();bg=Dt.z.object({platform:Dt.z.enum(["github","gitlab","jenkins"]),browsers:Dt.z.array(Dt.z.string()).default(["chromium"]),parallel:Dt.z.number().int().positive().default(2),headed:Dt.z.boolean().default(!1),env:Dt.z.string().optional(),device:Dt.z.string().optional(),yaml:Dt.z.string().optional()});vg={github:".github/workflows/assuremind.yml",gitlab:".gitlab-ci.yml",jenkins:"Jenkinsfile"}});async function Cg(r){r.get("/templates",async(e,t)=>{try{return t.send(Fb)}catch(s){return w(t,500,"Failed to list templates",s)}})}var Fb,Ig=b(()=>{"use strict";m();te();Fb=[{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 Pg(r){let e=r.rootDir;r.get("/flakiness",async(t,s)=>{try{let{suiteId:n,caseId:i}=t.query,o=(await Za(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 Rg=b(()=>{"use strict";m();tn();te()});function kg(r){return sc.default.join(r,"tests",".step-library.json")}async function As(r){let e=kg(r);if(!await Gi.default.pathExists(e))return[];try{let t=await Gi.default.readJson(e);return Array.isArray(t)?t.map(s=>Mb.parse(s)):[]}catch{return[]}}async function nc(r,e){let t=kg(r);await Gi.default.ensureDir(sc.default.dirname(t)),await W(t,e)}async function Ag(r,e){let t=await As(r),s=new Date().toISOString(),n={id:(0,Tg.v4)(),name:e.name,instruction:e.instruction,generatedCode:e.generatedCode??"",tags:e.tags??[],createdAt:s,updatedAt:s};return t.push(n),await nc(r,t),n}async function ic(r,e,t){let s=await As(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 nc(r,s),s[n]}async function $g(r,e){let s=(await As(r)).filter(n=>n.id!==e);await nc(r,s)}var sc,Gi,Tg,Nt,Mb,_g=b(()=>{"use strict";m();sc=x(require("path")),Gi=x(require("fs-extra")),Tg=require("uuid"),Nt=require("zod");ze();Mb=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 Og(r){let e=r.rootDir;r.get("/step-library",async(t,s)=>{try{let n=await As(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=jb.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid request",details:n.error.issues});try{let i=await Ag(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=Bb.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid request",details:n.error.issues});try{let i=await ic(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 $g(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 As(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 ic(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,jb,Bb,Lg=b(()=>{"use strict";m();Je=require("zod");_g();Te();pr();gr();Ys();te();jb=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()}),Bb=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 Ub(){return`
1114
+ `}function _g(r,e,t,s){return r==="github"?Vb(e,t,s):r==="gitlab"?Gb(e,t,s):zb(e,t,s)}async function Og(r){let e=r.rootDir;r.post("/ci-config",async(t,s)=>{let n=Ag.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=_g(i,a,o,c);return s.send({yaml:l,filename:$g[i]})}catch(i){return w(s,500,"Failed to generate CI config",i)}}),r.post("/ci-config/write",async(t,s)=>{let n=Ag.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:_g(a,o,c,l),d=$g[a],p=ic.default.join(e,d);return await ac.default.ensureDir(ic.default.dirname(p)),await ac.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 ic,ac,Nt,Ag,$g,Lg=b(()=>{"use strict";m();ic=x(require("path")),ac=x(require("fs-extra")),Nt=require("zod");te();Te();Ag=Nt.z.object({platform:Nt.z.enum(["github","gitlab","jenkins"]),browsers:Nt.z.array(Nt.z.string()).default(["chromium"]),parallel:Nt.z.number().int().positive().default(2),headed:Nt.z.boolean().default(!1),env:Nt.z.string().optional(),device:Nt.z.string().optional(),yaml:Nt.z.string().optional()});$g={github:".github/workflows/assuremind.yml",gitlab:".gitlab-ci.yml",jenkins:"Jenkinsfile"}});async function Dg(r){r.get("/templates",async(e,t)=>{try{return t.send(qb)}catch(s){return w(t,500,"Failed to list templates",s)}})}var qb,Ng=b(()=>{"use strict";m();te();qb=[{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 Fg(r){let e=r.rootDir;r.get("/flakiness",async(t,s)=>{try{let{suiteId:n,caseId:i}=t.query,o=(await no(e)).slice(0,20),c=new Map,l=new Map;for(let p of o)try{let g=await Vr(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 Mg=b(()=>{"use strict";m();rn();te()});function Bg(r){return cc.default.join(r,"tests",".step-library.json")}async function _s(r){let e=Bg(r);if(!await Ji.default.pathExists(e))return[];try{let t=await Ji.default.readJson(e);return Array.isArray(t)?t.map(s=>Kb.parse(s)):[]}catch{return[]}}async function lc(r,e){let t=Bg(r);await Ji.default.ensureDir(cc.default.dirname(t)),await W(t,e)}async function Ug(r,e){let t=await _s(r),s=new Date().toISOString(),n={id:(0,jg.v4)(),name:e.name,instruction:e.instruction,generatedCode:e.generatedCode??"",tags:e.tags??[],createdAt:s,updatedAt:s};return t.push(n),await lc(r,t),n}async function uc(r,e,t){let s=await _s(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 lc(r,s),s[n]}async function Hg(r,e){let s=(await _s(r)).filter(n=>n.id!==e);await lc(r,s)}var cc,Ji,jg,Ft,Kb,Vg=b(()=>{"use strict";m();cc=x(require("path")),Ji=x(require("fs-extra")),jg=require("uuid"),Ft=require("zod");ze();Kb=Ft.z.object({id:Ft.z.string(),name:Ft.z.string().min(1),instruction:Ft.z.string().min(1),generatedCode:Ft.z.string().optional().default(""),tags:Ft.z.array(Ft.z.string()).default([]),createdAt:Ft.z.string(),updatedAt:Ft.z.string()})});async function Gg(r){let e=r.rootDir;r.get("/step-library",async(t,s)=>{try{let n=await _s(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=Wb.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid request",details:n.error.issues});try{let i=await Ug(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=Xb.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid request",details:n.error.issues});try{let i=await uc(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 Hg(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 _s(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 ht({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 uc(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,Wb,Xb,zg=b(()=>{"use strict";m();Je=require("zod");Vg();Te();mr();fr();Qs();te();Wb=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()}),Xb=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 Jb(){return`
1115
1115
  (function() {
1116
1116
  if (window.__amListenersAttached) return;
1117
1117
  window.__amListenersAttached = true;
@@ -1500,65 +1500,65 @@ test:
1500
1500
  }
1501
1501
  }, true);
1502
1502
  })();
1503
- `}async function Hb(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||Vb(e.tag,e.type),o=e.ariaLabel||e.labelText||e.innerText||e.title||"",c=Gb(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 Oe.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 Oe.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 Vb(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 Gb(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 Dg,Oe,zi,Ng=b(()=>{"use strict";m();Dg=require("playwright");F();Oe=C("recorder");zi=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");Oe.info({url:this.options.startUrl},"Starting recorder"),this.actions=[],this.actionCounter=0,this.running=!0;try{this.browser=await Dg.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=Ub();await this.context.addInitScript(e),this.page=await this.context.newPage(),this.page.on("pageerror",o=>{Oe.warn({error:o.message},"Page error during recording")});let t=async o=>{try{await o.evaluate(e),Oe.debug({url:o.url(),name:o.name()},"Capture script injected into frame")}catch(c){Oe.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){Oe.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),Oe.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}}Oe.debug({dialogType:c,message:l},"Dialog auto-accepted and tagged on triggering action")}),this.page.on("close",()=>{this.running&&(Oe.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),Oe.info("Recorder started \u2014 browser is open for interaction")}catch(e){throw Oe.error({err:e},"Failed to start recorder"),await this.cleanup(),e}}async stop(){if(!this.running)return this.actions;Oe.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 Hb(this.page,s)}catch(o){Oe.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),Oe.debug({action:a.instruction,locator:n,strategy:"resolved"},"Recorded action")}catch(t){Oe.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 Fg(r){let e=r.rootDir,t=r.wsManager;r.post("/recorder/start",async(s,n)=>{try{if(Et?.isRunning)return n.status(409).send({error:"A recording session is already active. Stop it first."});let i=qb.parse(s.body||{}),a=await G(e),o=i.url||a.baseUrl||"https://www.google.com";return Et=new zi({startUrl:o,viewport:i.viewport,onAction:c=>{t.broadcast("recorder:action",c)},onStop:c=>{t.broadcast("recorder:stopped",{actionCount:c.length}),zb.info({actionCount:c.length},"Recording stopped (browser closed)")}}),await Et.start(),n.send({status:"recording",url:o,message:"Browser launched \u2014 interact with your app. Actions are streamed in real time."})}catch(i){return Et=null,w(n,500,"Failed to start recorder",i)}}),r.post("/recorder/stop",async(s,n)=>{try{if(!Et?.isRunning)return n.status(404).send({error:"No active recording session."});let i=await Et.stop();return Et=null,t.broadcast("recorder:stopped",{actionCount:i.length}),n.send({status:"stopped",actions:i,actionCount:i.length})}catch(i){return Et=null,w(n,500,"Failed to stop recorder",i)}}),r.get("/recorder/status",async(s,n)=>{let i=Et?.isRunning??!1,a=Et?.recordedActions.length??0;return n.send({recording:i,actionCount:a,actions:i?Et.recordedActions:[]})})}var $s,zb,qb,Et,Mg=b(()=>{"use strict";m();$s=require("zod");Ng();Te();te();F();zb=C("recorder-routes"),qb=$s.z.object({url:$s.z.string().url().optional(),viewport:$s.z.object({width:$s.z.number().int().positive(),height:$s.z.number().int().positive()}).optional()}),Et=null});var jg,Bg=b(()=>{"use strict";m();oo();jg=async r=>{r.get("/faker/generators",async(e,t)=>{let s=ci();return t.send(s)})}});async function Ug(r){let e=r.rootDir;r.get("/visual-regression/config",async(t,s)=>{try{let n=await an(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 an(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 gp(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 wp(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 bp(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(gn.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 fp(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 pi(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 hp(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 yp(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=gn.default.resolve(e,n);if(!i.startsWith(gn.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=gn.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,gn,Hg=b(()=>{"use strict";m();_s=x(require("fs-extra")),gn=x(require("path"));te();wo()});function Gg(r){return Os.default.join(r,".assuremind","ci-integration.json")}function zg(r){return Os.default.join(r,"results","quality-gates")}function Qb(r,e){return Os.default.join(zg(r),`${e}.json`)}async function Wi(r){let e=Gg(r);if(!await er.default.pathExists(e))return qi.parse({});try{let t=await er.default.readJson(e);return qi.parse(t)}catch{return qi.parse({})}}async function qg(r,e){let t=Gg(r),s=qi.parse(e);await er.default.ensureDir(Os.default.dirname(t)),await W(t,s)}async function Kg(r){let e=zg(r);if(!await er.default.pathExists(e))return[];try{let s=(await er.default.readdir(e)).filter(i=>i.endsWith(".json")).sort().reverse(),n=[];for(let i of s)try{let a=await er.default.readJson(Os.default.join(e,i));n.push(Vg.parse(a))}catch{}return n}catch{return[]}}async function Wg(r,e){let t=Qb(r,e);if(!await er.default.pathExists(t))return null;try{let s=await er.default.readJson(t);return Vg.parse(s)}catch{return null}}var Os,er,L,Ki,Kb,Wb,Xb,Jb,qi,Yb,Vg,Xg=b(()=>{"use strict";m();Os=x(require("path")),er=x(require("fs-extra")),L=require("zod");ze();Ki=L.z.enum(["every-run","failure","healing"]),Kb=L.z.object({enabled:L.z.boolean().default(!1),webhookUrl:L.z.string().default(""),on:L.z.array(Ki).default(["failure"])}),Wb=L.z.object({enabled:L.z.boolean().default(!1),recipients:L.z.array(L.z.string()).default([]),on:L.z.array(Ki).default(["failure"])}),Xb=L.z.object({enabled:L.z.boolean().default(!1),webhookUrl:L.z.string().default(""),on:L.z.array(Ki).default(["failure"])}),Jb=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(Ki).default(["failure"])}),qi=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:Kb.default({}),email:Wb.default({}),teams:Xb.default({}),customWebhook:Jb.default({})}).default({})}),Yb=L.z.object({name:L.z.string(),passed:L.z.boolean(),expected:L.z.string(),actual:L.z.string()}),Vg=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(Yb),reason:L.z.string().optional()})});function Jg(r){let e=Math.floor(r/60),t=r%60;return e>0?`${e}m ${t}s`:`${t}s`}function Zb(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:*
1503
+ `}async function Yb(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||Qb(e.tag,e.type),o=e.ariaLabel||e.labelText||e.innerText||e.title||"",c=Zb(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 Oe.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 Oe.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 Qb(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 Zb(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 qg,Oe,Yi,Kg=b(()=>{"use strict";m();qg=require("playwright");F();Oe=C("recorder");Yi=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");Oe.info({url:this.options.startUrl},"Starting recorder"),this.actions=[],this.actionCounter=0,this.running=!0;try{this.browser=await qg.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=Jb();await this.context.addInitScript(e),this.page=await this.context.newPage(),this.page.on("pageerror",o=>{Oe.warn({error:o.message},"Page error during recording")});let t=async o=>{try{await o.evaluate(e),Oe.debug({url:o.url(),name:o.name()},"Capture script injected into frame")}catch(c){Oe.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){Oe.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),Oe.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}}Oe.debug({dialogType:c,message:l},"Dialog auto-accepted and tagged on triggering action")}),this.page.on("close",()=>{this.running&&(Oe.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),Oe.info("Recorder started \u2014 browser is open for interaction")}catch(e){throw Oe.error({err:e},"Failed to start recorder"),await this.cleanup(),e}}async stop(){if(!this.running)return this.actions;Oe.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 Yb(this.page,s)}catch(o){Oe.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),Oe.debug({action:a.instruction,locator:n,strategy:"resolved"},"Recorded action")}catch(t){Oe.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 Wg(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=tv.parse(s.body||{}),a=await G(e),o=i.url||a.baseUrl||"https://www.google.com";return Ct=new Yi({startUrl:o,viewport:i.viewport,onAction:c=>{t.broadcast("recorder:action",c)},onStop:c=>{t.broadcast("recorder:stopped",{actionCount:c.length}),ev.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 Os,ev,tv,Ct,Xg=b(()=>{"use strict";m();Os=require("zod");Kg();Te();te();F();ev=C("recorder-routes"),tv=Os.z.object({url:Os.z.string().url().optional(),viewport:Os.z.object({width:Os.z.number().int().positive(),height:Os.z.number().int().positive()}).optional()}),Ct=null});var Jg,Yg=b(()=>{"use strict";m();mo();Jg=async r=>{r.get("/faker/generators",async(e,t)=>{let s=gi();return t.send(s)})}});async function Qg(r){let e=r.rootDir;r.get("/visual-regression/config",async(t,s)=>{try{let n=await on(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 on(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 kp(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 Ap(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 Ls.default.pathExists(n)?(await Ls.default.ensureDir(fn.default.dirname(i)),await Ls.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 Pp(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 wi(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 Rp(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 Tp(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=fn.default.resolve(e,n);if(!i.startsWith(fn.default.resolve(e)))return s.status(403).send({error:"Forbidden"});if(!await Ls.default.pathExists(i))return s.status(404).send({error:"Image not found"});let a=fn.default.extname(i).toLowerCase(),c={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp"}[a]??"application/octet-stream",l=await Ls.default.readFile(i);return s.type(c).send(l)}catch(n){return w(s,500,"Failed to serve image",n)}})}var Ls,fn,Zg=b(()=>{"use strict";m();Ls=x(require("fs-extra")),fn=x(require("path"));te();Eo()});function tf(r){return Ds.default.join(r,".assuremind","ci-integration.json")}function rf(r){return Ds.default.join(r,"results","quality-gates")}function ov(r,e){return Ds.default.join(rf(r),`${e}.json`)}async function ea(r){let e=tf(r);if(!await tr.default.pathExists(e))return Qi.parse({});try{let t=await tr.default.readJson(e);return Qi.parse(t)}catch{return Qi.parse({})}}async function sf(r,e){let t=tf(r),s=Qi.parse(e);await tr.default.ensureDir(Ds.default.dirname(t)),await W(t,s)}async function nf(r){let e=rf(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(Ds.default.join(e,i));n.push(ef.parse(a))}catch{}return n}catch{return[]}}async function af(r,e){let t=ov(r,e);if(!await tr.default.pathExists(t))return null;try{let s=await tr.default.readJson(t);return ef.parse(s)}catch{return null}}var Ds,tr,L,Zi,rv,sv,nv,iv,Qi,av,ef,of=b(()=>{"use strict";m();Ds=x(require("path")),tr=x(require("fs-extra")),L=require("zod");ze();Zi=L.z.enum(["every-run","failure","healing"]),rv=L.z.object({enabled:L.z.boolean().default(!1),webhookUrl:L.z.string().default(""),on:L.z.array(Zi).default(["failure"])}),sv=L.z.object({enabled:L.z.boolean().default(!1),recipients:L.z.array(L.z.string()).default([]),on:L.z.array(Zi).default(["failure"])}),nv=L.z.object({enabled:L.z.boolean().default(!1),webhookUrl:L.z.string().default(""),on:L.z.array(Zi).default(["failure"])}),iv=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(Zi).default(["failure"])}),Qi=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:rv.default({}),email:sv.default({}),teams:nv.default({}),customWebhook:iv.default({})}).default({})}),av=L.z.object({name:L.z.string(),passed:L.z.boolean(),expected:L.z.string(),actual:L.z.string()}),ef=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(av),reason:L.z.string().optional()})});function cf(r){let e=Math.floor(r/60),t=r%60;return e>0?`${e}m ${t}s`:`${t}s`}function cv(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:*
1504
1504
  ${s}`},{type:"mrkdwn",text:`*Pass Rate:*
1505
1505
  ${t}% (${r.passed}/${e})`},{type:"mrkdwn",text:`*Failed:*
1506
1506
  ${r.failed}`},{type:"mrkdwn",text:`*Duration:*
1507
- ${Jg(r.duration)}`}]}];return n.length>0&&i.push({type:"section",text:{type:"mrkdwn",text:`*Failed Tests:*
1507
+ ${cf(r.duration)}`}]}];return n.length>0&&i.push({type:"section",text:{type:"mrkdwn",text:`*Failed Tests:*
1508
1508
  ${n.map(a=>`\u2022 ${a}`).join(`
1509
- `)}`}}),i.push({type:"context",elements:[{type:"mrkdwn",text:":robot_face: Generated by Assuremind"}]}),{blocks:i}}function ev(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:Jg(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 tv(r,e){let t=Zb(e);tr.info("Sending Slack notification");let s=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(s.ok)tr.info("Slack notification sent");else{let n=await s.text();tr.error({status:s.status,text:n},"Failed to send Slack notification")}}async function rv(r,e){let t=ev(e);tr.info("Sending Teams notification");let s=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(s.ok)tr.info("Teams notification sent");else{let n=await s.text();tr.error({status:s.status,text:n},"Failed to send Teams notification")}}async function sv(r,e,t){tr.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)tr.info("Custom webhook notification sent");else{let n=await s.text();tr.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 tv(s,t),{ok:!0}):{ok:!1,error:"Slack webhook URL not configured"}}case"teams":{let{webhookUrl:s}=e.notifications.teams;return s?(await rv(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 sv(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 tr,Qg=b(()=>{"use strict";m();F();tr=C("notifier")});async function Zg(r){let e=r.rootDir;r.get("/ci-integration/config",async(t,s)=>{try{let n=await Wi(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 qg(e,n);let i=await Wi(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 Kg(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 Wg(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=nv.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid request",details:n.error.issues});try{let i=await Wi(e),a=await Yg(n.data.channel,i);return s.send(a)}catch(i){return w(s,500,"Failed to send test notification",i)}})}var ac,nv,ef=b(()=>{"use strict";m();ac=require("zod");Xg();Qg();te();nv=ac.z.object({channel:ac.z.enum(["slack","teams","custom"])})});var af={};Q(af,{startServer:()=>iv});async function iv(r){let{port:e,rootDir:t}=r,s=(0,rf.default)({logger:!1}),n=new In;return s.decorate("rootDir",t),s.decorate("wsManager",n),await s.register(sf.default,{origin:!0,methods:["GET","POST","PUT","PATCH","DELETE","OPTIONS"]}),await s.register(nf.default),s.get("/ws",{websocket:!0},i=>{n.add(i)}),await s.register(Gc,{prefix:"/api"}),await s.register(Jc,{prefix:"/api"}),await s.register(sl,{prefix:"/api"}),await s.register(cl,{prefix:"/api"}),await s.register(Nu,{prefix:"/api"}),await s.register(Wu,{prefix:"/api"}),await s.register(Ju,{prefix:"/api"}),await s.register(dd,{prefix:"/api"}),await s.register(Rm,{prefix:"/api"}),await s.register($m,{prefix:"/api"}),await s.register(Lm,{prefix:"/api"}),await s.register(Um,{prefix:"/api"}),await s.register(eg,{prefix:"/api"}),await s.register(og,{prefix:"/api"}),await s.register(ug,{prefix:"/api"}),await s.register(mg,{prefix:"/api"}),await s.register(yg,{prefix:"/api"}),await s.register(Sg,{prefix:"/api"}),await s.register(Cg,{prefix:"/api"}),await s.register(Pg,{prefix:"/api"}),await s.register(Og,{prefix:"/api"}),await s.register(Fg,{prefix:"/api"}),await s.register(jg,{prefix:"/api"}),await s.register(Ug,{prefix:"/api"}),await s.register(Zg,{prefix:"/api"}),await Uc(s,t),await s.listen({port:e,host:"127.0.0.1"}),tf.info({port:e,rootDir:t},`Assuremind Studio listening on http://127.0.0.1:${e}`),{async close(){await s.close(),tf.info("Server closed")}}}var rf,sf,nf,tf,of=b(()=>{"use strict";m();rf=x(require("fastify")),sf=x(require("@fastify/cors")),nf=x(require("@fastify/websocket"));jc();Bc();Hc();zc();Yc();nl();ll();Fu();Xu();Yu();pd();Tm();_m();Dm();Hm();tg();cg();dg();gg();wg();Eg();Ig();Rg();Lg();Mg();Bg();Hg();ef();F();tf=C("server")});var lf={};Q(lf,{runStudio:()=>av});async function av(r={}){process.on("unhandledRejection",n=>{let i=n instanceof Error?n.message:String(n);X(`Unhandled rejection (non-fatal): ${i}`)}),process.stdout.write(`
1509
+ `)}`}}),i.push({type:"context",elements:[{type:"mrkdwn",text:":robot_face: Generated by Assuremind"}]}),{blocks:i}}function lv(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:cf(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 uv(r,e){let t=cv(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 dv(r,e){let t=lv(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 pv(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 lf(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 uv(s,t),{ok:!0}):{ok:!1,error:"Slack webhook URL not configured"}}case"teams":{let{webhookUrl:s}=e.notifications.teams;return s?(await dv(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 pv(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,uf=b(()=>{"use strict";m();F();rr=C("notifier")});async function df(r){let e=r.rootDir;r.get("/ci-integration/config",async(t,s)=>{try{let n=await ea(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 sf(e,n);let i=await ea(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 nf(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 af(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=mv.safeParse(t.body);if(!n.success)return s.status(400).send({error:"Invalid request",details:n.error.issues});try{let i=await ea(e),a=await lf(n.data.channel,i);return s.send(a)}catch(i){return w(s,500,"Failed to send test notification",i)}})}var dc,mv,pf=b(()=>{"use strict";m();dc=require("zod");of();uf();te();mv=dc.z.object({channel:dc.z.enum(["slack","teams","custom"])})});var yf={};Q(yf,{startServer:()=>gv});async function gv(r){let{port:e,rootDir:t}=r,s=(0,gf.default)({logger:!1}),n=new Pn;return s.decorate("rootDir",t),s.decorate("wsManager",n),await s.register(ff.default,{origin:!0,methods:["GET","POST","PUT","PATCH","DELETE","OPTIONS"]}),await s.register(hf.default),s.get("/ws",{websocket:!0},i=>{n.add(i)}),await s.register(Xc,{prefix:"/api"}),await s.register(tl,{prefix:"/api"}),await s.register(cl,{prefix:"/api"}),await s.register(ml,{prefix:"/api"}),await s.register(qu,{prefix:"/api"}),await s.register(nd,{prefix:"/api"}),await s.register(od,{prefix:"/api"}),await s.register(Sd,{prefix:"/api"}),await s.register(Mm,{prefix:"/api"}),await s.register(Hm,{prefix:"/api"}),await s.register(zm,{prefix:"/api"}),await s.register(Qm,{prefix:"/api"}),await s.register(dg,{prefix:"/api"}),await s.register(wg,{prefix:"/api"}),await s.register(xg,{prefix:"/api"}),await s.register(Cg,{prefix:"/api"}),await s.register(Tg,{prefix:"/api"}),await s.register(Og,{prefix:"/api"}),await s.register(Dg,{prefix:"/api"}),await s.register(Fg,{prefix:"/api"}),await s.register(Gg,{prefix:"/api"}),await s.register(Wg,{prefix:"/api"}),await s.register(Jg,{prefix:"/api"}),await s.register(Qg,{prefix:"/api"}),await s.register(df,{prefix:"/api"}),await qc(s,t),await s.listen({port:e,host:"127.0.0.1"}),mf.info({port:e,rootDir:t},`Assuremind Studio listening on http://127.0.0.1:${e}`),{async close(){await s.close(),mf.info("Server closed")}}}var gf,ff,hf,mf,wf=b(()=>{"use strict";m();gf=x(require("fastify")),ff=x(require("@fastify/cors")),hf=x(require("@fastify/websocket"));Gc();zc();Kc();Jc();rl();ll();gl();Ku();id();cd();Ed();jm();Vm();qm();Zm();pg();bg();Sg();Ig();kg();Lg();Ng();Mg();zg();Xg();Yg();Zg();pf();F();mf=C("server")});var vf={};Q(vf,{runStudio:()=>fv});async function fv(r={}){process.on("unhandledRejection",n=>{let i=n instanceof Error?n.message:String(n);X(`Unhandled rejection (non-fatal): ${i}`)}),process.stdout.write(`
1510
1510
  `),V(`Starting Assuremind Studio\u2026
1511
- `),Vt()||Ge(`AI provider not configured. The Studio will start, but AI features
1511
+ `),Gt()||Ge(`AI provider not configured. The Studio will start, but AI features
1512
1512
  (test generation, code generation, self-healing) require a valid
1513
1513
  AI_PROVIDER and its API key in your .env file.
1514
1514
  See .env.example for details.
1515
- `);let t;try{let n=await G(process.cwd());t=r.port??n.studioPort}catch(n){X(`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(()=>(of(),af)).catch(()=>{throw new fe(`Server module is not available yet.
1515
+ `);let t;try{let n=await G(process.cwd());t=r.port??n.studioPort}catch(n){X(`Config error: ${n instanceof Error?n.message:String(n)}`),process.exit(1)}let s=Pt("Starting server\u2026");s.start();try{let{startServer:n}=await Promise.resolve().then(()=>(wf(),yf)).catch(()=>{throw new fe(`Server module is not available yet.
1516
1516
  This is expected during development \u2014 Phase 5 implements the server.
1517
- 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}`;Ut(["\u{1F9EA} Assuremind Studio","",` URL: ${a}`,` Port: ${t}`,"","Press Ctrl+C to stop"]),r.noOpen||await(0,cf.default)(a),await new Promise((o,c)=>{process.on("SIGINT",()=>{i.close().then(()=>{V(`
1517
+ 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,bf.default)(a),await new Promise((o,c)=>{process.on("SIGINT",()=>{i.close().then(()=>{V(`
1518
1518
  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")?(X(`Port ${t} is already in use.`),V(`Fix: kill the process using the port, then try again:
1519
1519
  npx kill-port ${t}
1520
1520
  npx assuremind studio --port ${t}
1521
1521
 
1522
1522
  Or use a different port:
1523
1523
  npx assuremind studio --port ${t+1}
1524
- `)):X(i),process.exit(1)}}var cf,uf=b(()=>{"use strict";m();cf=x(require("open"));Ht();lr();Te();re()});var pf={};Q(pf,{runRun:()=>pv});function ov(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 cv(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>
1525
- 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 oc(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 df(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 lv(r,e){let t=df(r.status),s=O.dim(`(${oc(r.duration)})`);if(process.stdout.write(` ${t} ${r.caseName} ${s}
1524
+ `)):X(i),process.exit(1)}}var bf,xf=b(()=>{"use strict";m();bf=x(require("open"));Vt();ur();Te();re()});var Ef={};Q(Ef,{runRun:()=>xv});function hv(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 yv(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>
1525
+ 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 pc(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 Sf(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 wv(r,e){let t=Sf(r.status),s=O.dim(`(${pc(r.duration)})`);if(process.stdout.write(` ${t} ${r.caseName} ${s}
1526
1526
  `),!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)}
1527
1527
  `),n.error){let i=n.error.split(`
1528
1528
  `)[0]?.slice(0,120)??"";process.stdout.write(` ${O.dim(i)}
1529
1529
  `)}n.healed&&process.stdout.write(` ${O.warn("\u2695")} ${O.dim("Self-healed \u2014 review in Studio")}
1530
- `)}}}function uv(r,e){let t=df(r.status),s=O.dim(`(${oc(r.duration)})`),n=O.dim(`[${r.browser}]`);process.stdout.write(`
1530
+ `)}}}function bv(r,e){let t=Sf(r.status),s=O.dim(`(${pc(r.duration)})`),n=O.dim(`[${r.browser}]`);process.stdout.write(`
1531
1531
  ${t} ${O.bold(r.suiteName)} ${n} ${s}
1532
- `);for(let i of r.cases)lv(i,e)}function dv(r,e){let t=oc(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(`
1533
- `);for(let o of r.suites)uv(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`];Ut(a)}async function pv(r){process.stdout.write(`
1534
- `);try{cv(r)}catch(d){X(d instanceof Error?d.message:String(d)),process.exit(1)}try{cr()}catch(d){X(d instanceof Error?d.message:String(d)),process.exit(1)}let e=process.cwd(),t;try{t=await G(e)}catch(d){X(d instanceof Error?d.message:String(d)),process.exit(1)}let s=ov(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(`
1535
- `);let o=It("Loading test runner\u2026");o.start();let c;try{c=(await Promise.resolve().then(()=>(Mo(),Pm))).runTests,o.succeed("Runner loaded")}catch{o.fail("Failed to load test runner"),X(`Test runner could not be loaded.
1536
- 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"),X(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")),dv(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 mf=b(()=>{"use strict";m();Ht();lr();Te();re()});var gf={};Q(gf,{runGenerate:()=>gv});async function mv(r){if(r.story)return r.story;if(r.storyFile){let e=Ls.default.resolve(r.storyFile);if(!await cc.default.pathExists(e))throw new fe(`Story file not found: "${e}"`,"STORY_FILE_NOT_FOUND");return cc.default.readFile(e,"utf8")}throw new fe('Provide a story with --story "<text>" or --story-file <path>',"GENERATE_NO_STORY")}async function gv(r){process.stdout.write(`
1537
- `);try{cr()}catch(o){X(o instanceof Error?o.message:String(o)),process.exit(1)}let e;try{e=await mv(r)}catch(o){X(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: ${O.dim(`${e.slice(0,80)}${e.length>80?"\u2026":""}`)}`),r.suite&&V(`Suite name: ${r.suite}`),V(`Output: ${s}`),process.stdout.write(`
1538
- `);let n=It("Loading AI layer\u2026");n.start();let i;try{i=(await Promise.resolve().then(()=>(gr(),Ou))).generateSuiteFromStory,n.succeed("AI layer ready")}catch{n.fail("Failed to load AI layer"),X(`AI layer could not be loaded.
1539
- 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(` ${O.accent("npx assuremind studio")}
1540
-
1541
- `)}catch(o){a.fail("Generation failed"),X(o instanceof Error?o.message:String(o)),process.exit(1)}}var Ls,cc,ff=b(()=>{"use strict";m();Ls=x(require("path")),cc=x(require("fs-extra"));Ht();lr();re()});var hf={};Q(hf,{runValidate:()=>bv});async function fv(r,e){if(V("Checking configuration\u2026"),!await fn.default.pathExists(Ds.default.join(r,"autotest.config.json"))&&!await fn.default.pathExists(Ds.default.join(r,"autotest.config.ts"))){X(' 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: ${O.accent(t.baseUrl)}, browsers: ${t.browsers.join(", ")}`),e.passed++}catch(t){X(` Config invalid: ${t instanceof Error?t.message:String(t)}`),e.errors++}}async function hv(r){if(V("Checking environment\u2026"),!await fn.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=Vt();if(!e){X(" .env validation failed \u2014 check required variables for your AI provider"),r.errors++;return}Pe(` Provider: ${O.accent(String(e.AI_PROVIDER))}, tiered: ${e.AI_TIERED_ENABLED}`),r.passed++}async function yv(r,e){V("Scanning test files\u2026");let t=Ds.default.join(r,"tests");if(!await fn.default.pathExists(t)){Ge(" tests/ directory not found \u2014 no tests to validate"),e.warnings++;return}let s=await At(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 Gt(o);n+=c.length;for(let l of c)try{await se(l)}catch{X(` Invalid: ${Ds.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 wv(r,e){V("Checking variable files\u2026");let t=await fl(r);if(t.length===0){Ge(" No variable files found"),e.warnings++;return}let s=0;for(let n of t)try{await ss(n)}catch{X(` Invalid: ${Ds.default.relative(r,n)}`),s++,e.errors++}s===0?(Pe(` ${t.length} variable file(s) \u2014 all valid`),e.passed++):e.warnings++}async function bv(){let r=process.cwd();process.stdout.write(`
1542
- `);let e={passed:0,warnings:0,errors:0};await fv(r,e),process.stdout.write(`
1543
- `),await hv(e),process.stdout.write(`
1544
- `),await yv(r,e),process.stdout.write(`
1545
- `),await wv(r,e),process.stdout.write(`
1532
+ `);for(let i of r.cases)wv(i,e)}function vv(r,e){let t=pc(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(`
1533
+ `);for(let o of r.suites)bv(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 xv(r){process.stdout.write(`
1534
+ `);try{yv(r)}catch(d){X(d instanceof Error?d.message:String(d)),process.exit(1)}try{lr()}catch(d){X(d instanceof Error?d.message:String(d)),process.exit(1)}let e=process.cwd(),t;try{t=await G(e)}catch(d){X(d instanceof Error?d.message:String(d)),process.exit(1)}let s=hv(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(`
1535
+ `);let o=Pt("Loading test runner\u2026");o.start();let c;try{c=(await Promise.resolve().then(()=>(Vo(),Fm))).runTests,o.succeed("Runner loaded")}catch{o.fail("Failed to load test runner"),X(`Test runner could not be loaded.
1536
+ Make sure you have run "npm run build" or are running from source.`),process.exit(1)}let l=Pt("Running tests\u2026");r.ci||l.start();let u;try{u=await c(e,s,t)}catch(d){r.ci||l.fail("Run failed"),X(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")),vv(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 Cf=b(()=>{"use strict";m();Vt();ur();Te();re()});var If={};Q(If,{runGenerate:()=>Ev});async function Sv(r){if(r.story)return r.story;if(r.storyFile){let e=Ns.default.resolve(r.storyFile);if(!await mc.default.pathExists(e))throw new fe(`Story file not found: "${e}"`,"STORY_FILE_NOT_FOUND");return mc.default.readFile(e,"utf8")}throw new fe('Provide a story with --story "<text>" or --story-file <path>',"GENERATE_NO_STORY")}async function Ev(r){process.stdout.write(`
1537
+ `);try{lr()}catch(o){X(o instanceof Error?o.message:String(o)),process.exit(1)}let e;try{e=await Sv(r)}catch(o){X(o instanceof Error?o.message:String(o)),process.exit(1)}let t=process.cwd(),s=r.output?Ns.default.resolve(r.output):Ns.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(`
1538
+ `);let n=Pt("Loading AI layer\u2026");n.start();let i;try{i=(await Promise.resolve().then(()=>(fr(),Vu))).generateSuiteFromStory,n.succeed("AI layer ready")}catch{n.fail("Failed to load AI layer"),X(`AI layer could not be loaded.
1539
+ Make sure you have run "npm run build" or are running from source.`),process.exit(1)}let a=Pt(`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??Ns.default.join(t,"tests");Pe(`Test suite created in: ${Ns.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")}
1540
+
1541
+ `)}catch(o){a.fail("Generation failed"),X(o instanceof Error?o.message:String(o)),process.exit(1)}}var Ns,mc,Pf=b(()=>{"use strict";m();Ns=x(require("path")),mc=x(require("fs-extra"));Vt();ur();re()});var Rf={};Q(Rf,{runValidate:()=>Tv});async function Cv(r,e){if(V("Checking configuration\u2026"),!await hn.default.pathExists(Fs.default.join(r,"autotest.config.json"))&&!await hn.default.pathExists(Fs.default.join(r,"autotest.config.ts"))){X(' 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: ${O.accent(t.baseUrl)}, browsers: ${t.browsers.join(", ")}`),e.passed++}catch(t){X(` Config invalid: ${t instanceof Error?t.message:String(t)}`),e.errors++}}async function Iv(r){if(V("Checking environment\u2026"),!await hn.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){X(" .env validation failed \u2014 check required variables for your AI provider"),r.errors++;return}Pe(` Provider: ${O.accent(String(e.AI_PROVIDER))}, tiered: ${e.AI_TIERED_ENABLED}`),r.passed++}async function Pv(r,e){V("Scanning test files\u2026");let t=Fs.default.join(r,"tests");if(!await hn.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{X(` Invalid: ${Fs.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 Rv(r,e){V("Checking variable files\u2026");let t=await Il(r);if(t.length===0){Ge(" No variable files found"),e.warnings++;return}let s=0;for(let n of t)try{await pr(n)}catch{X(` Invalid: ${Fs.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(`
1542
+ `);let e={passed:0,warnings:0,errors:0};await Cv(r,e),process.stdout.write(`
1543
+ `),await Iv(e),process.stdout.write(`
1544
+ `),await Pv(r,e),process.stdout.write(`
1545
+ `),await Rv(r,e),process.stdout.write(`
1546
1546
  `);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}
1547
1547
 
1548
- `),e.errors>0&&process.exit(1)}var Ds,fn,yf=b(()=>{"use strict";m();Ds=x(require("path")),fn=x(require("fs-extra"));Ht();Te();Ke();gt();pr();lr()});var wf={};Q(wf,{runDoctor:()=>Tv});function ge(r,e,t){return{label:r,ok:e,detail:t}}function uc(r){try{return(0,lc.execSync)(r,{stdio:"pipe"}).toString().trim()}catch{return""}}async function vv(){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 xv(){let r=uc("npm --version");return r?ge("npm",!0,`v${r}`):ge("npm",!1,"npm not found \u2014 ensure Node.js is installed correctly")}async function Sv(){let r=uc("npx playwright --version");if(!r)return ge("Playwright",!1,'Not found \u2014 run "npx assuremind init" to install');try{return(0,lc.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 Ev(){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=Vt();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 Cv(){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 Iv(){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 Pv(){let r=Vt();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=uc(`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 Rv(r){r.ok?Pe(` ${O.bold(r.label)}: ${O.dim(r.detail)}`):X(` ${O.bold(r.label)}: ${r.detail}`)}async function Tv(){process.stdout.write(`
1548
+ `),e.errors>0&&process.exit(1)}var Fs,hn,Tf=b(()=>{"use strict";m();Fs=x(require("path")),hn=x(require("fs-extra"));Vt();Te();Ke();gt();mr();ur()});var kf={};Q(kf,{runDoctor:()=>Fv});function ge(r,e,t){return{label:r,ok:e,detail:t}}function fc(r){try{return(0,gc.execSync)(r,{stdio:"pipe"}).toString().trim()}catch{return""}}async function kv(){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 Av(){let r=fc("npm --version");return r?ge("npm",!0,`v${r}`):ge("npm",!1,"npm not found \u2014 ensure Node.js is installed correctly")}async function $v(){let r=fc("npx playwright --version");if(!r)return ge("Playwright",!1,'Not found \u2014 run "npx assuremind init" to install');try{return(0,gc.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 _v(){if(!await ta.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 Ov(){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 Lv(){if(!await ta.default.pathExists("package.json"))return ge("package.json",!1,'Not found \u2014 run "npm init -y" first');try{let r=await ta.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 Dv(){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=fc(`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 Nv(r){r.ok?Pe(` ${O.bold(r.label)}: ${O.dim(r.detail)}`):X(` ${O.bold(r.label)}: ${r.detail}`)}async function Fv(){process.stdout.write(`
1549
1549
  `),V(`Running Assuremind system diagnostics\u2026
1550
- `);let r=await Promise.all([vv(),xv(),Iv(),Sv(),Ev(),Cv(),Pv()]);for(let s of r)Rv(s);let e=r.filter(s=>!s.ok),t=r.filter(s=>s.ok);process.stdout.write(`
1551
- `),e.length===0?Ut(["\u2705 All checks passed \u2014 Assuremind is ready!","","Run: npx assuremind studio"]):(Ut([`\u26A0 ${t.length}/${r.length} checks passed`,"",'Fix the issues above, then run "npx assuremind doctor" again.']),process.exit(1))}var lc,Xi,bf=b(()=>{"use strict";m();lc=require("child_process"),Xi=x(require("fs-extra"));Ht();lr();Te()});var Sf={};Q(Sf,{runApplyHealing:()=>Dv});async function kv(r,e){let t=await At(r);for(let s of t){let n=await Gt(s);for(let i of n)try{if((await se(i)).id===e)return i}catch{}}return null}async function Av(r,e){let t=Ns.default.join(r,"tests"),s=await kv(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 Ks(s,n),Pe(` Updated: ${Ns.default.relative(r,s)} \u203A step "${n.steps[i].instruction}"`)}function $v(r,e){return new Promise(t=>r.question(e,t))}function _v(r){process.stdout.write(`
1550
+ `);let r=await Promise.all([kv(),Av(),Lv(),$v(),_v(),Ov(),Dv()]);for(let s of r)Nv(s);let e=r.filter(s=>!s.ok),t=r.filter(s=>s.ok);process.stdout.write(`
1551
+ `),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 gc,ta,Af=b(()=>{"use strict";m();gc=require("child_process"),ta=x(require("fs-extra"));Vt();ur();Te()});var Of={};Q(Of,{runApplyHealing:()=>Gv});async function Mv(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 jv(r,e){let t=Ms.default.join(r,"tests"),s=await Mv(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 Xs(s,n),Pe(` Updated: ${Ms.default.relative(r,s)} \u203A step "${n.steps[i].instruction}"`)}function Bv(r,e){return new Promise(t=>r.question(e,t))}function Uv(r){process.stdout.write(`
1552
1552
  ${O.bold("Step:")} ${r.stepInstruction}
1553
1553
  ${O.bold("Case:")} ${r.caseId}
1554
1554
  ${O.dim("Error:")} ${r.error}
1555
1555
 
1556
1556
  ${O.error("- "+r.failedCode)}
1557
1557
  ${O.success("+ "+r.healedCode)}
1558
- `)}async function Ov(r,e,t){let s={accepted:0,rejected:0,skipped:0},n=vf.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
+ `)}async function Hv(r,e,t){let s={accepted:0,rejected:0,skipped:0},n=$f.default.createInterface({input:process.stdin,output:process.stdout});try{for(let i=0;i<e.length;i++){let a=e[i];process.stdout.write(`
1559
1559
  ${O.accent(`[${i+1}/${e.length}]`)} Healing event ${O.dim(a.id)}
1560
- `),_v(a);let o;if(t?(o="y",process.stdout.write(` Accept? ${O.dim("(auto-accepting all)")} y
1561
- `)):o=(await $v(n,` Accept? ${O.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 Av(r,a),await en(r,a.id),s.accepted++}catch(c){X(` Failed to apply: ${c instanceof Error?c.message:String(c)}`),s.skipped++}else await Gn(r,a.id),V(" Rejected \u2014 step will keep original code"),s.rejected++}}finally{n.close()}return s}async function Lv(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 ks(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)
1560
+ `),Uv(a);let o;if(t?(o="y",process.stdout.write(` Accept? ${O.dim("(auto-accepting all)")} y
1561
+ `)):o=(await Bv(n,` Accept? ${O.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 jv(r,a),await tn(r,a.id),s.accepted++}catch(c){X(` Failed to apply: ${c instanceof Error?c.message:String(c)}`),s.skipped++}else await Jn(r,a.id),V(" Rejected \u2014 step will keep original code"),s.rejected++}}finally{n.close()}return s}async function Vv(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 $s(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)
1562
1562
 
1563
1563
  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
1564
1564
 
@@ -1572,12 +1572,12 @@ Assuremind detected and fixed **${e}** broken test selector(s) during CI executi
1572
1572
  Review the changes and merge if the fixes look correct.
1573
1573
 
1574
1574
  ---
1575
- \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();X(`Failed to create PR: ${p.message||d.statusText}`)}await a.checkout(i)}catch(l){let u=l instanceof Error?l.message:String(l);X(`Auto PR failed: ${u}`);try{await a.checkout(i)}catch{}}}async function Dv(r){let e=process.cwd();(0,xf.config)({path:Ns.default.join(e,".env")}),process.stdout.write(`
1576
- `);let t;if(r.from){let n=Ns.default.resolve(r.from);await dc.default.pathExists(n)||(X(`Healing report not found: ${n}`),process.exit(1));try{let i=Ns.default.basename(n,".json").replace("healing-report-","");t=(await Vn(e,i)).events.filter(o=>o.status==="pending")}catch{let i=await dc.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 ${O.bold(String(t.length))} pending healing event(s).
1577
- `);let s=await Ov(e,t,r.yes??!1);if(process.stdout.write(`
1575
+ \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();X(`Failed to create PR: ${p.message||d.statusText}`)}await a.checkout(i)}catch(l){let u=l instanceof Error?l.message:String(l);X(`Auto PR failed: ${u}`);try{await a.checkout(i)}catch{}}}async function Gv(r){let e=process.cwd();(0,_f.config)({path:Ms.default.join(e,".env")}),process.stdout.write(`
1576
+ `);let t;if(r.from){let n=Ms.default.resolve(r.from);await hc.default.pathExists(n)||(X(`Healing report not found: ${n}`),process.exit(1));try{let i=Ms.default.basename(n,".json").replace("healing-report-","");t=(await Xn(e,i)).events.filter(o=>o.status==="pending")}catch{let i=await hc.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 ${O.bold(String(t.length))} pending healing event(s).
1577
+ `);let s=await Hv(e,t,r.yes??!1);if(process.stdout.write(`
1578
1578
  `),V(`Done: ${O.success(String(s.accepted)+" accepted")}, ${O.error(String(s.rejected)+" rejected")}, ${O.dim(String(s.skipped)+" skipped")}`),process.stdout.write(`
1579
1579
  `),s.accepted>0)try{(await G(e)).healing.autoPR&&(V(`Auto PR enabled \u2014 creating pull request with healed code...
1580
- `),await Lv(e,s.accepted))}catch{}}var Ns,dc,vf,xf,Ef=b(()=>{"use strict";m();Ns=x(require("path")),dc=x(require("fs-extra")),vf=x(require("readline")),xf=require("dotenv");zn();Ke();gt();Te();Xo();Ht()});m();var If=require("commander"),Pf=require("module");Ht();var Nv=(0,Pf.createRequire)(__filename),Cf=Nv("../../package.json"),rr=new If.Command;rr.name("assuremind").description(Cf.description).version(Cf.version,"-v, --version","Print version number");rr.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(()=>(_c(),$c));await e({skipPlaywright:r.skipPlaywright}).catch(Pt)});rr.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(()=>(uf(),lf));await e({port:r.port,noOpen:r.open===!1}).catch(Pt)});rr.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",`
1580
+ `),await Vv(e,s.accepted))}catch{}}var Ms,hc,$f,_f,Lf=b(()=>{"use strict";m();Ms=x(require("path")),hc=x(require("fs-extra")),$f=x(require("readline")),_f=require("dotenv");Yn();Ke();gt();Te();ec();Vt()});m();var Nf=require("commander"),Ff=require("module");Vt();var zv=(0,Ff.createRequire)(__filename),Df=zv("../../package.json"),sr=new Nf.Command;sr.name("assuremind").description(Df.description).version(Df.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(()=>(Fc(),Nc));await e({skipPlaywright:r.skipPlaywright}).catch(Rt)});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(()=>(xf(),vf));await e({port:r.port,noOpen:r.open===!1}).catch(Rt)});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",`
1581
1581
  Examples:
1582
1582
  assuremind run --all
1583
1583
  assuremind run --type ui
@@ -1595,7 +1595,7 @@ Examples:
1595
1595
 
1596
1596
  Filters are combinable (AND logic \u2014 all specified filters must match).
1597
1597
  Device names must match Playwright device descriptors exactly (case-sensitive).
1598
- `).action(async r=>{let{runRun:e}=await Promise.resolve().then(()=>(mf(),pf));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)});rr.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(()=>(ff(),gf));await e(r).catch(Pt)});rr.command("validate").description("Validate config, environment, and test files").action(async()=>{let{runValidate:r}=await Promise.resolve().then(()=>(yf(),hf));await r().catch(Pt)});rr.command("doctor").description("Check system requirements and configuration health").action(async()=>{let{runDoctor:r}=await Promise.resolve().then(()=>(bf(),wf));await r().catch(Pt)});rr.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(()=>(Ef(),Sf));await e(r).catch(Pt)});rr.parse(process.argv);
1598
+ `).action(async r=>{let{runRun:e}=await Promise.resolve().then(()=>(Cf(),Ef));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(Rt)});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(()=>(Pf(),If));await e(r).catch(Rt)});sr.command("validate").description("Validate config, environment, and test files").action(async()=>{let{runValidate:r}=await Promise.resolve().then(()=>(Tf(),Rf));await r().catch(Rt)});sr.command("doctor").description("Check system requirements and configuration health").action(async()=>{let{runDoctor:r}=await Promise.resolve().then(()=>(Af(),kf));await r().catch(Rt)});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(()=>(Lf(),Of));await e(r).catch(Rt)});sr.parse(process.argv);
1599
1599
  /*! Bundled license information:
1600
1600
 
1601
1601
  lighthouse-logger/index.js: