shiplightai 0.1.41 → 0.1.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +1 -1
- package/dist/cli.js +3 -3
- package/dist/index.js +1 -1
- package/dist/static/assets/index-BwByAqLF.js +198607 -0
- package/dist/static/assets/index-DJa6w3mN.js +652 -0
- package/dist/static/assets/index-Djm5SCeS.css +12609 -0
- package/dist/static/index.html +17 -0
- package/package.json +3 -3
package/dist/cjs/index.cjs
CHANGED
|
@@ -4366,7 +4366,7 @@ ${p.join(`
|
|
|
4366
4366
|
`)}function Cc(e,t){let i=[],n=t?.version||"unknown";i.push(`// @generated by shiplightai v${n}`),i.push(...Lo()),i.push(""),t?.use&&Object.keys(t.use).length>0&&(i.push(`test.use(${JSON.stringify(t.use,null,2)});`),i.push(""));let a=new Set,o={imports:a,actionEntityStore:t?.actionEntityStore},r=t?.testName||"Test Suite",s=Kn(t?.tags);i.push(`test.describe.serial('${s}${Ee(r)}', () => {`),e.beforeAll&&e.beforeAll.length>0&&(i.push(...Ti("beforeAll",e.beforeAll,o,1)),i.push("")),e.beforeEach&&e.beforeEach.length>0&&(i.push(...Ti("beforeEach",e.beforeEach,o,1)),i.push(""));for(let c=0;c<e.tests.length;c++){let d=e.tests[c],u=d.timeout||d.skip!==void 0||d.fail!==void 0||d.only||d.slow?{timeout:d.timeout,skip:d.skip,fail:d.fail,only:d.only,slow:d.slow}:void 0;if(d.parameters&&d.parameters.length>0)for(let p of d.parameters){let g=Do(d.testFlow,p.values);i.push(...$i(g,`${Ee(d.name)} [${Ee(p.name)}]`,o,1,u)),i.push("")}else i.push(...$i(d.testFlow,Ee(d.name),o,1,u)),(c<e.tests.length-1||e.afterEach||e.afterAll)&&i.push("")}return e.afterEach&&e.afterEach.length>0&&(i.push(...Ti("afterEach",e.afterEach,o,1)),i.push("")),e.afterAll&&e.afterAll.length>0&&i.push(...Ti("afterAll",e.afterAll,o,1)),i.push("});"),Ro(i,a),i.join(`
|
|
4367
4367
|
`)}function Kn(e){return e&&e.length>0?e.map(t=>`@${t}`).join(" ")+" ":""}var Pc=["testContext","request"];function Mi(e){let t=new Set;function i(n){for(let a of n)switch(a.type){case ge.ACTION:{let r=a.action_entity?.action_data?.kwargs;if(r?.args&&Array.isArray(r.args))for(let s of r.args)typeof s=="string"&&Pc.includes(s)&&t.add(s);break}case ge.STEP:i(a.statements);break;case ge.IF_ELSE:{let o=a;i(o.then),o.else&&i(o.else);break}case ge.WHILE_LOOP:i(a.body);break}}return i(e),t}function Oc(e){let t=Mi(e.statements??[]);if(e.teardown)for(let i of Mi(e.teardown))t.add(i);return t}function Vn(e){return`{ ${["page","agent",...Array.from(e).sort()].join(", ")} }`}function $i(e,t,i,n=0,a){let o=" ".repeat(n),r=[],s=Oc(e),l=Vn(s),c=a?.only?"test.only":"test";r.push(`${o}${c}('${t}', async (${l}) => {`),a?.skip===!0?r.push(`${o} test.skip();`):typeof a?.skip=="string"&&r.push(`${o} test.skip(true, '${Ee(a.skip)}');`),a?.fail===!0?r.push(`${o} test.fail();`):typeof a?.fail=="string"&&r.push(`${o} test.fail(true, '${Ee(a.fail)}');`),a?.slow&&r.push(`${o} test.slow();`),a?.timeout&&r.push(`${o} test.setTimeout(${a.timeout});`);let d=e.teardown&&e.teardown.length>0,u=n+1;if(d){if(r.push(`${o} try {`),e.statements&&e.statements.length>0){r.push(`${o} // Test steps`);let g=we(e.statements,u+1,i);r.push(...g)}r.push(`${o} } finally {`),r.push(`${o} // Teardown`);let p=we(e.teardown,u+1,i,"teardown");r.push(...p),r.push(`${o} }`)}else if(e.statements&&e.statements.length>0){r.push(`${o} // Test steps`);let p=we(e.statements,u,i);r.push(...p)}return r.push(`${o}});`),r}function Co(e,t,i){let n=[],a=No(t),o=Mi(a),r=Vn(o);return n.push(`test.${e}(async (${r}) => {`),n.push(...we(a,1,i,e)),n.push("});"),n}function Ti(e,t,i,n){let a=" ".repeat(n),o=[],r=No(t);if(e==="beforeAll"||e==="afterAll"){let l={...i,noAgent:!0};o.push(`${a}test.${e}(async ({ browser }, workerInfo) => {`),o.push(`${a} const page = await browser.newPage({ baseURL: workerInfo.project.use.baseURL });`),o.push(...we(r,n+1,l,e)),o.push(`${a} await page.close();`),o.push(`${a}});`)}else{let l=Mi(r),c=Vn(l);o.push(`${a}test.${e}(async (${c}) => {`),o.push(...we(r,n+1,i,e)),o.push(`${a}});`)}return o}function No(e){let i=(0,Oo.stringify)({goal:"_hook",statements:e});return fe(i).statements??[]}function Do(e,t){let i=Bn(e);for(let[n,a]of Object.entries(t))i=i.split(`<<${n}>>`).join(String(a));return fe(i)}function Lo(){return["import { test, expect } from 'shiplightai/fixture';"]}function Ro(e,t){if(t.size>0){let i=0;for(let a=0;a<e.length;a++)e[a].startsWith("import ")&&(i=a+1);let n=Array.from(t);e.splice(i,0,...n)}}var Po=5;function Wo(e,t){let i={expandingPaths:new Set([(0,bt.resolve)(t)]),depth:0,referencedPaths:new Set},n={...e};Array.isArray(n.statements)&&(n.statements=Ne(n.statements,t,i)),Array.isArray(n.teardown)&&(n.teardown=Ne(n.teardown,t,i));for(let a of["beforeAll","afterAll","beforeEach","afterEach"])Array.isArray(n[a])&&(n[a]=Ne(n[a],t,i));return{doc:n,referencedTemplatePaths:Array.from(i.referencedPaths)}}function Ne(e,t,i){let n=[];for(let a of e)if(Nc(a)){let o=Dc(a,t,i);n.push(...o)}else n.push(Lc(a,t,i));return n}function Nc(e){return typeof e=="object"&&e!==null&&typeof e.template=="string"}function Dc(e,t,i){if(i.depth>=Po)throw new Error(`Template expansion exceeded maximum depth of ${Po}. Check for deeply nested or circular template references.`);let n=(0,bt.resolve)((0,bt.dirname)(t),e.template);if(i.expandingPaths.has(n))throw new Error(`Circular template reference detected: ${n} is already being expanded. Stack: ${Array.from(i.expandingPaths).join(" \u2192 ")} \u2192 ${n}`);i.referencedPaths.add(n);let a;try{a=(0,Ho.readFileSync)(n,"utf-8")}catch(d){throw new Error(`Failed to read template file: ${n} (referenced from ${t}): ${d.message}`)}let o=(0,ft.parse)(a);if(!o||typeof o!="object")throw new Error(`Invalid template file: ${n} \u2014 expected a YAML object`);let r=o.params||[],s=e.params||{};for(let d of r)if(!(d in s))throw new Error(`Template ${e.template} requires param "${d}" but it was not provided. Required params: [${r.join(", ")}]`);let l=o.statements;if(!Array.isArray(l))throw new Error(`Template ${e.template} must have a "statements" array`);if(Object.keys(s).length>0){let u=(0,ft.stringify)(l);for(let[p,g]of Object.entries(s))u=u.split(`<<${p}>>`).join(String(g));l=(0,ft.parse)(u)}let c={expandingPaths:new Set([...i.expandingPaths,n]),depth:i.depth+1,referencedPaths:i.referencedPaths};return Ne(l,n,c)}function Lc(e,t,i){if(typeof e!="object"||e===null)return e;let n={...e};return Array.isArray(n.statements)&&(n.statements=Ne(n.statements,t,i)),Array.isArray(n.THEN)&&(n.THEN=Ne(n.THEN,t,i)),Array.isArray(n.ELSE)&&(n.ELSE=Ne(n.ELSE,t,i)),Array.isArray(n.DO)&&(n.DO=Ne(n.DO,t,i)),n}var Xn=class extends Error{constructor(e){super(e),this.name="YamlValidationError"}};function Yn(e,t){let i=(0,wt.parse)(e),n=i?.name,a=i?.tags,o=i?.use;if(i&&(i.name!==void 0||i.tags!==void 0||i.use!==void 0)&&(delete i.name,delete i.tags,delete i.use),i?.suite){if(i.goal||i.statements)throw new Xn('YAML file cannot have both "suite" and top-level "goal"/"statements". Use either suite format or single-test format.');return Fc(i,n,a,o,t)}return Rc(i,n,a,o,t)}function Rc(e,t,i,n,a){let o=e?.beforeEach,r=e?.afterEach,s=Bo(e?.parameters),l=e?.timeout,c=e?.skip,d=e?.fail,u=e?.only,p=e?.slow;if(e&&(delete e.beforeEach,delete e.afterEach,delete e.parameters,delete e.timeout,delete e.skip,delete e.fail,delete e.only,delete e.slow),e?.url)throw new Xn(`The "url" field is not supported in local YAML tests. Use "base_url: ${e.url}" and add "- URL: /" as the first statement instead.`);e&&!e.goal&&t&&(e.goal=t);let g=[];if(a&&e&&typeof e=="object"){let b=Wo(e,a);e=b.doc,g=b.referencedTemplatePaths}let f=(0,wt.stringify)(e),v=fe(f);return a&&(Ye(v.statements??[],a,"main"),v.teardown&&Ye(v.teardown,a,"teardown")),{testFlow:v,name:t,tags:i,use:n,beforeEach:o,afterEach:r,parameters:s,timeout:l,skip:c,fail:d,only:u,slow:p,referencedTemplatePaths:g}}function Fc(e,t,i,n,a){let o=e.suite;if(!Array.isArray(o.tests)||o.tests.length===0)throw new Error('Suite must have a non-empty "tests" array.');let r=o.beforeAll,s=o.afterAll,l=o.beforeEach,c=o.afterEach,d=[],u=o.tests.map(f=>{if(!f.name)throw new Error('Each test in a suite must have a "name" field.');if(!Array.isArray(f.statements)||f.statements.length===0)throw new Error(`Suite test "${f.name}" must have a non-empty "statements" array.`);let v={goal:f.name,statements:f.statements};f.teardown&&(v.teardown=f.teardown);let b=[],m=v;if(a&&typeof v=="object"){let A=Wo(v,a);m=A.doc,b=A.referencedTemplatePaths,d.push(...b)}let y=(0,wt.stringify)(m),S=fe(y),T=Bo(f.parameters);return{testFlow:S,name:f.name,tags:Array.isArray(f.tags)?f.tags:void 0,parameters:T,timeout:f.timeout,skip:f.skip,fail:f.fail,only:f.only,slow:f.slow}}),p=o.base_url,g=p?{...n,baseURL:p}:n;return{suite:{beforeAll:r,afterAll:s,beforeEach:l,afterEach:c,tests:u},name:t,tags:i,use:g,referencedTemplatePaths:d}}function Bo(e){if(!(!Array.isArray(e)||e.length===0))return e.map((t,i)=>{if(!t.name)throw new Error(`Parameter set at index ${i} must have a "name" field.`);if(!t.values||typeof t.values!="object")throw new Error(`Parameter set "${t.name}" must have a "values" object.`);return{name:t.name,values:t.values}})}function Ye(e,t,i){for(let n=0;n<e.length;n++){let a=e[n],o=`${i}.${n}`,r=a.description||"";if(a.uid=Hc(t,o,r),a.type===ge.STEP)Ye(a.statements,t,o);else if(a.type===ge.IF_ELSE){let s=a;Ye(s.then,t,`${o}.then`),s.else&&Ye(s.else,t,`${o}.else`)}else a.type===ge.WHILE_LOOP&&Ye(a.body,t,`${o}.body`)}}function Hc(e,t,i){let n=(0,Fo.createHash)("sha256").update(`${e}:${t}:${i}`).digest("hex");return`${n.slice(0,8)}-${n.slice(8,12)}-${n.slice(12,16)}-${n.slice(16,20)}-${n.slice(20,32)}`}function Go(e,t,i){let n=/\btemplate:\s/.test(e),a=/^suite:/m.test(e),o=n||a?null:Un(e);if(o&&!o.valid)return{valid:!1,errors:o.errors,warnings:[],stats:o.stats};let r,s,l=[];try{let c=i?.parsed??Yn(e,t);l=c.referencedTemplatePaths;let d={version:i?.version,actionEntityStore:i?.actionEntityStore},u=c.testFlow?.baseURL?{...c.use,baseURL:c.testFlow.baseURL}:c.use;c.suite?r=Cc(c.suite,{...d,testName:c.name,tags:c.tags,use:c.use}):r=Ic(c.testFlow,{...d,testName:c.name,tags:c.tags,use:u,beforeEach:c.beforeEach,afterEach:c.afterEach,parameters:c.parameters,timeout:c.timeout,skip:c.skip,fail:c.fail,only:c.only,slow:c.slow});let p=r.split(`
|
|
4368
4368
|
`).filter(g=>!g.startsWith("import ")).join(`
|
|
4369
|
-
`);new Function(p),s=t.replace(/\.test\.yaml$/,".yaml.spec.ts"),(0,yt.mkdirSync)((0,Uo.dirname)(s),{recursive:!0}),(0,yt.writeFileSync)(s,r)}catch(c){let d=c instanceof Xn?"":c.message.includes("Unexpected token")?" This usually means a YAML escaping issue \u2014 in double-quoted strings, use \\\\/ instead of \\/ for regex patterns, or use single quotes / block scalars.":" This may indicate a transpiler bug \u2014 please report it.";return{valid:!1,errors:[`Transpilation failed: ${c.message}.${d}`],warnings:[],stats:o?.stats??{total:0,action:0,draft:0,coverage:0},referencedTemplatePaths:l}}return{valid:!0,errors:[],warnings:o?.warnings??[],stats:o?.stats??{total:0,action:0,draft:0,coverage:0},specFile:s,referencedTemplatePaths:l}}var Jn="0.1.
|
|
4369
|
+
`);new Function(p),s=t.replace(/\.test\.yaml$/,".yaml.spec.ts"),(0,yt.mkdirSync)((0,Uo.dirname)(s),{recursive:!0}),(0,yt.writeFileSync)(s,r)}catch(c){let d=c instanceof Xn?"":c.message.includes("Unexpected token")?" This usually means a YAML escaping issue \u2014 in double-quoted strings, use \\\\/ instead of \\/ for regex patterns, or use single quotes / block scalars.":" This may indicate a transpiler bug \u2014 please report it.";return{valid:!1,errors:[`Transpilation failed: ${c.message}.${d}`],warnings:[],stats:o?.stats??{total:0,action:0,draft:0,coverage:0},referencedTemplatePaths:l}}return{valid:!0,errors:[],warnings:o?.warnings??[],stats:o?.stats??{total:0,action:0,draft:0,coverage:0},specFile:s,referencedTemplatePaths:l}}var Jn="0.1.42";function jo(e){try{return(0,De.statSync)(e).mtimeMs}catch{return 0}}var Wc=`// @generated by shiplightai v${Jn}`;function Bc(e,t){if(!(0,De.existsSync)(e)||(0,De.readFileSync)(e,"utf-8").split(`
|
|
4370
4370
|
`,1)[0]!==Wc)return!1;let n=jo(e);for(let a of t)if(jo(a)>n)return!1;return!0}function Uc(e){let t=process.argv.slice(2),i=[],n=(0,Je.resolve)(e);for(let a of t){if(a.startsWith("-"))continue;let o=a.endsWith(".yaml.spec.ts")?a.replace(/\.yaml\.spec\.ts$/,".test.yaml"):a;if(!o.endsWith(".test.yaml"))continue;let r=(0,Je.resolve)(e,o);(0,De.existsSync)(r)&&i.push(r.startsWith(n)?r.slice(n.length+1):o)}return i.length>0?i:null}function zo(e){let t=Uc(e.cwd),i=t??(0,Ko.globSync)("**/*.test.yaml",{cwd:e.cwd,ignore:["**/node_modules/**"]}),n=[];for(let a of i){let o=(0,Je.resolve)(e.cwd,a),r=o.replace(/\.test\.yaml$/,".yaml.spec.ts"),s=(0,De.readFileSync)(o,"utf-8");try{let l=Yn(s,o),c=(0,Je.relative)(e.cwd,o),d=e.actionEntityStores?.get(c)??e.actionEntityStores?.get("*");if(!(d&&Object.keys(d.entries).length>0)&&Bc(r,[o,...l.referencedTemplatePaths]))continue;let p=Go(s,o,{version:Jn,actionEntityStore:d,parsed:l});if(!p.valid)throw new Error(p.errors.join("; "))}catch(l){console.error(`[shiplight] Failed to transpile ${a}:`,l),n.push({file:a,error:l})}}if(n.length>0){let a=`[shiplight] Transpilation failed for ${n.length} file(s):
|
|
4371
4371
|
`+n.map(o=>` - ${o.file}`).join(`
|
|
4372
4372
|
`);if(t)throw new Error(a);console.warn(a+" (skipped)")}}var se=Y(require("fs"),1),xt=Y(require("path"),1),Yo=require("glob");function Jo(e){return process.env.CI&&process.env.SHIPLIGHT_API_TOKEN?new ea:new Qn(e)}var Kc=".shiplight/action-cache";function Xo(e){return e.replace(/\//g,"__")+".json"}function zc(e){return e.replace(/\.json$/,"").replace(/__/g,"/")}var Qn=class{constructor(t){this.cwd=t;this.cacheDir=xt.join(t,Kc)}isCloud=!1;cacheDir;async lookup(t){let i=new Map;if(t.length===0||!se.existsSync(this.cacheDir))return i;for(let n of t){let a=xt.join(this.cacheDir,Xo(n));try{if(se.existsSync(a)){let o=se.readFileSync(a,"utf-8");i.set(n,JSON.parse(o))}}catch{}}return i}async update(t){if(t.size===0)return 0;se.mkdirSync(this.cacheDir,{recursive:!0});let i=0;for(let[n,a]of t)try{let o=xt.join(this.cacheDir,Xo(n)),r=Gn();if(se.existsSync(o))try{r=JSON.parse(se.readFileSync(o,"utf-8"))}catch{}let s={...r,entries:{...r.entries,...a.entries}};se.writeFileSync(o,JSON.stringify(s,null,2)),i++}catch{}return i}loadAll(){if(!se.existsSync(this.cacheDir))return;let t=(0,Yo.globSync)("*.json",{cwd:this.cacheDir});if(t.length===0)return;let i=new Map,n=0;for(let a of t)try{let o=se.readFileSync(xt.join(this.cacheDir,a),"utf-8"),r=JSON.parse(o),s=zc(a);i.set(s,r),n+=Object.keys(r.entries??{}).length}catch{}if(i.size!==0)return console.log(`[shiplight] Cache: loaded ${n} cached action entit${n===1?"y":"ies"} for ${i.size} test file${i.size!==1?"s":""}`),i}},ea=class{isCloud=!0;async lookup(t){let{lookupActionStores:i}=await Promise.resolve().then(()=>(Zn(),qn));return i(t)}async update(t){let{updateActionStores:i}=await Promise.resolve().then(()=>(Zn(),qn));return i(t)}loadAll(){}};function er(e={}){e.dotenv!==!1&&Vc(e.scanDir||process.cwd());let t=e.scanDir||process.cwd(),n=Jo(t).loadAll();return zo({cwd:t,actionEntityStores:n}),e.apiKey&&(process.env.__SHIPLIGHT_API_KEY=e.apiKey),{reporter:[["list"],["shiplightai/reporter",{outputFolder:"shiplight-report",open:"never",reportToCloud:e.reportToCloud,apiKey:e.apiKey}]]}}function tr(e,...t){return(0,Qo.defineConfig)(e,...t)}function Vc(e){let t=[],i=Ue.resolve(e),n=Ue.resolve(process.cwd());for(;;){let a=Ue.join(i,".env");if(qo.existsSync(a)&&t.push(a),i===n)break;let o=Ue.dirname(i);if(o===i)break;i=o}for(let a of t)Zo.default.config({path:a})}F();F();Ft();et();var za=require("zod"),Wu=za.z.object({instruction:za.z.string().describe('The instruction of the operation to perform. Can only include one operation. Do not inlcude element indexes just describe the element, e.g. "select the text "Hello, world!" in "Hello, world!""')});function pl(e){e.register({name:"perform_accurate_operation",description:"Perform an operation that requires accurate interaction like dragging or interacting with a specific area of an element. Only use this action when neccecary.",schema:Wu,usesElementIndex:!1,async execute(t,i){let{instruction:n}=t,a={page:i.page,agentServices:i.agentServices,domService:i.domService},o=await Qe(n,a,{});if(o.status==="error"||!o.actionEntity)return{success:!1,actionEntity:{action_description:n,action_data:{action_name:"perform_accurate_operation",kwargs:{instruction:n}}},error:o.error||"Failed to generate action"};let{actionEntity:r}=o,s=await Lt(r,a);return{success:s.success,actionEntity:r,message:s.success?`Successfully executed action: ${r.action_data?.action_name}`:void 0,error:s.error}}})}Me();F();var gl=require("ai"),fl=require("html-to-text");async function Bu(e,t,i){let{apiKey:n,domain:a}=e;if(!n||!a)throw new Error("Mailgun configuration missing. Please provide apiKey and domain");let o=[];try{let r=`https://api.mailgun.net/v3/${a}/events`,s={event:"accepted",limit:"10",ascending:"yes",recipient:t};if(i.from_email&&(s.from=i.from_email),i.since)s.begin=Math.floor(i.since/1e3).toString();else{let d=new Date(Date.now()-6e5);s.begin=Math.floor(d.getTime()/1e3).toString()}h.info(`Mailgun params: ${JSON.stringify(s)}`);let l=await fetch(r+"?"+new URLSearchParams(s),{method:"GET",headers:{Authorization:`Basic ${Buffer.from(`api:${n}`).toString("base64")}`}});if(!l.ok){let d=await l.text();throw new Error(`Mailgun events API error: ${d}`)}let c=(await l.json()).items||[];for(let d of c.slice(0,10)){if(d.event!=="accepted")continue;let u=(d.storage||{}).url;if(h.info(`message_url: ${u}`),!u){let f=(d.message||{}).headers||{},v=f.subject||"",b=f.from||"",m=f.to||"";if(i.from_email&&!b.toLowerCase().includes(i.from_email.toLowerCase())||i.to_email&&!m.toLowerCase().includes(i.to_email.toLowerCase())||i.subject&&!v.toLowerCase().includes(i.subject.toLowerCase()))continue;o.push({subject:v,from:b,to:m,date:new Date(d.timestamp*1e3).toUTCString(),body:"Message body not available (Mailgun storage disabled)",message_id:f["message-id"]||""});continue}let p=u.split("/"),g=p[p.length-1];if(h.info(`Storage key: ${g}`),g){let f=`https://api.mailgun.net/v3/domains/${a}/messages/${g}`;try{let v=await fetch(f,{method:"GET",headers:{Authorization:`Basic ${Buffer.from(`api:${n}`).toString("base64")}`,Accept:"application/json"}});if(v.ok){let b=await v.json(),m=b.Subject||"",y=b.From||"",S=b.To||"",T=b.Date||"",A=b["Message-Id"]||"";h.info(`subject: ${m}`),h.info(`from_addr: ${y}`),h.info(`to_addr: ${S}`),h.info(`date: ${T}`),h.info(`message_id: ${A}`);let $=b["body-html"]||b["body-plain"]||"";if($&&$.includes("<")&&($=(0,fl.convert)($)),h.info(`Body: ${$.substring(0,200)}...`),i.subject&&!m.toLowerCase().includes(i.subject.toLowerCase())||i.body_contains&&!$.toLowerCase().includes(i.body_contains.toLowerCase()))continue;o.push({subject:m,from:y,to:S,date:T,body:$,message_id:A});continue}else h.warn(`Messages API returned ${v.status}`)}catch(v){h.warn(`Failed to parse JSON response: ${v}`)}}try{let f=await fetch(u,{method:"GET",headers:{Authorization:`Basic ${Buffer.from(`api:${n}`).toString("base64")}`}});if(!f.ok){h.warn(`Could not fetch stored message: ${f.status}`);continue}let v=await f.text();h.info(`Fallback: Raw email length: ${v.length}`);let b=v.split(`
|
package/dist/cli.js
CHANGED
|
@@ -33,7 +33,7 @@ test('__shiplight_debug__', async ({ page, agent }) => {
|
|
|
33
33
|
`),s=JSON.stringify(i);return["{ const _t = Date.now(); try {",...a.map(c=>` ${c}`),` console.log(\`[VERIFY:JS] \u2713 \${((Date.now()-_t)/1000).toFixed(1)}s: ${s}\`);`,"} catch (_e) {",` console.log(\`[VERIFY:JS\u2192AI] JS failed \${((Date.now()-_t)/1000).toFixed(1)}s: (\${_e instanceof Error ? _e.message : String(_e)}), falling back to AI: ${s}\`);`,` await agent.assert(page, ${s}, ${JSON.stringify(t||"")});`,"} }"]}return o?r.code.split(`
|
|
34
34
|
`):i?[`await agent.assert(page, ${JSON.stringify(i)}, ${JSON.stringify(t||"")});`]:["// Skipping verify: missing statement or code"]});w("ai_assert",P.get("verify"));w("assert",P.get("verify"));w("ai_action",(e,t)=>{let r=e.action_data?.kwargs?.statement;if(!r)return["// Skipping ai_action: missing statement"];let o=JSON.stringify(r),i=e.action_data?.kwargs?.use_pure_vision;return[`await agent.execute(page, ${o}, '${t||""}', ${i});`]});w("ai_step",(e,t)=>{let r=e.action_data?.kwargs?.statement;return r?[`await agent.run(page, ${JSON.stringify(r)}, '${t||""}');`]:["// Skipping ai_step: missing statement"]});w("ai_extract",(e,t)=>{let r=e.action_data?.kwargs?.element_description,o=e.action_data?.kwargs?.variable_name;if(!r||!o)return["// Skipping ai_extract: missing element_description or variable_name"];let i=JSON.stringify(r),n=JSON.stringify(o);return[`await agent.extract(page, ${i}, ${n}, '${t||""}');`]});w("ai_wait_until",(e,t)=>{let r=e.action_data?.kwargs?.condition,o=e.action_data?.kwargs?.timeout_seconds||60;return r?[`await agent.waitUntilCondition(page, ${JSON.stringify(r)}, ${o}, '${t||""}');`]:["// Skipping ai_wait_until: missing condition"]});w("save_variable",e=>{let t=e.action_data?.kwargs?.name||"",r=e.action_data?.kwargs?.value;return['await agent.execAction("save_variable", page, {',` action_data: { kwargs: { name: ${JSON.stringify(t)}, value: ${JSON.stringify(r)} } },`,"});"]});w("js_code",e=>{let t=e.action_data?.kwargs?.code;if(!t)return["// Skipping js_code: missing code"];let r=["{"],o=t.split(`
|
|
35
35
|
`);for(let i of o)r.push(` ${i}`);return r.push("}"),r});w("function",(e,t,r)=>{let o=e.action_data?.kwargs||{},i=o.functionName;if(i&&i.includes("#")){let[a,s]=i.split("#");if(a&&s){let c=a.replace(/\.(ts|js|mjs)$/,""),l=`import { ${s} } from '${c}';`;r?.imports?.add(l);let p={...o,functionName:s},d=Ut(p);return d?[d.endsWith(";")?d:`${d};`]:["// Skipping function: invalid export pattern"]}}let n=Ut(o);return n?[n.endsWith(";")?n:`${n};`]:["// Skipping function: missing functionName"]});w("generate_2fa_code",e=>{let t=e.action_data?.kwargs?.otp_secret_key||"";return['await agent.execAction("generate_2fa_code", page, {',` action_data: { kwargs: { otp_secret_key: ${JSON.stringify(t)} } },`,"});"]});w("upload_file",e=>{let t=e.action_data?.kwargs||{},r=[],o={};return t.paths?o.paths=t.paths:t.path&&(o.path=t.path),t.use_file_input&&(o.use_file_input=!0),r.push(`action_data: { kwargs: ${JSON.stringify(o)} }`),e.locator?r.push(`locator: ${JSON.stringify(e.locator)}`):e.xpath&&r.push(`xpath: ${JSON.stringify(e.xpath)}`),e.frame_path&&e.frame_path.length>0&&r.push(`frame_path: ${JSON.stringify(e.frame_path)}`),['await agent.execAction("upload_file", page, {',...r.map(i=>` ${i},`),"});"]});w("wait_for_download_complete",e=>['await agent.execAction("wait_for_download_complete", page, {',` action_data: { kwargs: { timeout_seconds: ${e.action_data?.kwargs?.timeout_seconds||10} } },`,"});"]);w("switch_tab",e=>['await agent.execAction("switch_tab", page, {',` action_data: { kwargs: { page_id: ${e.action_data?.kwargs?.page_id??e.action_data?.kwargs?.tab_index??0} } },`,"});"]);w("close_tab",e=>{let t=e.action_data?.kwargs?.page_id;return t=t??e.action_data?.kwargs?.index,['await agent.execAction("close_tab", page, {',` action_data: { kwargs: { page_id: ${t} } },`,"});"]});w("set_date_for_native_date_picker",e=>{let t=e.action_data?.kwargs?.date??"",r=[];return r.push(`action_data: { kwargs: { date: ${JSON.stringify(t)} } }`),e.locator?r.push(`locator: ${JSON.stringify(e.locator)}`):e.xpath&&r.push(`xpath: ${JSON.stringify(e.xpath)}`),e.frame_path&&e.frame_path.length>0&&r.push(`frame_path: ${JSON.stringify(e.frame_path)}`),['await agent.execAction("set_date_for_native_date_picker", page, {',...r.map(o=>` ${o},`),"});"]});w("done",()=>["// Done - no action needed"]);w("js_action",e=>{let t=e.action_data?.kwargs?.code;return t?t.split(`
|
|
36
|
-
`):["// Skipping js_action: missing code"]});Oo=["testContext","request"];Vt=5;He=class extends Error{constructor(e){super(e),this.name="YamlValidationError"}}});import{Router as Jo}from"express";import*as F from"fs/promises";import*as W from"path";import{stringify as Xo}from"yaml";function _e(e){if(!e||e.length===0)return[];let r=Xo({goal:"_hook",statements:e});return $(r).statements??[]}async function or(e){try{let t=await F.readdir(e,{withFileTypes:!0});for(let r of t)if(!(r.name==="node_modules"||r.name.startsWith("."))&&(r.isFile()&&r.name.endsWith(".test.yaml")||r.isDirectory()&&await or(W.join(e,r.name))))return!0}catch{}return!1}function ir(e){let{initialDir:t,initialFile:r,projectRoot:o,onFileSelected:i}=e,n=Jo();n.get("/api/files",async(s,c)=>{try{let l=typeof s.query.dir=="string"?s.query.dir:t,p=W.resolve(l),d=await F.readdir(p,{withFileTypes:!0}),g=[];for(let u of d)if(u.name!=="node_modules"&&!u.name.startsWith("."))if(u.isDirectory()){let m=W.join(p,u.name);await or(m)&&g.push({name:u.name,type:"directory",path:m})}else u.isFile()&&u.name.endsWith(".test.yaml")&&g.push({name:u.name,type:"file",path:W.join(p,u.name)});g.sort((u,m)=>u.type!==m.type?u.type==="directory"?-1:1:u.name.localeCompare(m.name));let h=W.dirname(p);c.json({dir:p,parent:h!==p?h:null,entries:g,initialFile:r??null,projectRoot:o??t})}catch(l){console.error("[debugger] Error listing files:",l),c.status(500).json({error:l.message})}});function a(s){if(typeof s=="string"&&s){let c=W.resolve(s);return c.endsWith(".test.yaml")?{filePath:c}:{error:"File must be a .test.yaml file"}}return r?{filePath:r}:{error:"No file specified. Pass ?file= parameter."}}return n.get("/api/test-flow",async(s,c)=>{let l=a(s.query.file);if("error"in l)return c.status(400).json({error:l.error});let p=l.filePath;try{i?.(p);let d=await F.readFile(p,"utf-8"),g=await F.stat(p),h=ae(d),u=Ue(d,p);if(u.suite){let m=u.suite,b={tests:m.tests.map(_=>({name:_.name,statements:_.testFlow.statements??[],teardown:_.testFlow.teardown,skip:_.skip,timeout:_.timeout,fail:_.fail,only:_.only,slow:_.slow})),beforeAll:_e(m.beforeAll),afterAll:_e(m.afterAll),beforeEach:_e(m.beforeEach),afterEach:_e(m.afterEach)},S={version:"1.3.0",baseURL:u.use?.baseURL,testGroup:b};c.json({isSuite:!0,testFlow:S,metadata:h,name:u.name,tags:u.tags,use:u.use,filePath:p,fileName:W.basename(p),lastModified:g.mtimeMs})}else{let m=u.testFlow;ge(d,m),c.json({isSuite:!1,testFlow:m,metadata:h,name:u.name,tags:u.tags,use:u.use,filePath:p,fileName:W.basename(p),lastModified:g.mtimeMs})}}catch(d){if(d.code==="ENOENT")return c.status(404).json({error:`File not found: ${p}`});console.error("[debugger] Error loading test flow:",d),c.status(500).json({error:d.message})}}),n.put("/api/test-flow",async(s,c)=>{try{let l=a(s.query.file);if("error"in l)return c.status(400).json({error:l.error});let p=l.filePath,{testFlow:d,metadata:g}=s.body;if(!d)return c.status(400).json({error:"testFlow is required"});let h=se(d,g),u=p+".tmp";await F.writeFile(u,h,"utf-8"),await F.rename(u,p);let m=await F.stat(p);c.json({success:!0,lastModified:m.mtimeMs})}catch(l){console.error("[debugger] Error saving test flow:",l),c.status(500).json({error:l.message})}}),n}var nr=v(()=>{"use strict";q();Ke()});import*as sr from"http";function ar(e){let{getPort:t,ensureReady:r}=e,o=null,i=0,n=5e3,a=async(s,c,l)=>{let p=t();if(p===null){if(!o&&Date.now()-i<n)return c.status(503).json({status:"error",message:"Sandbox not ready. Select a test file and try again."});o||(o=r().catch(h=>{throw i=Date.now(),o=null,h}));try{p=await o}catch(h){return c.status(503).json({status:"error",message:"Failed to start sandbox: "+h.message})}}let d=await new Promise((h,u)=>{let m=[];s.on("data",b=>m.push(b)),s.on("end",()=>h(Buffer.concat(m))),s.on("error",u),s.readableEnded&&h(Buffer.alloc(0))}),g=sr.request({hostname:"localhost",port:p,path:s.originalUrl,method:s.method,headers:{"content-type":s.headers["content-type"]||"application/json","content-length":String(d.length)},timeout:3e5},h=>{c.writeHead(h.statusCode,h.headers),h.on("data",u=>{c.write(u)}),h.on("end",()=>{c.end()}),h.on("error",()=>{c.writableEnded||c.end()})});g.on("error",h=>{c.headersSent||c.status(502).json({status:"error",message:"Inner server unavailable: "+h.message})}),g.end(d)};return a.reset=()=>{o=null},a.getPort=()=>t(),a.ensureReady=async()=>{let s=t();return s!==null?s:(o||(o=r().catch(c=>{throw i=Date.now(),o=null,c})),o)},a}var cr=v(()=>{"use strict"});var lr={};X(lr,{startDebuggerServer:()=>qo});import xe from"express";import*as Q from"path";async function qo(e){let{initialDir:t,initialFile:r,projectRoot:o,port:i}=e,n=r,a=m=>{n=m,e.onFileSelected?.(m)},s=null,c=null,l=ar({getPort:()=>s,ensureReady:async()=>{console.error("[debugger] Initializing sandbox on first use...");let m=await e.innerServerFactory();return s=m.port,c=m.cleanup,m.port}}),p=xe();p.use((m,b,S)=>{if(b.setHeader("Access-Control-Allow-Origin","*"),b.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, OPTIONS"),b.setHeader("Access-Control-Allow-Headers","Content-Type"),m.method==="OPTIONS")return b.sendStatus(204);S()}),p.post("/api/int-runner/create-session",xe.json(),async(m,b)=>{n&&(m.body.testFilePath=n);try{let S=l.getPort();S||(S=await l.ensureReady());let _=await fetch(`http://localhost:${S}/api/int-runner/create-session`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(m.body)}),y=await _.json();b.status(_.status).json(y)}catch(S){b.status(502).json({status:"error",message:S.message})}}),p.post("/api/int-runner/terminate-session",async(m,b)=>{let S=c;s=null,c=null,l.reset(),S&&(console.error("[debugger] Tearing down inner Playwright process for fresh restart..."),await S().catch(_=>console.error("[debugger] Cleanup error:",_.message))),b.json({status:"success",details:"Session terminated"})}),p.use("/api/int-runner",l),p.use("/api/browser-cdp",l),p.use(xe.json({limit:"10mb"})),p.use(ir({initialDir:t,initialFile:r,projectRoot:o,onFileSelected:a}));let d=typeof import.meta.dirname=="string"?import.meta.dirname:__dirname,g=d.includes(Q.sep+"src"+Q.sep)?Q.resolve(d,"../../dist/static"):Q.join(d,"static");p.use(xe.static(g)),p.get("*",(m,b,S)=>{if(m.path.startsWith("/api/"))return S();b.sendFile(Q.join(g,"index.html"),_=>{_&&b.send(Zo(t,i))})});let h=await new Promise((m,b)=>{let S=p.listen(i,"localhost",()=>{m(S)});S.on("error",b)}),u=`http://localhost:${i}`;return console.error(`[debugger] Server running at ${u}`),console.error(`[debugger] Directory: ${t}`),r&&console.error(`[debugger] File: ${r}`),{url:u,close:async()=>{c&&await c(),await new Promise((m,b)=>{h.close(S=>S?b(S):m())})}}}function Zo(e,t){return`<!DOCTYPE html>
|
|
36
|
+
`):["// Skipping js_action: missing code"]});Oo=["testContext","request"];Vt=5;He=class extends Error{constructor(e){super(e),this.name="YamlValidationError"}}});import{Router as Jo}from"express";import*as F from"fs/promises";import*as W from"path";import{stringify as Xo}from"yaml";function _e(e){if(!e||e.length===0)return[];let r=Xo({goal:"_hook",statements:e});return $(r).statements??[]}async function or(e){try{let t=await F.readdir(e,{withFileTypes:!0});for(let r of t)if(!(r.name==="node_modules"||r.name.startsWith("."))&&(r.isFile()&&r.name.endsWith(".test.yaml")||r.isDirectory()&&await or(W.join(e,r.name))))return!0}catch{}return!1}function ir(e){let{initialDir:t,initialFile:r,projectRoot:o,onFileSelected:i}=e,n=Jo();n.get("/api/files",async(s,c)=>{try{let l=typeof s.query.dir=="string"?s.query.dir:t,p=W.resolve(l),d=await F.readdir(p,{withFileTypes:!0}),g=[];for(let u of d)if(u.name!=="node_modules"&&!u.name.startsWith("."))if(u.isDirectory()){let m=W.join(p,u.name);await or(m)&&g.push({name:u.name,type:"directory",path:m})}else u.isFile()&&u.name.endsWith(".test.yaml")&&g.push({name:u.name,type:"file",path:W.join(p,u.name)});g.sort((u,m)=>u.type!==m.type?u.type==="directory"?-1:1:u.name.localeCompare(m.name));let h=W.dirname(p);c.json({dir:p,parent:h!==p?h:null,entries:g,initialFile:r??null,projectRoot:o??t})}catch(l){console.error("[debugger] Error listing files:",l),c.status(500).json({error:l.message})}});function a(s){if(typeof s=="string"&&s){let c=W.resolve(s);return c.endsWith(".test.yaml")?{filePath:c}:{error:"File must be a .test.yaml file"}}return r?{filePath:r}:{error:"No file specified. Pass ?file= parameter."}}return n.get("/api/test-flow",async(s,c)=>{let l=a(s.query.file);if("error"in l)return c.status(400).json({error:l.error});let p=l.filePath;try{i?.(p);let d=await F.readFile(p,"utf-8"),g=await F.stat(p),h=ae(d),u=Ue(d,p);if(u.suite){let m=u.suite,b={tests:m.tests.map(_=>({name:_.name,statements:_.testFlow.statements??[],teardown:_.testFlow.teardown,skip:_.skip,timeout:_.timeout,fail:_.fail,only:_.only,slow:_.slow})),beforeAll:_e(m.beforeAll),afterAll:_e(m.afterAll),beforeEach:_e(m.beforeEach),afterEach:_e(m.afterEach)},S={version:"1.3.0",baseURL:u.use?.baseURL,testGroup:b};c.json({isSuite:!0,testFlow:S,metadata:h,name:u.name,tags:u.tags,use:u.use,filePath:p,fileName:W.basename(p),lastModified:g.mtimeMs})}else{let m=u.testFlow;ge(d,m),c.json({isSuite:!1,testFlow:m,metadata:h,name:u.name,tags:u.tags,use:u.use,filePath:p,fileName:W.basename(p),lastModified:g.mtimeMs})}}catch(d){if(d.code==="ENOENT")return c.status(404).json({error:`File not found: ${p}`});console.error("[debugger] Error loading test flow:",d),c.status(500).json({error:d.message})}}),n.put("/api/test-flow",async(s,c)=>{try{let l=a(s.query.file);if("error"in l)return c.status(400).json({error:l.error});let p=l.filePath,{testFlow:d,metadata:g}=s.body;if(!d)return c.status(400).json({error:"testFlow is required"});let h=se(d,g),u=p+".tmp";await F.writeFile(u,h,"utf-8"),await F.rename(u,p);let m=await F.stat(p);c.json({success:!0,lastModified:m.mtimeMs})}catch(l){console.error("[debugger] Error saving test flow:",l),c.status(500).json({error:l.message})}}),n}var nr=v(()=>{"use strict";q();Ke()});import*as sr from"http";function ar(e){let{getPort:t,ensureReady:r}=e,o=null,i=0,n=5e3,a=async(s,c,l)=>{let p=t();if(p===null){if(!o&&Date.now()-i<n)return c.status(503).json({status:"error",message:"Sandbox not ready. Select a test file and try again."});o||(o=r().catch(h=>{throw i=Date.now(),o=null,h}));try{p=await o}catch(h){return c.status(503).json({status:"error",message:"Failed to start sandbox: "+h.message})}}let d=await new Promise((h,u)=>{let m=[];s.on("data",b=>m.push(b)),s.on("end",()=>h(Buffer.concat(m))),s.on("error",u),s.readableEnded&&h(Buffer.alloc(0))}),g=sr.request({hostname:"localhost",port:p,path:s.originalUrl,method:s.method,headers:{"content-type":s.headers["content-type"]||"application/json","content-length":String(d.length)},timeout:3e5},h=>{c.writeHead(h.statusCode,h.headers),h.on("data",u=>{c.write(u)}),h.on("end",()=>{c.end()}),h.on("error",()=>{c.writableEnded||c.end()})});g.on("error",h=>{c.headersSent||c.status(502).json({status:"error",message:"Inner server unavailable: "+h.message})}),g.end(d)};return a.reset=()=>{o=null},a.getPort=()=>t(),a.ensureReady=async()=>{let s=t();return s!==null?s:(o||(o=r().catch(c=>{throw i=Date.now(),o=null,c})),o)},a}var cr=v(()=>{"use strict"});var lr={};X(lr,{startDebuggerServer:()=>qo});import xe from"express";import*as Q from"path";async function qo(e){let{initialDir:t,initialFile:r,projectRoot:o,port:i}=e,n=r,a=m=>{n=m,e.onFileSelected?.(m)},s=null,c=null,l=ar({getPort:()=>s,ensureReady:async()=>{console.error("[debugger] Initializing sandbox on first use...");let m=await e.innerServerFactory();return s=m.port,c=m.cleanup,m.port}}),p=xe();p.use((m,b,S)=>{if(b.setHeader("Access-Control-Allow-Origin","*"),b.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, OPTIONS"),b.setHeader("Access-Control-Allow-Headers","Content-Type"),m.method==="OPTIONS")return b.sendStatus(204);S()}),p.post("/api/int-runner/create-session",xe.json(),async(m,b)=>{n&&(m.body.testFilePath=n);try{let S=l.getPort();S||(S=await l.ensureReady());let _=await fetch(`http://localhost:${S}/api/int-runner/create-session`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(m.body)}),y=await _.json();b.status(_.status).json(y)}catch(S){b.status(502).json({status:"error",message:S.message})}}),p.post("/api/int-runner/terminate-session",async(m,b)=>{let S=c;s=null,c=null,l.reset(),S&&(console.error("[debugger] Tearing down inner Playwright process for fresh restart..."),await S().catch(_=>console.error("[debugger] Cleanup error:",_.message))),b.json({status:"success",details:"Session terminated"})}),p.use("/api/int-runner",l),p.use("/api/browser-cdp",l),p.use(xe.json({limit:"10mb"})),p.use(ir({initialDir:t,initialFile:r,projectRoot:o,onFileSelected:a}));let d=typeof import.meta.dirname=="string"?import.meta.dirname:__dirname,g=d.includes(Q.sep+"src"+Q.sep)?Q.resolve(d,"../../dist/static"):Q.join(d,"static");p.use(xe.static(g)),p.get("*path",(m,b,S)=>{if(m.path.startsWith("/api/"))return S();b.sendFile(Q.join(g,"index.html"),_=>{_&&b.send(Zo(t,i))})});let h=await new Promise((m,b)=>{let S=p.listen(i,"localhost",()=>{m(S)});S.on("error",b)}),u=`http://localhost:${i}`;return console.error(`[debugger] Server running at ${u}`),console.error(`[debugger] Directory: ${t}`),r&&console.error(`[debugger] File: ${r}`),{url:u,close:async()=>{c&&await c(),await new Promise((m,b)=>{h.close(S=>S?b(S):m())})}}}function Zo(e,t){return`<!DOCTYPE html>
|
|
37
37
|
<html>
|
|
38
38
|
<head>
|
|
39
39
|
<meta charset="utf-8">
|
|
@@ -919,9 +919,9 @@ Merged ${c.length} tests from ${p} shards into: ${g}`),r&&Si(c),t)try{let h=(awa
|
|
|
919
919
|
`;for(let c of i){let{name:l}=et(c);s+=`- <sub>${l}</sub>
|
|
920
920
|
`}s+=`
|
|
921
921
|
</details>
|
|
922
|
-
`}k.appendFileSync(t,s),console.log("GitHub step summary written.")}var Ar=v(()=>{"use strict";_r()});var Pr,Er=v(()=>{"use strict";Pr="0.1.
|
|
922
|
+
`}k.appendFileSync(t,s),console.log("GitHub step summary written.")}var Ar=v(()=>{"use strict";_r()});var Pr,Er=v(()=>{"use strict";Pr="0.1.42"});var $r={};X($r,{runTranspile:()=>_i});import*as Pe from"path";import{glob as vi}from"glob";async function _i(e){(e.includes("--help")||e.includes("-h"))&&(console.log("Usage: shiplight transpile [glob]"),console.log(""),console.log("Transpiles YAML test files to Playwright spec files (.yaml.spec.ts)."),console.log("Validates syntax and reports action coverage warnings."),console.log("Default glob: **/*.test.yaml"),console.log(""),console.log("Examples:"),console.log(" shiplight transpile # transpile all YAML tests"),console.log(' shiplight transpile "tests/**/*.test.yaml" # transpile specific directory'),console.log(" shiplight transpile tests/login.test.yaml # transpile a single file"),process.exit(0));let t=e[0]||"**/*.test.yaml",r=process.cwd(),o=await vi(t,{cwd:r,ignore:["node_modules/**","*.yaml.spec.ts"]});o.length===0&&(console.log(`No files matched: ${t}`),process.exit(0));let i=0,n=0,a=0;for(let s of o.sort()){let c=Pe.resolve(r,s),l=rr(c,{version:Pr});if(!l.valid){i++,console.log(`
|
|
923
923
|
\u2717 ${s}`);for(let d of l.errors)console.log(` ERROR: ${d}`);continue}a++;let p=Pe.basename(l.specFile);if(l.warnings.length>0){n++,console.log(`\u26A0 ${s} \u2192 ${p}`);for(let d of l.warnings)console.log(` WARNING: ${d}`)}else console.log(`\u2713 ${s} \u2192 ${p}`)}console.log(`
|
|
924
|
-
${o.length} file(s): ${a} transpiled, ${i} error(s), ${n} warning(s)`),process.exit(i>0?1:0)}var Mr=v(()=>{"use strict";Ke();Er()});var Lr={};X(Lr,{runInspect:()=>xi});import*as Ee from"fs";import*as Or from"path";async function xi(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(console.log("Usage: shiplight inspect <file.test.yaml> [options]"),console.log(""),console.log("Parse a YAML test file and output the resulting TestFlow JSON."),console.log("Useful for verifying YAML \u2192 JSON conversion."),console.log(""),console.log("Options:"),console.log(" --pretty Pretty-print JSON (default)"),console.log(" --compact Compact JSON output"),console.log(" --stats Show statement statistics only"),console.log(""),console.log("Examples:"),console.log(" shiplight inspect tests/login.test.yaml"),console.log(" shiplight inspect tests/suite.test.yaml --stats"),console.log(" shiplight inspect tests/login.test.yaml --compact | jq ."),process.exit(e.length===0?1:0));let t=e.includes("--compact"),r=e.includes("--stats"),o=e.find(a=>!a.startsWith("--"));o||(console.error("Error: no file specified"),process.exit(1));let i=Or.resolve(process.cwd(),o);Ee.existsSync(i)||(console.error(`Error: file not found: ${i}`),process.exit(1));let n=Ee.readFileSync(i,"utf-8");try{let a=ae(n),s=$(n);if(r)ki(s,a);else{let c={...a.test_case_id!==void 0?{test_case_id:a.test_case_id}:{},...a.name?{name:a.name}:{},testFlow:s};console.log(JSON.stringify(c,null,t?0:2))}}catch(a){console.error(`Error parsing ${o}: ${a.message}`),process.exit(1)}}function ki(e,t){if(console.log(`File: ${t.name||"(unnamed)"}`),t.test_case_id!==void 0&&console.log(`Cloud ID: ${t.test_case_id}`),console.log(`Version: ${e.version||"unknown"}`),e.testGroup){let r=e.testGroup;console.log("Type: suite (testGroup)"),console.log(`Tests: ${r.tests.length}`);for(let o of r.tests){let i=o.skip?` [SKIP${typeof o.skip=="string"?`: ${o.skip}`:""}]`:"";console.log(` - ${o.name}: ${o.statements.length} statements${o.teardown?`, ${o.teardown.length} teardown`:""}${i}`)}r.beforeAll?.length&&console.log(`Hooks: beforeAll (${r.beforeAll.length})`),r.afterAll?.length&&console.log(`Hooks: afterAll (${r.afterAll.length})`),r.beforeEach?.length&&console.log(`Hooks: beforeEach (${r.beforeEach.length})`),r.afterEach?.length&&console.log(`Hooks: afterEach (${r.afterEach.length})`)}else{console.log("Type: single test"),console.log(`Goal: ${e.goal}`),e.url&&console.log(`URL: ${e.url}`),e.baseURL&&console.log(`Base URL: ${e.baseURL}`),console.log(`Statements: ${e.statements?.length??0}`),e.teardown?.length&&console.log(`Teardown: ${e.teardown.length}`);let r=Ir(e.statements??[]);console.log(` DRAFT: ${r.drafts}, ACTION: ${r.actions}, STEP: ${r.steps}`)}}function Ir(e){let t={drafts:0,actions:0,steps:0};for(let r of e)if(r.type==="DRAFT")t.drafts++;else if(r.type==="ACTION")t.actions++;else if(r.type==="STEP"){t.steps++;let o=Ir(r.statements??[]);t.drafts+=o.drafts,t.actions+=o.actions,t.steps+=o.steps}return t}var Dr=v(()=>{"use strict";q()});var Cr=Rr((Fa,Ti)=>{Ti.exports={name:"shiplightai",version:"0.1.
|
|
924
|
+
${o.length} file(s): ${a} transpiled, ${i} error(s), ${n} warning(s)`),process.exit(i>0?1:0)}var Mr=v(()=>{"use strict";Ke();Er()});var Lr={};X(Lr,{runInspect:()=>xi});import*as Ee from"fs";import*as Or from"path";async function xi(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(console.log("Usage: shiplight inspect <file.test.yaml> [options]"),console.log(""),console.log("Parse a YAML test file and output the resulting TestFlow JSON."),console.log("Useful for verifying YAML \u2192 JSON conversion."),console.log(""),console.log("Options:"),console.log(" --pretty Pretty-print JSON (default)"),console.log(" --compact Compact JSON output"),console.log(" --stats Show statement statistics only"),console.log(""),console.log("Examples:"),console.log(" shiplight inspect tests/login.test.yaml"),console.log(" shiplight inspect tests/suite.test.yaml --stats"),console.log(" shiplight inspect tests/login.test.yaml --compact | jq ."),process.exit(e.length===0?1:0));let t=e.includes("--compact"),r=e.includes("--stats"),o=e.find(a=>!a.startsWith("--"));o||(console.error("Error: no file specified"),process.exit(1));let i=Or.resolve(process.cwd(),o);Ee.existsSync(i)||(console.error(`Error: file not found: ${i}`),process.exit(1));let n=Ee.readFileSync(i,"utf-8");try{let a=ae(n),s=$(n);if(r)ki(s,a);else{let c={...a.test_case_id!==void 0?{test_case_id:a.test_case_id}:{},...a.name?{name:a.name}:{},testFlow:s};console.log(JSON.stringify(c,null,t?0:2))}}catch(a){console.error(`Error parsing ${o}: ${a.message}`),process.exit(1)}}function ki(e,t){if(console.log(`File: ${t.name||"(unnamed)"}`),t.test_case_id!==void 0&&console.log(`Cloud ID: ${t.test_case_id}`),console.log(`Version: ${e.version||"unknown"}`),e.testGroup){let r=e.testGroup;console.log("Type: suite (testGroup)"),console.log(`Tests: ${r.tests.length}`);for(let o of r.tests){let i=o.skip?` [SKIP${typeof o.skip=="string"?`: ${o.skip}`:""}]`:"";console.log(` - ${o.name}: ${o.statements.length} statements${o.teardown?`, ${o.teardown.length} teardown`:""}${i}`)}r.beforeAll?.length&&console.log(`Hooks: beforeAll (${r.beforeAll.length})`),r.afterAll?.length&&console.log(`Hooks: afterAll (${r.afterAll.length})`),r.beforeEach?.length&&console.log(`Hooks: beforeEach (${r.beforeEach.length})`),r.afterEach?.length&&console.log(`Hooks: afterEach (${r.afterEach.length})`)}else{console.log("Type: single test"),console.log(`Goal: ${e.goal}`),e.url&&console.log(`URL: ${e.url}`),e.baseURL&&console.log(`Base URL: ${e.baseURL}`),console.log(`Statements: ${e.statements?.length??0}`),e.teardown?.length&&console.log(`Teardown: ${e.teardown.length}`);let r=Ir(e.statements??[]);console.log(` DRAFT: ${r.drafts}, ACTION: ${r.actions}, STEP: ${r.steps}`)}}function Ir(e){let t={drafts:0,actions:0,steps:0};for(let r of e)if(r.type==="DRAFT")t.drafts++;else if(r.type==="ACTION")t.actions++;else if(r.type==="STEP"){t.steps++;let o=Ir(r.statements??[]);t.drafts+=o.drafts,t.actions+=o.actions,t.steps+=o.steps}return t}var Dr=v(()=>{"use strict";q()});var Cr=Rr((Fa,Ti)=>{Ti.exports={name:"shiplightai",version:"0.1.42",type:"module",description:"Shiplight CLI for running and debugging .test.yaml files",main:"dist/index.js",types:"dist/index.d.ts",bin:{shiplight:"dist/cli.js"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js",require:"./dist/cjs/index.cjs",default:"./dist/index.js"},"./fixture":{types:"./dist/fixture.d.ts",import:"./dist/fixture.js",require:"./dist/cjs/fixture.cjs",default:"./dist/fixture.js"},"./debugger-pw":{types:"./dist/debugger-pw.d.ts",import:"./dist/debugger-pw.js",require:"./dist/cjs/debugger-pw.cjs",default:"./dist/debugger-pw.js"},"./reporter":{types:"./dist/reporter.d.ts",import:"./dist/reporter.js",require:"./dist/cjs/reporter.cjs",default:"./dist/reporter.js"}},files:["dist","!dist/**/*.map","README.md"],publishConfig:{registry:"https://registry.npmjs.org",access:"public"},scripts:{build:"tsup && cd ../frontend && npx vite build --config vite.debugger.config.ts",pack:"pnpm build && pnpm pack",clean:"rm -rf dist",dev:"tsup --watch",test:"playwright test","test:unit":"tsx --test 'src/**/*.test.ts'",typecheck:"tsc --noEmit"},dependencies:{"@ai-sdk/anthropic":"^3.0.1","@ai-sdk/google":"^3.0.1","@ai-sdk/google-vertex":"^4.0.1","@ai-sdk/openai":"^3.0.1","@ai-sdk/provider":"^3.0.1","@anthropic-ai/claude-agent-sdk":"^0.1.72","@babel/parser":"^7.28.5","@babel/plugin-transform-typescript":"^7.27.0","@google/genai":"^1.34.0","google-auth-library":"^10.0.0","@babel/preset-env":"^7.26.9","@babel/preset-typescript":"^7.27.0","@modelcontextprotocol/sdk":"^1.29.0",ai:"^6.0.3",axios:"^1.6.0",chalk:"^4.1.2",commander:"^11.0.0",dotenv:"^16.0.3",express:"^5.2.1","fs-extra":"^11.2.0",glob:"^13.0.0","html-to-text":"^9.0.5",open:"^10.1.0",openai:"^6.25.0",ora:"^5.4.1",otplib:"^13.4.0","p-retry":"^6.2.1",sharp:"^0.34.5",uuid:"^11.1.0",yaml:"^2.8.3",zod:"^3.22.0","zod-to-json-schema":"^3.24.6"},devDependencies:{"@playwright/test":"1.58.2","@types/express":"^4.17.21","@types/node":"^24.0.0","mcp-tools":"workspace:*","sdk-core":"workspace:*","sdk-internal":"workspace:*","shiplight-tools":"workspace:*","shiplight-types":"workspace:*",tsup:"^8.3.5",typescript:"5.5.4"},peerDependencies:{"@playwright/test":"1.58.2"},engines:{node:">=22.0.0"},keywords:["playwright","yaml","testing","automation","ai","shiplight","mcp"],author:"Shiplight",license:"MIT"}});import Ai from"dotenv";Ai.config();function Nr(){console.log(`
|
|
925
925
|
Usage: shiplight <command> [options]
|
|
926
926
|
|
|
927
927
|
Commands:
|
package/dist/index.js
CHANGED
|
@@ -4368,7 +4368,7 @@ ${p.join(`
|
|
|
4368
4368
|
`)}function Jl(e,t){let i=[],n=t?.version||"unknown";i.push(`// @generated by shiplightai v${n}`),i.push(...oo()),i.push(""),t?.use&&Object.keys(t.use).length>0&&(i.push(`test.use(${JSON.stringify(t.use,null,2)});`),i.push(""));let a=new Set,o={imports:a,actionEntityStore:t?.actionEntityStore},r=t?.testName||"Test Suite",s=En(t?.tags);i.push(`test.describe.serial('${s}${ke(r)}', () => {`),e.beforeAll&&e.beforeAll.length>0&&(i.push(...mi("beforeAll",e.beforeAll,o,1)),i.push("")),e.beforeEach&&e.beforeEach.length>0&&(i.push(...mi("beforeEach",e.beforeEach,o,1)),i.push(""));for(let c=0;c<e.tests.length;c++){let d=e.tests[c],u=d.timeout||d.skip!==void 0||d.fail!==void 0||d.only||d.slow?{timeout:d.timeout,skip:d.skip,fail:d.fail,only:d.only,slow:d.slow}:void 0;if(d.parameters&&d.parameters.length>0)for(let p of d.parameters){let g=ao(d.testFlow,p.values);i.push(...fi(g,`${ke(d.name)} [${ke(p.name)}]`,o,1,u)),i.push("")}else i.push(...fi(d.testFlow,ke(d.name),o,1,u)),(c<e.tests.length-1||e.afterEach||e.afterAll)&&i.push("")}return e.afterEach&&e.afterEach.length>0&&(i.push(...mi("afterEach",e.afterEach,o,1)),i.push("")),e.afterAll&&e.afterAll.length>0&&i.push(...mi("afterAll",e.afterAll,o,1)),i.push("});"),ro(i,a),i.join(`
|
|
4369
4369
|
`)}function En(e){return e&&e.length>0?e.map(t=>`@${t}`).join(" ")+" ":""}var ql=["testContext","request"];function gi(e){let t=new Set;function i(n){for(let a of n)switch(a.type){case me.ACTION:{let r=a.action_entity?.action_data?.kwargs;if(r?.args&&Array.isArray(r.args))for(let s of r.args)typeof s=="string"&&ql.includes(s)&&t.add(s);break}case me.STEP:i(a.statements);break;case me.IF_ELSE:{let o=a;i(o.then),o.else&&i(o.else);break}case me.WHILE_LOOP:i(a.body);break}}return i(e),t}function Zl(e){let t=gi(e.statements??[]);if(e.teardown)for(let i of gi(e.teardown))t.add(i);return t}function An(e){return`{ ${["page","agent",...Array.from(e).sort()].join(", ")} }`}function fi(e,t,i,n=0,a){let o=" ".repeat(n),r=[],s=Zl(e),l=An(s),c=a?.only?"test.only":"test";r.push(`${o}${c}('${t}', async (${l}) => {`),a?.skip===!0?r.push(`${o} test.skip();`):typeof a?.skip=="string"&&r.push(`${o} test.skip(true, '${ke(a.skip)}');`),a?.fail===!0?r.push(`${o} test.fail();`):typeof a?.fail=="string"&&r.push(`${o} test.fail(true, '${ke(a.fail)}');`),a?.slow&&r.push(`${o} test.slow();`),a?.timeout&&r.push(`${o} test.setTimeout(${a.timeout});`);let d=e.teardown&&e.teardown.length>0,u=n+1;if(d){if(r.push(`${o} try {`),e.statements&&e.statements.length>0){r.push(`${o} // Test steps`);let g=fe(e.statements,u+1,i);r.push(...g)}r.push(`${o} } finally {`),r.push(`${o} // Teardown`);let p=fe(e.teardown,u+1,i,"teardown");r.push(...p),r.push(`${o} }`)}else if(e.statements&&e.statements.length>0){r.push(`${o} // Test steps`);let p=fe(e.statements,u,i);r.push(...p)}return r.push(`${o}});`),r}function eo(e,t,i){let n=[],a=no(t),o=gi(a),r=An(o);return n.push(`test.${e}(async (${r}) => {`),n.push(...fe(a,1,i,e)),n.push("});"),n}function mi(e,t,i,n){let a=" ".repeat(n),o=[],r=no(t);if(e==="beforeAll"||e==="afterAll"){let l={...i,noAgent:!0};o.push(`${a}test.${e}(async ({ browser }, workerInfo) => {`),o.push(`${a} const page = await browser.newPage({ baseURL: workerInfo.project.use.baseURL });`),o.push(...fe(r,n+1,l,e)),o.push(`${a} await page.close();`),o.push(`${a}});`)}else{let l=gi(r),c=An(l);o.push(`${a}test.${e}(async (${c}) => {`),o.push(...fe(r,n+1,i,e)),o.push(`${a}});`)}return o}function no(e){let i=Dl({goal:"_hook",statements:e});return ge(i).statements??[]}function ao(e,t){let i=vn(e);for(let[n,a]of Object.entries(t))i=i.split(`<<${n}>>`).join(String(a));return ge(i)}function oo(){return["import { test, expect } from 'shiplightai/fixture';"]}function ro(e,t){if(t.size>0){let i=0;for(let a=0;a<e.length;a++)e[a].startsWith("import ")&&(i=a+1);let n=Array.from(t);e.splice(i,0,...n)}}var io=5;function co(e,t){let i={expandingPaths:new Set([lo(t)]),depth:0,referencedPaths:new Set},n={...e};Array.isArray(n.statements)&&(n.statements=Pe(n.statements,t,i)),Array.isArray(n.teardown)&&(n.teardown=Pe(n.teardown,t,i));for(let a of["beforeAll","afterAll","beforeEach","afterEach"])Array.isArray(n[a])&&(n[a]=Pe(n[a],t,i));return{doc:n,referencedTemplatePaths:Array.from(i.referencedPaths)}}function Pe(e,t,i){let n=[];for(let a of e)if(ac(a)){let o=oc(a,t,i);n.push(...o)}else n.push(rc(a,t,i));return n}function ac(e){return typeof e=="object"&&e!==null&&typeof e.template=="string"}function oc(e,t,i){if(i.depth>=io)throw new Error(`Template expansion exceeded maximum depth of ${io}. Check for deeply nested or circular template references.`);let n=lo(ic(t),e.template);if(i.expandingPaths.has(n))throw new Error(`Circular template reference detected: ${n} is already being expanded. Stack: ${Array.from(i.expandingPaths).join(" \u2192 ")} \u2192 ${n}`);i.referencedPaths.add(n);let a;try{a=tc(n,"utf-8")}catch(d){throw new Error(`Failed to read template file: ${n} (referenced from ${t}): ${d.message}`)}let o=to(a);if(!o||typeof o!="object")throw new Error(`Invalid template file: ${n} \u2014 expected a YAML object`);let r=o.params||[],s=e.params||{};for(let d of r)if(!(d in s))throw new Error(`Template ${e.template} requires param "${d}" but it was not provided. Required params: [${r.join(", ")}]`);let l=o.statements;if(!Array.isArray(l))throw new Error(`Template ${e.template} must have a "statements" array`);if(Object.keys(s).length>0){let u=nc(l);for(let[p,g]of Object.entries(s))u=u.split(`<<${p}>>`).join(String(g));l=to(u)}let c={expandingPaths:new Set([...i.expandingPaths,n]),depth:i.depth+1,referencedPaths:i.referencedPaths};return Pe(l,n,c)}function rc(e,t,i){if(typeof e!="object"||e===null)return e;let n={...e};return Array.isArray(n.statements)&&(n.statements=Pe(n.statements,t,i)),Array.isArray(n.THEN)&&(n.THEN=Pe(n.THEN,t,i)),Array.isArray(n.ELSE)&&(n.ELSE=Pe(n.ELSE,t,i)),Array.isArray(n.DO)&&(n.DO=Pe(n.DO,t,i)),n}var Mn=class extends Error{constructor(e){super(e),this.name="YamlValidationError"}};function $n(e,t){let i=ec(e),n=i?.name,a=i?.tags,o=i?.use;if(i&&(i.name!==void 0||i.tags!==void 0||i.use!==void 0)&&(delete i.name,delete i.tags,delete i.use),i?.suite){if(i.goal||i.statements)throw new Mn('YAML file cannot have both "suite" and top-level "goal"/"statements". Use either suite format or single-test format.');return lc(i,n,a,o,t)}return sc(i,n,a,o,t)}function sc(e,t,i,n,a){let o=e?.beforeEach,r=e?.afterEach,s=uo(e?.parameters),l=e?.timeout,c=e?.skip,d=e?.fail,u=e?.only,p=e?.slow;if(e&&(delete e.beforeEach,delete e.afterEach,delete e.parameters,delete e.timeout,delete e.skip,delete e.fail,delete e.only,delete e.slow),e?.url)throw new Mn(`The "url" field is not supported in local YAML tests. Use "base_url: ${e.url}" and add "- URL: /" as the first statement instead.`);e&&!e.goal&&t&&(e.goal=t);let g=[];if(a&&e&&typeof e=="object"){let b=co(e,a);e=b.doc,g=b.referencedTemplatePaths}let f=so(e),v=ge(f);return a&&(Ve(v.statements??[],a,"main"),v.teardown&&Ve(v.teardown,a,"teardown")),{testFlow:v,name:t,tags:i,use:n,beforeEach:o,afterEach:r,parameters:s,timeout:l,skip:c,fail:d,only:u,slow:p,referencedTemplatePaths:g}}function lc(e,t,i,n,a){let o=e.suite;if(!Array.isArray(o.tests)||o.tests.length===0)throw new Error('Suite must have a non-empty "tests" array.');let r=o.beforeAll,s=o.afterAll,l=o.beforeEach,c=o.afterEach,d=[],u=o.tests.map(f=>{if(!f.name)throw new Error('Each test in a suite must have a "name" field.');if(!Array.isArray(f.statements)||f.statements.length===0)throw new Error(`Suite test "${f.name}" must have a non-empty "statements" array.`);let v={goal:f.name,statements:f.statements};f.teardown&&(v.teardown=f.teardown);let b=[],m=v;if(a&&typeof v=="object"){let A=co(v,a);m=A.doc,b=A.referencedTemplatePaths,d.push(...b)}let y=so(m),S=ge(y),T=uo(f.parameters);return{testFlow:S,name:f.name,tags:Array.isArray(f.tags)?f.tags:void 0,parameters:T,timeout:f.timeout,skip:f.skip,fail:f.fail,only:f.only,slow:f.slow}}),p=o.base_url,g=p?{...n,baseURL:p}:n;return{suite:{beforeAll:r,afterAll:s,beforeEach:l,afterEach:c,tests:u},name:t,tags:i,use:g,referencedTemplatePaths:d}}function uo(e){if(!(!Array.isArray(e)||e.length===0))return e.map((t,i)=>{if(!t.name)throw new Error(`Parameter set at index ${i} must have a "name" field.`);if(!t.values||typeof t.values!="object")throw new Error(`Parameter set "${t.name}" must have a "values" object.`);return{name:t.name,values:t.values}})}function Ve(e,t,i){for(let n=0;n<e.length;n++){let a=e[n],o=`${i}.${n}`,r=a.description||"";if(a.uid=cc(t,o,r),a.type===me.STEP)Ve(a.statements,t,o);else if(a.type===me.IF_ELSE){let s=a;Ve(s.then,t,`${o}.then`),s.else&&Ve(s.else,t,`${o}.else`)}else a.type===me.WHILE_LOOP&&Ve(a.body,t,`${o}.body`)}}function cc(e,t,i){let n=Ql("sha256").update(`${e}:${t}:${i}`).digest("hex");return`${n.slice(0,8)}-${n.slice(8,12)}-${n.slice(12,16)}-${n.slice(16,20)}-${n.slice(20,32)}`}function ho(e,t,i){let n=/\btemplate:\s/.test(e),a=/^suite:/m.test(e),o=n||a?null:_n(e);if(o&&!o.valid)return{valid:!1,errors:o.errors,warnings:[],stats:o.stats};let r,s,l=[];try{let c=i?.parsed??$n(e,t);l=c.referencedTemplatePaths;let d={version:i?.version,actionEntityStore:i?.actionEntityStore},u=c.testFlow?.baseURL?{...c.use,baseURL:c.testFlow.baseURL}:c.use;c.suite?r=Jl(c.suite,{...d,testName:c.name,tags:c.tags,use:c.use}):r=Yl(c.testFlow,{...d,testName:c.name,tags:c.tags,use:u,beforeEach:c.beforeEach,afterEach:c.afterEach,parameters:c.parameters,timeout:c.timeout,skip:c.skip,fail:c.fail,only:c.only,slow:c.slow});let p=r.split(`
|
|
4370
4370
|
`).filter(g=>!g.startsWith("import ")).join(`
|
|
4371
|
-
`);new Function(p),s=t.replace(/\.test\.yaml$/,".yaml.spec.ts"),uc(hc(s),{recursive:!0}),dc(s,r)}catch(c){let d=c instanceof Mn?"":c.message.includes("Unexpected token")?" This usually means a YAML escaping issue \u2014 in double-quoted strings, use \\\\/ instead of \\/ for regex patterns, or use single quotes / block scalars.":" This may indicate a transpiler bug \u2014 please report it.";return{valid:!1,errors:[`Transpilation failed: ${c.message}.${d}`],warnings:[],stats:o?.stats??{total:0,action:0,draft:0,coverage:0},referencedTemplatePaths:l}}return{valid:!0,errors:[],warnings:o?.warnings??[],stats:o?.stats??{total:0,action:0,draft:0,coverage:0},specFile:s,referencedTemplatePaths:l}}var In="0.1.
|
|
4371
|
+
`);new Function(p),s=t.replace(/\.test\.yaml$/,".yaml.spec.ts"),uc(hc(s),{recursive:!0}),dc(s,r)}catch(c){let d=c instanceof Mn?"":c.message.includes("Unexpected token")?" This usually means a YAML escaping issue \u2014 in double-quoted strings, use \\\\/ instead of \\/ for regex patterns, or use single quotes / block scalars.":" This may indicate a transpiler bug \u2014 please report it.";return{valid:!1,errors:[`Transpilation failed: ${c.message}.${d}`],warnings:[],stats:o?.stats??{total:0,action:0,draft:0,coverage:0},referencedTemplatePaths:l}}return{valid:!0,errors:[],warnings:o?.warnings??[],stats:o?.stats??{total:0,action:0,draft:0,coverage:0},specFile:s,referencedTemplatePaths:l}}var In="0.1.42";function mo(e){try{return mc(e).mtimeMs}catch{return 0}}var fc=`// @generated by shiplightai v${In}`;function wc(e,t){if(!go(e)||po(e,"utf-8").split(`
|
|
4372
4372
|
`,1)[0]!==fc)return!1;let n=mo(e);for(let a of t)if(mo(a)>n)return!1;return!0}function bc(e){let t=process.argv.slice(2),i=[],n=Cn(e);for(let a of t){if(a.startsWith("-"))continue;let o=a.endsWith(".yaml.spec.ts")?a.replace(/\.yaml\.spec\.ts$/,".test.yaml"):a;if(!o.endsWith(".test.yaml"))continue;let r=Cn(e,o);go(r)&&i.push(r.startsWith(n)?r.slice(n.length+1):o)}return i.length>0?i:null}function fo(e){let t=bc(e.cwd),i=t??gc("**/*.test.yaml",{cwd:e.cwd,ignore:["**/node_modules/**"]}),n=[];for(let a of i){let o=Cn(e.cwd,a),r=o.replace(/\.test\.yaml$/,".yaml.spec.ts"),s=po(o,"utf-8");try{let l=$n(s,o),c=pc(e.cwd,o),d=e.actionEntityStores?.get(c)??e.actionEntityStores?.get("*");if(!(d&&Object.keys(d.entries).length>0)&&wc(r,[o,...l.referencedTemplatePaths]))continue;let p=ho(s,o,{version:In,actionEntityStore:d,parsed:l});if(!p.valid)throw new Error(p.errors.join("; "))}catch(l){console.error(`[shiplight] Failed to transpile ${a}:`,l),n.push({file:a,error:l})}}if(n.length>0){let a=`[shiplight] Transpilation failed for ${n.length} file(s):
|
|
4373
4373
|
`+n.map(o=>` - ${o.file}`).join(`
|
|
4374
4374
|
`);if(t)throw new Error(a);console.warn(a+" (skipped)")}}import*as oe from"fs";import*as ht from"path";import{globSync as vc}from"glob";function yo(e){return process.env.CI&&process.env.SHIPLIGHT_API_TOKEN?new Dn:new Nn(e)}var _c=".shiplight/action-cache";function bo(e){return e.replace(/\//g,"__")+".json"}function kc(e){return e.replace(/\.json$/,"").replace(/__/g,"/")}var Nn=class{constructor(t){this.cwd=t;this.cacheDir=ht.join(t,_c)}isCloud=!1;cacheDir;async lookup(t){let i=new Map;if(t.length===0||!oe.existsSync(this.cacheDir))return i;for(let n of t){let a=ht.join(this.cacheDir,bo(n));try{if(oe.existsSync(a)){let o=oe.readFileSync(a,"utf-8");i.set(n,JSON.parse(o))}}catch{}}return i}async update(t){if(t.size===0)return 0;oe.mkdirSync(this.cacheDir,{recursive:!0});let i=0;for(let[n,a]of t)try{let o=ht.join(this.cacheDir,bo(n)),r=kn();if(oe.existsSync(o))try{r=JSON.parse(oe.readFileSync(o,"utf-8"))}catch{}let s={...r,entries:{...r.entries,...a.entries}};oe.writeFileSync(o,JSON.stringify(s,null,2)),i++}catch{}return i}loadAll(){if(!oe.existsSync(this.cacheDir))return;let t=vc("*.json",{cwd:this.cacheDir});if(t.length===0)return;let i=new Map,n=0;for(let a of t)try{let o=oe.readFileSync(ht.join(this.cacheDir,a),"utf-8"),r=JSON.parse(o),s=kc(a);i.set(s,r),n+=Object.keys(r.entries??{}).length}catch{}if(i.size!==0)return console.log(`[shiplight] Cache: loaded ${n} cached action entit${n===1?"y":"ies"} for ${i.size} test file${i.size!==1?"s":""}`),i}},Dn=class{isCloud=!0;async lookup(t){let{lookupActionStores:i}=await Promise.resolve().then(()=>(On(),Pn));return i(t)}async update(t){let{updateActionStores:i}=await Promise.resolve().then(()=>(On(),Pn));return i(t)}loadAll(){}};function Tc(e={}){e.dotenv!==!1&&Mc(e.scanDir||process.cwd());let t=e.scanDir||process.cwd(),n=yo(t).loadAll();return fo({cwd:t,actionEntityStores:n}),e.apiKey&&(process.env.__SHIPLIGHT_API_KEY=e.apiKey),{reporter:[["list"],["shiplightai/reporter",{outputFolder:"shiplight-report",open:"never",reportToCloud:e.reportToCloud,apiKey:e.apiKey}]]}}function Ac(e,...t){return Ec(e,...t)}function Mc(e){let t=[],i=We.resolve(e),n=We.resolve(process.cwd());for(;;){let a=We.join(i,".env");if(xo.existsSync(a)&&t.push(a),i===n)break;let o=We.dirname(i);if(o===i)break;i=o}for(let a of t)Sc.config({path:a})}R();R();Mt();qe();import{z as Ps}from"zod";var Uu=Ps.object({instruction:Ps.string().describe('The instruction of the operation to perform. Can only include one operation. Do not inlcude element indexes just describe the element, e.g. "select the text "Hello, world!" in "Hello, world!""')});function Os(e){e.register({name:"perform_accurate_operation",description:"Perform an operation that requires accurate interaction like dragging or interacting with a specific area of an element. Only use this action when neccecary.",schema:Uu,usesElementIndex:!1,async execute(t,i){let{instruction:n}=t,a={page:i.page,agentServices:i.agentServices,domService:i.domService},o=await Je(n,a,{});if(o.status==="error"||!o.actionEntity)return{success:!1,actionEntity:{action_description:n,action_data:{action_name:"perform_accurate_operation",kwargs:{instruction:n}}},error:o.error||"Failed to generate action"};let{actionEntity:r}=o,s=await Tt(r,a);return{success:s.success,actionEntity:r,message:s.success?`Successfully executed action: ${r.action_data?.action_name}`:void 0,error:s.error}}})}Te();R();import{generateText as Gu}from"ai";import{convert as ju}from"html-to-text";async function Ku(e,t,i){let{apiKey:n,domain:a}=e;if(!n||!a)throw new Error("Mailgun configuration missing. Please provide apiKey and domain");let o=[];try{let r=`https://api.mailgun.net/v3/${a}/events`,s={event:"accepted",limit:"10",ascending:"yes",recipient:t};if(i.from_email&&(s.from=i.from_email),i.since)s.begin=Math.floor(i.since/1e3).toString();else{let d=new Date(Date.now()-6e5);s.begin=Math.floor(d.getTime()/1e3).toString()}h.info(`Mailgun params: ${JSON.stringify(s)}`);let l=await fetch(r+"?"+new URLSearchParams(s),{method:"GET",headers:{Authorization:`Basic ${Buffer.from(`api:${n}`).toString("base64")}`}});if(!l.ok){let d=await l.text();throw new Error(`Mailgun events API error: ${d}`)}let c=(await l.json()).items||[];for(let d of c.slice(0,10)){if(d.event!=="accepted")continue;let u=(d.storage||{}).url;if(h.info(`message_url: ${u}`),!u){let f=(d.message||{}).headers||{},v=f.subject||"",b=f.from||"",m=f.to||"";if(i.from_email&&!b.toLowerCase().includes(i.from_email.toLowerCase())||i.to_email&&!m.toLowerCase().includes(i.to_email.toLowerCase())||i.subject&&!v.toLowerCase().includes(i.subject.toLowerCase()))continue;o.push({subject:v,from:b,to:m,date:new Date(d.timestamp*1e3).toUTCString(),body:"Message body not available (Mailgun storage disabled)",message_id:f["message-id"]||""});continue}let p=u.split("/"),g=p[p.length-1];if(h.info(`Storage key: ${g}`),g){let f=`https://api.mailgun.net/v3/domains/${a}/messages/${g}`;try{let v=await fetch(f,{method:"GET",headers:{Authorization:`Basic ${Buffer.from(`api:${n}`).toString("base64")}`,Accept:"application/json"}});if(v.ok){let b=await v.json(),m=b.Subject||"",y=b.From||"",S=b.To||"",T=b.Date||"",A=b["Message-Id"]||"";h.info(`subject: ${m}`),h.info(`from_addr: ${y}`),h.info(`to_addr: ${S}`),h.info(`date: ${T}`),h.info(`message_id: ${A}`);let $=b["body-html"]||b["body-plain"]||"";if($&&$.includes("<")&&($=ju($)),h.info(`Body: ${$.substring(0,200)}...`),i.subject&&!m.toLowerCase().includes(i.subject.toLowerCase())||i.body_contains&&!$.toLowerCase().includes(i.body_contains.toLowerCase()))continue;o.push({subject:m,from:y,to:S,date:T,body:$,message_id:A});continue}else h.warn(`Messages API returned ${v.status}`)}catch(v){h.warn(`Failed to parse JSON response: ${v}`)}}try{let f=await fetch(u,{method:"GET",headers:{Authorization:`Basic ${Buffer.from(`api:${n}`).toString("base64")}`}});if(!f.ok){h.warn(`Could not fetch stored message: ${f.status}`);continue}let v=await f.text();h.info(`Fallback: Raw email length: ${v.length}`);let b=v.split(`
|