assuremind 1.5.3 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/cli/index.js +198 -198
- package/dist/index.d.mts +144 -149
- package/dist/index.d.ts +144 -149
- package/dist/index.js +31 -31
- package/dist/index.mjs +32 -32
- package/docs/GETTING-STARTED.md +39 -12
- package/package.json +1 -1
- package/templates/docs/GETTING-STARTED.md +7 -6
- package/ui/dist/assets/index-BsxznSas.css +1 -0
- package/ui/dist/assets/index-DdWg6Y6w.js +1032 -0
- package/ui/dist/index.html +2 -2
- package/ui/dist/assets/index-CDdZfob4.css +0 -1
- package/ui/dist/assets/index-Dqfu_NfK.js +0 -1029
package/dist/index.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
"use strict";var Ut=Object.create;var Y=Object.defineProperty;var kt=Object.getOwnPropertyDescriptor;var Gt=Object.getOwnPropertyNames;var Mt=Object.getPrototypeOf,Bt=Object.prototype.hasOwnProperty;var Wt=(e,t)=>{for(var n in t)Y(e,n,{get:t[n],enumerable:!0})},Ve=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Gt(t))!Bt.call(e,i)&&i!==n&&Y(e,i,{get:()=>t[i],enumerable:!(r=kt(t,i))||r.enumerable});return e};var h=(e,t,n)=>(n=e!=null?Ut(Mt(e)):{},Ve(t||!e||!e.__esModule?Y(n,"default",{value:e,enumerable:!0}):n,e)),Jt=e=>Ve(Y({},"__esModule",{value:!0}),e);var Jn={};Wt(Jn,{AssuremindError:()=>v,ConfigError:()=>C,ExecutionError:()=>Z,HealingError:()=>Q,ProviderError:()=>X,StorageError:()=>g,ValidationError:()=>u,acceptHealingEvent:()=>Ct,appendPendingEvent:()=>jt,callFaker:()=>zt,clearEnvCache:()=>Dt,configExists:()=>ut,createCase:()=>et,createChildLogger:()=>b,createSuite:()=>Ke,defineConfig:()=>Wn,deleteCase:()=>nt,deleteGlobalVariable:()=>ct,deleteResult:()=>bt,deleteSuite:()=>qe,formatError:()=>Ue,generateCacheKey:()=>$t,getAvailableGenerators:()=>Ft,getCasePath:()=>it,getHealingStats:()=>_t,isAssuremindError:()=>ze,listCasePaths:()=>Se,listCases:()=>rt,listHealingReportIds:()=>Nt,listResultIds:()=>_e,listResults:()=>xt,listSuiteDirs:()=>ne,listSuites:()=>Xe,listSuitesWithCounts:()=>Ze,listVariableFiles:()=>lt,logger:()=>he,normalizeUrl:()=>$e,pruneResolvedEvents:()=>Pt,readCase:()=>ae,readConfig:()=>le,readEnvVariables:()=>ve,readGlobalVariables:()=>we,readHealingReport:()=>It,readPendingEvents:()=>V,readResult:()=>Pe,readSuite:()=>G,readVariables:()=>H,redactSecrets:()=>Be,rejectHealingEvent:()=>Tt,resolveVariables:()=>ot,sanitizeGeneratedCode:()=>Me,screenshotsDir:()=>St,setGlobalVariable:()=>st,sha256:()=>Oe,toSlug:()=>N,tracesDir:()=>Et,tryGetEnv:()=>Ht,updateCase:()=>tt,updateConfig:()=>pt,updateSuite:()=>Ye,validateConfig:()=>dt,validateEnv:()=>Le,videosDir:()=>yt,writeCase:()=>oe,writeConfig:()=>Ie,writeHealingReport:()=>Rt,writeResult:()=>ht,writeSuite:()=>te,writeVariables:()=>se});module.exports=Jt(Jn);var c=require("zod"),Kt=c.z.enum(["off","on","only-on-failure"]),Yt=c.z.enum(["off","on","on-first-retry","retain-on-failure"]),qt=c.z.enum(["off","on","on-first-retry","retain-on-failure"]),De=c.z.enum(["chromium","firefox","webkit"]),Xt=c.z.enum(["commit","domcontentloaded","load","networkidle"]),He=c.z.enum(["dev","stage","test","prod"]),Zt=c.z.object({dev:c.z.string().url().or(c.z.literal("")).default(""),stage:c.z.string().url().or(c.z.literal("")).default(""),test:c.z.string().url().or(c.z.literal("")).default(""),prod:c.z.string().url().or(c.z.literal("")).default("")}),Qt=c.z.object({enabled:c.z.boolean(),maxLevel:c.z.number().int().min(1).max(5),dailyBudget:c.z.number().positive(),autoPR:c.z.boolean(),healAssertionLocators:c.z.boolean().default(!1)}),en=c.z.object({allure:c.z.boolean(),html:c.z.boolean(),json:c.z.boolean()}),tn=c.z.object({width:c.z.number().int().positive(),height:c.z.number().int().positive()}),nn=c.z.object({name:c.z.string().min(1),environment:He,baseUrl:c.z.string().url(),browsers:c.z.array(De).min(1),headless:c.z.boolean().optional()}),z=c.z.object({baseUrl:c.z.string().url(),environment:He.default("stage"),environmentUrls:Zt.default({dev:"",stage:"",test:"",prod:""}),browsers:c.z.array(De).min(1),headless:c.z.boolean(),viewport:tn.default({width:1280,height:720}),timeout:c.z.number().int().positive(),retries:c.z.number().int().min(0),parallel:c.z.number().int().positive(),pageLoad:Xt.default("domcontentloaded"),screenshot:Kt,video:Yt,trace:qt,healing:Qt,reporting:en,studioPort:c.z.number().int().min(1024).max(65535),profiles:c.z.array(nn).default([]),activeProfile:c.z.string().optional(),device:c.z.string().optional(),rag:c.z.object({enabled:c.z.boolean(),codeCorpus:c.z.object({enabled:c.z.boolean(),maxEntries:c.z.number().int().positive(),similarityThreshold:c.z.number().min(0).max(1),directUseThreshold:c.z.number().min(0).max(1)}),healingCorpus:c.z.object({enabled:c.z.boolean(),maxEntries:c.z.number().int().positive(),similarityThreshold:c.z.number().min(0).max(1)}),errorCatalog:c.z.object({enabled:c.z.boolean(),maxEntries:c.z.number().int().positive()}),embedder:c.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:c.z.object({enabled:c.z.boolean(),headless:c.z.boolean(),actThenScript:c.z.boolean(),proactiveHealing:c.z.boolean(),actionTimeout:c.z.number().int().positive(),idleTimeout:c.z.number().int().positive()}).default({enabled:!0,headless:!0,actThenScript:!1,proactiveHealing:!1,actionTimeout:15e3,idleTimeout:3e4}),ci:c.z.object({writeToRepo:c.z.boolean()}).default({writeToRepo:!1})}),q={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 S=h(require("path")),I=h(require("fs-extra")),Je=require("uuid");var l=require("zod"),U=l.z.object({id:l.z.string().min(1),order:l.z.number().int().positive(),instruction:l.z.string().min(1),generatedCode:l.z.string(),strategy:l.z.enum(["template","cache","rag","batch","fast","primary","recorder"]),stepType:l.z.enum(["ui","api","mock"]).default("ui"),lastHealed:l.z.string().nullable(),timeout:l.z.number().int().positive().optional(),retries:l.z.number().int().min(0).optional(),mockUrl:l.z.string().optional(),mockResponse:l.z.string().optional(),mockStatus:l.z.number().int().optional(),runAudit:l.z.boolean().optional(),soft:l.z.boolean().optional(),visualCheck:l.z.boolean().optional()}),rn=l.z.object({type:l.z.enum(["inline","json-file","csv-file"]),path:l.z.string().optional(),data:l.z.array(l.z.record(l.z.string())).optional()}).optional(),Fe=l.z.object({id:l.z.string(),instruction:l.z.string(),generatedCode:l.z.string().default(""),order:l.z.number().int().default(0)}),an=l.z.object({before:l.z.array(Fe).default([]),after:l.z.array(Fe).default([])}).default({before:[],after:[]}),de=l.z.object({id:l.z.string().min(1),name:l.z.string().min(1),description:l.z.string(),tags:l.z.array(l.z.string()),priority:l.z.enum(["critical","high","medium","low"]),timeout:l.z.number().int().positive().optional(),dataSource:rn,steps:l.z.array(U),caseHooks:an,lighthouseCategories:l.z.array(l.z.enum(["performance","accessibility","seo"])).default(["performance","accessibility","seo"]),createdAt:l.z.string().datetime(),updatedAt:l.z.string().datetime()}),ge=l.z.object({id:l.z.string().min(1),name:l.z.string().min(1),description:l.z.string(),tags:l.z.array(l.z.string()),type:l.z.enum(["ui","api","audit","performance"]).default("ui"),timeout:l.z.number().int().positive().optional(),createdAt:l.z.string().datetime(),updatedAt:l.z.string().datetime()}),Xn=l.z.enum(["before_all","before_each","after_each","after_all"]),Zn=l.z.object({before_all:l.z.array(U).default([]),before_each:l.z.array(U).default([]),after_each:l.z.array(U).default([]),after_all:l.z.array(U).default([])});var v=class extends Error{code;constructor(t,n){super(t),this.name="AssuremindError",this.code=n,Object.setPrototypeOf(this,new.target.prototype)}},X=class extends v{provider;constructor(t,n,r="PROVIDER_ERROR"){super(t,r),this.name="ProviderError",this.provider=n}},Z=class extends v{stepId;constructor(t,n,r="EXECUTION_ERROR"){super(t,r),this.name="ExecutionError",this.stepId=n}},C=class extends v{constructor(t,n="CONFIG_ERROR"){super(t,n),this.name="ConfigError"}},u=class extends v{field;constructor(t,n,r="VALIDATION_ERROR"){super(t,r),this.name="ValidationError",this.field=n}},Q=class extends v{level;constructor(t,n,r="HEALING_ERROR"){super(t,r),this.name="HealingError",this.level=n}},g=class extends v{path;constructor(t,n,r="STORAGE_ERROR"){super(t,r),this.name="StorageError",this.path=n}};function ze(e){return e instanceof v}function Ue(e){return e instanceof v?`[${e.code}] ${e.message}`:e instanceof Error?e.message:String(e)}var fe=h(require("pino")),on=h(require("fs-extra"));var sn=process.env.NODE_ENV!=="production",ke=sn?{target:"pino-pretty",options:{colorize:!0,translateTime:"HH:MM:ss",ignore:"pid,hostname",messageFormat:"[assuremind] {msg}"}}:void 0,he=(0,fe.default)({level:process.env.LOG_LEVEL??"info",base:{name:"assuremind"}},ke?fe.default.transport(ke):void 0);function b(e){return he.child({component:e})}function cn(e){let t=/^```(?:typescript|javascript|ts|js)?\n?([\s\S]*?)```\s*$/m,n=e.match(t);return n?.[1]!==void 0?n[1].trim():e.trim()}var ln=[/\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*\(/];function mn(e){for(let t of ln)if(t.test(e))throw new u(`Generated code contains forbidden pattern: ${t.source}. This may be a prompt injection attempt. Please regenerate the step.`,"generatedCode","UNSAFE_CODE")}var pn=/\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;function Ge(e){let t=e.replace(pn,"").trim();return t.length>0?t:e}function un(e){let t=e;return t=t.replace(/(getBy(?:Label|Placeholder)\(\s*)(['"`])([\s\S]*?)\2/g,(n,r,i,a)=>`${r}${i}${Ge(a)}${i}`),t=t.replace(/(name:\s*)(['"`])([\s\S]*?)\2/g,(n,r,i,a)=>`${r}${i}${Ge(a)}${i}`),t}function dn(e){return e.replace(/\blocator\((['"`])([\s\S]*?)\1\)/g,(t,n,r)=>{if(!r.includes(" >> "))return t;let i=r.split(" >> ").map(a=>a.trim()).filter(Boolean);return i.length<2?t:i.map(a=>`locator(${n}${a}${n})`).join(".")})}function gn(e){let t=e;return t=dn(t),t=t.replace(/\.or\((?:[^()]*|\([^()]*\))*\)(?:\.(?:first|last)\(\))?/g,""),t=t.replace(/\.(?:first|last)\(\)(?=\.\w)/g,""),t=un(t),t}function Me(e){let t=cn(e);if(!t)throw new u("AI returned an empty code response. Please try regenerating.","generatedCode","EMPTY_CODE");let n=gn(t);return mn(n),n}function N(e){return e.toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function Be(e,t){let n=e;for(let r of t)r.length>0&&(n=n.replaceAll(r,"[REDACTED]"));return n}var xe=h(require("path")),R=h(require("fs-extra"));async function x(e,t){let n=xe.default.dirname(e);await R.default.ensureDir(n);let r=`${e}.${process.pid}.tmp`;try{await R.default.writeJson(r,t,{spaces:2}),await R.default.rename(r,e)}catch(i){throw await R.default.remove(r).catch(()=>{}),new g(`Failed to write file "${e}": ${i instanceof Error?i.message:String(i)}`,e,"WRITE_FAILED")}}async function E(e){try{return await R.default.readJson(e)}catch(t){throw new g(`Failed to read JSON file "${e}": ${t instanceof Error?t.message:String(t)}`,e,"READ_FAILED")}}async function We(e,t){let n=xe.default.dirname(e);await R.default.ensureDir(n);let r=`${e}.${process.pid}.tmp`;try{await R.default.writeFile(r,t,"utf8"),await R.default.rename(r,e)}catch(i){throw await R.default.remove(r).catch(()=>{}),new g(`Failed to write file "${e}": ${i instanceof Error?i.message:String(i)}`,e,"WRITE_FAILED")}}var k=b("suite-store"),ee="suite.json";async function G(e){let t=S.default.join(e,ee);if(!await I.default.pathExists(t))throw new g(`Suite file not found at "${t}". Ensure the suite directory exists and contains a suite.json file.`,t,"SUITE_NOT_FOUND");let n=await E(t),r=ge.safeParse(n);if(!r.success){let a=r.error.issues.map(p=>` \u2022 ${p.path.join(".")}: ${p.message}`).join(`
|
|
2
|
-
`);throw new
|
|
3
|
-
${a}`,"suite","INVALID_SUITE")}if(!n.type){let a=S.default.basename(S.default.dirname(e));a==="api"?r.data.type="api":a==="audit"||a==="performance"?r.data.type="audit":r.data.type="ui"}return r.data}async function
|
|
4
|
-
`);throw new
|
|
5
|
-
${i}`,"suite","INVALID_SUITE")}await x(n,r.data),k.debug({suiteId:t.id,path:n},"Suite written")}async function
|
|
6
|
-
`);throw new
|
|
7
|
-
${r}`,"case","INVALID_CASE")}return n.data}async function
|
|
8
|
-
`);throw new
|
|
9
|
-
${r}`,"case","INVALID_CASE")}await x(e,n.data),
|
|
10
|
-
`);throw new
|
|
11
|
-
${r}`,"variables","INVALID_VARIABLES")}return n.data}async function
|
|
12
|
-
`);throw new
|
|
13
|
-
${r}`,"variables","INVALID_VARIABLES")}await x(e,n.data),
|
|
14
|
-
`);throw new
|
|
15
|
-
${
|
|
1
|
+
"use strict";var Bt=Object.create;var X=Object.defineProperty;var Wt=Object.getOwnPropertyDescriptor;var Jt=Object.getOwnPropertyNames;var Kt=Object.getPrototypeOf,Yt=Object.prototype.hasOwnProperty;var Xt=(e,t)=>{for(var n in t)X(e,n,{get:t[n],enumerable:!0})},De=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Jt(t))!Yt.call(e,i)&&i!==n&&X(e,i,{get:()=>t[i],enumerable:!(r=Wt(t,i))||r.enumerable});return e};var h=(e,t,n)=>(n=e!=null?Bt(Kt(e)):{},De(t||!e||!e.__esModule?X(n,"default",{value:e,enumerable:!0}):n,e)),qt=e=>De(X({},"__esModule",{value:!0}),e);var qn={};Xt(qn,{AssuremindError:()=>v,ConfigError:()=>T,ExecutionError:()=>Q,HealingError:()=>ee,ProviderError:()=>Z,StorageError:()=>g,ValidationError:()=>p,acceptHealingEvent:()=>Ot,appendPendingEvent:()=>_t,callFaker:()=>Mt,clearEnvCache:()=>Ut,configExists:()=>ft,createCase:()=>nt,createChildLogger:()=>b,createSuite:()=>Xe,defineConfig:()=>Xn,deleteCase:()=>it,deleteGlobalVariable:()=>ut,deleteResult:()=>wt,deleteSuite:()=>Ze,formatError:()=>Ge,generateCacheKey:()=>Ht,getAvailableGenerators:()=>Gt,getCasePath:()=>ot,getHealingStats:()=>Vt,isAssuremindError:()=>ke,listCasePaths:()=>ve,listCases:()=>at,listHealingReportIds:()=>Lt,listResultIds:()=>de,listResults:()=>Et,listSuiteDirs:()=>re,listSuites:()=>Qe,listSuitesWithCounts:()=>et,listVariableFiles:()=>pt,logger:()=>ye,normalizeUrl:()=>Ve,pruneResolvedEvents:()=>$t,readCase:()=>oe,readConfig:()=>me,readEnvVariables:()=>je,readGlobalVariables:()=>Ie,readHealingReport:()=>Ct,readPendingEvents:()=>L,readResult:()=>Oe,readSuite:()=>G,readVariables:()=>H,redactSecrets:()=>Je,rejectHealingEvent:()=>Nt,resolveVariables:()=>lt,sanitizeGeneratedCode:()=>We,screenshotsDir:()=>vt,setGlobalVariable:()=>mt,sha256:()=>$e,toSlug:()=>$,tracesDir:()=>Rt,tryGetEnv:()=>kt,updateCase:()=>rt,updateConfig:()=>gt,updateSuite:()=>qe,validateConfig:()=>ht,validateEnv:()=>Le,videosDir:()=>At,writeCase:()=>se,writeConfig:()=>Ce,writeHealingReport:()=>Pt,writeResult:()=>yt,writeSuite:()=>ne,writeVariables:()=>ce});module.exports=qt(qn);var c=require("zod"),Zt=c.z.enum(["off","on","only-on-failure"]),Qt=c.z.enum(["off","on","on-first-retry","retain-on-failure"]),en=c.z.enum(["off","on","on-first-retry","retain-on-failure"]),He=c.z.enum(["chromium","firefox","webkit"]),tn=c.z.enum(["commit","domcontentloaded","load","networkidle"]),Fe=c.z.string().min(1),ze=["DEV","TEST","STAGE","INT","PROD"],nn=c.z.record(c.z.string(),c.z.string()).default({}),rn=c.z.object({enabled:c.z.boolean(),maxLevel:c.z.number().int().min(1).max(5),dailyBudget:c.z.number().positive(),autoPR:c.z.boolean(),healAssertionLocators:c.z.boolean().default(!1)}),an=c.z.object({allure:c.z.boolean(),html:c.z.boolean(),json:c.z.boolean()}),on=c.z.object({width:c.z.number().int().positive(),height:c.z.number().int().positive()}),sn=c.z.object({name:c.z.string().min(1),environment:Fe,baseUrl:c.z.string().url(),browsers:c.z.array(He).min(1),headless:c.z.boolean().optional()}),z=c.z.object({baseUrl:c.z.string().url(),environment:Fe.default("DEV"),environments:c.z.array(c.z.string().min(1)).default([...ze]),environmentUrls:nn.default({DEV:"",TEST:"",STAGE:"",INT:"",PROD:""}),browsers:c.z.array(He).min(1),headless:c.z.boolean(),viewport:on.default({width:1280,height:720}),timeout:c.z.number().int().positive(),retries:c.z.number().int().min(0),parallel:c.z.number().int().positive(),pageLoad:tn.default("domcontentloaded"),screenshot:Zt,video:Qt,trace:en,healing:rn,reporting:an,studioPort:c.z.number().int().min(1024).max(65535),profiles:c.z.array(sn).default([]),activeProfile:c.z.string().optional(),device:c.z.string().optional(),rag:c.z.object({enabled:c.z.boolean(),codeCorpus:c.z.object({enabled:c.z.boolean(),maxEntries:c.z.number().int().positive(),similarityThreshold:c.z.number().min(0).max(1),directUseThreshold:c.z.number().min(0).max(1)}),healingCorpus:c.z.object({enabled:c.z.boolean(),maxEntries:c.z.number().int().positive(),similarityThreshold:c.z.number().min(0).max(1)}),errorCatalog:c.z.object({enabled:c.z.boolean(),maxEntries:c.z.number().int().positive()}),embedder:c.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:c.z.object({enabled:c.z.boolean(),headless:c.z.boolean(),actThenScript:c.z.boolean(),proactiveHealing:c.z.boolean(),actionTimeout:c.z.number().int().positive(),idleTimeout:c.z.number().int().positive()}).default({enabled:!0,headless:!0,actThenScript:!1,proactiveHealing:!1,actionTimeout:15e3,idleTimeout:3e4}),ci:c.z.object({writeToRepo:c.z.boolean()}).default({writeToRepo:!1})}),q={baseUrl:"http://localhost:3000",environment:"DEV",environments:[...ze],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 S=h(require("path")),j=h(require("fs-extra")),Ye=require("uuid");var m=require("zod"),U=m.z.object({id:m.z.string().min(1),order:m.z.number().int().positive(),instruction:m.z.string().min(1),generatedCode:m.z.string(),strategy:m.z.enum(["template","cache","rag","batch","fast","primary","recorder"]),stepType:m.z.enum(["ui","api","mock"]).default("ui"),lastHealed:m.z.string().nullable(),timeout:m.z.number().int().positive().optional(),retries:m.z.number().int().min(0).optional(),mockUrl:m.z.string().optional(),mockResponse:m.z.string().optional(),mockStatus:m.z.number().int().optional(),runAudit:m.z.boolean().optional(),soft:m.z.boolean().optional(),visualCheck:m.z.boolean().optional()}),cn=m.z.object({type:m.z.enum(["inline","json-file","csv-file"]),path:m.z.string().optional(),data:m.z.array(m.z.record(m.z.string())).optional()}).optional(),Ue=m.z.object({id:m.z.string(),instruction:m.z.string(),generatedCode:m.z.string().default(""),order:m.z.number().int().default(0)}),ln=m.z.object({before:m.z.array(Ue).default([]),after:m.z.array(Ue).default([])}).default({before:[],after:[]}),xe=m.z.object({id:m.z.string().min(1),name:m.z.string().min(1),description:m.z.string(),tags:m.z.array(m.z.string()),priority:m.z.enum(["critical","high","medium","low"]),timeout:m.z.number().int().positive().optional(),dataSource:cn,steps:m.z.array(U),caseHooks:ln,lighthouseCategories:m.z.array(m.z.enum(["performance","accessibility","seo"])).default(["performance","accessibility","seo"]),createdAt:m.z.string().datetime(),updatedAt:m.z.string().datetime()}),be=m.z.object({id:m.z.string().min(1),name:m.z.string().min(1),description:m.z.string(),tags:m.z.array(m.z.string()),type:m.z.enum(["ui","api","audit","performance"]).default("ui"),timeout:m.z.number().int().positive().optional(),createdAt:m.z.string().datetime(),updatedAt:m.z.string().datetime()}),tr=m.z.enum(["before_all","before_each","after_each","after_all"]),nr=m.z.object({before_all:m.z.array(U).default([]),before_each:m.z.array(U).default([]),after_each:m.z.array(U).default([]),after_all:m.z.array(U).default([])});var v=class extends Error{code;constructor(t,n){super(t),this.name="AssuremindError",this.code=n,Object.setPrototypeOf(this,new.target.prototype)}},Z=class extends v{provider;constructor(t,n,r="PROVIDER_ERROR"){super(t,r),this.name="ProviderError",this.provider=n}},Q=class extends v{stepId;constructor(t,n,r="EXECUTION_ERROR"){super(t,r),this.name="ExecutionError",this.stepId=n}},T=class extends v{constructor(t,n="CONFIG_ERROR"){super(t,n),this.name="ConfigError"}},p=class extends v{field;constructor(t,n,r="VALIDATION_ERROR"){super(t,r),this.name="ValidationError",this.field=n}},ee=class extends v{level;constructor(t,n,r="HEALING_ERROR"){super(t,r),this.name="HealingError",this.level=n}},g=class extends v{path;constructor(t,n,r="STORAGE_ERROR"){super(t,r),this.name="StorageError",this.path=n}};function ke(e){return e instanceof v}function Ge(e){return e instanceof v?`[${e.code}] ${e.message}`:e instanceof Error?e.message:String(e)}var Se=h(require("pino")),mn=h(require("fs-extra"));var un=process.env.NODE_ENV!=="production",Me=un?{target:"pino-pretty",options:{colorize:!0,translateTime:"HH:MM:ss",ignore:"pid,hostname",messageFormat:"[assuremind] {msg}"}}:void 0,ye=(0,Se.default)({level:process.env.LOG_LEVEL??"info",base:{name:"assuremind"}},Me?Se.default.transport(Me):void 0);function b(e){return ye.child({component:e})}function pn(e){let t=/^```(?:typescript|javascript|ts|js)?\n?([\s\S]*?)```\s*$/m,n=e.match(t);return n?.[1]!==void 0?n[1].trim():e.trim()}var dn=[/\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*\(/];function gn(e){for(let t of dn)if(t.test(e))throw new p(`Generated code contains forbidden pattern: ${t.source}. This may be a prompt injection attempt. Please regenerate the step.`,"generatedCode","UNSAFE_CODE")}var fn=/\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;function Be(e){let t=e.replace(fn,"").trim();return t.length>0?t:e}function hn(e){let t=e;return t=t.replace(/(getBy(?:Label|Placeholder)\(\s*)(['"`])([\s\S]*?)\2/g,(n,r,i,a)=>`${r}${i}${Be(a)}${i}`),t=t.replace(/(name:\s*)(['"`])([\s\S]*?)\2/g,(n,r,i,a)=>`${r}${i}${Be(a)}${i}`),t}function xn(e){return e.replace(/\blocator\((['"`])([\s\S]*?)\1\)/g,(t,n,r)=>{if(!r.includes(" >> "))return t;let i=r.split(" >> ").map(a=>a.trim()).filter(Boolean);return i.length<2?t:i.map(a=>`locator(${n}${a}${n})`).join(".")})}function bn(e){let t=e;return t=xn(t),t=t.replace(/\.or\((?:[^()]*|\([^()]*\))*\)(?:\.(?:first|last)\(\))?/g,""),t=t.replace(/\.(?:first|last)\(\)(?=\.\w)/g,""),t=hn(t),t}function We(e){let t=pn(e);if(!t)throw new p("AI returned an empty code response. Please try regenerating.","generatedCode","EMPTY_CODE");let n=bn(t);return gn(n),n}function $(e){return e.toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function Je(e,t){let n=e;for(let r of t)r.length>0&&(n=n.replaceAll(r,"[REDACTED]"));return n}var Ee=h(require("path")),I=h(require("fs-extra"));async function x(e,t){let n=Ee.default.dirname(e);await I.default.ensureDir(n);let r=`${e}.${process.pid}.tmp`;try{await I.default.writeJson(r,t,{spaces:2}),await I.default.rename(r,e)}catch(i){throw await I.default.remove(r).catch(()=>{}),new g(`Failed to write file "${e}": ${i instanceof Error?i.message:String(i)}`,e,"WRITE_FAILED")}}async function E(e){try{return await I.default.readJson(e)}catch(t){throw new g(`Failed to read JSON file "${e}": ${t instanceof Error?t.message:String(t)}`,e,"READ_FAILED")}}async function Ke(e,t){let n=Ee.default.dirname(e);await I.default.ensureDir(n);let r=`${e}.${process.pid}.tmp`;try{await I.default.writeFile(r,t,"utf8"),await I.default.rename(r,e)}catch(i){throw await I.default.remove(r).catch(()=>{}),new g(`Failed to write file "${e}": ${i instanceof Error?i.message:String(i)}`,e,"WRITE_FAILED")}}var k=b("suite-store"),te="suite.json";async function G(e){let t=S.default.join(e,te);if(!await j.default.pathExists(t))throw new g(`Suite file not found at "${t}". Ensure the suite directory exists and contains a suite.json file.`,t,"SUITE_NOT_FOUND");let n=await E(t),r=be.safeParse(n);if(!r.success){let a=r.error.issues.map(l=>` \u2022 ${l.path.join(".")}: ${l.message}`).join(`
|
|
2
|
+
`);throw new p(`Invalid suite.json at "${t}":
|
|
3
|
+
${a}`,"suite","INVALID_SUITE")}if(!n.type){let a=S.default.basename(S.default.dirname(e));a==="api"?r.data.type="api":a==="audit"||a==="performance"?r.data.type="audit":r.data.type="ui"}return r.data}async function ne(e,t){await j.default.ensureDir(e);let n=S.default.join(e,te),r=be.safeParse(t);if(!r.success){let i=r.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
|
|
4
|
+
`);throw new p(`Cannot write invalid suite to "${n}":
|
|
5
|
+
${i}`,"suite","INVALID_SUITE")}await x(n,r.data),k.debug({suiteId:t.id,path:n},"Suite written")}async function Xe(e,t){let n=new Date().toISOString(),r=t.type??"ui",i={...t,type:r,id:(0,Ye.v4)(),createdAt:n,updatedAt:n},a=S.default.join(e,r),l=S.default.join(a,$(i.name));if(await j.default.pathExists(S.default.join(l,te)))throw new g(`Suite directory already exists at "${l}". Choose a different name or delete the existing suite first.`,l,"SUITE_ALREADY_EXISTS");return await ne(l,i),k.info({suiteId:i.id,path:l},"Suite created"),{suiteDir:l,suiteId:i.id}}async function qe(e,t){let n=await G(e),r={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:new Date().toISOString()};return await ne(e,r),r}async function Ze(e){if(!await j.default.pathExists(e))throw new g(`Suite directory not found at "${e}".`,e,"SUITE_NOT_FOUND");await j.default.remove(e),k.info({path:e},"Suite deleted")}async function re(e){let t=[],n=[S.default.join(e,"ui"),S.default.join(e,"api"),S.default.join(e,"audit"),S.default.join(e,"performance"),e];for(let r of n){if(!await j.default.pathExists(r))continue;let i=await j.default.readdir(r,{withFileTypes:!0});for(let a of i){if(!a.isDirectory()||r===e&&(a.name==="ui"||a.name==="api"||a.name==="audit"||a.name==="performance"))continue;let l=S.default.join(r,a.name,te);await j.default.pathExists(l)&&t.push(S.default.join(r,a.name))}}return t}async function Qe(e){let t=await re(e),n=[];for(let r of t)try{n.push(await G(r))}catch(i){k.warn({path:r,err:i},"Failed to read suite \u2014 skipping")}return n}async function et(e){let t=await re(e),n=[];for(let r of t)try{let i=await G(r),l=(await j.default.readdir(r,{withFileTypes:!0})).filter(y=>y.isFile()&&y.name.endsWith(".test.json")).length;n.push({...i,caseCount:l})}catch(i){k.warn({path:r,err:i},"Failed to read suite \u2014 skipping")}return n}var ie=h(require("path")),D=h(require("fs-extra")),tt=require("uuid");var ae=b("case-store"),we=".test.json";async function oe(e){if(!await D.default.pathExists(e))throw new g(`Test case file not found at "${e}".`,e,"CASE_NOT_FOUND");let t=await E(e),n=xe.safeParse(t);if(!n.success){let r=n.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
|
|
6
|
+
`);throw new p(`Invalid test case file at "${e}":
|
|
7
|
+
${r}`,"case","INVALID_CASE")}return n.data}async function se(e,t){let n=xe.safeParse(t);if(!n.success){let r=n.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
|
|
8
|
+
`);throw new p(`Cannot write invalid test case to "${e}":
|
|
9
|
+
${r}`,"case","INVALID_CASE")}await x(e,n.data),ae.debug({caseId:t.id,path:e},"Test case written")}async function nt(e,t){let n=new Date().toISOString(),r={...t,id:(0,tt.v4)(),createdAt:n,updatedAt:n},i=ie.default.join(e,`${$(r.name)}${we}`);return await se(i,r),ae.info({caseId:r.id,path:i},"Test case created"),i}async function rt(e,t){let n=await oe(e),r={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:new Date().toISOString()};return await se(e,r),r}async function it(e){if(!await D.default.pathExists(e))throw new g(`Test case file not found at "${e}".`,e,"CASE_NOT_FOUND");await D.default.remove(e),ae.info({path:e},"Test case deleted")}async function ve(e){return await D.default.pathExists(e)?(await D.default.readdir(e,{withFileTypes:!0})).filter(n=>n.isFile()&&n.name.endsWith(we)).map(n=>ie.default.join(e,n.name)):[]}async function at(e){let t=await ve(e),n=[];for(let r of t)try{n.push(await oe(r))}catch(i){ae.warn({path:r,err:i},"Failed to read test case \u2014 skipping")}return n.sort((r,i)=>r.name.localeCompare(i.name))}function ot(e,t){return ie.default.join(e,`${$(t)}${we}`)}var C=h(require("path")),M=h(require("fs-extra"));var P=require("zod"),Sn=P.z.object({value:P.z.string(),secret:P.z.literal(!0)}),yn=P.z.union([P.z.string(),Sn]),Ae=P.z.record(P.z.string(),yn);function En(e){return typeof e=="object"&&e.secret===!0}function st(e){return En(e)?e.value:e}var ct=b("variable-store"),B="variables",Re="global.json";function wn(e){return`${e}.env.json`}async function H(e){if(!await M.default.pathExists(e))return{};let t=await E(e),n=Ae.safeParse(t);if(!n.success){let r=n.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
|
|
10
|
+
`);throw new p(`Invalid variables file at "${e}":
|
|
11
|
+
${r}`,"variables","INVALID_VARIABLES")}return n.data}async function ce(e,t){let n=Ae.safeParse(t);if(!n.success){let r=n.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
|
|
12
|
+
`);throw new p(`Cannot write invalid variables to "${e}":
|
|
13
|
+
${r}`,"variables","INVALID_VARIABLES")}await x(e,n.data),ct.debug({path:e},"Variables written")}async function Ie(e){let t=C.default.join(e,B,Re);return H(t)}async function je(e,t){let n=C.default.join(e,B,wn(t));return H(n)}async function lt(e,t){let n=await Ie(e),r=t?await je(e,t):{},i={...n,...r},a={};for(let[l,y]of Object.entries(i)){let he=process.env[`AM_${l}`];he!==void 0&&he!==""?(ct.debug({key:l},`Variable overridden by AM_${l} CI secret`),a[l]=he):a[l]=st(y)}return a}async function mt(e,t,n){let r=C.default.join(e,B,Re);await M.default.ensureDir(C.default.dirname(r));let i=await H(r);i[t]=n,await ce(r,i)}async function ut(e,t){let n=C.default.join(e,B,Re),r=await H(n);if(!(t in r))throw new g(`Variable "${t}" not found in global variables.`,n,"VARIABLE_NOT_FOUND");delete r[t],await ce(n,r)}async function pt(e){let t=C.default.join(e,B);return await M.default.pathExists(t)?(await M.default.readdir(t,{withFileTypes:!0})).filter(r=>r.isFile()&&r.name.endsWith(".json")).map(r=>C.default.join(t,r.name)):[]}var F=h(require("path")),le=h(require("fs-extra"));var Te=b("config-store"),Pe="autotest.config.json",dt="autotest.config.ts";async function me(e){let t=F.default.join(e,Pe);if(!await le.default.pathExists(t))return Te.debug({rootDir:e},"No autotest.config.json found \u2014 using defaults"),q;let n=await E(t),r=z.safeParse(n);if(!r.success){let a=r.error.issues.map(l=>` \u2022 ${l.path.join(".")}: ${l.message}`).join(`
|
|
14
|
+
`);throw new p(`Invalid autotest.config.json at "${t}":
|
|
15
|
+
${a}
|
|
16
16
|
|
|
17
|
-
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")}
|
|
18
|
-
`);throw new
|
|
19
|
-
${a}`,"config","INVALID_CONFIG")}let r=F.default.join(e,
|
|
17
|
+
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 i=r.data;if(n&&typeof n=="object"&&"environments"in n)i.environment&&!i.environments.includes(i.environment)&&(i.environments=[...i.environments,i.environment]);else{let a=new Set;for(let l of Object.keys(i.environmentUrls??{}))a.add(l);i.environment&&a.add(i.environment),a.size>0&&(i.environments=[...a])}return i}async function Ce(e,t){let n=z.safeParse(t);if(!n.success){let a=n.error.issues.map(l=>` \u2022 ${l.path.join(".")}: ${l.message}`).join(`
|
|
18
|
+
`);throw new p(`Cannot write invalid config:
|
|
19
|
+
${a}`,"config","INVALID_CONFIG")}let r=F.default.join(e,Pe);await x(r,n.data);let i=F.default.join(e,dt);await Ke(i,vn(n.data)),Te.info({rootDir:e},"Config saved")}async function gt(e,t){let n=await me(e),r={...n,...t,healing:{...n.healing,...t.healing??{}},reporting:{...n.reporting,...t.reporting??{}},environmentUrls:{...n.environmentUrls,...t.environmentUrls??{}}};return await Ce(e,r),r}async function ft(e){let t=F.default.join(e,Pe),n=F.default.join(e,dt);return await le.default.pathExists(t)||await le.default.pathExists(n)}async function ht(e){let t=await me(e);if(!t.baseUrl)throw new T('baseUrl is required in autotest.config.ts. Set it to your application URL, e.g. "http://localhost:3000".',"CONFIG_BASE_URL_MISSING");Te.debug({config:t},"Config validated successfully")}function vn(e){return`import { defineConfig } from 'assuremind';
|
|
20
20
|
|
|
21
21
|
export default defineConfig({
|
|
22
22
|
baseUrl: '${e.baseUrl}',
|
|
@@ -41,22 +41,22 @@ export default defineConfig({
|
|
|
41
41
|
},
|
|
42
42
|
studioPort: ${e.studioPort},
|
|
43
43
|
});
|
|
44
|
-
`}var
|
|
45
|
-
`);throw new
|
|
46
|
-
${i}`,"result","INVALID_RESULT")}let r=
|
|
47
|
-
`);throw new
|
|
48
|
-
${a}`,"result","INVALID_RESULT")}return i.data}async function
|
|
49
|
-
`);throw new
|
|
50
|
-
${a}`,"healingReport","INVALID_HEALING_REPORT")}let r=w.default.join(e,
|
|
51
|
-
`);throw new
|
|
52
|
-
${
|
|
53
|
-
`);throw new
|
|
44
|
+
`}var R=h(require("path")),_=h(require("fs-extra"));var s=require("zod"),ue=s.z.enum(["pending","running","passed","failed","skipped"]),An=s.z.object({method:s.z.string(),url:s.z.string(),headers:s.z.record(s.z.string()).optional(),body:s.z.string().optional()}).optional(),Rn=s.z.object({status:s.z.number(),statusText:s.z.string(),headers:s.z.record(s.z.string()).optional(),body:s.z.string().optional(),duration:s.z.number()}).optional(),A=s.z.number().nullish().transform(e=>e??void 0),xt=s.z.object({id:s.z.string(),title:s.z.string(),passed:s.z.boolean(),partial:s.z.boolean().optional(),na:s.z.boolean().optional()}),In=s.z.object({url:s.z.string(),stepIndex:s.z.number().int(),stepInstruction:s.z.string(),score:A,a11yScore:A,seoScore:A,fcp:A,lcp:A,cls:A,ttfb:A,tbt:A,si:A,tti:A,inp:A,a11yAudits:s.z.array(xt).optional(),seoAudits:s.z.array(xt).optional(),lighthouseError:s.z.string().optional()}),jn=s.z.object({stepId:s.z.string(),instruction:s.z.string(),status:ue,code:s.z.string(),error:s.z.string().optional(),duration:s.z.number(),screenshotPath:s.z.string().optional(),healed:s.z.boolean().optional(),healedCode:s.z.string().optional(),stepType:s.z.enum(["ui","api","mock"]).optional(),apiRequest:An,apiResponse:Rn,navigatedToUrl:s.z.string().optional(),auditUrl:s.z.string().optional()}),Tn=s.z.object({caseId:s.z.string(),caseName:s.z.string(),status:ue,steps:s.z.array(jn),duration:s.z.number(),browser:s.z.string(),device:s.z.string().optional(),startedAt:s.z.string().datetime(),finishedAt:s.z.string().datetime(),videoPath:s.z.string().optional(),tracePath:s.z.string().optional(),downloadPaths:s.z.array(s.z.string()).default([]),dataRowIndex:s.z.number().int().optional(),dataRow:s.z.record(s.z.string()).optional(),pageLoads:s.z.array(In).default([])}),Pn=s.z.object({suiteId:s.z.string(),suiteName:s.z.string(),suiteType:s.z.enum(["ui","api","audit","performance"]).optional(),status:ue,cases:s.z.array(Tn),duration:s.z.number(),browser:s.z.string(),startedAt:s.z.string().datetime(),finishedAt:s.z.string().datetime()}),_e=s.z.object({runId:s.z.string(),status:ue,environment:s.z.string().optional(),suites:s.z.array(Pn),duration:s.z.number(),startedAt:s.z.string().datetime(),finishedAt:s.z.string().datetime(),totalTests:s.z.number().int(),passed:s.z.number().int(),failed:s.z.number().int(),skipped:s.z.number().int(),healed:s.z.number().int().optional(),logFilePath:s.z.string().optional()});var W=b("result-store"),O="results",St="runs",bt=15;function pe(e,t){return R.default.join(e,St,`${t}.json`)}async function yt(e,t){let n=_e.safeParse(t);if(!n.success){let i=n.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
|
|
45
|
+
`);throw new p(`Cannot write invalid run result:
|
|
46
|
+
${i}`,"result","INVALID_RESULT")}let r=pe(R.default.join(e,O),t.runId);await x(r,n.data),W.info({runId:t.runId,status:t.status},"Run result saved"),await Cn(e).catch(i=>{W.warn({err:i},"Failed to prune old run results")})}async function Cn(e){let n=(await de(e)).slice(bt);if(n.length===0)return;let r=R.default.join(e,O);for(let i of n)await _.default.remove(pe(r,i)).catch(()=>{});W.info({pruned:n.length,retained:bt},"Pruned old run results")}async function Oe(e,t){let n=pe(R.default.join(e,O),t);if(!await _.default.pathExists(n))throw new g(`Run result not found for runId "${t}".`,n,"RESULT_NOT_FOUND");let r=await E(n),i=_e.safeParse(r);if(!i.success){let a=i.error.issues.map(l=>` \u2022 ${l.path.join(".")}: ${l.message}`).join(`
|
|
47
|
+
`);throw new p(`Invalid run result at "${n}":
|
|
48
|
+
${a}`,"result","INVALID_RESULT")}return i.data}async function de(e){let t=R.default.join(e,O,St);if(!await _.default.pathExists(t))return[];let r=(await _.default.readdir(t,{withFileTypes:!0})).filter(a=>a.isFile()&&a.name.endsWith(".json")).map(a=>a.name.replace(".json",""));return(await Promise.all(r.map(async a=>{let l=await _.default.stat(R.default.join(t,`${a}.json`));return{id:a,mtime:l.mtimeMs}}))).sort((a,l)=>l.mtime-a.mtime).map(a=>a.id)}async function Et(e,t=20){let n=await de(e),r=[];for(let i of n.slice(0,t))try{let a=await Oe(e,i);r.push({runId:a.runId,status:a.status,environment:a.environment,startedAt:a.startedAt,finishedAt:a.finishedAt,totalTests:a.totalTests,passed:a.passed,failed:a.failed,skipped:a.skipped,duration:a.duration,suiteIds:a.suites.map(l=>l.suiteId)})}catch(a){W.warn({runId:i,err:a},"Failed to read run result \u2014 skipping")}return r}async function wt(e,t){let n=pe(R.default.join(e,O),t);if(!await _.default.pathExists(n))throw new g(`Run result not found for runId "${t}".`,n,"RESULT_NOT_FOUND");await _.default.remove(n),W.info({runId:t},"Run result deleted")}function vt(e){return R.default.join(e,O,"screenshots")}function At(e){return R.default.join(e,O,"videos")}function Rt(e){return R.default.join(e,O,"traces")}var w=h(require("path")),V=h(require("fs-extra"));var d=require("zod"),_n=d.z.enum(["pending","accepted","rejected"]),On=d.z.enum(["retry","regenerate","multi-selector","visual","decompose","manual"]),ge=d.z.object({id:d.z.string(),runId:d.z.string(),suiteId:d.z.string(),caseId:d.z.string(),stepId:d.z.string(),stepInstruction:d.z.string(),failedCode:d.z.string(),healedCode:d.z.string(),error:d.z.string(),strategy:On,level:d.z.number().int().min(1).max(6),status:_n,pageUrl:d.z.string(),timestamp:d.z.string().datetime(),acceptedAt:d.z.string().datetime().optional(),rejectedAt:d.z.string().datetime().optional()}),Ne=d.z.object({runId:d.z.string(),generatedAt:d.z.string().datetime(),totalHeals:d.z.number().int(),accepted:d.z.number().int(),rejected:d.z.number().int(),pending:d.z.number().int(),events:d.z.array(ge)});var J=b("healing-store"),N=w.default.join("results","healing"),Nn="pending.json",fe="healing-report-";function Tt(e,t){return w.default.join(e,`${fe}${t}.json`)}function K(e){return w.default.join(e,Nn)}async function Pt(e,t){let n=Ne.safeParse(t);if(!n.success){let a=n.error.issues.map(l=>` \u2022 ${l.path.join(".")}: ${l.message}`).join(`
|
|
49
|
+
`);throw new p(`Cannot write invalid healing report:
|
|
50
|
+
${a}`,"healingReport","INVALID_HEALING_REPORT")}let r=w.default.join(e,N),i=Tt(r,t.runId);await x(i,n.data),J.info({runId:t.runId,totalHeals:t.totalHeals},"Healing report saved")}async function Ct(e,t){let n=w.default.join(e,N),r=Tt(n,t);if(!await V.default.pathExists(r))throw new g(`Healing report not found for runId "${t}".`,r,"HEALING_REPORT_NOT_FOUND");let i=await E(r),a=Ne.safeParse(i);if(!a.success){let l=a.error.issues.map(y=>` \u2022 ${y.path.join(".")}: ${y.message}`).join(`
|
|
51
|
+
`);throw new p(`Invalid healing report at "${r}":
|
|
52
|
+
${l}`,"healingReport","INVALID_HEALING_REPORT")}return a.data}async function L(e){let t=w.default.join(e,N),n=K(t);if(!await V.default.pathExists(n))return[];let r=await E(n),i=ge.array().safeParse(r);return i.success?i.data:(J.warn({path:n},"Pending healing file is malformed \u2014 resetting"),[])}var It=50,jt=["pending","rejected","accepted"];function $n(e){if(e.length<=It)return e;let t=[...e].sort((i,a)=>{let l=jt.indexOf(i.status),y=jt.indexOf(a.status);return l!==y?l-y:i.timestamp<a.timestamp?-1:1}),n=e.length-It,r=new Set(t.slice(0,n).map(i=>i.id));return J.info({excess:n,deleted:r.size},"Auto-pruning healing events to enforce cap"),e.filter(i=>!r.has(i.id))}async function _t(e,t){let n=ge.safeParse(t);if(!n.success)throw new p(`Invalid healing event: ${n.error.message}`,"healingEvent","INVALID_HEALING_EVENT");let r=w.default.join(e,N);await V.default.ensureDir(r);let i=await L(e);i.push(n.data),await x(K(r),$n(i))}async function Ot(e,t){let n=await L(e),r=n.findIndex(a=>a.id===t);if(r===-1)throw new g(`Healing event "${t}" not found in pending list.`,t,"HEALING_EVENT_NOT_FOUND");n[r]={...n[r],status:"accepted",acceptedAt:new Date().toISOString()};let i=w.default.join(e,N);return await x(K(i),n),J.info({eventId:t},"Healing event accepted"),n[r]}async function Nt(e,t){let n=await L(e),r=n.findIndex(a=>a.id===t);if(r===-1)throw new g(`Healing event "${t}" not found in pending list.`,t,"HEALING_EVENT_NOT_FOUND");n[r]={...n[r],status:"rejected",rejectedAt:new Date().toISOString()};let i=w.default.join(e,N);return await x(K(i),n),J.info({eventId:t},"Healing event rejected"),n[r]}async function $t(e,t=30){let n=await L(e),r=Date.now()-t*24*60*60*1e3,i=n.length,a=n.filter(l=>{if(l.status==="pending")return!0;let y=l.acceptedAt??l.rejectedAt;return y?new Date(y).getTime()>r:!0});if(a.length<i){let l=w.default.join(e,N);await x(K(l),a)}return i-a.length}async function Vt(e){let t=await L(e),n=t.filter(a=>a.status==="pending").length,r=t.filter(a=>a.status==="accepted").length,i=t.filter(a=>a.status==="rejected").length;return{pending:n,accepted:r,rejected:i,total:t.length}}async function Lt(e){let t=w.default.join(e,N);if(!await V.default.pathExists(t))return[];let r=(await V.default.readdir(t,{withFileTypes:!0})).filter(a=>a.isFile()&&a.name.startsWith(fe)&&a.name.endsWith(".json")).map(a=>a.name.slice(fe.length,-5));return(await Promise.all(r.map(async a=>{let l=await V.default.stat(w.default.join(t,`${fe}${a}.json`));return{id:a,mtime:l.mtimeMs}}))).sort((a,l)=>l.mtime-a.mtime).map(a=>a.id)}var Dt=require("crypto");function $e(e){return(0,Dt.createHash)("sha256").update(e,"utf8").digest("hex")}function Ve(e){try{return new URL(e).pathname.split("/").map(r=>/^\d+$/.test(r)||/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(r)||/^[a-z0-9-]{8,}$/i.test(r)&&/-/.test(r)?"*":r).join("/")}catch{return e}}function Ht(e,t){let n=e.toLowerCase().replace(/\s+/g," ").trim(),r=Ve(t);return $e(`${n}|${r}`).slice(0,16)}var zt=require("dotenv"),u=require("zod");(0,zt.config)();var Ft=["anthropic","openai","google","azure-openai","bedrock","deepseek","groq","together","qwen","perplexity","ollama","custom"],Vn=u.z.object({NODE_ENV:u.z.enum(["development","production","test"]).default("development"),LOG_LEVEL:u.z.enum(["trace","debug","info","warn","error","fatal"]).default("info"),AI_PROVIDER:u.z.enum(Ft),AI_TIERED_ENABLED:u.z.string().transform(e=>e==="true").default("false"),AI_TIERED_FAST_PROVIDER:u.z.enum(Ft).optional(),AI_TIERED_FAST_MODEL:u.z.string().optional(),AI_TIMEOUT:u.z.coerce.number().int().positive().default(30),AI_MAX_RETRIES:u.z.coerce.number().int().min(0).max(10).default(2)}),Ln=u.z.object({ANTHROPIC_API_KEY:u.z.string().min(1),ANTHROPIC_MODEL:u.z.string().default("claude-sonnet-4-20250514")}),Dn=u.z.object({OPENAI_API_KEY:u.z.string().min(1),OPENAI_MODEL:u.z.string().default("gpt-4o")}),Hn=u.z.object({GOOGLE_API_KEY:u.z.string().min(1),GOOGLE_MODEL:u.z.string().default("gemini-2.5-pro")}),Fn=u.z.object({AZURE_OPENAI_API_KEY:u.z.string().min(1),AZURE_OPENAI_ENDPOINT:u.z.string().url(),AZURE_OPENAI_DEPLOYMENT:u.z.string().min(1),AZURE_OPENAI_API_VERSION:u.z.string().default("2024-10-21")}),zn=u.z.object({AWS_ACCESS_KEY_ID:u.z.string().min(1),AWS_SECRET_ACCESS_KEY:u.z.string().min(1),AWS_SESSION_TOKEN:u.z.string().optional(),AWS_REGION:u.z.string().default("us-east-1"),BEDROCK_MODEL:u.z.string().default("anthropic.claude-sonnet-4-20250514-v1:0")}),Un=u.z.object({DEEPSEEK_API_KEY:u.z.string().min(1),DEEPSEEK_MODEL:u.z.string().default("deepseek-chat")}),kn=u.z.object({GROQ_API_KEY:u.z.string().min(1),GROQ_MODEL:u.z.string().default("llama-3.3-70b-versatile")}),Gn=u.z.object({TOGETHER_API_KEY:u.z.string().min(1),TOGETHER_MODEL:u.z.string().default("meta-llama/Llama-3.3-70B-Instruct-Turbo")}),Mn=u.z.object({QWEN_API_KEY:u.z.string().min(1),QWEN_BASE_URL:u.z.string().url().default("https://dashscope-intl.aliyuncs.com/compatible-mode/v1"),QWEN_MODEL:u.z.string().default("qwen-max")}),Bn=u.z.object({PERPLEXITY_API_KEY:u.z.string().min(1),PERPLEXITY_MODEL:u.z.string().default("sonar-pro")}),Wn=u.z.object({OLLAMA_BASE_URL:u.z.string().url().default("http://localhost:11434"),OLLAMA_MODEL:u.z.string().default("llama3.3")}),Jn=u.z.object({CUSTOM_API_KEY:u.z.string().min(1),CUSTOM_BASE_URL:u.z.string().url(),CUSTOM_MODEL:u.z.string().min(1)}),Kn={anthropic:Ln,openai:Dn,google:Hn,"azure-openai":Fn,bedrock:zn,deepseek:Un,groq:kn,together:Gn,qwen:Mn,perplexity:Bn,ollama:Wn,custom:Jn},Y=null;function Le(){if(Y!==null)return Y;let e=Vn.safeParse(process.env);if(!e.success){let a=e.error.issues.map(l=>` \u2022 ${l.path.join(".")}: ${l.message}`).join(`
|
|
53
|
+
`);throw new T(`Missing or invalid environment variables:
|
|
54
54
|
${a}
|
|
55
55
|
|
|
56
|
-
How to fix: Copy .env.example to .env and fill in your AI provider credentials.`,"ENV_VALIDATION_FAILED")}let t=e.data.AI_PROVIDER,r=
|
|
57
|
-
`);throw new
|
|
56
|
+
How to fix: Copy .env.example to .env and fill in your AI provider credentials.`,"ENV_VALIDATION_FAILED")}let t=e.data.AI_PROVIDER,r=Kn[t].safeParse(process.env);if(!r.success){let a=r.error.issues.map(l=>` \u2022 ${l.path.join(".")}: ${l.message}`).join(`
|
|
57
|
+
`);throw new T(`Provider "${t}" is missing required environment variables:
|
|
58
58
|
${a}
|
|
59
59
|
|
|
60
|
-
How to fix: Check .env.example for the ${t} section and add the required keys to .env.`,"PROVIDER_ENV_MISSING")}return
|
|
60
|
+
How to fix: Check .env.example for the ${t} section and add the required keys to .env.`,"PROVIDER_ENV_MISSING")}return Y={...e.data,...r.data},Y}function Ut(){Y=null}function kt(){try{return Le()}catch{return null}}var o=require("@faker-js/faker");function Gt(){return[{category:"person",methods:[{name:"fullName",example:o.faker.person.fullName()},{name:"firstName",example:o.faker.person.firstName()},{name:"lastName",example:o.faker.person.lastName()},{name:"middleName",example:o.faker.person.middleName()},{name:"sex",example:o.faker.person.sex()},{name:"prefix",example:o.faker.person.prefix()},{name:"suffix",example:o.faker.person.suffix()},{name:"jobTitle",example:o.faker.person.jobTitle()},{name:"jobArea",example:o.faker.person.jobArea()},{name:"jobType",example:o.faker.person.jobType()},{name:"bio",example:o.faker.person.bio()}]},{category:"internet",methods:[{name:"email",example:o.faker.internet.email()},{name:"userName",example:o.faker.internet.username()},{name:"password",example:o.faker.internet.password()},{name:"url",example:o.faker.internet.url()},{name:"domainName",example:o.faker.internet.domainName()},{name:"domainWord",example:o.faker.internet.domainWord()},{name:"ip",example:o.faker.internet.ip()},{name:"ipv6",example:o.faker.internet.ipv6()},{name:"mac",example:o.faker.internet.mac()},{name:"userAgent",example:o.faker.internet.userAgent()},{name:"emoji",example:o.faker.internet.emoji()}]},{category:"phone",methods:[{name:"number",example:o.faker.phone.number()},{name:"imei",example:o.faker.phone.imei()}]},{category:"location",methods:[{name:"streetAddress",example:o.faker.location.streetAddress()},{name:"street",example:o.faker.location.street()},{name:"city",example:o.faker.location.city()},{name:"state",example:o.faker.location.state()},{name:"zipCode",example:o.faker.location.zipCode()},{name:"country",example:o.faker.location.country()},{name:"countryCode",example:o.faker.location.countryCode()},{name:"county",example:o.faker.location.county()},{name:"latitude",example:String(o.faker.location.latitude())},{name:"longitude",example:String(o.faker.location.longitude())},{name:"timeZone",example:o.faker.location.timeZone()},{name:"buildingNumber",example:o.faker.location.buildingNumber()}]},{category:"company",methods:[{name:"name",example:o.faker.company.name()},{name:"catchPhrase",example:o.faker.company.catchPhrase()},{name:"buzzPhrase",example:o.faker.company.buzzPhrase()},{name:"buzzNoun",example:o.faker.company.buzzNoun()},{name:"buzzVerb",example:o.faker.company.buzzVerb()},{name:"buzzAdjective",example:o.faker.company.buzzAdjective()}]},{category:"finance",methods:[{name:"accountNumber",example:o.faker.finance.accountNumber()},{name:"accountName",example:o.faker.finance.accountName()},{name:"creditCardNumber",example:o.faker.finance.creditCardNumber()},{name:"creditCardCVV",example:o.faker.finance.creditCardCVV()},{name:"currencyCode",example:o.faker.finance.currencyCode()},{name:"currencyName",example:o.faker.finance.currencyName()},{name:"amount",example:o.faker.finance.amount()},{name:"iban",example:o.faker.finance.iban()},{name:"bic",example:o.faker.finance.bic()},{name:"bitcoinAddress",example:o.faker.finance.bitcoinAddress()},{name:"transactionType",example:o.faker.finance.transactionType()}]},{category:"date",methods:[{name:"past",example:o.faker.date.past().toISOString()},{name:"future",example:o.faker.date.future().toISOString()},{name:"recent",example:o.faker.date.recent().toISOString()},{name:"soon",example:o.faker.date.soon().toISOString()},{name:"birthdate",example:o.faker.date.birthdate().toISOString()},{name:"month",example:o.faker.date.month()},{name:"weekday",example:o.faker.date.weekday()}]},{category:"lorem",methods:[{name:"word",example:o.faker.lorem.word()},{name:"words",example:o.faker.lorem.words()},{name:"sentence",example:o.faker.lorem.sentence()},{name:"sentences",example:o.faker.lorem.sentences()},{name:"paragraph",example:o.faker.lorem.paragraph()},{name:"slug",example:o.faker.lorem.slug()},{name:"lines",example:o.faker.lorem.lines(1)}]},{category:"string",methods:[{name:"uuid",example:o.faker.string.uuid()},{name:"alphanumeric",example:o.faker.string.alphanumeric(10)},{name:"numeric",example:o.faker.string.numeric(6)},{name:"alpha",example:o.faker.string.alpha(8)},{name:"nanoid",example:o.faker.string.nanoid()},{name:"hexadecimal",example:o.faker.string.hexadecimal({length:8})},{name:"sample",example:o.faker.string.sample(12)}]},{category:"number",methods:[{name:"int",example:String(o.faker.number.int({max:9999}))},{name:"float",example:String(o.faker.number.float({max:100,fractionDigits:2}))}]},{category:"datatype",methods:[{name:"boolean",example:String(o.faker.datatype.boolean())}]},{category:"image",methods:[{name:"avatar",example:o.faker.image.avatar()},{name:"url",example:o.faker.image.url()}]},{category:"color",methods:[{name:"human",example:o.faker.color.human()},{name:"rgb",example:o.faker.color.rgb()},{name:"hex",example:o.faker.color.rgb({format:"hex"})}]},{category:"commerce",methods:[{name:"productName",example:o.faker.commerce.productName()},{name:"price",example:o.faker.commerce.price()},{name:"department",example:o.faker.commerce.department()},{name:"productDescription",example:o.faker.commerce.productDescription().slice(0,60)+"..."},{name:"isbn",example:o.faker.commerce.isbn()}]},{category:"vehicle",methods:[{name:"vehicle",example:o.faker.vehicle.vehicle()},{name:"manufacturer",example:o.faker.vehicle.manufacturer()},{name:"model",example:o.faker.vehicle.model()},{name:"vin",example:o.faker.vehicle.vin()},{name:"vrm",example:o.faker.vehicle.vrm()}]},{category:"system",methods:[{name:"fileName",example:o.faker.system.fileName()},{name:"mimeType",example:o.faker.system.mimeType()},{name:"fileExt",example:o.faker.system.fileExt()},{name:"filePath",example:o.faker.system.filePath()},{name:"semver",example:o.faker.system.semver()}]}]}var Yn={"internet.userName":"username"};function Mt(e,t){let n=o.faker[e],r=Yn[`${e}.${t}`]??t;if(!n||typeof n[r]!="function")return`[unknown: ${e}.${t}]`;let i=n[r]();return i instanceof Date?i.toISOString():String(i)}function Xn(e){let t={...q,...e},n=z.safeParse(t);if(!n.success){let r=n.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
|
|
61
61
|
`);throw new Error(`Invalid assuremind config:
|
|
62
62
|
${r}`)}return n.data}0&&(module.exports={AssuremindError,ConfigError,ExecutionError,HealingError,ProviderError,StorageError,ValidationError,acceptHealingEvent,appendPendingEvent,callFaker,clearEnvCache,configExists,createCase,createChildLogger,createSuite,defineConfig,deleteCase,deleteGlobalVariable,deleteResult,deleteSuite,formatError,generateCacheKey,getAvailableGenerators,getCasePath,getHealingStats,isAssuremindError,listCasePaths,listCases,listHealingReportIds,listResultIds,listResults,listSuiteDirs,listSuites,listSuitesWithCounts,listVariableFiles,logger,normalizeUrl,pruneResolvedEvents,readCase,readConfig,readEnvVariables,readGlobalVariables,readHealingReport,readPendingEvents,readResult,readSuite,readVariables,redactSecrets,rejectHealingEvent,resolveVariables,sanitizeGeneratedCode,screenshotsDir,setGlobalVariable,sha256,toSlug,tracesDir,tryGetEnv,updateCase,updateConfig,updateSuite,validateConfig,validateEnv,videosDir,writeCase,writeConfig,writeHealingReport,writeResult,writeSuite,writeVariables});
|
package/dist/index.mjs
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import{z as c}from"zod";var
|
|
2
|
-
`);throw new
|
|
3
|
-
${a}`,"suite","INVALID_SUITE")}if(!n.type){let a=E.basename(E.dirname(e));a==="api"?r.data.type="api":a==="audit"||a==="performance"?r.data.type="audit":r.data.type="ui"}return r.data}async function
|
|
4
|
-
`);throw new
|
|
5
|
-
${i}`,"suite","INVALID_SUITE")}await x(n,r.data),F.debug({suiteId:t.id,path:n},"Suite written")}async function
|
|
6
|
-
`);throw new
|
|
7
|
-
${r}`,"case","INVALID_CASE")}return n.data}async function
|
|
8
|
-
`);throw new
|
|
9
|
-
${r}`,"case","INVALID_CASE")}await x(e,n.data),q.debug({caseId:t.id,path:e},"Test case written")}async function
|
|
10
|
-
`);throw new
|
|
11
|
-
${r}`,"variables","INVALID_VARIABLES")}return n.data}async function
|
|
12
|
-
`);throw new
|
|
13
|
-
${r}`,"variables","INVALID_VARIABLES")}await x(e,n.data),
|
|
14
|
-
`);throw new
|
|
15
|
-
${
|
|
1
|
+
import{z as c}from"zod";var Qe=c.enum(["off","on","only-on-failure"]),et=c.enum(["off","on","on-first-retry","retain-on-failure"]),tt=c.enum(["off","on","on-first-retry","retain-on-failure"]),Re=c.enum(["chromium","firefox","webkit"]),nt=c.enum(["commit","domcontentloaded","load","networkidle"]),Ie=c.string().min(1),je=["DEV","TEST","STAGE","INT","PROD"],rt=c.record(c.string(),c.string()).default({}),it=c.object({enabled:c.boolean(),maxLevel:c.number().int().min(1).max(5),dailyBudget:c.number().positive(),autoPR:c.boolean(),healAssertionLocators:c.boolean().default(!1)}),at=c.object({allure:c.boolean(),html:c.boolean(),json:c.boolean()}),ot=c.object({width:c.number().int().positive(),height:c.number().int().positive()}),st=c.object({name:c.string().min(1),environment:Ie,baseUrl:c.string().url(),browsers:c.array(Re).min(1),headless:c.boolean().optional()}),D=c.object({baseUrl:c.string().url(),environment:Ie.default("DEV"),environments:c.array(c.string().min(1)).default([...je]),environmentUrls:rt.default({DEV:"",TEST:"",STAGE:"",INT:"",PROD:""}),browsers:c.array(Re).min(1),headless:c.boolean(),viewport:ot.default({width:1280,height:720}),timeout:c.number().int().positive(),retries:c.number().int().min(0),parallel:c.number().int().positive(),pageLoad:nt.default("domcontentloaded"),screenshot:Qe,video:et,trace:tt,healing:it,reporting:at,studioPort:c.number().int().min(1024).max(65535),profiles:c.array(st).default([]),activeProfile:c.string().optional(),device:c.string().optional(),rag:c.object({enabled:c.boolean(),codeCorpus:c.object({enabled:c.boolean(),maxEntries:c.number().int().positive(),similarityThreshold:c.number().min(0).max(1),directUseThreshold:c.number().min(0).max(1)}),healingCorpus:c.object({enabled:c.boolean(),maxEntries:c.number().int().positive(),similarityThreshold:c.number().min(0).max(1)}),errorCatalog:c.object({enabled:c.boolean(),maxEntries:c.number().int().positive()}),embedder:c.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:c.object({enabled:c.boolean(),headless:c.boolean(),actThenScript:c.boolean(),proactiveHealing:c.boolean(),actionTimeout:c.number().int().positive(),idleTimeout:c.number().int().positive()}).default({enabled:!0,headless:!0,actThenScript:!1,proactiveHealing:!1,actionTimeout:15e3,idleTimeout:3e4}),ci:c.object({writeToRepo:c.boolean()}).default({writeToRepo:!1})}),K={baseUrl:"http://localhost:3000",environment:"DEV",environments:[...je],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}};import E from"path";import j from"fs-extra";import{v4 as wt}from"uuid";import{z as m}from"zod";var H=m.object({id:m.string().min(1),order:m.number().int().positive(),instruction:m.string().min(1),generatedCode:m.string(),strategy:m.enum(["template","cache","rag","batch","fast","primary","recorder"]),stepType:m.enum(["ui","api","mock"]).default("ui"),lastHealed:m.string().nullable(),timeout:m.number().int().positive().optional(),retries:m.number().int().min(0).optional(),mockUrl:m.string().optional(),mockResponse:m.string().optional(),mockStatus:m.number().int().optional(),runAudit:m.boolean().optional(),soft:m.boolean().optional(),visualCheck:m.boolean().optional()}),ct=m.object({type:m.enum(["inline","json-file","csv-file"]),path:m.string().optional(),data:m.array(m.record(m.string())).optional()}).optional(),Te=m.object({id:m.string(),instruction:m.string(),generatedCode:m.string().default(""),order:m.number().int().default(0)}),lt=m.object({before:m.array(Te).default([]),after:m.array(Te).default([])}).default({before:[],after:[]}),ie=m.object({id:m.string().min(1),name:m.string().min(1),description:m.string(),tags:m.array(m.string()),priority:m.enum(["critical","high","medium","low"]),timeout:m.number().int().positive().optional(),dataSource:ct,steps:m.array(H),caseHooks:lt,lighthouseCategories:m.array(m.enum(["performance","accessibility","seo"])).default(["performance","accessibility","seo"]),createdAt:m.string().datetime(),updatedAt:m.string().datetime()}),ae=m.object({id:m.string().min(1),name:m.string().min(1),description:m.string(),tags:m.array(m.string()),type:m.enum(["ui","api","audit","performance"]).default("ui"),timeout:m.number().int().positive().optional(),createdAt:m.string().datetime(),updatedAt:m.string().datetime()}),Mn=m.enum(["before_all","before_each","after_each","after_all"]),Bn=m.object({before_all:m.array(H).default([]),before_each:m.array(H).default([]),after_each:m.array(H).default([]),after_all:m.array(H).default([])});var v=class extends Error{code;constructor(t,n){super(t),this.name="AssuremindError",this.code=n,Object.setPrototypeOf(this,new.target.prototype)}},oe=class extends v{provider;constructor(t,n,r="PROVIDER_ERROR"){super(t,r),this.name="ProviderError",this.provider=n}},se=class extends v{stepId;constructor(t,n,r="EXECUTION_ERROR"){super(t,r),this.name="ExecutionError",this.stepId=n}},T=class extends v{constructor(t,n="CONFIG_ERROR"){super(t,n),this.name="ConfigError"}},p=class extends v{field;constructor(t,n,r="VALIDATION_ERROR"){super(t,r),this.name="ValidationError",this.field=n}},ce=class extends v{level;constructor(t,n,r="HEALING_ERROR"){super(t,r),this.name="HealingError",this.level=n}},g=class extends v{path;constructor(t,n,r="STORAGE_ERROR"){super(t,r),this.name="StorageError",this.path=n}};function mt(e){return e instanceof v}function ut(e){return e instanceof v?`[${e.code}] ${e.message}`:e instanceof Error?e.message:String(e)}import Pe from"pino";import Zn from"fs-extra";var pt=process.env.NODE_ENV!=="production",Ce=pt?{target:"pino-pretty",options:{colorize:!0,translateTime:"HH:MM:ss",ignore:"pid,hostname",messageFormat:"[assuremind] {msg}"}}:void 0,_e=Pe({level:process.env.LOG_LEVEL??"info",base:{name:"assuremind"}},Ce?Pe.transport(Ce):void 0);function S(e){return _e.child({component:e})}function dt(e){let t=/^```(?:typescript|javascript|ts|js)?\n?([\s\S]*?)```\s*$/m,n=e.match(t);return n?.[1]!==void 0?n[1].trim():e.trim()}var gt=[/\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*\(/];function ft(e){for(let t of gt)if(t.test(e))throw new p(`Generated code contains forbidden pattern: ${t.source}. This may be a prompt injection attempt. Please regenerate the step.`,"generatedCode","UNSAFE_CODE")}var ht=/\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;function Oe(e){let t=e.replace(ht,"").trim();return t.length>0?t:e}function xt(e){let t=e;return t=t.replace(/(getBy(?:Label|Placeholder)\(\s*)(['"`])([\s\S]*?)\2/g,(n,r,i,a)=>`${r}${i}${Oe(a)}${i}`),t=t.replace(/(name:\s*)(['"`])([\s\S]*?)\2/g,(n,r,i,a)=>`${r}${i}${Oe(a)}${i}`),t}function bt(e){return e.replace(/\blocator\((['"`])([\s\S]*?)\1\)/g,(t,n,r)=>{if(!r.includes(" >> "))return t;let i=r.split(" >> ").map(a=>a.trim()).filter(Boolean);return i.length<2?t:i.map(a=>`locator(${n}${a}${n})`).join(".")})}function St(e){let t=e;return t=bt(t),t=t.replace(/\.or\((?:[^()]*|\([^()]*\))*\)(?:\.(?:first|last)\(\))?/g,""),t=t.replace(/\.(?:first|last)\(\)(?=\.\w)/g,""),t=xt(t),t}function yt(e){let t=dt(e);if(!t)throw new p("AI returned an empty code response. Please try regenerating.","generatedCode","EMPTY_CODE");let n=St(t);return ft(n),n}function $(e){return e.toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function Et(e,t){let n=e;for(let r of t)r.length>0&&(n=n.replaceAll(r,"[REDACTED]"));return n}import Ne from"path";import I from"fs-extra";async function x(e,t){let n=Ne.dirname(e);await I.ensureDir(n);let r=`${e}.${process.pid}.tmp`;try{await I.writeJson(r,t,{spaces:2}),await I.rename(r,e)}catch(i){throw await I.remove(r).catch(()=>{}),new g(`Failed to write file "${e}": ${i instanceof Error?i.message:String(i)}`,e,"WRITE_FAILED")}}async function y(e){try{return await I.readJson(e)}catch(t){throw new g(`Failed to read JSON file "${e}": ${t instanceof Error?t.message:String(t)}`,e,"READ_FAILED")}}async function $e(e,t){let n=Ne.dirname(e);await I.ensureDir(n);let r=`${e}.${process.pid}.tmp`;try{await I.writeFile(r,t,"utf8"),await I.rename(r,e)}catch(i){throw await I.remove(r).catch(()=>{}),new g(`Failed to write file "${e}": ${i instanceof Error?i.message:String(i)}`,e,"WRITE_FAILED")}}var F=S("suite-store"),Y="suite.json";async function X(e){let t=E.join(e,Y);if(!await j.pathExists(t))throw new g(`Suite file not found at "${t}". Ensure the suite directory exists and contains a suite.json file.`,t,"SUITE_NOT_FOUND");let n=await y(t),r=ae.safeParse(n);if(!r.success){let a=r.error.issues.map(l=>` \u2022 ${l.path.join(".")}: ${l.message}`).join(`
|
|
2
|
+
`);throw new p(`Invalid suite.json at "${t}":
|
|
3
|
+
${a}`,"suite","INVALID_SUITE")}if(!n.type){let a=E.basename(E.dirname(e));a==="api"?r.data.type="api":a==="audit"||a==="performance"?r.data.type="audit":r.data.type="ui"}return r.data}async function le(e,t){await j.ensureDir(e);let n=E.join(e,Y),r=ae.safeParse(t);if(!r.success){let i=r.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
|
|
4
|
+
`);throw new p(`Cannot write invalid suite to "${n}":
|
|
5
|
+
${i}`,"suite","INVALID_SUITE")}await x(n,r.data),F.debug({suiteId:t.id,path:n},"Suite written")}async function vt(e,t){let n=new Date().toISOString(),r=t.type??"ui",i={...t,type:r,id:wt(),createdAt:n,updatedAt:n},a=E.join(e,r),l=E.join(a,$(i.name));if(await j.pathExists(E.join(l,Y)))throw new g(`Suite directory already exists at "${l}". Choose a different name or delete the existing suite first.`,l,"SUITE_ALREADY_EXISTS");return await le(l,i),F.info({suiteId:i.id,path:l},"Suite created"),{suiteDir:l,suiteId:i.id}}async function At(e,t){let n=await X(e),r={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:new Date().toISOString()};return await le(e,r),r}async function Rt(e){if(!await j.pathExists(e))throw new g(`Suite directory not found at "${e}".`,e,"SUITE_NOT_FOUND");await j.remove(e),F.info({path:e},"Suite deleted")}async function me(e){let t=[],n=[E.join(e,"ui"),E.join(e,"api"),E.join(e,"audit"),E.join(e,"performance"),e];for(let r of n){if(!await j.pathExists(r))continue;let i=await j.readdir(r,{withFileTypes:!0});for(let a of i){if(!a.isDirectory()||r===e&&(a.name==="ui"||a.name==="api"||a.name==="audit"||a.name==="performance"))continue;let l=E.join(r,a.name,Y);await j.pathExists(l)&&t.push(E.join(r,a.name))}}return t}async function It(e){let t=await me(e),n=[];for(let r of t)try{n.push(await X(r))}catch(i){F.warn({path:r,err:i},"Failed to read suite \u2014 skipping")}return n}async function jt(e){let t=await me(e),n=[];for(let r of t)try{let i=await X(r),l=(await j.readdir(r,{withFileTypes:!0})).filter(b=>b.isFile()&&b.name.endsWith(".test.json")).length;n.push({...i,caseCount:l})}catch(i){F.warn({path:r,err:i},"Failed to read suite \u2014 skipping")}return n}import ue from"path";import z from"fs-extra";import{v4 as Tt}from"uuid";var q=S("case-store"),pe=".test.json";async function de(e){if(!await z.pathExists(e))throw new g(`Test case file not found at "${e}".`,e,"CASE_NOT_FOUND");let t=await y(e),n=ie.safeParse(t);if(!n.success){let r=n.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
|
|
6
|
+
`);throw new p(`Invalid test case file at "${e}":
|
|
7
|
+
${r}`,"case","INVALID_CASE")}return n.data}async function ge(e,t){let n=ie.safeParse(t);if(!n.success){let r=n.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
|
|
8
|
+
`);throw new p(`Cannot write invalid test case to "${e}":
|
|
9
|
+
${r}`,"case","INVALID_CASE")}await x(e,n.data),q.debug({caseId:t.id,path:e},"Test case written")}async function Pt(e,t){let n=new Date().toISOString(),r={...t,id:Tt(),createdAt:n,updatedAt:n},i=ue.join(e,`${$(r.name)}${pe}`);return await ge(i,r),q.info({caseId:r.id,path:i},"Test case created"),i}async function Ct(e,t){let n=await de(e),r={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:new Date().toISOString()};return await ge(e,r),r}async function _t(e){if(!await z.pathExists(e))throw new g(`Test case file not found at "${e}".`,e,"CASE_NOT_FOUND");await z.remove(e),q.info({path:e},"Test case deleted")}async function Ve(e){return await z.pathExists(e)?(await z.readdir(e,{withFileTypes:!0})).filter(n=>n.isFile()&&n.name.endsWith(pe)).map(n=>ue.join(e,n.name)):[]}async function Ot(e){let t=await Ve(e),n=[];for(let r of t)try{n.push(await de(r))}catch(i){q.warn({path:r,err:i},"Failed to read test case \u2014 skipping")}return n.sort((r,i)=>r.name.localeCompare(i.name))}function Nt(e,t){return ue.join(e,`${$(t)}${pe}`)}import O from"path";import Z from"fs-extra";import{z as _}from"zod";var $t=_.object({value:_.string(),secret:_.literal(!0)}),Vt=_.union([_.string(),$t]),fe=_.record(_.string(),Vt);function Lt(e){return typeof e=="object"&&e.secret===!0}function Le(e){return Lt(e)?e.value:e}var De=S("variable-store"),U="variables",he="global.json";function Dt(e){return`${e}.env.json`}async function k(e){if(!await Z.pathExists(e))return{};let t=await y(e),n=fe.safeParse(t);if(!n.success){let r=n.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
|
|
10
|
+
`);throw new p(`Invalid variables file at "${e}":
|
|
11
|
+
${r}`,"variables","INVALID_VARIABLES")}return n.data}async function xe(e,t){let n=fe.safeParse(t);if(!n.success){let r=n.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
|
|
12
|
+
`);throw new p(`Cannot write invalid variables to "${e}":
|
|
13
|
+
${r}`,"variables","INVALID_VARIABLES")}await x(e,n.data),De.debug({path:e},"Variables written")}async function He(e){let t=O.join(e,U,he);return k(t)}async function Fe(e,t){let n=O.join(e,U,Dt(t));return k(n)}async function Ht(e,t){let n=await He(e),r=t?await Fe(e,t):{},i={...n,...r},a={};for(let[l,b]of Object.entries(i)){let re=process.env[`AM_${l}`];re!==void 0&&re!==""?(De.debug({key:l},`Variable overridden by AM_${l} CI secret`),a[l]=re):a[l]=Le(b)}return a}async function Ft(e,t,n){let r=O.join(e,U,he);await Z.ensureDir(O.dirname(r));let i=await k(r);i[t]=n,await xe(r,i)}async function zt(e,t){let n=O.join(e,U,he),r=await k(n);if(!(t in r))throw new g(`Variable "${t}" not found in global variables.`,n,"VARIABLE_NOT_FOUND");delete r[t],await xe(n,r)}async function Ut(e){let t=O.join(e,U);return await Z.pathExists(t)?(await Z.readdir(t,{withFileTypes:!0})).filter(r=>r.isFile()&&r.name.endsWith(".json")).map(r=>O.join(t,r.name)):[]}import G from"path";import be from"fs-extra";var Se=S("config-store"),ye="autotest.config.json",ze="autotest.config.ts";async function Ee(e){let t=G.join(e,ye);if(!await be.pathExists(t))return Se.debug({rootDir:e},"No autotest.config.json found \u2014 using defaults"),K;let n=await y(t),r=D.safeParse(n);if(!r.success){let a=r.error.issues.map(l=>` \u2022 ${l.path.join(".")}: ${l.message}`).join(`
|
|
14
|
+
`);throw new p(`Invalid autotest.config.json at "${t}":
|
|
15
|
+
${a}
|
|
16
16
|
|
|
17
|
-
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")}
|
|
18
|
-
`);throw new
|
|
19
|
-
${a}`,"config","INVALID_CONFIG")}let r=G.join(e,
|
|
17
|
+
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 i=r.data;if(n&&typeof n=="object"&&"environments"in n)i.environment&&!i.environments.includes(i.environment)&&(i.environments=[...i.environments,i.environment]);else{let a=new Set;for(let l of Object.keys(i.environmentUrls??{}))a.add(l);i.environment&&a.add(i.environment),a.size>0&&(i.environments=[...a])}return i}async function Ue(e,t){let n=D.safeParse(t);if(!n.success){let a=n.error.issues.map(l=>` \u2022 ${l.path.join(".")}: ${l.message}`).join(`
|
|
18
|
+
`);throw new p(`Cannot write invalid config:
|
|
19
|
+
${a}`,"config","INVALID_CONFIG")}let r=G.join(e,ye);await x(r,n.data);let i=G.join(e,ze);await $e(i,Bt(n.data)),Se.info({rootDir:e},"Config saved")}async function kt(e,t){let n=await Ee(e),r={...n,...t,healing:{...n.healing,...t.healing??{}},reporting:{...n.reporting,...t.reporting??{}},environmentUrls:{...n.environmentUrls,...t.environmentUrls??{}}};return await Ue(e,r),r}async function Gt(e){let t=G.join(e,ye),n=G.join(e,ze);return await be.pathExists(t)||await be.pathExists(n)}async function Mt(e){let t=await Ee(e);if(!t.baseUrl)throw new T('baseUrl is required in autotest.config.ts. Set it to your application URL, e.g. "http://localhost:3000".',"CONFIG_BASE_URL_MISSING");Se.debug({config:t},"Config validated successfully")}function Bt(e){return`import { defineConfig } from 'assuremind';
|
|
20
20
|
|
|
21
21
|
export default defineConfig({
|
|
22
22
|
baseUrl: '${e.baseUrl}',
|
|
@@ -41,22 +41,22 @@ export default defineConfig({
|
|
|
41
41
|
},
|
|
42
42
|
studioPort: ${e.studioPort},
|
|
43
43
|
});
|
|
44
|
-
`}import
|
|
45
|
-
`);throw new
|
|
46
|
-
${i}`,"result","INVALID_RESULT")}let r=
|
|
47
|
-
`);throw new
|
|
48
|
-
${a}`,"result","INVALID_RESULT")}return i.data}async function
|
|
49
|
-
`);throw new
|
|
50
|
-
${a}`,"healingReport","INVALID_HEALING_REPORT")}let r=w.join(e,
|
|
51
|
-
`);throw new
|
|
52
|
-
${
|
|
53
|
-
`);throw new
|
|
44
|
+
`}import R from"path";import N from"fs-extra";import{z as s}from"zod";var Q=s.enum(["pending","running","passed","failed","skipped"]),Wt=s.object({method:s.string(),url:s.string(),headers:s.record(s.string()).optional(),body:s.string().optional()}).optional(),Jt=s.object({status:s.number(),statusText:s.string(),headers:s.record(s.string()).optional(),body:s.string().optional(),duration:s.number()}).optional(),A=s.number().nullish().transform(e=>e??void 0),ke=s.object({id:s.string(),title:s.string(),passed:s.boolean(),partial:s.boolean().optional(),na:s.boolean().optional()}),Kt=s.object({url:s.string(),stepIndex:s.number().int(),stepInstruction:s.string(),score:A,a11yScore:A,seoScore:A,fcp:A,lcp:A,cls:A,ttfb:A,tbt:A,si:A,tti:A,inp:A,a11yAudits:s.array(ke).optional(),seoAudits:s.array(ke).optional(),lighthouseError:s.string().optional()}),Yt=s.object({stepId:s.string(),instruction:s.string(),status:Q,code:s.string(),error:s.string().optional(),duration:s.number(),screenshotPath:s.string().optional(),healed:s.boolean().optional(),healedCode:s.string().optional(),stepType:s.enum(["ui","api","mock"]).optional(),apiRequest:Wt,apiResponse:Jt,navigatedToUrl:s.string().optional(),auditUrl:s.string().optional()}),Xt=s.object({caseId:s.string(),caseName:s.string(),status:Q,steps:s.array(Yt),duration:s.number(),browser:s.string(),device:s.string().optional(),startedAt:s.string().datetime(),finishedAt:s.string().datetime(),videoPath:s.string().optional(),tracePath:s.string().optional(),downloadPaths:s.array(s.string()).default([]),dataRowIndex:s.number().int().optional(),dataRow:s.record(s.string()).optional(),pageLoads:s.array(Kt).default([])}),qt=s.object({suiteId:s.string(),suiteName:s.string(),suiteType:s.enum(["ui","api","audit","performance"]).optional(),status:Q,cases:s.array(Xt),duration:s.number(),browser:s.string(),startedAt:s.string().datetime(),finishedAt:s.string().datetime()}),we=s.object({runId:s.string(),status:Q,environment:s.string().optional(),suites:s.array(qt),duration:s.number(),startedAt:s.string().datetime(),finishedAt:s.string().datetime(),totalTests:s.number().int(),passed:s.number().int(),failed:s.number().int(),skipped:s.number().int(),healed:s.number().int().optional(),logFilePath:s.string().optional()});var M=S("result-store"),P="results",Me="runs",Ge=15;function ee(e,t){return R.join(e,Me,`${t}.json`)}async function Zt(e,t){let n=we.safeParse(t);if(!n.success){let i=n.error.issues.map(a=>` \u2022 ${a.path.join(".")}: ${a.message}`).join(`
|
|
45
|
+
`);throw new p(`Cannot write invalid run result:
|
|
46
|
+
${i}`,"result","INVALID_RESULT")}let r=ee(R.join(e,P),t.runId);await x(r,n.data),M.info({runId:t.runId,status:t.status},"Run result saved"),await Qt(e).catch(i=>{M.warn({err:i},"Failed to prune old run results")})}async function Qt(e){let n=(await ve(e)).slice(Ge);if(n.length===0)return;let r=R.join(e,P);for(let i of n)await N.remove(ee(r,i)).catch(()=>{});M.info({pruned:n.length,retained:Ge},"Pruned old run results")}async function Be(e,t){let n=ee(R.join(e,P),t);if(!await N.pathExists(n))throw new g(`Run result not found for runId "${t}".`,n,"RESULT_NOT_FOUND");let r=await y(n),i=we.safeParse(r);if(!i.success){let a=i.error.issues.map(l=>` \u2022 ${l.path.join(".")}: ${l.message}`).join(`
|
|
47
|
+
`);throw new p(`Invalid run result at "${n}":
|
|
48
|
+
${a}`,"result","INVALID_RESULT")}return i.data}async function ve(e){let t=R.join(e,P,Me);if(!await N.pathExists(t))return[];let r=(await N.readdir(t,{withFileTypes:!0})).filter(a=>a.isFile()&&a.name.endsWith(".json")).map(a=>a.name.replace(".json",""));return(await Promise.all(r.map(async a=>{let l=await N.stat(R.join(t,`${a}.json`));return{id:a,mtime:l.mtimeMs}}))).sort((a,l)=>l.mtime-a.mtime).map(a=>a.id)}async function en(e,t=20){let n=await ve(e),r=[];for(let i of n.slice(0,t))try{let a=await Be(e,i);r.push({runId:a.runId,status:a.status,environment:a.environment,startedAt:a.startedAt,finishedAt:a.finishedAt,totalTests:a.totalTests,passed:a.passed,failed:a.failed,skipped:a.skipped,duration:a.duration,suiteIds:a.suites.map(l=>l.suiteId)})}catch(a){M.warn({runId:i,err:a},"Failed to read run result \u2014 skipping")}return r}async function tn(e,t){let n=ee(R.join(e,P),t);if(!await N.pathExists(n))throw new g(`Run result not found for runId "${t}".`,n,"RESULT_NOT_FOUND");await N.remove(n),M.info({runId:t},"Run result deleted")}function nn(e){return R.join(e,P,"screenshots")}function rn(e){return R.join(e,P,"videos")}function an(e){return R.join(e,P,"traces")}import w from"path";import V from"fs-extra";import{z as d}from"zod";var on=d.enum(["pending","accepted","rejected"]),sn=d.enum(["retry","regenerate","multi-selector","visual","decompose","manual"]),te=d.object({id:d.string(),runId:d.string(),suiteId:d.string(),caseId:d.string(),stepId:d.string(),stepInstruction:d.string(),failedCode:d.string(),healedCode:d.string(),error:d.string(),strategy:sn,level:d.number().int().min(1).max(6),status:on,pageUrl:d.string(),timestamp:d.string().datetime(),acceptedAt:d.string().datetime().optional(),rejectedAt:d.string().datetime().optional()}),Ae=d.object({runId:d.string(),generatedAt:d.string().datetime(),totalHeals:d.number().int(),accepted:d.number().int(),rejected:d.number().int(),pending:d.number().int(),events:d.array(te)});var B=S("healing-store"),C=w.join("results","healing"),cn="pending.json",ne="healing-report-";function Ke(e,t){return w.join(e,`${ne}${t}.json`)}function W(e){return w.join(e,cn)}async function ln(e,t){let n=Ae.safeParse(t);if(!n.success){let a=n.error.issues.map(l=>` \u2022 ${l.path.join(".")}: ${l.message}`).join(`
|
|
49
|
+
`);throw new p(`Cannot write invalid healing report:
|
|
50
|
+
${a}`,"healingReport","INVALID_HEALING_REPORT")}let r=w.join(e,C),i=Ke(r,t.runId);await x(i,n.data),B.info({runId:t.runId,totalHeals:t.totalHeals},"Healing report saved")}async function mn(e,t){let n=w.join(e,C),r=Ke(n,t);if(!await V.pathExists(r))throw new g(`Healing report not found for runId "${t}".`,r,"HEALING_REPORT_NOT_FOUND");let i=await y(r),a=Ae.safeParse(i);if(!a.success){let l=a.error.issues.map(b=>` \u2022 ${b.path.join(".")}: ${b.message}`).join(`
|
|
51
|
+
`);throw new p(`Invalid healing report at "${r}":
|
|
52
|
+
${l}`,"healingReport","INVALID_HEALING_REPORT")}return a.data}async function L(e){let t=w.join(e,C),n=W(t);if(!await V.pathExists(n))return[];let r=await y(n),i=te.array().safeParse(r);return i.success?i.data:(B.warn({path:n},"Pending healing file is malformed \u2014 resetting"),[])}var We=50,Je=["pending","rejected","accepted"];function un(e){if(e.length<=We)return e;let t=[...e].sort((i,a)=>{let l=Je.indexOf(i.status),b=Je.indexOf(a.status);return l!==b?l-b:i.timestamp<a.timestamp?-1:1}),n=e.length-We,r=new Set(t.slice(0,n).map(i=>i.id));return B.info({excess:n,deleted:r.size},"Auto-pruning healing events to enforce cap"),e.filter(i=>!r.has(i.id))}async function pn(e,t){let n=te.safeParse(t);if(!n.success)throw new p(`Invalid healing event: ${n.error.message}`,"healingEvent","INVALID_HEALING_EVENT");let r=w.join(e,C);await V.ensureDir(r);let i=await L(e);i.push(n.data),await x(W(r),un(i))}async function dn(e,t){let n=await L(e),r=n.findIndex(a=>a.id===t);if(r===-1)throw new g(`Healing event "${t}" not found in pending list.`,t,"HEALING_EVENT_NOT_FOUND");n[r]={...n[r],status:"accepted",acceptedAt:new Date().toISOString()};let i=w.join(e,C);return await x(W(i),n),B.info({eventId:t},"Healing event accepted"),n[r]}async function gn(e,t){let n=await L(e),r=n.findIndex(a=>a.id===t);if(r===-1)throw new g(`Healing event "${t}" not found in pending list.`,t,"HEALING_EVENT_NOT_FOUND");n[r]={...n[r],status:"rejected",rejectedAt:new Date().toISOString()};let i=w.join(e,C);return await x(W(i),n),B.info({eventId:t},"Healing event rejected"),n[r]}async function fn(e,t=30){let n=await L(e),r=Date.now()-t*24*60*60*1e3,i=n.length,a=n.filter(l=>{if(l.status==="pending")return!0;let b=l.acceptedAt??l.rejectedAt;return b?new Date(b).getTime()>r:!0});if(a.length<i){let l=w.join(e,C);await x(W(l),a)}return i-a.length}async function hn(e){let t=await L(e),n=t.filter(a=>a.status==="pending").length,r=t.filter(a=>a.status==="accepted").length,i=t.filter(a=>a.status==="rejected").length;return{pending:n,accepted:r,rejected:i,total:t.length}}async function xn(e){let t=w.join(e,C);if(!await V.pathExists(t))return[];let r=(await V.readdir(t,{withFileTypes:!0})).filter(a=>a.isFile()&&a.name.startsWith(ne)&&a.name.endsWith(".json")).map(a=>a.name.slice(ne.length,-5));return(await Promise.all(r.map(async a=>{let l=await V.stat(w.join(t,`${ne}${a}.json`));return{id:a,mtime:l.mtimeMs}}))).sort((a,l)=>l.mtime-a.mtime).map(a=>a.id)}import{createHash as bn}from"crypto";function Ye(e){return bn("sha256").update(e,"utf8").digest("hex")}function Xe(e){try{return new URL(e).pathname.split("/").map(r=>/^\d+$/.test(r)||/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(r)||/^[a-z0-9-]{8,}$/i.test(r)&&/-/.test(r)?"*":r).join("/")}catch{return e}}function Sn(e,t){let n=e.toLowerCase().replace(/\s+/g," ").trim(),r=Xe(t);return Ye(`${n}|${r}`).slice(0,16)}import{config as yn}from"dotenv";import{z as u}from"zod";yn();var qe=["anthropic","openai","google","azure-openai","bedrock","deepseek","groq","together","qwen","perplexity","ollama","custom"],En=u.object({NODE_ENV:u.enum(["development","production","test"]).default("development"),LOG_LEVEL:u.enum(["trace","debug","info","warn","error","fatal"]).default("info"),AI_PROVIDER:u.enum(qe),AI_TIERED_ENABLED:u.string().transform(e=>e==="true").default("false"),AI_TIERED_FAST_PROVIDER:u.enum(qe).optional(),AI_TIERED_FAST_MODEL:u.string().optional(),AI_TIMEOUT:u.coerce.number().int().positive().default(30),AI_MAX_RETRIES:u.coerce.number().int().min(0).max(10).default(2)}),wn=u.object({ANTHROPIC_API_KEY:u.string().min(1),ANTHROPIC_MODEL:u.string().default("claude-sonnet-4-20250514")}),vn=u.object({OPENAI_API_KEY:u.string().min(1),OPENAI_MODEL:u.string().default("gpt-4o")}),An=u.object({GOOGLE_API_KEY:u.string().min(1),GOOGLE_MODEL:u.string().default("gemini-2.5-pro")}),Rn=u.object({AZURE_OPENAI_API_KEY:u.string().min(1),AZURE_OPENAI_ENDPOINT:u.string().url(),AZURE_OPENAI_DEPLOYMENT:u.string().min(1),AZURE_OPENAI_API_VERSION:u.string().default("2024-10-21")}),In=u.object({AWS_ACCESS_KEY_ID:u.string().min(1),AWS_SECRET_ACCESS_KEY:u.string().min(1),AWS_SESSION_TOKEN:u.string().optional(),AWS_REGION:u.string().default("us-east-1"),BEDROCK_MODEL:u.string().default("anthropic.claude-sonnet-4-20250514-v1:0")}),jn=u.object({DEEPSEEK_API_KEY:u.string().min(1),DEEPSEEK_MODEL:u.string().default("deepseek-chat")}),Tn=u.object({GROQ_API_KEY:u.string().min(1),GROQ_MODEL:u.string().default("llama-3.3-70b-versatile")}),Pn=u.object({TOGETHER_API_KEY:u.string().min(1),TOGETHER_MODEL:u.string().default("meta-llama/Llama-3.3-70B-Instruct-Turbo")}),Cn=u.object({QWEN_API_KEY:u.string().min(1),QWEN_BASE_URL:u.string().url().default("https://dashscope-intl.aliyuncs.com/compatible-mode/v1"),QWEN_MODEL:u.string().default("qwen-max")}),_n=u.object({PERPLEXITY_API_KEY:u.string().min(1),PERPLEXITY_MODEL:u.string().default("sonar-pro")}),On=u.object({OLLAMA_BASE_URL:u.string().url().default("http://localhost:11434"),OLLAMA_MODEL:u.string().default("llama3.3")}),Nn=u.object({CUSTOM_API_KEY:u.string().min(1),CUSTOM_BASE_URL:u.string().url(),CUSTOM_MODEL:u.string().min(1)}),$n={anthropic:wn,openai:vn,google:An,"azure-openai":Rn,bedrock:In,deepseek:jn,groq:Tn,together:Pn,qwen:Cn,perplexity:_n,ollama:On,custom:Nn},J=null;function Ze(){if(J!==null)return J;let e=En.safeParse(process.env);if(!e.success){let a=e.error.issues.map(l=>` \u2022 ${l.path.join(".")}: ${l.message}`).join(`
|
|
53
|
+
`);throw new T(`Missing or invalid environment variables:
|
|
54
54
|
${a}
|
|
55
55
|
|
|
56
|
-
How to fix: Copy .env.example to .env and fill in your AI provider credentials.`,"ENV_VALIDATION_FAILED")}let t=e.data.AI_PROVIDER,r
|
|
57
|
-
`);throw new
|
|
56
|
+
How to fix: Copy .env.example to .env and fill in your AI provider credentials.`,"ENV_VALIDATION_FAILED")}let t=e.data.AI_PROVIDER,r=$n[t].safeParse(process.env);if(!r.success){let a=r.error.issues.map(l=>` \u2022 ${l.path.join(".")}: ${l.message}`).join(`
|
|
57
|
+
`);throw new T(`Provider "${t}" is missing required environment variables:
|
|
58
58
|
${a}
|
|
59
59
|
|
|
60
|
-
How to fix: Check .env.example for the ${t} section and add the required keys to .env.`,"PROVIDER_ENV_MISSING")}return
|
|
60
|
+
How to fix: Check .env.example for the ${t} section and add the required keys to .env.`,"PROVIDER_ENV_MISSING")}return J={...e.data,...r.data},J}function Vn(){J=null}function Ln(){try{return Ze()}catch{return null}}import{faker as o}from"@faker-js/faker";function Dn(){return[{category:"person",methods:[{name:"fullName",example:o.person.fullName()},{name:"firstName",example:o.person.firstName()},{name:"lastName",example:o.person.lastName()},{name:"middleName",example:o.person.middleName()},{name:"sex",example:o.person.sex()},{name:"prefix",example:o.person.prefix()},{name:"suffix",example:o.person.suffix()},{name:"jobTitle",example:o.person.jobTitle()},{name:"jobArea",example:o.person.jobArea()},{name:"jobType",example:o.person.jobType()},{name:"bio",example:o.person.bio()}]},{category:"internet",methods:[{name:"email",example:o.internet.email()},{name:"userName",example:o.internet.username()},{name:"password",example:o.internet.password()},{name:"url",example:o.internet.url()},{name:"domainName",example:o.internet.domainName()},{name:"domainWord",example:o.internet.domainWord()},{name:"ip",example:o.internet.ip()},{name:"ipv6",example:o.internet.ipv6()},{name:"mac",example:o.internet.mac()},{name:"userAgent",example:o.internet.userAgent()},{name:"emoji",example:o.internet.emoji()}]},{category:"phone",methods:[{name:"number",example:o.phone.number()},{name:"imei",example:o.phone.imei()}]},{category:"location",methods:[{name:"streetAddress",example:o.location.streetAddress()},{name:"street",example:o.location.street()},{name:"city",example:o.location.city()},{name:"state",example:o.location.state()},{name:"zipCode",example:o.location.zipCode()},{name:"country",example:o.location.country()},{name:"countryCode",example:o.location.countryCode()},{name:"county",example:o.location.county()},{name:"latitude",example:String(o.location.latitude())},{name:"longitude",example:String(o.location.longitude())},{name:"timeZone",example:o.location.timeZone()},{name:"buildingNumber",example:o.location.buildingNumber()}]},{category:"company",methods:[{name:"name",example:o.company.name()},{name:"catchPhrase",example:o.company.catchPhrase()},{name:"buzzPhrase",example:o.company.buzzPhrase()},{name:"buzzNoun",example:o.company.buzzNoun()},{name:"buzzVerb",example:o.company.buzzVerb()},{name:"buzzAdjective",example:o.company.buzzAdjective()}]},{category:"finance",methods:[{name:"accountNumber",example:o.finance.accountNumber()},{name:"accountName",example:o.finance.accountName()},{name:"creditCardNumber",example:o.finance.creditCardNumber()},{name:"creditCardCVV",example:o.finance.creditCardCVV()},{name:"currencyCode",example:o.finance.currencyCode()},{name:"currencyName",example:o.finance.currencyName()},{name:"amount",example:o.finance.amount()},{name:"iban",example:o.finance.iban()},{name:"bic",example:o.finance.bic()},{name:"bitcoinAddress",example:o.finance.bitcoinAddress()},{name:"transactionType",example:o.finance.transactionType()}]},{category:"date",methods:[{name:"past",example:o.date.past().toISOString()},{name:"future",example:o.date.future().toISOString()},{name:"recent",example:o.date.recent().toISOString()},{name:"soon",example:o.date.soon().toISOString()},{name:"birthdate",example:o.date.birthdate().toISOString()},{name:"month",example:o.date.month()},{name:"weekday",example:o.date.weekday()}]},{category:"lorem",methods:[{name:"word",example:o.lorem.word()},{name:"words",example:o.lorem.words()},{name:"sentence",example:o.lorem.sentence()},{name:"sentences",example:o.lorem.sentences()},{name:"paragraph",example:o.lorem.paragraph()},{name:"slug",example:o.lorem.slug()},{name:"lines",example:o.lorem.lines(1)}]},{category:"string",methods:[{name:"uuid",example:o.string.uuid()},{name:"alphanumeric",example:o.string.alphanumeric(10)},{name:"numeric",example:o.string.numeric(6)},{name:"alpha",example:o.string.alpha(8)},{name:"nanoid",example:o.string.nanoid()},{name:"hexadecimal",example:o.string.hexadecimal({length:8})},{name:"sample",example:o.string.sample(12)}]},{category:"number",methods:[{name:"int",example:String(o.number.int({max:9999}))},{name:"float",example:String(o.number.float({max:100,fractionDigits:2}))}]},{category:"datatype",methods:[{name:"boolean",example:String(o.datatype.boolean())}]},{category:"image",methods:[{name:"avatar",example:o.image.avatar()},{name:"url",example:o.image.url()}]},{category:"color",methods:[{name:"human",example:o.color.human()},{name:"rgb",example:o.color.rgb()},{name:"hex",example:o.color.rgb({format:"hex"})}]},{category:"commerce",methods:[{name:"productName",example:o.commerce.productName()},{name:"price",example:o.commerce.price()},{name:"department",example:o.commerce.department()},{name:"productDescription",example:o.commerce.productDescription().slice(0,60)+"..."},{name:"isbn",example:o.commerce.isbn()}]},{category:"vehicle",methods:[{name:"vehicle",example:o.vehicle.vehicle()},{name:"manufacturer",example:o.vehicle.manufacturer()},{name:"model",example:o.vehicle.model()},{name:"vin",example:o.vehicle.vin()},{name:"vrm",example:o.vehicle.vrm()}]},{category:"system",methods:[{name:"fileName",example:o.system.fileName()},{name:"mimeType",example:o.system.mimeType()},{name:"fileExt",example:o.system.fileExt()},{name:"filePath",example:o.system.filePath()},{name:"semver",example:o.system.semver()}]}]}var Hn={"internet.userName":"username"};function Fn(e,t){let n=o[e],r=Hn[`${e}.${t}`]??t;if(!n||typeof n[r]!="function")return`[unknown: ${e}.${t}]`;let i=n[r]();return i instanceof Date?i.toISOString():String(i)}function Mi(e){let t={...K,...e},n=D.safeParse(t);if(!n.success){let r=n.error.issues.map(i=>` \u2022 ${i.path.join(".")}: ${i.message}`).join(`
|
|
61
61
|
`);throw new Error(`Invalid assuremind config:
|
|
62
|
-
${r}`)}return n.data}export{v as AssuremindError,
|
|
62
|
+
${r}`)}return n.data}export{v as AssuremindError,T as ConfigError,se as ExecutionError,ce as HealingError,oe as ProviderError,g as StorageError,p as ValidationError,dn as acceptHealingEvent,pn as appendPendingEvent,Fn as callFaker,Vn as clearEnvCache,Gt as configExists,Pt as createCase,S as createChildLogger,vt as createSuite,Mi as defineConfig,_t as deleteCase,zt as deleteGlobalVariable,tn as deleteResult,Rt as deleteSuite,ut as formatError,Sn as generateCacheKey,Dn as getAvailableGenerators,Nt as getCasePath,hn as getHealingStats,mt as isAssuremindError,Ve as listCasePaths,Ot as listCases,xn as listHealingReportIds,ve as listResultIds,en as listResults,me as listSuiteDirs,It as listSuites,jt as listSuitesWithCounts,Ut as listVariableFiles,_e as logger,Xe as normalizeUrl,fn as pruneResolvedEvents,de as readCase,Ee as readConfig,Fe as readEnvVariables,He as readGlobalVariables,mn as readHealingReport,L as readPendingEvents,Be as readResult,X as readSuite,k as readVariables,Et as redactSecrets,gn as rejectHealingEvent,Ht as resolveVariables,yt as sanitizeGeneratedCode,nn as screenshotsDir,Ft as setGlobalVariable,Ye as sha256,$ as toSlug,an as tracesDir,Ln as tryGetEnv,Ct as updateCase,kt as updateConfig,At as updateSuite,Mt as validateConfig,Ze as validateEnv,rn as videosDir,ge as writeCase,Ue as writeConfig,ln as writeHealingReport,Zt as writeResult,le as writeSuite,xe as writeVariables};
|