assuremind 1.5.3 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/cli/index.js +129 -129
- package/dist/index.d.mts +137 -149
- package/dist/index.d.ts +137 -149
- package/dist/index.js +31 -31
- package/dist/index.mjs +32 -32
- package/docs/GETTING-STARTED.md +28 -12
- package/package.json +1 -1
- package/templates/docs/GETTING-STARTED.md +7 -6
- package/ui/dist/assets/index-6jqOR-Hh.js +1029 -0
- package/ui/dist/assets/index-BGDCUDyt.css +1 -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 te(e,t){await I.default.ensureDir(e);let n=S.default.join(e,ee),r=
|
|
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 oe(e,t){let n=
|
|
8
|
-
`);throw new
|
|
9
|
-
${r}`,"case","INVALID_CASE")}await x(e,n.data),ie.debug({caseId:t.id,path:e},"Test case written")}async function
|
|
10
|
-
`);throw new
|
|
11
|
-
${r}`,"variables","INVALID_VARIABLES")}return n.data}async function se(e,t){let n=
|
|
12
|
-
`);throw new
|
|
13
|
-
${r}`,"variables","INVALID_VARIABLES")}await x(e,n.data),
|
|
14
|
-
`);throw new
|
|
15
|
-
${
|
|
1
|
+
"use strict";var Gt=Object.create;var Y=Object.defineProperty;var Mt=Object.getOwnPropertyDescriptor;var Bt=Object.getOwnPropertyNames;var Wt=Object.getPrototypeOf,Jt=Object.prototype.hasOwnProperty;var Kt=(e,t)=>{for(var n in t)Y(e,n,{get:t[n],enumerable:!0})},De=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Bt(t))!Jt.call(e,i)&&i!==n&&Y(e,i,{get:()=>t[i],enumerable:!(r=Mt(t,i))||r.enumerable});return e};var h=(e,t,n)=>(n=e!=null?Gt(Wt(e)):{},De(t||!e||!e.__esModule?Y(n,"default",{value:e,enumerable:!0}):n,e)),Yt=e=>De(Y({},"__esModule",{value:!0}),e);var Yn={};Kt(Yn,{AssuremindError:()=>v,ConfigError:()=>T,ExecutionError:()=>Z,HealingError:()=>Q,ProviderError:()=>X,StorageError:()=>g,ValidationError:()=>p,acceptHealingEvent:()=>Ct,appendPendingEvent:()=>Pt,callFaker:()=>kt,clearEnvCache:()=>Ft,configExists:()=>gt,createCase:()=>nt,createChildLogger:()=>b,createSuite:()=>qe,defineConfig:()=>Kn,deleteCase:()=>it,deleteGlobalVariable:()=>mt,deleteResult:()=>yt,deleteSuite:()=>Ze,formatError:()=>Ge,generateCacheKey:()=>Lt,getAvailableGenerators:()=>Ut,getCasePath:()=>ot,getHealingStats:()=>Nt,isAssuremindError:()=>ke,listCasePaths:()=>ye,listCases:()=>at,listHealingReportIds:()=>$t,listResultIds:()=>Oe,listResults:()=>St,listSuiteDirs:()=>ne,listSuites:()=>Qe,listSuitesWithCounts:()=>et,listVariableFiles:()=>ut,logger:()=>xe,normalizeUrl:()=>Ve,pruneResolvedEvents:()=>Ot,readCase:()=>ae,readConfig:()=>le,readEnvVariables:()=>Ae,readGlobalVariables:()=>ve,readHealingReport:()=>Tt,readPendingEvents:()=>L,readResult:()=>_e,readSuite:()=>G,readVariables:()=>H,redactSecrets:()=>Je,rejectHealingEvent:()=>_t,resolveVariables:()=>ct,sanitizeGeneratedCode:()=>We,screenshotsDir:()=>Et,setGlobalVariable:()=>lt,sha256:()=>$e,toSlug:()=>O,tracesDir:()=>vt,tryGetEnv:()=>zt,updateCase:()=>rt,updateConfig:()=>dt,updateSuite:()=>Xe,validateConfig:()=>ft,validateEnv:()=>Le,videosDir:()=>wt,writeCase:()=>oe,writeConfig:()=>je,writeHealingReport:()=>jt,writeResult:()=>bt,writeSuite:()=>te,writeVariables:()=>se});module.exports=Yt(Yn);var c=require("zod"),qt=c.z.enum(["off","on","only-on-failure"]),Xt=c.z.enum(["off","on","on-first-retry","retain-on-failure"]),Zt=c.z.enum(["off","on","on-first-retry","retain-on-failure"]),He=c.z.enum(["chromium","firefox","webkit"]),Qt=c.z.enum(["commit","domcontentloaded","load","networkidle"]),Fe=c.z.string().min(1),ze=["DEV","TEST","STAGE","INT","PROD"],en=c.z.record(c.z.string(),c.z.string()).default({}),tn=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)}),nn=c.z.object({allure:c.z.boolean(),html:c.z.boolean(),json:c.z.boolean()}),rn=c.z.object({width:c.z.number().int().positive(),height:c.z.number().int().positive()}),an=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:en.default({DEV:"",TEST:"",STAGE:"",INT:"",PROD:""}),browsers:c.z.array(He).min(1),headless:c.z.boolean(),viewport:rn.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:Qt.default("domcontentloaded"),screenshot:qt,video:Xt,trace:Zt,healing:tn,reporting:nn,studioPort:c.z.number().int().min(1024).max(65535),profiles:c.z.array(an).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")),I=h(require("fs-extra")),Ye=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()}),on=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(),Ue=l.z.object({id:l.z.string(),instruction:l.z.string(),generatedCode:l.z.string().default(""),order:l.z.number().int().default(0)}),sn=l.z.object({before:l.z.array(Ue).default([]),after:l.z.array(Ue).default([])}).default({before:[],after:[]}),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()),priority:l.z.enum(["critical","high","medium","low"]),timeout:l.z.number().int().positive().optional(),dataSource:on,steps:l.z.array(U),caseHooks:sn,lighthouseCategories:l.z.array(l.z.enum(["performance","accessibility","seo"])).default(["performance","accessibility","seo"]),createdAt:l.z.string().datetime(),updatedAt:l.z.string().datetime()}),fe=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()}),Qn=l.z.enum(["before_all","before_each","after_each","after_all"]),er=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}},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}},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 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 he=h(require("pino")),cn=h(require("fs-extra"));var ln=process.env.NODE_ENV!=="production",Me=ln?{target:"pino-pretty",options:{colorize:!0,translateTime:"HH:MM:ss",ignore:"pid,hostname",messageFormat:"[assuremind] {msg}"}}:void 0,xe=(0,he.default)({level:process.env.LOG_LEVEL??"info",base:{name:"assuremind"}},Me?he.default.transport(Me):void 0);function b(e){return xe.child({component:e})}function mn(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 un=[/\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 pn(e){for(let t of un)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 dn=/\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(dn,"").trim();return t.length>0?t:e}function gn(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 fn(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 hn(e){let t=e;return t=fn(t),t=t.replace(/\.or\((?:[^()]*|\([^()]*\))*\)(?:\.(?:first|last)\(\))?/g,""),t=t.replace(/\.(?:first|last)\(\)(?=\.\w)/g,""),t=gn(t),t}function We(e){let t=mn(e);if(!t)throw new p("AI returned an empty code response. Please try regenerating.","generatedCode","EMPTY_CODE");let n=hn(t);return pn(n),n}function O(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 be=h(require("path")),R=h(require("fs-extra"));async function x(e,t){let n=be.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 Ke(e,t){let n=be.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=fe.safeParse(n);if(!r.success){let a=r.error.issues.map(m=>` \u2022 ${m.path.join(".")}: ${m.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 te(e,t){await I.default.ensureDir(e);let n=S.default.join(e,ee),r=fe.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 qe(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),m=S.default.join(a,O(i.name));if(await I.default.pathExists(S.default.join(m,ee)))throw new g(`Suite directory already exists at "${m}". Choose a different name or delete the existing suite first.`,m,"SUITE_ALREADY_EXISTS");return await te(m,i),k.info({suiteId:i.id,path:m},"Suite created"),{suiteDir:m,suiteId:i.id}}async function Xe(e,t){let n=await G(e),r={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:new Date().toISOString()};return await te(e,r),r}async function Ze(e){if(!await I.default.pathExists(e))throw new g(`Suite directory not found at "${e}".`,e,"SUITE_NOT_FOUND");await I.default.remove(e),k.info({path:e},"Suite deleted")}async function ne(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 I.default.pathExists(r))continue;let i=await I.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 m=S.default.join(r,a.name,ee);await I.default.pathExists(m)&&t.push(S.default.join(r,a.name))}}return t}async function Qe(e){let t=await ne(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 ne(e),n=[];for(let r of t)try{let i=await G(r),m=(await I.default.readdir(r,{withFileTypes:!0})).filter(y=>y.isFile()&&y.name.endsWith(".test.json")).length;n.push({...i,caseCount:m})}catch(i){k.warn({path:r,err:i},"Failed to read suite \u2014 skipping")}return n}var re=h(require("path")),D=h(require("fs-extra")),tt=require("uuid");var ie=b("case-store"),Se=".test.json";async function ae(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=ge.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 oe(e,t){let n=ge.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),ie.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=re.default.join(e,`${O(r.name)}${Se}`);return await oe(i,r),ie.info({caseId:r.id,path:i},"Test case created"),i}async function rt(e,t){let n=await ae(e),r={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:new Date().toISOString()};return await oe(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),ie.info({path:e},"Test case deleted")}async function ye(e){return await D.default.pathExists(e)?(await D.default.readdir(e,{withFileTypes:!0})).filter(n=>n.isFile()&&n.name.endsWith(Se)).map(n=>re.default.join(e,n.name)):[]}async function at(e){let t=await ye(e),n=[];for(let r of t)try{n.push(await ae(r))}catch(i){ie.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 re.default.join(e,`${O(t)}${Se}`)}var C=h(require("path")),M=h(require("fs-extra"));var P=require("zod"),xn=P.z.object({value:P.z.string(),secret:P.z.literal(!0)}),bn=P.z.union([P.z.string(),xn]),Ee=P.z.record(P.z.string(),bn);function Sn(e){return typeof e=="object"&&e.secret===!0}function st(e){return Sn(e)?e.value:e}var yn=b("variable-store"),B="variables",we="global.json";function En(e){return`${e}.env.json`}async function H(e){if(!await M.default.pathExists(e))return{};let t=await E(e),n=Ee.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 se(e,t){let n=Ee.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),yn.debug({path:e},"Variables written")}async function ve(e){let t=C.default.join(e,B,we);return H(t)}async function Ae(e,t){let n=C.default.join(e,B,En(t));return H(n)}async function ct(e,t){let n=await ve(e),r=t?await Ae(e,t):{},i={...n,...r},a={};for(let[m,y]of Object.entries(i)){let de=process.env[m];a[m]=de!==void 0&&de!==""?de:st(y)}return a}async function lt(e,t,n){let r=C.default.join(e,B,we);await M.default.ensureDir(C.default.dirname(r));let i=await H(r);i[t]=n,await se(r,i)}async function mt(e,t){let n=C.default.join(e,B,we),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 se(n,r)}async function ut(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")),ce=h(require("fs-extra"));var Re=b("config-store"),Ie="autotest.config.json",pt="autotest.config.ts";async function le(e){let t=F.default.join(e,Ie);if(!await ce.default.pathExists(t))return Re.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(m=>` \u2022 ${m.path.join(".")}: ${m.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 m of Object.keys(i.environmentUrls??{}))a.add(m);i.environment&&a.add(i.environment),a.size>0&&(i.environments=[...a])}return i}async function je(e,t){let n=z.safeParse(t);if(!n.success){let a=n.error.issues.map(m=>` \u2022 ${m.path.join(".")}: ${m.message}`).join(`
|
|
18
|
+
`);throw new p(`Cannot write invalid config:
|
|
19
|
+
${a}`,"config","INVALID_CONFIG")}let r=F.default.join(e,Ie);await x(r,n.data);let i=F.default.join(e,pt);await Ke(i,wn(n.data)),Re.info({rootDir:e},"Config saved")}async function dt(e,t){let n=await le(e),r={...n,...t,healing:{...n.healing,...t.healing??{}},reporting:{...n.reporting,...t.reporting??{}},environmentUrls:{...n.environmentUrls,...t.environmentUrls??{}}};return await je(e,r),r}async function gt(e){let t=F.default.join(e,Ie),n=F.default.join(e,pt);return await ce.default.pathExists(t)||await ce.default.pathExists(n)}async function ft(e){let t=await le(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");Re.debug({config:t},"Config validated successfully")}function wn(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 j=h(require("path")),
|
|
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,_),i=
|
|
51
|
-
`);throw new
|
|
52
|
-
${
|
|
53
|
-
`);throw new
|
|
44
|
+
`}var j=h(require("path")),N=h(require("fs-extra"));var s=require("zod"),me=s.z.enum(["pending","running","passed","failed","skipped"]),vn=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(),An=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),ht=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()}),Rn=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(ht).optional(),seoAudits:s.z.array(ht).optional(),lighthouseError:s.z.string().optional()}),In=s.z.object({stepId:s.z.string(),instruction:s.z.string(),status:me,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:vn,apiResponse:An,navigatedToUrl:s.z.string().optional(),auditUrl:s.z.string().optional()}),jn=s.z.object({caseId:s.z.string(),caseName:s.z.string(),status:me,steps:s.z.array(In),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(Rn).default([])}),Tn=s.z.object({suiteId:s.z.string(),suiteName:s.z.string(),suiteType:s.z.enum(["ui","api","audit","performance"]).optional(),status:me,cases:s.z.array(jn),duration:s.z.number(),browser:s.z.string(),startedAt:s.z.string().datetime(),finishedAt:s.z.string().datetime()}),Te=s.z.object({runId:s.z.string(),status:me,environment:s.z.string().optional(),suites:s.z.array(Tn),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(),logFilePath:s.z.string().optional()});var Pe=b("result-store"),$="results",xt="runs";function Ce(e,t){return j.default.join(e,xt,`${t}.json`)}async function bt(e,t){let n=Te.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=Ce(j.default.join(e,$),t.runId);await x(r,n.data),Pe.info({runId:t.runId,status:t.status},"Run result saved")}async function _e(e,t){let n=Ce(j.default.join(e,$),t);if(!await N.default.pathExists(n))throw new g(`Run result not found for runId "${t}".`,n,"RESULT_NOT_FOUND");let r=await E(n),i=Te.safeParse(r);if(!i.success){let a=i.error.issues.map(m=>` \u2022 ${m.path.join(".")}: ${m.message}`).join(`
|
|
47
|
+
`);throw new p(`Invalid run result at "${n}":
|
|
48
|
+
${a}`,"result","INVALID_RESULT")}return i.data}async function Oe(e){let t=j.default.join(e,$,xt);if(!await N.default.pathExists(t))return[];let r=(await N.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 m=await N.default.stat(j.default.join(t,`${a}.json`));return{id:a,mtime:m.mtimeMs}}))).sort((a,m)=>m.mtime-a.mtime).map(a=>a.id)}async function St(e,t=20){let n=await Oe(e),r=[];for(let i of n.slice(0,t))try{let a=await _e(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(m=>m.suiteId)})}catch(a){Pe.warn({runId:i,err:a},"Failed to read run result \u2014 skipping")}return r}async function yt(e,t){let n=Ce(j.default.join(e,$),t);if(!await N.default.pathExists(n))throw new g(`Run result not found for runId "${t}".`,n,"RESULT_NOT_FOUND");await N.default.remove(n),Pe.info({runId:t},"Run result deleted")}function Et(e){return j.default.join(e,$,"screenshots")}function wt(e){return j.default.join(e,$,"videos")}function vt(e){return j.default.join(e,$,"traces")}var w=h(require("path")),V=h(require("fs-extra"));var d=require("zod"),Pn=d.z.enum(["pending","accepted","rejected"]),Cn=d.z.enum(["retry","regenerate","multi-selector","visual","decompose","manual"]),ue=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:Cn,level:d.z.number().int().min(1).max(6),status:Pn,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(ue)});var W=b("healing-store"),_=w.default.join("results","healing"),_n="pending.json",pe="healing-report-";function It(e,t){return w.default.join(e,`${pe}${t}.json`)}function J(e){return w.default.join(e,_n)}async function jt(e,t){let n=Ne.safeParse(t);if(!n.success){let a=n.error.issues.map(m=>` \u2022 ${m.path.join(".")}: ${m.message}`).join(`
|
|
49
|
+
`);throw new p(`Cannot write invalid healing report:
|
|
50
|
+
${a}`,"healingReport","INVALID_HEALING_REPORT")}let r=w.default.join(e,_),i=It(r,t.runId);await x(i,n.data),W.info({runId:t.runId,totalHeals:t.totalHeals},"Healing report saved")}async function Tt(e,t){let n=w.default.join(e,_),r=It(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 m=a.error.issues.map(y=>` \u2022 ${y.path.join(".")}: ${y.message}`).join(`
|
|
51
|
+
`);throw new p(`Invalid healing report at "${r}":
|
|
52
|
+
${m}`,"healingReport","INVALID_HEALING_REPORT")}return a.data}async function L(e){let t=w.default.join(e,_),n=J(t);if(!await V.default.pathExists(n))return[];let r=await E(n),i=ue.array().safeParse(r);return i.success?i.data:(W.warn({path:n},"Pending healing file is malformed \u2014 resetting"),[])}var At=50,Rt=["pending","rejected","accepted"];function On(e){if(e.length<=At)return e;let t=[...e].sort((i,a)=>{let m=Rt.indexOf(i.status),y=Rt.indexOf(a.status);return m!==y?m-y:i.timestamp<a.timestamp?-1:1}),n=e.length-At,r=new Set(t.slice(0,n).map(i=>i.id));return W.info({excess:n,deleted:r.size},"Auto-pruning healing events to enforce cap"),e.filter(i=>!r.has(i.id))}async function Pt(e,t){let n=ue.safeParse(t);if(!n.success)throw new p(`Invalid healing event: ${n.error.message}`,"healingEvent","INVALID_HEALING_EVENT");let r=w.default.join(e,_);await V.default.ensureDir(r);let i=await L(e);i.push(n.data),await x(J(r),On(i))}async function Ct(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,_);return await x(J(i),n),W.info({eventId:t},"Healing event accepted"),n[r]}async function _t(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,_);return await x(J(i),n),W.info({eventId:t},"Healing event rejected"),n[r]}async function Ot(e,t=30){let n=await L(e),r=Date.now()-t*24*60*60*1e3,i=n.length,a=n.filter(m=>{if(m.status==="pending")return!0;let y=m.acceptedAt??m.rejectedAt;return y?new Date(y).getTime()>r:!0});if(a.length<i){let m=w.default.join(e,_);await x(J(m),a)}return i-a.length}async function Nt(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 $t(e){let t=w.default.join(e,_);if(!await V.default.pathExists(t))return[];let r=(await V.default.readdir(t,{withFileTypes:!0})).filter(a=>a.isFile()&&a.name.startsWith(pe)&&a.name.endsWith(".json")).map(a=>a.name.slice(pe.length,-5));return(await Promise.all(r.map(async a=>{let m=await V.default.stat(w.default.join(t,`${pe}${a}.json`));return{id:a,mtime:m.mtimeMs}}))).sort((a,m)=>m.mtime-a.mtime).map(a=>a.id)}var Vt=require("crypto");function $e(e){return(0,Vt.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 Lt(e,t){let n=e.toLowerCase().replace(/\s+/g," ").trim(),r=Ve(t);return $e(`${n}|${r}`).slice(0,16)}var Ht=require("dotenv"),u=require("zod");(0,Ht.config)();var Dt=["anthropic","openai","google","azure-openai","bedrock","deepseek","groq","together","qwen","perplexity","ollama","custom"],Nn=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(Dt),AI_TIERED_ENABLED:u.z.string().transform(e=>e==="true").default("false"),AI_TIERED_FAST_PROVIDER:u.z.enum(Dt).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)}),$n=u.z.object({ANTHROPIC_API_KEY:u.z.string().min(1),ANTHROPIC_MODEL:u.z.string().default("claude-sonnet-4-20250514")}),Vn=u.z.object({OPENAI_API_KEY:u.z.string().min(1),OPENAI_MODEL:u.z.string().default("gpt-4o")}),Ln=u.z.object({GOOGLE_API_KEY:u.z.string().min(1),GOOGLE_MODEL:u.z.string().default("gemini-2.5-pro")}),Dn=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")}),Hn=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")}),Fn=u.z.object({DEEPSEEK_API_KEY:u.z.string().min(1),DEEPSEEK_MODEL:u.z.string().default("deepseek-chat")}),zn=u.z.object({GROQ_API_KEY:u.z.string().min(1),GROQ_MODEL:u.z.string().default("llama-3.3-70b-versatile")}),Un=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")}),kn=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")}),Gn=u.z.object({PERPLEXITY_API_KEY:u.z.string().min(1),PERPLEXITY_MODEL:u.z.string().default("sonar-pro")}),Mn=u.z.object({OLLAMA_BASE_URL:u.z.string().url().default("http://localhost:11434"),OLLAMA_MODEL:u.z.string().default("llama3.3")}),Bn=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)}),Wn={anthropic:$n,openai:Vn,google:Ln,"azure-openai":Dn,bedrock:Hn,deepseek:Fn,groq:zn,together:Un,qwen:kn,perplexity:Gn,ollama:Mn,custom:Bn},K=null;function Le(){if(K!==null)return K;let e=Nn.safeParse(process.env);if(!e.success){let a=e.error.issues.map(m=>` \u2022 ${m.path.join(".")}: ${m.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=Wn[t].safeParse(process.env);if(!r.success){let a=r.error.issues.map(m=>` \u2022 ${m.path.join(".")}: ${m.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 K={...e.data,...r.data},K}function
|
|
60
|
+
How to fix: Check .env.example for the ${t} section and add the required keys to .env.`,"PROVIDER_ENV_MISSING")}return K={...e.data,...r.data},K}function Ft(){K=null}function zt(){try{return Le()}catch{return null}}var o=require("@faker-js/faker");function Ut(){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 Jn={"internet.userName":"username"};function kt(e,t){let n=o.faker[e],r=Jn[`${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 Kn(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 pe(e,t){let n=
|
|
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 Xe=c.enum(["off","on","only-on-failure"]),Ze=c.enum(["off","on","on-first-retry","retain-on-failure"]),Qe=c.enum(["off","on","on-first-retry","retain-on-failure"]),Ae=c.enum(["chromium","firefox","webkit"]),et=c.enum(["commit","domcontentloaded","load","networkidle"]),Re=c.string().min(1),Ie=["DEV","TEST","STAGE","INT","PROD"],tt=c.record(c.string(),c.string()).default({}),nt=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)}),rt=c.object({allure:c.boolean(),html:c.boolean(),json:c.boolean()}),it=c.object({width:c.number().int().positive(),height:c.number().int().positive()}),at=c.object({name:c.string().min(1),environment:Re,baseUrl:c.string().url(),browsers:c.array(Ae).min(1),headless:c.boolean().optional()}),D=c.object({baseUrl:c.string().url(),environment:Re.default("DEV"),environments:c.array(c.string().min(1)).default([...Ie]),environmentUrls:tt.default({DEV:"",TEST:"",STAGE:"",INT:"",PROD:""}),browsers:c.array(Ae).min(1),headless:c.boolean(),viewport:it.default({width:1280,height:720}),timeout:c.number().int().positive(),retries:c.number().int().min(0),parallel:c.number().int().positive(),pageLoad:et.default("domcontentloaded"),screenshot:Xe,video:Ze,trace:Qe,healing:nt,reporting:rt,studioPort:c.number().int().min(1024).max(65535),profiles:c.array(at).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})}),J={baseUrl:"http://localhost:3000",environment:"DEV",environments:[...Ie],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 I from"fs-extra";import{v4 as yt}from"uuid";import{z as l}from"zod";var H=l.object({id:l.string().min(1),order:l.number().int().positive(),instruction:l.string().min(1),generatedCode:l.string(),strategy:l.enum(["template","cache","rag","batch","fast","primary","recorder"]),stepType:l.enum(["ui","api","mock"]).default("ui"),lastHealed:l.string().nullable(),timeout:l.number().int().positive().optional(),retries:l.number().int().min(0).optional(),mockUrl:l.string().optional(),mockResponse:l.string().optional(),mockStatus:l.number().int().optional(),runAudit:l.boolean().optional(),soft:l.boolean().optional(),visualCheck:l.boolean().optional()}),ot=l.object({type:l.enum(["inline","json-file","csv-file"]),path:l.string().optional(),data:l.array(l.record(l.string())).optional()}).optional(),je=l.object({id:l.string(),instruction:l.string(),generatedCode:l.string().default(""),order:l.number().int().default(0)}),st=l.object({before:l.array(je).default([]),after:l.array(je).default([])}).default({before:[],after:[]}),ne=l.object({id:l.string().min(1),name:l.string().min(1),description:l.string(),tags:l.array(l.string()),priority:l.enum(["critical","high","medium","low"]),timeout:l.number().int().positive().optional(),dataSource:ot,steps:l.array(H),caseHooks:st,lighthouseCategories:l.array(l.enum(["performance","accessibility","seo"])).default(["performance","accessibility","seo"]),createdAt:l.string().datetime(),updatedAt:l.string().datetime()}),re=l.object({id:l.string().min(1),name:l.string().min(1),description:l.string(),tags:l.array(l.string()),type:l.enum(["ui","api","audit","performance"]).default("ui"),timeout:l.number().int().positive().optional(),createdAt:l.string().datetime(),updatedAt:l.string().datetime()}),kn=l.enum(["before_all","before_each","after_each","after_all"]),Gn=l.object({before_all:l.array(H).default([]),before_each:l.array(H).default([]),after_each:l.array(H).default([]),after_all:l.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)}},ie=class extends v{provider;constructor(t,n,r="PROVIDER_ERROR"){super(t,r),this.name="ProviderError",this.provider=n}},ae=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}},oe=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 ct(e){return e instanceof v}function lt(e){return e instanceof v?`[${e.code}] ${e.message}`:e instanceof Error?e.message:String(e)}import Te from"pino";import qn from"fs-extra";var mt=process.env.NODE_ENV!=="production",Pe=mt?{target:"pino-pretty",options:{colorize:!0,translateTime:"HH:MM:ss",ignore:"pid,hostname",messageFormat:"[assuremind] {msg}"}}:void 0,Ce=Te({level:process.env.LOG_LEVEL??"info",base:{name:"assuremind"}},Pe?Te.transport(Pe):void 0);function S(e){return Ce.child({component:e})}function ut(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 pt=[/\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 dt(e){for(let t of pt)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 gt=/\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 _e(e){let t=e.replace(gt,"").trim();return t.length>0?t:e}function ft(e){let t=e;return t=t.replace(/(getBy(?:Label|Placeholder)\(\s*)(['"`])([\s\S]*?)\2/g,(n,r,i,a)=>`${r}${i}${_e(a)}${i}`),t=t.replace(/(name:\s*)(['"`])([\s\S]*?)\2/g,(n,r,i,a)=>`${r}${i}${_e(a)}${i}`),t}function ht(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 xt(e){let t=e;return t=ht(t),t=t.replace(/\.or\((?:[^()]*|\([^()]*\))*\)(?:\.(?:first|last)\(\))?/g,""),t=t.replace(/\.(?:first|last)\(\)(?=\.\w)/g,""),t=ft(t),t}function bt(e){let t=ut(e);if(!t)throw new p("AI returned an empty code response. Please try regenerating.","generatedCode","EMPTY_CODE");let n=xt(t);return dt(n),n}function N(e){return e.toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function St(e,t){let n=e;for(let r of t)r.length>0&&(n=n.replaceAll(r,"[REDACTED]"));return n}import Oe from"path";import R from"fs-extra";async function x(e,t){let n=Oe.dirname(e);await R.ensureDir(n);let r=`${e}.${process.pid}.tmp`;try{await R.writeJson(r,t,{spaces:2}),await R.rename(r,e)}catch(i){throw await R.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 R.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 Ne(e,t){let n=Oe.dirname(e);await R.ensureDir(n);let r=`${e}.${process.pid}.tmp`;try{await R.writeFile(r,t,"utf8"),await R.rename(r,e)}catch(i){throw await R.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"),K="suite.json";async function Y(e){let t=E.join(e,K);if(!await I.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=re.safeParse(n);if(!r.success){let a=r.error.issues.map(m=>` \u2022 ${m.path.join(".")}: ${m.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 se(e,t){await I.ensureDir(e);let n=E.join(e,K),r=re.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 Et(e,t){let n=new Date().toISOString(),r=t.type??"ui",i={...t,type:r,id:yt(),createdAt:n,updatedAt:n},a=E.join(e,r),m=E.join(a,N(i.name));if(await I.pathExists(E.join(m,K)))throw new g(`Suite directory already exists at "${m}". Choose a different name or delete the existing suite first.`,m,"SUITE_ALREADY_EXISTS");return await se(m,i),F.info({suiteId:i.id,path:m},"Suite created"),{suiteDir:m,suiteId:i.id}}async function wt(e,t){let n=await Y(e),r={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:new Date().toISOString()};return await se(e,r),r}async function vt(e){if(!await I.pathExists(e))throw new g(`Suite directory not found at "${e}".`,e,"SUITE_NOT_FOUND");await I.remove(e),F.info({path:e},"Suite deleted")}async function ce(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 I.pathExists(r))continue;let i=await I.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 m=E.join(r,a.name,K);await I.pathExists(m)&&t.push(E.join(r,a.name))}}return t}async function At(e){let t=await ce(e),n=[];for(let r of t)try{n.push(await Y(r))}catch(i){F.warn({path:r,err:i},"Failed to read suite \u2014 skipping")}return n}async function Rt(e){let t=await ce(e),n=[];for(let r of t)try{let i=await Y(r),m=(await I.readdir(r,{withFileTypes:!0})).filter(b=>b.isFile()&&b.name.endsWith(".test.json")).length;n.push({...i,caseCount:m})}catch(i){F.warn({path:r,err:i},"Failed to read suite \u2014 skipping")}return n}import le from"path";import z from"fs-extra";import{v4 as It}from"uuid";var q=S("case-store"),me=".test.json";async function ue(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=ne.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 pe(e,t){let n=ne.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 jt(e,t){let n=new Date().toISOString(),r={...t,id:It(),createdAt:n,updatedAt:n},i=le.join(e,`${N(r.name)}${me}`);return await pe(i,r),q.info({caseId:r.id,path:i},"Test case created"),i}async function Tt(e,t){let n=await ue(e),r={...n,...t,id:n.id,createdAt:n.createdAt,updatedAt:new Date().toISOString()};return await pe(e,r),r}async function Pt(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 $e(e){return await z.pathExists(e)?(await z.readdir(e,{withFileTypes:!0})).filter(n=>n.isFile()&&n.name.endsWith(me)).map(n=>le.join(e,n.name)):[]}async function Ct(e){let t=await $e(e),n=[];for(let r of t)try{n.push(await ue(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 _t(e,t){return le.join(e,`${N(t)}${me}`)}import _ from"path";import X from"fs-extra";import{z as C}from"zod";var Ot=C.object({value:C.string(),secret:C.literal(!0)}),Nt=C.union([C.string(),Ot]),de=C.record(C.string(),Nt);function $t(e){return typeof e=="object"&&e.secret===!0}function Ve(e){return $t(e)?e.value:e}var Vt=S("variable-store"),U="variables",ge="global.json";function Lt(e){return`${e}.env.json`}async function k(e){if(!await X.pathExists(e))return{};let t=await y(e),n=de.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 fe(e,t){let n=de.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),Vt.debug({path:e},"Variables written")}async function Le(e){let t=_.join(e,U,ge);return k(t)}async function De(e,t){let n=_.join(e,U,Lt(t));return k(n)}async function Dt(e,t){let n=await Le(e),r=t?await De(e,t):{},i={...n,...r},a={};for(let[m,b]of Object.entries(i)){let te=process.env[m];a[m]=te!==void 0&&te!==""?te:Ve(b)}return a}async function Ht(e,t,n){let r=_.join(e,U,ge);await X.ensureDir(_.dirname(r));let i=await k(r);i[t]=n,await fe(r,i)}async function Ft(e,t){let n=_.join(e,U,ge),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 fe(n,r)}async function zt(e){let t=_.join(e,U);return await X.pathExists(t)?(await X.readdir(t,{withFileTypes:!0})).filter(r=>r.isFile()&&r.name.endsWith(".json")).map(r=>_.join(t,r.name)):[]}import G from"path";import he from"fs-extra";var xe=S("config-store"),be="autotest.config.json",He="autotest.config.ts";async function Se(e){let t=G.join(e,be);if(!await he.pathExists(t))return xe.debug({rootDir:e},"No autotest.config.json found \u2014 using defaults"),J;let n=await y(t),r=D.safeParse(n);if(!r.success){let a=r.error.issues.map(m=>` \u2022 ${m.path.join(".")}: ${m.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 m of Object.keys(i.environmentUrls??{}))a.add(m);i.environment&&a.add(i.environment),a.size>0&&(i.environments=[...a])}return i}async function Fe(e,t){let n=D.safeParse(t);if(!n.success){let a=n.error.issues.map(m=>` \u2022 ${m.path.join(".")}: ${m.message}`).join(`
|
|
18
|
+
`);throw new p(`Cannot write invalid config:
|
|
19
|
+
${a}`,"config","INVALID_CONFIG")}let r=G.join(e,be);await x(r,n.data);let i=G.join(e,He);await Ne(i,Mt(n.data)),xe.info({rootDir:e},"Config saved")}async function Ut(e,t){let n=await Se(e),r={...n,...t,healing:{...n.healing,...t.healing??{}},reporting:{...n.reporting,...t.reporting??{}},environmentUrls:{...n.environmentUrls,...t.environmentUrls??{}}};return await Fe(e,r),r}async function kt(e){let t=G.join(e,be),n=G.join(e,He);return await he.pathExists(t)||await he.pathExists(n)}async function Gt(e){let t=await Se(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");xe.debug({config:t},"Config validated successfully")}function Mt(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 j from"path";import $ from"fs-extra";import{z as s}from"zod";var Z=s.enum(["pending","running","passed","failed","skipped"]),
|
|
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 j from"path";import $ from"fs-extra";import{z as s}from"zod";var Z=s.enum(["pending","running","passed","failed","skipped"]),Bt=s.object({method:s.string(),url:s.string(),headers:s.record(s.string()).optional(),body:s.string().optional()}).optional(),Wt=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),ze=s.object({id:s.string(),title:s.string(),passed:s.boolean(),partial:s.boolean().optional(),na:s.boolean().optional()}),Jt=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(ze).optional(),seoAudits:s.array(ze).optional(),lighthouseError:s.string().optional()}),Kt=s.object({stepId:s.string(),instruction:s.string(),status:Z,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:Bt,apiResponse:Wt,navigatedToUrl:s.string().optional(),auditUrl:s.string().optional()}),Yt=s.object({caseId:s.string(),caseName:s.string(),status:Z,steps:s.array(Kt),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(Jt).default([])}),qt=s.object({suiteId:s.string(),suiteName:s.string(),suiteType:s.enum(["ui","api","audit","performance"]).optional(),status:Z,cases:s.array(Yt),duration:s.number(),browser:s.string(),startedAt:s.string().datetime(),finishedAt:s.string().datetime()}),ye=s.object({runId:s.string(),status:Z,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(),logFilePath:s.string().optional()});var Ee=S("result-store"),O="results",Ue="runs";function we(e,t){return j.join(e,Ue,`${t}.json`)}async function Xt(e,t){let n=ye.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=we(j.join(e,O),t.runId);await x(r,n.data),Ee.info({runId:t.runId,status:t.status},"Run result saved")}async function ke(e,t){let n=we(j.join(e,O),t);if(!await $.pathExists(n))throw new g(`Run result not found for runId "${t}".`,n,"RESULT_NOT_FOUND");let r=await y(n),i=ye.safeParse(r);if(!i.success){let a=i.error.issues.map(m=>` \u2022 ${m.path.join(".")}: ${m.message}`).join(`
|
|
47
|
+
`);throw new p(`Invalid run result at "${n}":
|
|
48
|
+
${a}`,"result","INVALID_RESULT")}return i.data}async function Ge(e){let t=j.join(e,O,Ue);if(!await $.pathExists(t))return[];let r=(await $.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 m=await $.stat(j.join(t,`${a}.json`));return{id:a,mtime:m.mtimeMs}}))).sort((a,m)=>m.mtime-a.mtime).map(a=>a.id)}async function Zt(e,t=20){let n=await Ge(e),r=[];for(let i of n.slice(0,t))try{let a=await ke(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(m=>m.suiteId)})}catch(a){Ee.warn({runId:i,err:a},"Failed to read run result \u2014 skipping")}return r}async function Qt(e,t){let n=we(j.join(e,O),t);if(!await $.pathExists(n))throw new g(`Run result not found for runId "${t}".`,n,"RESULT_NOT_FOUND");await $.remove(n),Ee.info({runId:t},"Run result deleted")}function en(e){return j.join(e,O,"screenshots")}function tn(e){return j.join(e,O,"videos")}function nn(e){return j.join(e,O,"traces")}import w from"path";import V from"fs-extra";import{z as d}from"zod";var rn=d.enum(["pending","accepted","rejected"]),an=d.enum(["retry","regenerate","multi-selector","visual","decompose","manual"]),Q=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:an,level:d.number().int().min(1).max(6),status:rn,pageUrl:d.string(),timestamp:d.string().datetime(),acceptedAt:d.string().datetime().optional(),rejectedAt:d.string().datetime().optional()}),ve=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(Q)});var M=S("healing-store"),P=w.join("results","healing"),on="pending.json",ee="healing-report-";function We(e,t){return w.join(e,`${ee}${t}.json`)}function B(e){return w.join(e,on)}async function sn(e,t){let n=ve.safeParse(t);if(!n.success){let a=n.error.issues.map(m=>` \u2022 ${m.path.join(".")}: ${m.message}`).join(`
|
|
49
|
+
`);throw new p(`Cannot write invalid healing report:
|
|
50
|
+
${a}`,"healingReport","INVALID_HEALING_REPORT")}let r=w.join(e,P),i=We(r,t.runId);await x(i,n.data),M.info({runId:t.runId,totalHeals:t.totalHeals},"Healing report saved")}async function cn(e,t){let n=w.join(e,P),r=We(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=ve.safeParse(i);if(!a.success){let m=a.error.issues.map(b=>` \u2022 ${b.path.join(".")}: ${b.message}`).join(`
|
|
51
|
+
`);throw new p(`Invalid healing report at "${r}":
|
|
52
|
+
${m}`,"healingReport","INVALID_HEALING_REPORT")}return a.data}async function L(e){let t=w.join(e,P),n=B(t);if(!await V.pathExists(n))return[];let r=await y(n),i=Q.array().safeParse(r);return i.success?i.data:(M.warn({path:n},"Pending healing file is malformed \u2014 resetting"),[])}var Me=50,Be=["pending","rejected","accepted"];function ln(e){if(e.length<=Me)return e;let t=[...e].sort((i,a)=>{let m=Be.indexOf(i.status),b=Be.indexOf(a.status);return m!==b?m-b:i.timestamp<a.timestamp?-1:1}),n=e.length-Me,r=new Set(t.slice(0,n).map(i=>i.id));return M.info({excess:n,deleted:r.size},"Auto-pruning healing events to enforce cap"),e.filter(i=>!r.has(i.id))}async function mn(e,t){let n=Q.safeParse(t);if(!n.success)throw new p(`Invalid healing event: ${n.error.message}`,"healingEvent","INVALID_HEALING_EVENT");let r=w.join(e,P);await V.ensureDir(r);let i=await L(e);i.push(n.data),await x(B(r),ln(i))}async function un(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,P);return await x(B(i),n),M.info({eventId:t},"Healing event accepted"),n[r]}async function pn(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,P);return await x(B(i),n),M.info({eventId:t},"Healing event rejected"),n[r]}async function dn(e,t=30){let n=await L(e),r=Date.now()-t*24*60*60*1e3,i=n.length,a=n.filter(m=>{if(m.status==="pending")return!0;let b=m.acceptedAt??m.rejectedAt;return b?new Date(b).getTime()>r:!0});if(a.length<i){let m=w.join(e,P);await x(B(m),a)}return i-a.length}async function gn(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 fn(e){let t=w.join(e,P);if(!await V.pathExists(t))return[];let r=(await V.readdir(t,{withFileTypes:!0})).filter(a=>a.isFile()&&a.name.startsWith(ee)&&a.name.endsWith(".json")).map(a=>a.name.slice(ee.length,-5));return(await Promise.all(r.map(async a=>{let m=await V.stat(w.join(t,`${ee}${a}.json`));return{id:a,mtime:m.mtimeMs}}))).sort((a,m)=>m.mtime-a.mtime).map(a=>a.id)}import{createHash as hn}from"crypto";function Je(e){return hn("sha256").update(e,"utf8").digest("hex")}function Ke(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 xn(e,t){let n=e.toLowerCase().replace(/\s+/g," ").trim(),r=Ke(t);return Je(`${n}|${r}`).slice(0,16)}import{config as bn}from"dotenv";import{z as u}from"zod";bn();var Ye=["anthropic","openai","google","azure-openai","bedrock","deepseek","groq","together","qwen","perplexity","ollama","custom"],Sn=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(Ye),AI_TIERED_ENABLED:u.string().transform(e=>e==="true").default("false"),AI_TIERED_FAST_PROVIDER:u.enum(Ye).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)}),yn=u.object({ANTHROPIC_API_KEY:u.string().min(1),ANTHROPIC_MODEL:u.string().default("claude-sonnet-4-20250514")}),En=u.object({OPENAI_API_KEY:u.string().min(1),OPENAI_MODEL:u.string().default("gpt-4o")}),wn=u.object({GOOGLE_API_KEY:u.string().min(1),GOOGLE_MODEL:u.string().default("gemini-2.5-pro")}),vn=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")}),An=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")}),Rn=u.object({DEEPSEEK_API_KEY:u.string().min(1),DEEPSEEK_MODEL:u.string().default("deepseek-chat")}),In=u.object({GROQ_API_KEY:u.string().min(1),GROQ_MODEL:u.string().default("llama-3.3-70b-versatile")}),jn=u.object({TOGETHER_API_KEY:u.string().min(1),TOGETHER_MODEL:u.string().default("meta-llama/Llama-3.3-70B-Instruct-Turbo")}),Tn=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")}),Pn=u.object({PERPLEXITY_API_KEY:u.string().min(1),PERPLEXITY_MODEL:u.string().default("sonar-pro")}),Cn=u.object({OLLAMA_BASE_URL:u.string().url().default("http://localhost:11434"),OLLAMA_MODEL:u.string().default("llama3.3")}),_n=u.object({CUSTOM_API_KEY:u.string().min(1),CUSTOM_BASE_URL:u.string().url(),CUSTOM_MODEL:u.string().min(1)}),On={anthropic:yn,openai:En,google:wn,"azure-openai":vn,bedrock:An,deepseek:Rn,groq:In,together:jn,qwen:Tn,perplexity:Pn,ollama:Cn,custom:_n},W=null;function qe(){if(W!==null)return W;let e=Sn.safeParse(process.env);if(!e.success){let a=e.error.issues.map(m=>` \u2022 ${m.path.join(".")}: ${m.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=On[t].safeParse(process.env);if(!r.success){let a=r.error.issues.map(m=>` \u2022 ${m.path.join(".")}: ${m.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 W={...e.data,...r.data},W}function
|
|
60
|
+
How to fix: Check .env.example for the ${t} section and add the required keys to .env.`,"PROVIDER_ENV_MISSING")}return W={...e.data,...r.data},W}function Nn(){W=null}function $n(){try{return qe()}catch{return null}}import{faker as o}from"@faker-js/faker";function Vn(){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 Ln={"internet.userName":"username"};function Dn(e,t){let n=o[e],r=Ln[`${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 ki(e){let t={...J,...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,ae as ExecutionError,oe as HealingError,ie as ProviderError,g as StorageError,p as ValidationError,un as acceptHealingEvent,mn as appendPendingEvent,Dn as callFaker,Nn as clearEnvCache,kt as configExists,jt as createCase,S as createChildLogger,Et as createSuite,ki as defineConfig,Pt as deleteCase,Ft as deleteGlobalVariable,Qt as deleteResult,vt as deleteSuite,lt as formatError,xn as generateCacheKey,Vn as getAvailableGenerators,_t as getCasePath,gn as getHealingStats,ct as isAssuremindError,$e as listCasePaths,Ct as listCases,fn as listHealingReportIds,Ge as listResultIds,Zt as listResults,ce as listSuiteDirs,At as listSuites,Rt as listSuitesWithCounts,zt as listVariableFiles,Ce as logger,Ke as normalizeUrl,dn as pruneResolvedEvents,ue as readCase,Se as readConfig,De as readEnvVariables,Le as readGlobalVariables,cn as readHealingReport,L as readPendingEvents,ke as readResult,Y as readSuite,k as readVariables,St as redactSecrets,pn as rejectHealingEvent,Dt as resolveVariables,bt as sanitizeGeneratedCode,en as screenshotsDir,Ht as setGlobalVariable,Je as sha256,N as toSlug,nn as tracesDir,$n as tryGetEnv,Tt as updateCase,Ut as updateConfig,wt as updateSuite,Gt as validateConfig,qe as validateEnv,tn as videosDir,pe as writeCase,Fe as writeConfig,sn as writeHealingReport,Xt as writeResult,se as writeSuite,fe as writeVariables};
|