shiplightai 0.1.14 → 0.1.15

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.
@@ -4707,17 +4707,17 @@ Additional instructions: ${e.additional_prompt}
4707
4707
  `);try{ie.log("Level 3: Attempting agent-based login"),ie.log(`Login prompt:
4708
4708
  ${i}`);let s=this.agentServices.knowledgeRetriever,a=!1;this.agentServices.hasKnowledgeRetriever()&&s&&(ie.log("Setting up login knowledge retriever..."),this.agentServices.setKnowledgeRetriever(async(m,f,y,g)=>await s(m,f,y,"login")),a=!0,ie.log("Login knowledge retriever configured"));let o;try{if(o=await this.run(r,i,"login"),!o.success)return ie.log("Level 3 FAILED: Agent login failed"),N.info("Login: Failed"),{success:!1,page:r}}finally{a&&s&&(this.agentServices.setKnowledgeRetriever(s),ie.log("Restored original knowledge retriever"))}let l=await r.context().storageState(),c;if(e.num_verification_exprs!==0)try{ie.log("Generating validation locators for future login verification...");let m=await Yb(r,e.site_url,{verification_hint:e.verification_hint,num_verification_exprs:e.num_verification_exprs},async(f,y)=>this.run(f,y),async f=>this.getDOMText(f));m?(c=m,ie.log(`Generated ${c.length} validation locator(s): ${JSON.stringify(c)}`)):ie.log("Failed to generate validation locators, login will still succeed")}catch(m){ie.log(`Error generating validation locators: ${m.message}`)}else ie.log("Skipping validation locator generation (num_verification_exprs=0)");ie.log("Level 3 SUCCESS: Agent login succeeded"),N.info("Login: Agent login succeeded");let d=o.actions||[],p=d.length>0?d:t?.cached_actions;return{success:!0,page:r,storage_state:l,cached_actions:p,validation_exprs:c}}catch(s){return ie.error(`Agent login failed: ${s.message}`),N.info("Login: Failed"),{success:!1,page:r}}}async executeCachedLogin(r,e,t){let n=(await Promise.resolve().then(()=>(Fu(),$u))).default,i=new n;for(let s=0;s<e.length;s++){let a=e[s];ie.log(`Executing cached action ${s+1}/${e.length}: ${a.action_description||a.action_data?.action_name}`);try{if(!a.action_data){ie.log(`Action ${s+1} missing action_data, skipping`);continue}await i.execute(r,a,this.agentServices),await this.waitUntilStable(r,5e3)}catch(o){return ie.error(`Cached action ${s+1} failed: ${o.message}`),{success:!1}}}return t&&t.length>0&&!await Sf(r,t)?{success:!1}:{success:!0}}getCompletedExecutionHistory(){if(!this.context.executionHistory||this.context.executionHistory.length===0)return[];let r=this.context.executionHistory[this.context.executionHistory.length-1];return!r[1]||r[1].trim()===""?this.context.executionHistory.slice(0,-1):this.context.executionHistory}addToExecutionHistory(r,e){this.context.executionHistory||(this.context.executionHistory=[]),this.context.executionHistory.push([r,e])}async createStepResult(r,e,t){if(!this.context.stepTracking||this.context.stepTracking.results[e])return;this.context.stepTracking.currentStepId=e,this.context.stepTracking.onStepChange&&this.context.stepTracking.onStepChange(e),r=await this.agentServices.validatePage(r),await this.waitUntilStable(r);let n={description:t,startTime:Date.now(),artifacts:[]};if(this.context.stepTracking.artifactsDir){let i=zr.join(this.context.stepTracking.artifactsDir,e.replace(/\./g,"-"));Sr.mkdirSync(i,{recursive:!0});let s=zr.join(i,"screenshot.png");await r.screenshot({type:"png",path:s}),n.screenshot=s}this.context.stepTracking.results[e]=n}saveDebugInfoToFiles(r,e,t){let n={};if(!this.context.stepTracking?.artifactsDir)return N.debug("[saveDebugInfoToFiles] No artifacts directory configured, skipping debug info save"),n;let i=zr.join(this.context.stepTracking.artifactsDir,r.replace(/\./g,"-"));try{if(Sr.mkdirSync(i,{recursive:!0}),e.systemPrompt){let s=zr.join(i,"system_prompt.txt");Sr.writeFileSync(s,e.systemPrompt),n.system_prompt_path=s,N.debug(`[saveDebugInfoToFiles] Saved system prompt to: ${s}`)}if(e.userPrompt)if(typeof e.userPrompt=="string"){let s=zr.join(i,"user_prompt.txt");Sr.writeFileSync(s,e.userPrompt),n.user_prompt_path=s,N.debug(`[saveDebugInfoToFiles] Saved user prompt to: ${s}`)}else{let s=e.userPrompt.map(l=>Array.isArray(l.content)?{...l,content:l.content.map(c=>c.type==="image"&&c.file?.startsWith("data:")?{...c,file:"[base64 image data stripped]"}:c)}:l),a=zr.join(i,"messages.json"),o={system:e.systemPrompt,messages:s};Sr.writeFileSync(a,JSON.stringify(o,null,2)),n.messages_path=a,N.debug(`[saveDebugInfoToFiles] Saved messages to: ${a}`)}if(e.rawLlmResponse){let s=t?t.replace(/[\/\\:]/g,"-"):"llm",a=zr.join(i,`${s}_response.txt`);Sr.writeFileSync(a,e.rawLlmResponse),n.response_path=a,N.debug(`[saveDebugInfoToFiles] Saved LLM response to: ${a}`)}if(e.screenshotWithSom){let s=zr.join(i,"screenshot.png");Sr.writeFileSync(s,Buffer.from(e.screenshotWithSom,"base64")),n.screenshot_path=s,N.debug(`[saveDebugInfoToFiles] Saved SOM screenshot to: ${s}`)}if(e.reasoningContent){let s=zr.join(i,"reasoning.txt");Sr.writeFileSync(s,e.reasoningContent),n.reasoning_path=s,N.debug(`[saveDebugInfoToFiles] Saved reasoning to: ${s}`)}N.debug(`[saveDebugInfoToFiles] Saved ${Object.keys(n).length} artifacts for step ${r}`)}catch(s){N.error(`[saveDebugInfoToFiles] Failed to save debug info for step ${r}:`,s)}return n}async updateStepResult(r,e,t,n,i){if(!this.context.stepTracking)return;let s=this.context.stepTracking.results[r];if(s){if(e&&(s.status=e,this.context.stepTracking.currentStepId=void 0,this.context.stepTracking.onStepChange&&this.context.stepTracking.onStepChange(void 0)),t!==void 0&&(s.message=t),n&&s.artifacts.push(n),i){let a=i.tokenUsages?.[0]?.model,o=this.saveDebugInfoToFiles(r,i,a);Object.keys(o).length>0&&s.artifacts.push(o)}s.duration=Date.now()-s.startTime,this.context.stepTracking.onStepComplete&&this.context.stepTracking.onStepComplete(r,s)}}async writeExecutionResults(r,e){try{if(await Sr.promises.mkdir(r,{recursive:!0}),this.context.stepTracking?.results&&Object.keys(this.context.stepTracking.results).length>0){let t=zr.join(r,"test-results.json");await Sr.promises.writeFile(t,JSON.stringify(this.context.stepTracking.results,null,2)),N.debug(`Test results written to: ${t}`)}if(e?.tokenUsages&&this.context.tokenUsages&&this.context.tokenUsages.length>0){let t=zr.join(r,"token-usages.json");await Sr.promises.writeFile(t,JSON.stringify(this.context.tokenUsages,null,2)),N.debug(`Token usages written to: ${t}`)}if(this.context.aiActionDetails&&this.context.aiActionDetails.length>0){let t=zr.join(r,"ai-actions.json");await Sr.promises.writeFile(t,JSON.stringify(this.context.aiActionDetails,null,2)),N.debug(`AI action details written to: ${t}`)}}catch(t){throw N.error("Failed to write execution results:",t),t}}}});function qle(){let r=new Date,e=new Intl.DateTimeFormat("en-US",{timeZone:"America/Los_Angeles",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}).formatToParts(r),t=e.find(v=>v.type==="year").value,n=e.find(v=>v.type==="month").value,i=e.find(v=>v.type==="day").value,s=e.find(v=>v.type==="hour").value,a=e.find(v=>v.type==="minute").value,o=e.find(v=>v.type==="second").value,l=String(r.getMilliseconds()).padStart(3,"0"),c=`${t}-${n}-${i}T${s}:${a}:${o}.${l}`,d=r.toISOString().slice(0,-1),p=Date.parse(c+"Z"),m=Date.parse(d+"Z"),f=Math.round((m-p)/(1e3*60)),y=String(Math.floor(Math.abs(f)/60)).padStart(2,"0"),g=String(Math.abs(f)%60).padStart(2,"0"),_=f<=0?"+":"-";return`${t}-${n}-${i}T${s}:${a}:${o}.${l}${_}${y}:${g}`}function Cf(r){let e=r.variableStore;return e.has("currentTime")||e.set("currentTime",qle()),{model:r.model,variableStore:e,organizationId:r.organizationId,organizationSettings:r.organizationSettings,executionHistory:r.executionHistory||[],testDataDir:r.testDataDir,downloadDir:r.downloadDir,useNativeGenerator:r.useNativeGenerator,autoDisableModal:r.autoDisableModal,tokenUsages:[],aiActionDetails:[]}}var t9=T(()=>{"use strict"});var r9={};vs(r9,{ActionHandler:()=>nb,ActionHelper:()=>Yh,Agent:()=>kf,AgentServices:()=>hw,AgentStepEventTypes:()=>Gk,AgentTaskFailedError:()=>fw,BrowserManager:()=>sB,DEFAULT_EVENT_LISTENER_LIMIT:()=>xy,DomService:()=>bi,EVENT_LISTENER_CANDIDATE_SELECTORS:()=>vy,HistoryTreeProcessor:()=>n8,INIT_SCRIPT:()=>Bu,INTERACTION_EVENT_TYPES:()=>Eu,INTERACTIVE_ROLES:()=>nh,LogLevel:()=>gE,LoginType:()=>wf,MCPToolProvider:()=>zj,OpenAIToolProvider:()=>km,SDK_VERSION:()=>Gle,ToolRegistry:()=>Mc,TwoFactorAuthType:()=>xk,VariableStore:()=>vf,WebAgent:()=>kf,configureSdk:()=>Sm,createAgent:()=>Wle,createAgentContext:()=>Cf,createToolRegistry:()=>qj,createToolRegistryWithCapabilities:()=>Wj,ensureToolsRegistered:()=>Uj,evaluateStatement:()=>hl,executeStep:()=>pl,exportMCPTools:()=>Kj,filterInteractionListeners:()=>q5,generateActionStep:()=>Pu,getActionEntityLocatorInfo:()=>Mt,getBrowserCdpUrl:()=>lb,getCapabilitySummary:()=>Gj,getFramePath:()=>TT,getModel:()=>es,getPageInfo:()=>J$,getPageWsUrl:()=>K$,getPlatformFromDeviceName:()=>oB,getProviderOptions:()=>ts,getSdkConfig:()=>$r,getToolRegistry:()=>Hj,injectUserFunction:()=>Av,isInteractionEventType:()=>H5,isInteractiveRole:()=>U5,loadKnowledgeMappings:()=>NP,loadKnowledges:()=>PP,loadUserFunctions:()=>CP,logger:()=>N,newBrowserContext:()=>z$,parseSSEStream:()=>RP,pickBestLocator:()=>kd,pickBestLocatorForElement:()=>Mm,pickBestLocators:()=>HP,replaceVariables:()=>Kb,runTask:()=>fl,setWindowBounds:()=>cb,toolRegistry:()=>Vt});function Wle(r){let e=new vf,t=new Set(r.sensitiveKeys||[]);if(r.variables)for(let[i,s]of Object.entries(r.variables))e.set(i,s,t.has(i));let n=Cf({model:r.model,variableStore:e,testDataDir:r.testDataDir,downloadDir:r.downloadDir});return new kf(n)}var Gle,zk=T(()=>{"use strict";IP();OP();MP();Vj();Jj();Xj();vk();CA();wk();bk();aB();lB();cB();e9();ch();wy();by();Cm();Pm();Rc();ep();tp();Ds();Td();Ed();Oy();dl();rh();ih();Au();sh();ah();Zb();Zn();Wk();Ek();id();Qb();Qs();Uu();Qa();op();jp();Vk();EA();Sy();Ty();Ey();Ay();ky();Cy();Iy();Py();Ry();My();uh();dh();hh();fh();mh();gh();yh();bh();wh();xh();Sh();Th();Eh();Ah();kh();Ih();Ph();Nh();Oh();Rh();Mh();Dh();Lh();zh();Kh();Jh();Xh();Zy();ph();vr();So();sr();Cn();ku();rb();qt();t9();Ai();Gle="1.0.0"});var Kle={};vs(Kle,{VariableStore:()=>vf,WebAgent:()=>kf,authSetup:()=>l9,configureSdk:()=>Sm,createAgentContext:()=>Cf,resolveLoginConfig:()=>_m,shiplightConfig:()=>p9});module.exports=z7(Kle);var sa=ot(require("fs"),1),hs=ot(require("path"),1),u9=ot(require("dotenv"),1),d9=require("glob");var _s=require("fs"),TP=require("path"),EP=require("glob");var xd=require("yaml");bd();var lP=require("fs"),vd=require("path"),wd=require("yaml"),oP=5;function wv(r,e){let t={expandingPaths:new Set([(0,vd.resolve)(e)]),depth:0,referencedPaths:new Set},n={...r};Array.isArray(n.statements)&&(n.statements=va(n.statements,e,t)),Array.isArray(n.teardown)&&(n.teardown=va(n.teardown,e,t));for(let i of["beforeAll","afterAll","beforeEach","afterEach"])Array.isArray(n[i])&&(n[i]=va(n[i],e,t));return{doc:n,referencedTemplatePaths:Array.from(t.referencedPaths)}}function va(r,e,t){let n=[];for(let i of r)if(dU(i)){let s=pU(i,e,t);n.push(...s)}else n.push(hU(i,e,t));return n}function dU(r){return typeof r=="object"&&r!==null&&typeof r.template=="string"}function pU(r,e,t){if(t.depth>=oP)throw new Error(`Template expansion exceeded maximum depth of ${oP}. Check for deeply nested or circular template references.`);let n=(0,vd.resolve)((0,vd.dirname)(e),r.template);if(t.expandingPaths.has(n))throw new Error(`Circular template reference detected: ${n} is already being expanded. Stack: ${Array.from(t.expandingPaths).join(" \u2192 ")} \u2192 ${n}`);t.referencedPaths.add(n);let i;try{i=(0,lP.readFileSync)(n,"utf-8")}catch(d){throw new Error(`Failed to read template file: ${n} (referenced from ${e}): ${d.message}`)}let s=(0,wd.parse)(i);if(!s||typeof s!="object")throw new Error(`Invalid template file: ${n} \u2014 expected a YAML object`);let a=s.params||[],o=r.params||{};for(let d of a)if(!(d in o))throw new Error(`Template ${r.template} requires param "${d}" but it was not provided. Required params: [${a.join(", ")}]`);let l=s.statements;if(!Array.isArray(l))throw new Error(`Template ${r.template} must have a "statements" array`);if(Object.keys(o).length>0){let p=(0,wd.stringify)(l);for(let[m,f]of Object.entries(o))p=p.replaceAll(`<<${m}>>`,String(f));l=(0,wd.parse)(p)}let c={expandingPaths:new Set([...t.expandingPaths,n]),depth:t.depth+1,referencedPaths:t.referencedPaths};return va(l,n,c)}function hU(r,e,t){if(typeof r!="object"||r===null)return r;let n={...r};return Array.isArray(n.statements)&&(n.statements=va(n.statements,e,t)),Array.isArray(n.THEN)&&(n.THEN=va(n.THEN,e,t)),Array.isArray(n.ELSE)&&(n.ELSE=va(n.ELSE,e,t)),Array.isArray(n.DO)&&(n.DO=va(n.DO,e,t)),n}function cP(r,e){let t=(0,xd.parse)(r),n=t?.name,i=t?.tags,s=t?.use;if(t&&(t.name!==void 0||t.tags!==void 0||t.use!==void 0)&&(delete t.name,delete t.tags,delete t.use),t?.suite){if(t.goal||t.statements)throw new Error('YAML file cannot have both "suite" and top-level "goal"/"statements". Use either suite format or single-test format.');return mU(t,n,i,s,e)}return fU(t,n,i,s,e)}function fU(r,e,t,n,i){let s=r?.beforeEach,a=r?.afterEach,o=uP(r?.parameters),l=r?.timeout,c=r?.skip,d=r?.fail,p=r?.only,m=r?.slow;r&&(delete r.beforeEach,delete r.afterEach,delete r.parameters,delete r.timeout,delete r.skip,delete r.fail,delete r.only,delete r.slow),r&&!r.goal&&e&&(r.goal=e);let f=[];if(i&&r&&typeof r=="object"){let _=wv(r,i);r=_.doc,f=_.referencedTemplatePaths}let y=(0,xd.stringify)(r);return{testFlow:nn(y),name:e,tags:t,use:n,beforeEach:s,afterEach:a,parameters:o,timeout:l,skip:c,fail:d,only:p,slow:m,referencedTemplatePaths:f}}function mU(r,e,t,n,i){let s=r.suite;if(!Array.isArray(s.tests)||s.tests.length===0)throw new Error('Suite must have a non-empty "tests" array.');let a=s.serial,o=s.beforeAll,l=s.afterAll,c=s.beforeEach,d=s.afterEach,p=[],m=s.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 y={goal:f.name,statements:f.statements};f.teardown&&(y.teardown=f.teardown);let g=[],_=y;if(i&&typeof y=="object"){let M=wv(y,i);_=M.doc,g=M.referencedTemplatePaths,p.push(...g)}let v=(0,xd.stringify)(_),S=nn(v),L=uP(f.parameters);return{testFlow:S,name:f.name,parameters:L,timeout:f.timeout,skip:f.skip,fail:f.fail,only:f.only,slow:f.slow}});return{suite:{serial:a,beforeAll:o,afterAll:l,beforeEach:c,afterEach:d,tests:m},name:e,tags:t,use:n,referencedTemplatePaths:p}}function uP(r){if(!(!Array.isArray(r)||r.length===0))return r.map((e,t)=>{if(!e.name)throw new Error(`Parameter set at index ${t} must have a "name" field.`);if(!e.values||typeof e.values!="object")throw new Error(`Parameter set "${e.name}" must have a "values" object.`);return{name:e.name,values:e.values}})}bd();var Sv=require("yaml");bd();function Yn(r){return r.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function ir(r){return r.replace(/\r\n/g," ").replace(/\n/g," ").replace(/\r/g," ").trim()}function gU(r){let e=r.frame_path;return!e||e.length===0?"page":`page.frameLocator('${e[0]}')`}function yU(r){let e=r.xpath;return typeof e=="string"&&e.trim()?!e.startsWith("xpath=")&&!e.startsWith("/")&&!e.startsWith("//")?`xpath=//${e}`:e.startsWith("xpath=")?e:`xpath=${e}`:null}function vv(r){let e=gU(r),t=r.locator;if(typeof t=="string"&&t.trim())return t=t.trim(),t.endsWith("first()")?`${e}.${t}`:`${e}.${t}.first()`;let n=yU(r);if(n){let i=JSON.stringify(n);return`${e}.locator(${i}).first()`}return null}var bU=["ai_action","ai_step","ai_assert","ai_extract","ai_wait_until","verify","assert"],wU=["js_code","function","wait","wait_for_download_complete","wait_for_page_ready","extract_email_content","extract_activation_code"];function xv(r){let e=r.action_data?.action_name;return!e||(e==="verify"||e==="ai_assert"||e==="assert")&&r.action_data?.kwargs?.code?!1:bU.includes(e)}function dP(r){let e=r.action_data?.action_name;return!e||(e==="verify"||e==="ai_assert"||e==="assert")&&r.action_data?.kwargs?.code?!1:!wU.includes(e)}var Lr=new Map;function nt(r,e){Lr.set(r,e)}function fP(r){return Lr.get(r)}function xo(r,e,t=[]){let n=[...t];return e.locator?n.push(`locator: ${JSON.stringify(e.locator)}`):e.xpath&&n.push(`xpath: ${JSON.stringify(e.xpath)}`),e.frame_path&&e.frame_path.length>0&&n.push(`frame_path: ${JSON.stringify(e.frame_path)}`),n.length===0?[`await agent.execAction("${r}", page, {});`]:[`await agent.execAction("${r}", page, {`,...n.map(i=>` ${i},`),"});"]}nt("click",r=>{let e=vv(r);return e?[`await ${e}.click({ timeout: ${5e3} });`]:['await agent.execAction("click", page, {});']});nt("click_element",Lr.get("click"));nt("click_element_by_index",Lr.get("click"));nt("double_click",r=>xo("double_click",r));nt("double_click_on_element",Lr.get("double_click"));nt("right_click",r=>xo("right_click",r));nt("right_click_on_element",Lr.get("right_click"));nt("hover",r=>xo("hover",r));nt("hover_element_by_index",Lr.get("hover"));nt("input_text",r=>{let e=r.action_data?.kwargs?.text??r.action_data?.kwargs?.value??"";return xo("input_text",r,[`action_data: { kwargs: { text: ${JSON.stringify(e)} } }`])});nt("fill",Lr.get("input_text"));nt("clear_input",r=>xo("clear_input",r));nt("press",r=>{let e=r.action_data?.kwargs?.keys;return[`await page.keyboard.press(${JSON.stringify(e)});`]});nt("send_keys",Lr.get("press"));nt("send_keys_on_element",r=>{let e=vv(r),t=r.action_data?.kwargs?.keys||"";return e?[`await ${e}.press(${JSON.stringify(t)}, { timeout: ${5e3} });`]:['await agent.execAction("send_keys_on_element", page, {',` action_data: { kwargs: { keys: ${JSON.stringify(t)} } },`,"});"]});nt("select_dropdown_option",r=>{let e=r.action_data?.kwargs?.text||r.action_data?.kwargs?.option||"";return xo("select_dropdown_option",r,[`action_data: { kwargs: { text: ${JSON.stringify(e)} } }`])});nt("scroll",r=>{let e=r.action_data?.kwargs?.down??!0;return[`await page.evaluate('window.scrollBy(0, window.innerHeight * ${(r.action_data?.kwargs?.num_pages??1)*(e?1:-1)})');`]});nt("scroll_down",Lr.get("scroll"));nt("scroll_up",Lr.get("scroll"));nt("scroll_element",Lr.get("scroll"));nt("scroll_to_text",r=>{let e=r.action_data?.kwargs?.text||"";return[`await page.getByText(${JSON.stringify(e)}, { exact: false }).first().scrollIntoViewIfNeeded();`]});nt("scroll_on_element",r=>xo("scroll_on_element",r,[`action_data: { kwargs: ${JSON.stringify(r.action_data?.kwargs||{})} }`]));nt("go_to_url",r=>{let e=r.action_data?.kwargs?.url||"";return r.action_data?.kwargs?.new_tab===!0?['await agent.execAction("go_to_url", page, {',` action_data: { kwargs: { url: ${JSON.stringify(e)}, new_tab: true } },`,"});"]:['await agent.execAction("go_to_url", page, {',` action_data: { kwargs: { url: ${JSON.stringify(e)} } },`,"});"]});nt("open_tab",Lr.get("go_to_url"));nt("go_back",()=>['await agent.execAction("go_back", page, {});']);nt("reload_page",()=>['await agent.execAction("reload_page", page, {});']);nt("wait",r=>[`await page.waitForTimeout(${(r.action_data?.kwargs?.seconds||1)*1e3});`]);nt("wait_for_page_ready",()=>["await page.waitForLoadState('domcontentloaded');"]);nt("verify",(r,e)=>{let t=r.action_data?.kwargs;if(t?.code)return t.code.split(`
4709
4709
  `);let n=t?.statement||r.action_description;return n?[`await agent.assert(page, ${JSON.stringify(n)}, '${e||""}');`]:["// Skipping verify: missing statement or code"]});nt("ai_assert",Lr.get("verify"));nt("assert",Lr.get("verify"));nt("ai_action",(r,e)=>{let t=r.action_data?.kwargs?.statement;if(!t)return["// Skipping ai_action: missing statement"];let n=JSON.stringify(t),i=r.action_data?.kwargs?.use_pure_vision;return[`await agent.execute(page, ${n}, '${e||""}', ${i});`]});nt("ai_step",(r,e)=>{let t=r.action_data?.kwargs?.statement;return t?[`await agent.run(page, ${JSON.stringify(t)}, '${e||""}');`]:["// Skipping ai_step: missing statement"]});nt("ai_extract",(r,e)=>{let t=r.action_data?.kwargs?.element_description,n=r.action_data?.kwargs?.variable_name;if(!t||!n)return["// Skipping ai_extract: missing element_description or variable_name"];let i=JSON.stringify(t),s=JSON.stringify(n);return[`await agent.extract(page, ${i}, ${s}, '${e||""}');`]});nt("ai_wait_until",(r,e)=>{let t=r.action_data?.kwargs?.condition,n=r.action_data?.kwargs?.timeout_seconds||60;return t?[`await agent.waitUntilCondition(page, ${JSON.stringify(t)}, ${n}, '${e||""}');`]:["// Skipping ai_wait_until: missing condition"]});nt("save_variable",r=>{let e=r.action_data?.kwargs?.name||"",t=r.action_data?.kwargs?.value;return['await agent.execAction("save_variable", page, {',` action_data: { kwargs: { name: ${JSON.stringify(e)}, value: ${JSON.stringify(t)} } },`,"});"]});nt("js_code",r=>{let e=r.action_data?.kwargs?.code;if(!e)return["// Skipping js_code: missing code"];let t=["{"],n=e.split(`
4710
- `);for(let i of n)t.push(` ${i}`);return t.push("}"),t});nt("function",(r,e,t)=>{let n=r.action_data?.kwargs||{},i=n.functionName;if(i&&i.includes("#")){let[a,o]=i.split("#");if(a&&o){let l=a.replace(/\.(ts|js|mjs)$/,""),c=`import { ${o} } from '${l}';`;t?.imports?.add(c);let d={...n,functionName:o},p=pP(d);return p?[p.endsWith(";")?p:`${p};`]:["// Skipping function: invalid export pattern"]}}let s=pP(n);return s?[s.endsWith(";")?s:`${s};`]:["// Skipping function: missing functionName"]});nt("generate_2fa_code",r=>{let e=r.action_data?.kwargs?.otp_secret_key||"";return['await agent.execAction("generate_2fa_code", page, {',` action_data: { kwargs: { otp_secret_key: ${JSON.stringify(e)} } },`,"});"]});nt("upload_file",r=>{let e=r.action_data?.kwargs||{},t=[],n={};return e.paths?n.paths=e.paths:e.path&&(n.path=e.path),e.use_file_input&&(n.use_file_input=!0),t.push(`action_data: { kwargs: ${JSON.stringify(n)} }`),r.locator?t.push(`locator: ${JSON.stringify(r.locator)}`):r.xpath&&t.push(`xpath: ${JSON.stringify(r.xpath)}`),r.frame_path&&r.frame_path.length>0&&t.push(`frame_path: ${JSON.stringify(r.frame_path)}`),['await agent.execAction("upload_file", page, {',...t.map(i=>` ${i},`),"});"]});nt("wait_for_download_complete",r=>['await agent.execAction("wait_for_download_complete", page, {',` action_data: { kwargs: { timeout_seconds: ${r.action_data?.kwargs?.timeout_seconds||10} } },`,"});"]);nt("switch_tab",r=>['await agent.execAction("switch_tab", page, {',` action_data: { kwargs: { page_id: ${r.action_data?.kwargs?.page_id??0} } },`,"});"]);nt("close_tab",r=>{let e=r.action_data?.kwargs?.page_id;return e=e??r.action_data?.kwargs?.index,['await agent.execAction("close_tab", page, {',` action_data: { kwargs: { page_id: ${e} } },`,"});"]});nt("set_date_for_native_date_picker",r=>{let e=r.action_data?.kwargs?.date??"",t=[];return t.push(`action_data: { kwargs: { date: ${JSON.stringify(e)} } }`),r.locator?t.push(`locator: ${JSON.stringify(r.locator)}`):r.xpath&&t.push(`xpath: ${JSON.stringify(r.xpath)}`),r.frame_path&&r.frame_path.length>0&&t.push(`frame_path: ${JSON.stringify(r.frame_path)}`),['await agent.execAction("set_date_for_native_date_picker", page, {',...t.map(n=>` ${n},`),"});"]});nt("done",()=>["// Done - no action needed"]);function pP(r){let e=r.functionName;if(!e)return null;let t={},n=r.parameterNames||[],i=r.parameterValues||r.args||[];if(n.forEach((l,c)=>{c<i.length&&(t[l]=i[c])}),Object.keys(t).length===0)return`await ${e}()`;let s=["page","testContext","request","agentServices"],a=["undefined","null","true","false"],o=Object.entries(t).map(([l,c])=>{let d=String(c);return c==null?"undefined":s.includes(l)&&s.includes(d)||a.includes(d)||/^-?\d+(\.\d+)?$/.test(d)?d:d.startsWith("$")?`agent.agentServices.readVariable('${d.substring(1)}')`:`"${d}"`});return`await ${e}(${o.join(", ")})`}function kn(r,e,t,n="main"){let i=[];for(let s=0;s<r.length;s++){let a=r[s],o=`${n}.${s}`,l=vU(a,e,o,t);l.length>0&&(i.push(...l),s<r.length-1&&i.push(""))}return i}function vU(r,e,t,n){let i=" ".repeat(e);switch(r.type){case"DRAFT":return xU(r,e,t,n);case"ACTION":return _U(r,e,t,n);case"STEP":return SU(r,e,t,n);case"IF_ELSE":return TU(r,e,t,n);case"WHILE_LOOP":return EU(r,e,t,n);default:return[`${i}// Unknown statement type: ${r.type}`]}}function xU(r,e,t,n){let i=" ".repeat(e),s=r.description?.trim()||"";if(!s)return[`${i}// ${t}: Skipping - no description`];if(n.noAgent)return[`${i}// ${t}: ${ir(s)}`,`${i}// DRAFT: ${ir(s)} (requires agent - skipped in hook)`];let a=JSON.stringify(s);return[`${i}// ${t}: ${ir(s)}`,`${i}// \u26A0 DRAFT: AI-resolved at runtime (~5-10s). Add a locator to make this <1s.`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.run(page, ${a}, '${t}');`]}function _U(r,e,t,n){let i=" ".repeat(e),s=r.description,a=r.uid,l=n.actionEntityStore?.entries[r.uid]?.action_entity??r.action_entity;if(!l){if(!s)return[`${i}// ${t}: Skipping - no description`];if(n.noAgent)return[`${i}// ${t}: ${ir(s)}`,`${i}// DRAFT: ${ir(s)} (requires agent - skipped in hook)`];let L=JSON.stringify(s),M=!!r.use_pure_vision;return[`${i}// ${t}: ${ir(s)}`,`${i}// \u26A0 DRAFT: AI-resolved at runtime (~5-10s). Add a locator to make this <1s.`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.execute(page, ${L}, '${t}', ${M});`]}let c=r.locator?{...l,locator:r.locator}:l;s&&s!==c.action_description&&(c={...c,action_description:s});let d=c.action_data?.action_name||"",p=c.action_description||"",m=fP(d);if(!m)return[`${i}// ${t}: Unknown action: ${d}`];let f={imports:n.imports},y=m(c,t,f);if(n.noAgent){if(xv(c))return[`${i}// ${t}: ${ir(p)}`,`${i}// AI action: ${ir(p)} (requires agent - skipped in hook)`];let L=AU(c,d,i,t);return L||[`${i}// ${t}: ${ir(p)}`,...y.map(M=>`${i}${M}`)]}if(xv(c))return[`${i}// ${t}: ${ir(p)}`,`${i}page = agent.agentServices.validatePage(page);`,...y.map(L=>`${i}${L}`)];let g=JSON.stringify(p),_=y.map(L=>`${i} ${L}`),v=dP(c),S=a?`'${a}'`:"undefined";return[`${i}// ${t}: ${ir(p)}`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.step(page, async () => {`,..._,`${i}}, ${g}, '${t}', ${S}, ${v});`]}function SU(r,e,t,n){let i=" ".repeat(e),s=[];r.description&&r.description.trim()&&s.push(`${i}// Step: ${ir(r.description)}`);let a=kn(r.statements,e,n,t);return s.push(...a),s}function TU(r,e,t,n){let i=" ".repeat(e),s=[];if(s.push(`${i}// ${t}: Conditional check`),r.condition.type==="JS_CODE")s.push(`${i}if (${r.condition.expression}) {`);else{s.push(`${i}// AI Condition: ${ir(r.condition.expression)}`);let o=JSON.stringify(r.condition.expression);s.push(`${i}if (await agent.evaluate(page, ${o}, "${t}")) {`)}let a=kn(r.then,e+1,n,`${t}.then`);if(s.push(...a),r.else&&r.else.length>0){s.push(`${i}} else {`);let o=kn(r.else,e+1,n,`${t}.else`);s.push(...o)}return s.push(`${i}}`),s}function EU(r,e,t,n){let i=" ".repeat(e),s=[];s.push(`${i}// ${t}: Loop`);let a=r.timeout_ms??ym,o=a/1e3,l=r.timeout_ms?`While loop exceeded timeout of ${o}s`:`While loop exceeded default timeout of ${o}s`,c=`loop_${t.replace(/\./g,"_")}`;if(s.push(`${i}const ${c}_start = Date.now();`),s.push(`${i}const ${c}_timeout = ${a};`),s.push(`${i}const ${c}_check = () => {`),s.push(`${i} if (Date.now() - ${c}_start > ${c}_timeout) {`),s.push(`${i} throw new Error('${l}');`),s.push(`${i} }`),s.push(`${i} return true;`),s.push(`${i}};`),r.condition.type==="JS_CODE")s.push(`${i}while (${c}_check() && (${r.condition.expression})) {`);else{s.push(`${i}// AI Loop Condition: ${ir(r.condition.expression)}`);let p=JSON.stringify(r.condition.expression);s.push(`${i}while (${c}_check() && await agent.evaluate(page, ${p}, "${t}")) {`)}let d=kn(r.body,e+1,n,`${t}.body`);return s.push(...d),s.push(`${i}}`),s}function AU(r,e,t,n){let i=r.action_description||"",s=r.action_data?.kwargs||{};switch(e){case"go_to_url":case"open_tab":{let a=s.url||"";return[`${t}// ${n}: ${ir(i)}`,`${t}await page.goto(${JSON.stringify(a)}, { waitUntil: 'domcontentloaded' });`]}case"go_back":return[`${t}// ${n}: ${ir(i)}`,`${t}await page.goBack();`];case"go_forward":return[`${t}// ${n}: ${ir(i)}`,`${t}await page.goForward();`];case"input_text":{let a=s.text||"",o=getPageLocatorExpression(r);return o?[`${t}// ${n}: ${ir(i)}`,`${t}await ${o}.fill(${JSON.stringify(a)}, { timeout: ${ACTION_TIMEOUT} });`]:null}case"select_dropdown_option":{let a=s.text||s.label||"",o=getPageLocatorExpression(r);return o?[`${t}// ${n}: ${ir(i)}`,`${t}await ${o}.selectOption({ label: ${JSON.stringify(a)} }, { timeout: ${ACTION_TIMEOUT} });`]:null}default:return null}}var mP={name:"shiplightai",version:"0.1.14",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"}},files:["dist","README.md"],publishConfig:{registry:"https://registry.npmjs.org",access:"public"},scripts:{build:"tsup","build:cli":"tsup",clean:"rm -rf dist",dev:"tsup --watch",test:"playwright test",typecheck:"tsc --noEmit"},dependencies:{"@babel/plugin-transform-typescript":"^7.27.0","@babel/preset-env":"^7.26.9","@babel/preset-typescript":"^7.27.0","@anthropic-ai/claude-agent-sdk":"^0.1.72","@modelcontextprotocol/sdk":"^0.5.0",axios:"^1.6.0",dotenv:"^16.0.3",express:"^4.21.0",glob:"^13.0.0",open:"^10.1.0",sharp:"^0.34.5",uuid:"^11.1.0",yaml:"^2.8.0",zod:"^3.22.0","zod-to-json-schema":"^3.24.6"},devDependencies:{"@playwright/test":"1.55.0","@types/express":"^4.17.21","@types/node":"^24.0.0",copilot3:"workspace:*","mcp-tools":"workspace:*","sdk-core":"workspace:*","sdk-internal":"workspace:*","shiplight-types":"workspace:*",tsup:"^8.3.5",typescript:"5.5.4","web-session":"workspace:*"},peerDependencies:{"@playwright/test":">=1.40.0"},engines:{node:">=22.0.0"},keywords:["playwright","yaml","testing","automation","ai","shiplight","mcp"],author:"Shiplight",license:"MIT"};var _d=mP.version;function yP(r,e){let t=[];t.push(`// @generated by shiplightai v${_d}`),t.push(...xP()),t.push(""),e?.use&&Object.keys(e.use).length>0&&(t.push(`test.use(${JSON.stringify(e.use,null,2)});`),t.push(""));let n=new Set,i={imports:n};e?.beforeEach&&e.beforeEach.length>0&&(t.push(...gP("beforeEach",e.beforeEach,i)),t.push(""));let s=e?.timeout||e?.skip!==void 0||e?.fail!==void 0||e?.only||e?.slow?{timeout:e.timeout,skip:e.skip,fail:e.fail,only:e.only,slow:e.slow}:void 0;if(e?.parameters&&e.parameters.length>0){let a=e?.testName||r.goal||"Generated test",o=_v(e?.tags);for(let l of e.parameters){let c=vP(r,l.values);t.push(...wm(c,`${o}${Yn(a)} [${Yn(l.name)}]`,i,0,s)),t.push("")}}else{let a=e?.testName||r.goal||"Generated test",o=_v(e?.tags);t.push(...wm(r,`${o}${Yn(a)}`,i,0,s))}return e?.afterEach&&e.afterEach.length>0&&(t.push(""),t.push(...gP("afterEach",e.afterEach,i))),_P(t,n),t.join(`
4710
+ `);for(let i of n)t.push(` ${i}`);return t.push("}"),t});nt("function",(r,e,t)=>{let n=r.action_data?.kwargs||{},i=n.functionName;if(i&&i.includes("#")){let[a,o]=i.split("#");if(a&&o){let l=a.replace(/\.(ts|js|mjs)$/,""),c=`import { ${o} } from '${l}';`;t?.imports?.add(c);let d={...n,functionName:o},p=pP(d);return p?[p.endsWith(";")?p:`${p};`]:["// Skipping function: invalid export pattern"]}}let s=pP(n);return s?[s.endsWith(";")?s:`${s};`]:["// Skipping function: missing functionName"]});nt("generate_2fa_code",r=>{let e=r.action_data?.kwargs?.otp_secret_key||"";return['await agent.execAction("generate_2fa_code", page, {',` action_data: { kwargs: { otp_secret_key: ${JSON.stringify(e)} } },`,"});"]});nt("upload_file",r=>{let e=r.action_data?.kwargs||{},t=[],n={};return e.paths?n.paths=e.paths:e.path&&(n.path=e.path),e.use_file_input&&(n.use_file_input=!0),t.push(`action_data: { kwargs: ${JSON.stringify(n)} }`),r.locator?t.push(`locator: ${JSON.stringify(r.locator)}`):r.xpath&&t.push(`xpath: ${JSON.stringify(r.xpath)}`),r.frame_path&&r.frame_path.length>0&&t.push(`frame_path: ${JSON.stringify(r.frame_path)}`),['await agent.execAction("upload_file", page, {',...t.map(i=>` ${i},`),"});"]});nt("wait_for_download_complete",r=>['await agent.execAction("wait_for_download_complete", page, {',` action_data: { kwargs: { timeout_seconds: ${r.action_data?.kwargs?.timeout_seconds||10} } },`,"});"]);nt("switch_tab",r=>['await agent.execAction("switch_tab", page, {',` action_data: { kwargs: { page_id: ${r.action_data?.kwargs?.page_id??0} } },`,"});"]);nt("close_tab",r=>{let e=r.action_data?.kwargs?.page_id;return e=e??r.action_data?.kwargs?.index,['await agent.execAction("close_tab", page, {',` action_data: { kwargs: { page_id: ${e} } },`,"});"]});nt("set_date_for_native_date_picker",r=>{let e=r.action_data?.kwargs?.date??"",t=[];return t.push(`action_data: { kwargs: { date: ${JSON.stringify(e)} } }`),r.locator?t.push(`locator: ${JSON.stringify(r.locator)}`):r.xpath&&t.push(`xpath: ${JSON.stringify(r.xpath)}`),r.frame_path&&r.frame_path.length>0&&t.push(`frame_path: ${JSON.stringify(r.frame_path)}`),['await agent.execAction("set_date_for_native_date_picker", page, {',...t.map(n=>` ${n},`),"});"]});nt("done",()=>["// Done - no action needed"]);function pP(r){let e=r.functionName;if(!e)return null;let t={},n=r.parameterNames||[],i=r.parameterValues||r.args||[];if(n.forEach((l,c)=>{c<i.length&&(t[l]=i[c])}),Object.keys(t).length===0)return`await ${e}()`;let s=["page","testContext","request","agentServices"],a=["undefined","null","true","false"],o=Object.entries(t).map(([l,c])=>{let d=String(c);return c==null?"undefined":s.includes(l)&&s.includes(d)||a.includes(d)||/^-?\d+(\.\d+)?$/.test(d)?d:d.startsWith("$")?`agent.agentServices.readVariable('${d.substring(1)}')`:`"${d}"`});return`await ${e}(${o.join(", ")})`}function kn(r,e,t,n="main"){let i=[];for(let s=0;s<r.length;s++){let a=r[s],o=`${n}.${s}`,l=vU(a,e,o,t);l.length>0&&(i.push(...l),s<r.length-1&&i.push(""))}return i}function vU(r,e,t,n){let i=" ".repeat(e);switch(r.type){case"DRAFT":return xU(r,e,t,n);case"ACTION":return _U(r,e,t,n);case"STEP":return SU(r,e,t,n);case"IF_ELSE":return TU(r,e,t,n);case"WHILE_LOOP":return EU(r,e,t,n);default:return[`${i}// Unknown statement type: ${r.type}`]}}function xU(r,e,t,n){let i=" ".repeat(e),s=r.description?.trim()||"";if(!s)return[`${i}// ${t}: Skipping - no description`];if(n.noAgent)return[`${i}// ${t}: ${ir(s)}`,`${i}// DRAFT: ${ir(s)} (requires agent - skipped in hook)`];let a=JSON.stringify(s);return[`${i}// ${t}: ${ir(s)}`,`${i}// \u26A0 DRAFT: AI-resolved at runtime (~5-10s). Add a locator to make this <1s.`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.run(page, ${a}, '${t}');`]}function _U(r,e,t,n){let i=" ".repeat(e),s=r.description,a=r.uid,l=n.actionEntityStore?.entries[r.uid]?.action_entity??r.action_entity;if(!l){if(!s)return[`${i}// ${t}: Skipping - no description`];if(n.noAgent)return[`${i}// ${t}: ${ir(s)}`,`${i}// DRAFT: ${ir(s)} (requires agent - skipped in hook)`];let L=JSON.stringify(s),M=!!r.use_pure_vision;return[`${i}// ${t}: ${ir(s)}`,`${i}// \u26A0 DRAFT: AI-resolved at runtime (~5-10s). Add a locator to make this <1s.`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.execute(page, ${L}, '${t}', ${M});`]}let c=r.locator?{...l,locator:r.locator}:l;s&&s!==c.action_description&&(c={...c,action_description:s});let d=c.action_data?.action_name||"",p=c.action_description||"",m=fP(d);if(!m)return[`${i}// ${t}: Unknown action: ${d}`];let f={imports:n.imports},y=m(c,t,f);if(n.noAgent){if(xv(c))return[`${i}// ${t}: ${ir(p)}`,`${i}// AI action: ${ir(p)} (requires agent - skipped in hook)`];let L=AU(c,d,i,t);return L||[`${i}// ${t}: ${ir(p)}`,...y.map(M=>`${i}${M}`)]}if(xv(c))return[`${i}// ${t}: ${ir(p)}`,`${i}page = agent.agentServices.validatePage(page);`,...y.map(L=>`${i}${L}`)];let g=JSON.stringify(p),_=y.map(L=>`${i} ${L}`),v=dP(c),S=a?`'${a}'`:"undefined";return[`${i}// ${t}: ${ir(p)}`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.step(page, async () => {`,..._,`${i}}, ${g}, '${t}', ${S}, ${v});`]}function SU(r,e,t,n){let i=" ".repeat(e),s=[];r.description&&r.description.trim()&&s.push(`${i}// Step: ${ir(r.description)}`);let a=kn(r.statements,e,n,t);return s.push(...a),s}function TU(r,e,t,n){let i=" ".repeat(e),s=[];if(s.push(`${i}// ${t}: Conditional check`),r.condition.type==="JS_CODE")s.push(`${i}if (${r.condition.expression}) {`);else{s.push(`${i}// AI Condition: ${ir(r.condition.expression)}`);let o=JSON.stringify(r.condition.expression);s.push(`${i}if (await agent.evaluate(page, ${o}, "${t}")) {`)}let a=kn(r.then,e+1,n,`${t}.then`);if(s.push(...a),r.else&&r.else.length>0){s.push(`${i}} else {`);let o=kn(r.else,e+1,n,`${t}.else`);s.push(...o)}return s.push(`${i}}`),s}function EU(r,e,t,n){let i=" ".repeat(e),s=[];s.push(`${i}// ${t}: Loop`);let a=r.timeout_ms??ym,o=a/1e3,l=r.timeout_ms?`While loop exceeded timeout of ${o}s`:`While loop exceeded default timeout of ${o}s`,c=`loop_${t.replace(/\./g,"_")}`;if(s.push(`${i}const ${c}_start = Date.now();`),s.push(`${i}const ${c}_timeout = ${a};`),s.push(`${i}const ${c}_check = () => {`),s.push(`${i} if (Date.now() - ${c}_start > ${c}_timeout) {`),s.push(`${i} throw new Error('${l}');`),s.push(`${i} }`),s.push(`${i} return true;`),s.push(`${i}};`),r.condition.type==="JS_CODE")s.push(`${i}while (${c}_check() && (${r.condition.expression})) {`);else{s.push(`${i}// AI Loop Condition: ${ir(r.condition.expression)}`);let p=JSON.stringify(r.condition.expression);s.push(`${i}while (${c}_check() && await agent.evaluate(page, ${p}, "${t}")) {`)}let d=kn(r.body,e+1,n,`${t}.body`);return s.push(...d),s.push(`${i}}`),s}function AU(r,e,t,n){let i=r.action_description||"",s=r.action_data?.kwargs||{};switch(e){case"go_to_url":case"open_tab":{let a=s.url||"";return[`${t}// ${n}: ${ir(i)}`,`${t}await page.goto(${JSON.stringify(a)}, { waitUntil: 'domcontentloaded' });`]}case"go_back":return[`${t}// ${n}: ${ir(i)}`,`${t}await page.goBack();`];case"go_forward":return[`${t}// ${n}: ${ir(i)}`,`${t}await page.goForward();`];case"input_text":{let a=s.text||"",o=getPageLocatorExpression(r);return o?[`${t}// ${n}: ${ir(i)}`,`${t}await ${o}.fill(${JSON.stringify(a)}, { timeout: ${ACTION_TIMEOUT} });`]:null}case"select_dropdown_option":{let a=s.text||s.label||"",o=getPageLocatorExpression(r);return o?[`${t}// ${n}: ${ir(i)}`,`${t}await ${o}.selectOption({ label: ${JSON.stringify(a)} }, { timeout: ${ACTION_TIMEOUT} });`]:null}default:return null}}var mP={name:"shiplightai",version:"0.1.15",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"}},files:["dist","README.md"],publishConfig:{registry:"https://registry.npmjs.org",access:"public"},scripts:{build:"tsup","build:cli":"tsup",clean:"rm -rf dist",dev:"tsup --watch",test:"playwright test",typecheck:"tsc --noEmit"},dependencies:{"@babel/plugin-transform-typescript":"^7.27.0","@babel/preset-env":"^7.26.9","@babel/preset-typescript":"^7.27.0","@anthropic-ai/claude-agent-sdk":"^0.1.72","@modelcontextprotocol/sdk":"^0.5.0",axios:"^1.6.0",dotenv:"^16.0.3",express:"^4.21.0",glob:"^13.0.0",open:"^10.1.0",sharp:"^0.34.5",uuid:"^11.1.0",yaml:"^2.8.0",zod:"^3.22.0","zod-to-json-schema":"^3.24.6"},devDependencies:{"@playwright/test":"1.55.0","@types/express":"^4.17.21","@types/node":"^24.0.0",copilot3:"workspace:*","mcp-tools":"workspace:*","sdk-core":"workspace:*","sdk-internal":"workspace:*","shiplight-types":"workspace:*",tsup:"^8.3.5",typescript:"5.5.4","web-session":"workspace:*"},peerDependencies:{"@playwright/test":">=1.40.0"},engines:{node:">=22.0.0"},keywords:["playwright","yaml","testing","automation","ai","shiplight","mcp"],author:"Shiplight",license:"MIT"};var _d=mP.version;function yP(r,e){let t=[];t.push(`// @generated by shiplightai v${_d}`),t.push(...xP()),t.push(""),e?.use&&Object.keys(e.use).length>0&&(t.push(`test.use(${JSON.stringify(e.use,null,2)});`),t.push(""));let n=new Set,i={imports:n};e?.beforeEach&&e.beforeEach.length>0&&(t.push(...gP("beforeEach",e.beforeEach,i)),t.push(""));let s=e?.timeout||e?.skip!==void 0||e?.fail!==void 0||e?.only||e?.slow?{timeout:e.timeout,skip:e.skip,fail:e.fail,only:e.only,slow:e.slow}:void 0;if(e?.parameters&&e.parameters.length>0){let a=e?.testName||r.goal||"Generated test",o=_v(e?.tags);for(let l of e.parameters){let c=vP(r,l.values);t.push(...wm(c,`${o}${Yn(a)} [${Yn(l.name)}]`,i,0,s)),t.push("")}}else{let a=e?.testName||r.goal||"Generated test",o=_v(e?.tags);t.push(...wm(r,`${o}${Yn(a)}`,i,0,s))}return e?.afterEach&&e.afterEach.length>0&&(t.push(""),t.push(...gP("afterEach",e.afterEach,i))),_P(t,n),t.join(`
4711
4711
  `)}function bP(r,e){let t=[];t.push(`// @generated by shiplightai v${_d}`),t.push(...xP()),t.push(""),e?.use&&Object.keys(e.use).length>0&&(t.push(`test.use(${JSON.stringify(e.use,null,2)});`),t.push(""));let n=new Set,i={imports:n},s=e?.testName||"Test Suite",a=_v(e?.tags),o=r.serial?"test.describe.serial":"test.describe";t.push(`${o}('${a}${Yn(s)}', () => {`),r.beforeAll&&r.beforeAll.length>0&&(t.push(...bm("beforeAll",r.beforeAll,i,1)),t.push("")),r.beforeEach&&r.beforeEach.length>0&&(t.push(...bm("beforeEach",r.beforeEach,i,1)),t.push(""));for(let l=0;l<r.tests.length;l++){let c=r.tests[l],d=c.timeout||c.skip!==void 0||c.fail!==void 0||c.only||c.slow?{timeout:c.timeout,skip:c.skip,fail:c.fail,only:c.only,slow:c.slow}:void 0;if(c.parameters&&c.parameters.length>0)for(let p of c.parameters){let m=vP(c.testFlow,p.values);t.push(...wm(m,`${Yn(c.name)} [${Yn(p.name)}]`,i,1,d)),t.push("")}else t.push(...wm(c.testFlow,Yn(c.name),i,1,d)),(l<r.tests.length-1||r.afterEach||r.afterAll)&&t.push("")}return r.afterEach&&r.afterEach.length>0&&(t.push(...bm("afterEach",r.afterEach,i,1)),t.push("")),r.afterAll&&r.afterAll.length>0&&t.push(...bm("afterAll",r.afterAll,i,1)),t.push("});"),_P(t,n),t.join(`
4712
4712
  `)}function _v(r){return r&&r.length>0?r.map(e=>`@${e}`).join(" ")+" ":""}function wm(r,e,t,n=0,i){let s=" ".repeat(n),a=[],o=i?.only?"test.only":"test";a.push(`${s}${o}('${e}', async ({ page, agent }) => {`),i?.skip===!0?a.push(`${s} test.skip();`):typeof i?.skip=="string"&&a.push(`${s} test.skip(true, '${Yn(i.skip)}');`),i?.fail===!0?a.push(`${s} test.fail();`):typeof i?.fail=="string"&&a.push(`${s} test.fail(true, '${Yn(i.fail)}');`),i?.slow&&a.push(`${s} test.slow();`),i?.timeout&&a.push(`${s} test.setTimeout(${i.timeout});`);let l=r.teardown&&r.teardown.length>0,c=n+1;if(l){if(a.push(`${s} try {`),r.statements&&r.statements.length>0){a.push(`${s} // Test steps`);let p=kn(r.statements,c+1,t);a.push(...p)}a.push(`${s} } finally {`),a.push(`${s} // Teardown`);let d=kn(r.teardown,c+1,t,"teardown");a.push(...d),a.push(`${s} }`)}else if(r.statements&&r.statements.length>0){a.push(`${s} // Test steps`);let d=kn(r.statements,c,t);a.push(...d)}return a.push(`${s}});`),a}function gP(r,e,t){let n=[],i=wP(e);return n.push(`test.${r}(async ({ page, agent }) => {`),n.push(...kn(i,1,t,r)),n.push("});"),n}function bm(r,e,t,n){let i=" ".repeat(n),s=[],a=wP(e);if(r==="beforeAll"||r==="afterAll"){let l={...t,noAgent:!0};s.push(`${i}test.${r}(async ({ browser }, workerInfo) => {`),s.push(`${i} const page = await browser.newPage({ baseURL: workerInfo.project.use.baseURL });`),s.push(...kn(a,n+1,l,r)),s.push(`${i} await page.close();`),s.push(`${i}});`)}else s.push(`${i}test.${r}(async ({ page, agent }) => {`),s.push(...kn(a,n+1,t,r)),s.push(`${i}});`);return s}function wP(r){let t=(0,Sv.stringify)({goal:"_hook",statements:r});return nn(t).statements}function vP(r,e){let t=(0,Sv.stringify)({goal:r.goal,statements:r.statements,teardown:r.teardown});for(let[n,i]of Object.entries(e))t=t.replaceAll(`<<${n}>>`,String(i));return nn(t)}function xP(){return["import { test, expect } from 'shiplightai/fixture';"]}function _P(r,e){if(e.size>0){let t=0;for(let i=0;i<r.length;i++)r[i].startsWith("import ")&&(t=i+1);let n=Array.from(e);r.splice(t,0,...n)}}function SP(r){try{return(0,_s.statSync)(r).mtimeMs}catch{return 0}}var CU=`// @generated by shiplightai v${_d}`;function IU(r,e){if(!(0,_s.existsSync)(r)||(0,_s.readFileSync)(r,"utf-8").split(`
4713
4713
  `,1)[0]!==CU)return!1;let n=SP(r);for(let i of e)if(SP(i)>n)return!1;return!0}function AP(r){let e=(0,EP.globSync)("**/*.test.yaml",{cwd:r.cwd,ignore:["**/node_modules/**"]}),t=[];for(let n of e){let i=(0,TP.resolve)(r.cwd,n),s=i.replace(/\.test\.yaml$/,".yaml.spec.ts"),a=(0,_s.readFileSync)(i,"utf-8");try{let o=cP(a,i);if(IU(s,[i,...o.referencedTemplatePaths]))continue;let l;o.suite?l=bP(o.suite,{testName:o.name,tags:o.tags,use:o.use}):l=yP(o.testFlow,{testName:o.name,tags:o.tags,use:o.use,beforeEach:o.beforeEach,afterEach:o.afterEach,parameters:o.parameters,timeout:o.timeout,skip:o.skip,fail:o.fail,only:o.only,slow:o.slow}),(0,_s.writeFileSync)(s,l)}catch(o){console.error(`[shiplight] Failed to transpile ${n}:`,o),t.push({file:n,error:o})}}if(t.length>0)throw new Error(`[shiplight] Transpilation failed for ${t.length} file(s):
4714
4714
  `+t.map(n=>` - ${n.file}`).join(`
4715
4715
  `))}var Sl=ot(require("path"),1),s9=ot(require("fs"),1),a9=require("fs/promises");var xm=ot(require("fs"),1),_o=ot(require("path"),1);function _m(r){let e=null,t=process.env.SHIPLIGHT_LOGIN_EMAIL,n=process.env.SHIPLIGHT_LOGIN_PASSWORD;return t&&n&&(e={username:t,password:n}),e||(e=PU(r)),e?(process.env.SHIPLIGHT_LOGIN_URL&&(e.loginUrl=process.env.SHIPLIGHT_LOGIN_URL),process.env.SHIPLIGHT_LOGIN_TOTP_SECRET&&(e.totpSecret=process.env.SHIPLIGHT_LOGIN_TOTP_SECRET),e):null}function vm(r){if(r.startsWith("$")){let e=r.slice(1);return process.env[e]||r}return r}function PU(r){let e=_o.resolve(r),t=_o.resolve(process.cwd());for(;;){for(let i of["shiplight.config.json","login.config.json"]){let s=_o.join(e,i);if(xm.existsSync(s))try{let a=JSON.parse(xm.readFileSync(s,"utf-8"));if(a.username&&a.password)return{username:vm(a.username),password:vm(a.password),loginUrl:a.url?vm(a.url):void 0,totpSecret:a.totp_secret?vm(a.totp_secret):void 0}}catch{}}if(e===t)break;let n=_o.dirname(e);if(n===e)break;e=n}return null}var o9="auth.setup.ts",n9=".auth",i9="storage-state.json";async function l9(r,e){let t=Sl.resolve(e),n=Sl.join(t,n9,i9);if(s9.existsSync(n)){console.log("[INFO] Storage state exists, skipping login. Delete",n,"to force re-auth.");return}let i=_m(t);if(!i)return;let{WebAgent:s,createAgentContext:a,configureSdk:o,VariableStore:l,LoginType:c,TwoFactorAuthType:d}=await Promise.resolve().then(()=>(zk(),r9));o({env:{GOOGLE_API_KEY:process.env.GOOGLE_API_KEY??"",ANTHROPIC_API_KEY:process.env.ANTHROPIC_API_KEY??""}});let{resolveModelFromEnv:p}=await Promise.resolve().then(()=>(bd(),aP)),m=p(process.env);if(!m)throw new Error("No AI model configured. Set WEB_AGENT_MODEL, ANTHROPIC_API_KEY, or GOOGLE_API_KEY.");let f=new s(a({model:m,variableStore:new l})),{username:y,password:g,loginUrl:_,totpSecret:v}=i,S=_||r.url()||"about:blank";if(!(await f.loginPage(r,{site_url:S,num_verification_exprs:0,account:{type:c.PASSWORD,username:y,password:g,...v&&{two_factor_auth_config:{type:d.TOTP,data:v}}}})).success)throw new Error("Login failed.");let M=Sl.join(t,n9);await(0,a9.mkdir)(M,{recursive:!0}),await r.context().storageState({path:Sl.join(M,i9)})}function c9(){return`// @generated by shiplightai \u2014 do not edit
4716
4716
  import { test as setup } from '@playwright/test';
4717
- import { authSetup } from 'shiplightai';
4718
4717
 
4719
4718
  setup('authenticate', async ({ page }) => {
4720
- await authSetup(page, import.meta.dirname);
4719
+ const { authSetup } = await import('shiplightai');
4720
+ await authSetup(page, __dirname);
4721
4721
  });
4722
4722
  `}function p9(r={}){r.dotenv!==!1&&Vle(r.scanDir||process.cwd());let e=r.scanDir||process.cwd();return AP({cwd:e}),zle(e),r.apiKey&&(process.env.__SHIPLIGHT_API_KEY=r.apiKey),{}}function Vle(r){let e=[],t=hs.resolve(r),n=hs.resolve(process.cwd());for(;;){let i=hs.join(t,".env");if(sa.existsSync(i)&&e.push(i),t===n)break;let s=hs.dirname(t);if(s===t)break;t=s}for(let i of e)u9.default.config({path:i})}function zle(r){let e=(0,d9.globSync)("**/shiplight.config.json",{cwd:r,ignore:["**/node_modules/**"]});for(let t of e){let n=hs.resolve(r,t),i=hs.dirname(n),s=hs.join(i,o9),a=!1;try{let o=JSON.parse(sa.readFileSync(n,"utf-8"));a=!!(o.username&&o.password)}catch{}if(!a&&process.env.SHIPLIGHT_LOGIN_EMAIL&&process.env.SHIPLIGHT_LOGIN_PASSWORD&&(a=!0),!!a){try{let o=sa.statSync(n).mtimeMs;if(sa.statSync(s).mtimeMs>o)continue}catch{}sa.writeFileSync(s,c9())}}}zk();0&&(module.exports={VariableStore,WebAgent,authSetup,configureSdk,createAgentContext,resolveLoginConfig,shiplightConfig});
4723
4723
  /*! Bundled license information:
package/dist/cli.js CHANGED
@@ -8315,12 +8315,12 @@ statements:
8315
8315
  `});var VTn={};bs(VTn,{runTests:()=>$5o});import{spawn as j5o}from"child_process";import*as $Tn from"fs";import*as GTn from"path";async function $5o(e){(e.includes("--help")||e.includes("-h"))&&(console.log("Usage: shiplight test [playwright-args...]"),console.log(""),console.log("Delegates to `npx playwright test` with all arguments forwarded."),console.log("Auto-detects playwright.config.ts in the current directory."),console.log(""),console.log("Examples:"),console.log(" shiplight test # run all tests"),console.log(" shiplight test --headed # run tests with browser visible"),console.log(" shiplight test tests/login.test.yaml # run a specific YAML test"),console.log(" shiplight test tests/login.test.ts # run a specific TS test"),console.log(" shiplight test --grep 'login' # filter tests by name"),process.exit(0));let t=process.cwd();["playwright.config.ts","playwright.config.js","playwright.config.mjs"].some(a=>$Tn.existsSync(GTn.join(t,a)))||(console.warn("Warning: No playwright.config.ts found in current directory."),console.warn(`Make sure you're running from your project root.
8316
8316
  `));let i=e.map(a=>a.endsWith(".test.yaml")?a.replace(/\.test\.yaml$/,".yaml.spec.ts"):a),s=j5o("npx",["playwright","test",...i],{stdio:"inherit",shell:!0,cwd:t}),o=await new Promise(a=>{s.on("close",u=>a(u??1))});process.exit(o)}var WTn=k(()=>{"use strict"});import{readFileSync as G5o}from"fs";import{resolve as JTn,dirname as V5o}from"path";import{parse as YTn,stringify as W5o}from"yaml";function Lvt(e,t){let r={expandingPaths:new Set([JTn(t)]),depth:0,referencedPaths:new Set},n={...e};Array.isArray(n.statements)&&(n.statements=hP(n.statements,t,r)),Array.isArray(n.teardown)&&(n.teardown=hP(n.teardown,t,r));for(let i of["beforeAll","afterAll","beforeEach","afterEach"])Array.isArray(n[i])&&(n[i]=hP(n[i],t,r));return{doc:n,referencedTemplatePaths:Array.from(r.referencedPaths)}}function hP(e,t,r){let n=[];for(let i of e)if(Y5o(i)){let s=z5o(i,t,r);n.push(...s)}else n.push(J5o(i,t,r));return n}function Y5o(e){return typeof e=="object"&&e!==null&&typeof e.template=="string"}function z5o(e,t,r){if(r.depth>=zTn)throw new Error(`Template expansion exceeded maximum depth of ${zTn}. Check for deeply nested or circular template references.`);let n=JTn(V5o(t),e.template);if(r.expandingPaths.has(n))throw new Error(`Circular template reference detected: ${n} is already being expanded. Stack: ${Array.from(r.expandingPaths).join(" \u2192 ")} \u2192 ${n}`);r.referencedPaths.add(n);let i;try{i=G5o(n,"utf-8")}catch(c){throw new Error(`Failed to read template file: ${n} (referenced from ${t}): ${c.message}`)}let s=YTn(i);if(!s||typeof s!="object")throw new Error(`Invalid template file: ${n} \u2014 expected a YAML object`);let o=s.params||[],a=e.params||{};for(let c of o)if(!(c in a))throw new Error(`Template ${e.template} requires param "${c}" but it was not provided. Required params: [${o.join(", ")}]`);let u=s.statements;if(!Array.isArray(u))throw new Error(`Template ${e.template} must have a "statements" array`);if(Object.keys(a).length>0){let d=W5o(u);for(let[f,p]of Object.entries(a))d=d.replaceAll(`<<${f}>>`,String(p));u=YTn(d)}let l={expandingPaths:new Set([...r.expandingPaths,n]),depth:r.depth+1,referencedPaths:r.referencedPaths};return hP(u,n,l)}function J5o(e,t,r){if(typeof e!="object"||e===null)return e;let n={...e};return Array.isArray(n.statements)&&(n.statements=hP(n.statements,t,r)),Array.isArray(n.THEN)&&(n.THEN=hP(n.THEN,t,r)),Array.isArray(n.ELSE)&&(n.ELSE=hP(n.ELSE,t,r)),Array.isArray(n.DO)&&(n.DO=hP(n.DO,t,r)),n}var zTn,KTn=k(()=>{"use strict";zTn=5});import{parse as K5o,stringify as XTn}from"yaml";function ZTn(e,t){let r=K5o(e),n=r?.name,i=r?.tags,s=r?.use;if(r&&(r.name!==void 0||r.tags!==void 0||r.use!==void 0)&&(delete r.name,delete r.tags,delete r.use),r?.suite){if(r.goal||r.statements)throw new Error('YAML file cannot have both "suite" and top-level "goal"/"statements". Use either suite format or single-test format.');return Z5o(r,n,i,s,t)}return X5o(r,n,i,s,t)}function X5o(e,t,r,n,i){let s=e?.beforeEach,o=e?.afterEach,a=eBn(e?.parameters),u=e?.timeout,l=e?.skip,c=e?.fail,d=e?.only,f=e?.slow;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&&!e.goal&&t&&(e.goal=t);let p=[];if(i&&e&&typeof e=="object"){let b=Lvt(e,i);e=b.doc,p=b.referencedTemplatePaths}let m=XTn(e);return{testFlow:og(m),name:t,tags:r,use:n,beforeEach:s,afterEach:o,parameters:a,timeout:u,skip:l,fail:c,only:d,slow:f,referencedTemplatePaths:p}}function Z5o(e,t,r,n,i){let s=e.suite;if(!Array.isArray(s.tests)||s.tests.length===0)throw new Error('Suite must have a non-empty "tests" array.');let o=s.serial,a=s.beforeAll,u=s.afterAll,l=s.beforeEach,c=s.afterEach,d=[],f=s.tests.map(p=>{if(!p.name)throw new Error('Each test in a suite must have a "name" field.');if(!Array.isArray(p.statements)||p.statements.length===0)throw new Error(`Suite test "${p.name}" must have a non-empty "statements" array.`);let m={goal:p.name,statements:p.statements};p.teardown&&(m.teardown=p.teardown);let y=[],b=m;if(i&&typeof m=="object"){let T=Lvt(m,i);b=T.doc,y=T.referencedTemplatePaths,d.push(...y)}let w=XTn(b),C=og(w),S=eBn(p.parameters);return{testFlow:C,name:p.name,parameters:S,timeout:p.timeout,skip:p.skip,fail:p.fail,only:p.only,slow:p.slow}});return{suite:{serial:o,beforeAll:a,afterAll:u,beforeEach:l,afterEach:c,tests:f},name:t,tags:r,use:n,referencedTemplatePaths:d}}function eBn(e){if(!(!Array.isArray(e)||e.length===0))return e.map((t,r)=>{if(!t.name)throw new Error(`Parameter set at index ${r} 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}})}var tBn=k(()=>{"use strict";su();KTn()});function Wx(e){return e.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function rp(e){return e.replace(/\r\n/g," ").replace(/\n/g," ").replace(/\r/g," ").trim()}function eOo(e){let t=e.frame_path;return!t||t.length===0?"page":`page.frameLocator('${t[0]}')`}function tOo(e){let t=e.xpath;return typeof t=="string"&&t.trim()?!t.startsWith("xpath=")&&!t.startsWith("/")&&!t.startsWith("//")?`xpath=//${t}`:t.startsWith("xpath=")?t:`xpath=${t}`:null}function Qvt(e){let t=eOo(e),r=e.locator;if(typeof r=="string"&&r.trim())return r=r.trim(),r.endsWith("first()")?`${t}.${r}`:`${t}.${r}.first()`;let n=tOo(e);if(n){let i=JSON.stringify(n);return`${t}.locator(${i}).first()`}return null}function Uvt(e){let t=e.action_data?.action_name;return!t||(t==="verify"||t==="ai_assert"||t==="assert")&&e.action_data?.kwargs?.code?!1:rOo.includes(t)}function rBn(e){let t=e.action_data?.action_name;return!t||(t==="verify"||t==="ai_assert"||t==="assert")&&e.action_data?.kwargs?.code?!1:!nOo.includes(t)}var rOo,nOo,cse=k(()=>{"use strict";rOo=["ai_action","ai_step","ai_assert","ai_extract","ai_wait_until","verify","assert"],nOo=["js_code","function","wait","wait_for_download_complete","wait_for_page_ready","extract_email_content","extract_activation_code"]});function As(e,t){T0.set(e,t)}function sBn(e){return T0.get(e)}function NM(e,t,r=[]){let n=[...r];return t.locator?n.push(`locator: ${JSON.stringify(t.locator)}`):t.xpath&&n.push(`xpath: ${JSON.stringify(t.xpath)}`),t.frame_path&&t.frame_path.length>0&&n.push(`frame_path: ${JSON.stringify(t.frame_path)}`),n.length===0?[`await agent.execAction("${e}", page, {});`]:[`await agent.execAction("${e}", page, {`,...n.map(i=>` ${i},`),"});"]}function nBn(e){let t=e.functionName;if(!t)return null;let r={},n=e.parameterNames||[],i=e.parameterValues||e.args||[];if(n.forEach((u,l)=>{l<i.length&&(r[u]=i[l])}),Object.keys(r).length===0)return`await ${t}()`;let s=["page","testContext","request","agentServices"],o=["undefined","null","true","false"],a=Object.entries(r).map(([u,l])=>{let c=String(l);return l==null?"undefined":s.includes(u)&&s.includes(c)||o.includes(c)||/^-?\d+(\.\d+)?$/.test(c)?c:c.startsWith("$")?`agent.agentServices.readVariable('${c.substring(1)}')`:`"${c}"`});return`await ${t}(${a.join(", ")})`}var T0,oBn=k(()=>{"use strict";cse();T0=new Map;As("click",e=>{let t=Qvt(e);return t?[`await ${t}.click({ timeout: ${5e3} });`]:['await agent.execAction("click", page, {});']});As("click_element",T0.get("click"));As("click_element_by_index",T0.get("click"));As("double_click",e=>NM("double_click",e));As("double_click_on_element",T0.get("double_click"));As("right_click",e=>NM("right_click",e));As("right_click_on_element",T0.get("right_click"));As("hover",e=>NM("hover",e));As("hover_element_by_index",T0.get("hover"));As("input_text",e=>{let t=e.action_data?.kwargs?.text??e.action_data?.kwargs?.value??"";return NM("input_text",e,[`action_data: { kwargs: { text: ${JSON.stringify(t)} } }`])});As("fill",T0.get("input_text"));As("clear_input",e=>NM("clear_input",e));As("press",e=>{let t=e.action_data?.kwargs?.keys;return[`await page.keyboard.press(${JSON.stringify(t)});`]});As("send_keys",T0.get("press"));As("send_keys_on_element",e=>{let t=Qvt(e),r=e.action_data?.kwargs?.keys||"";return t?[`await ${t}.press(${JSON.stringify(r)}, { timeout: ${5e3} });`]:['await agent.execAction("send_keys_on_element", page, {',` action_data: { kwargs: { keys: ${JSON.stringify(r)} } },`,"});"]});As("select_dropdown_option",e=>{let t=e.action_data?.kwargs?.text||e.action_data?.kwargs?.option||"";return NM("select_dropdown_option",e,[`action_data: { kwargs: { text: ${JSON.stringify(t)} } }`])});As("scroll",e=>{let t=e.action_data?.kwargs?.down??!0;return[`await page.evaluate('window.scrollBy(0, window.innerHeight * ${(e.action_data?.kwargs?.num_pages??1)*(t?1:-1)})');`]});As("scroll_down",T0.get("scroll"));As("scroll_up",T0.get("scroll"));As("scroll_element",T0.get("scroll"));As("scroll_to_text",e=>{let t=e.action_data?.kwargs?.text||"";return[`await page.getByText(${JSON.stringify(t)}, { exact: false }).first().scrollIntoViewIfNeeded();`]});As("scroll_on_element",e=>NM("scroll_on_element",e,[`action_data: { kwargs: ${JSON.stringify(e.action_data?.kwargs||{})} }`]));As("go_to_url",e=>{let t=e.action_data?.kwargs?.url||"";return e.action_data?.kwargs?.new_tab===!0?['await agent.execAction("go_to_url", page, {',` action_data: { kwargs: { url: ${JSON.stringify(t)}, new_tab: true } },`,"});"]:['await agent.execAction("go_to_url", page, {',` action_data: { kwargs: { url: ${JSON.stringify(t)} } },`,"});"]});As("open_tab",T0.get("go_to_url"));As("go_back",()=>['await agent.execAction("go_back", page, {});']);As("reload_page",()=>['await agent.execAction("reload_page", page, {});']);As("wait",e=>[`await page.waitForTimeout(${(e.action_data?.kwargs?.seconds||1)*1e3});`]);As("wait_for_page_ready",()=>["await page.waitForLoadState('domcontentloaded');"]);As("verify",(e,t)=>{let r=e.action_data?.kwargs;if(r?.code)return r.code.split(`
8317
8317
  `);let n=r?.statement||e.action_description;return n?[`await agent.assert(page, ${JSON.stringify(n)}, '${t||""}');`]:["// Skipping verify: missing statement or code"]});As("ai_assert",T0.get("verify"));As("assert",T0.get("verify"));As("ai_action",(e,t)=>{let r=e.action_data?.kwargs?.statement;if(!r)return["// Skipping ai_action: missing statement"];let n=JSON.stringify(r),i=e.action_data?.kwargs?.use_pure_vision;return[`await agent.execute(page, ${n}, '${t||""}', ${i});`]});As("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"]});As("ai_extract",(e,t)=>{let r=e.action_data?.kwargs?.element_description,n=e.action_data?.kwargs?.variable_name;if(!r||!n)return["// Skipping ai_extract: missing element_description or variable_name"];let i=JSON.stringify(r),s=JSON.stringify(n);return[`await agent.extract(page, ${i}, ${s}, '${t||""}');`]});As("ai_wait_until",(e,t)=>{let r=e.action_data?.kwargs?.condition,n=e.action_data?.kwargs?.timeout_seconds||60;return r?[`await agent.waitUntilCondition(page, ${JSON.stringify(r)}, ${n}, '${t||""}');`]:["// Skipping ai_wait_until: missing condition"]});As("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)} } },`,"});"]});As("js_code",e=>{let t=e.action_data?.kwargs?.code;if(!t)return["// Skipping js_code: missing code"];let r=["{"],n=t.split(`
8318
- `);for(let i of n)r.push(` ${i}`);return r.push("}"),r});As("function",(e,t,r)=>{let n=e.action_data?.kwargs||{},i=n.functionName;if(i&&i.includes("#")){let[o,a]=i.split("#");if(o&&a){let u=o.replace(/\.(ts|js|mjs)$/,""),l=`import { ${a} } from '${u}';`;r?.imports?.add(l);let c={...n,functionName:a},d=nBn(c);return d?[d.endsWith(";")?d:`${d};`]:["// Skipping function: invalid export pattern"]}}let s=nBn(n);return s?[s.endsWith(";")?s:`${s};`]:["// Skipping function: missing functionName"]});As("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)} } },`,"});"]});As("upload_file",e=>{let t=e.action_data?.kwargs||{},r=[],n={};return t.paths?n.paths=t.paths:t.path&&(n.path=t.path),t.use_file_input&&(n.use_file_input=!0),r.push(`action_data: { kwargs: ${JSON.stringify(n)} }`),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},`),"});"]});As("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} } },`,"});"]);As("switch_tab",e=>['await agent.execAction("switch_tab", page, {',` action_data: { kwargs: { page_id: ${e.action_data?.kwargs?.page_id??0} } },`,"});"]);As("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} } },`,"});"]});As("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(n=>` ${n},`),"});"]});As("done",()=>["// Done - no action needed"])});function DC(e,t,r,n="main"){let i=[];for(let s=0;s<e.length;s++){let o=e[s],a=`${n}.${s}`,u=iOo(o,t,a,r);u.length>0&&(i.push(...u),s<e.length-1&&i.push(""))}return i}function iOo(e,t,r,n){let i=" ".repeat(t);switch(e.type){case"DRAFT":return sOo(e,t,r,n);case"ACTION":return oOo(e,t,r,n);case"STEP":return aOo(e,t,r,n);case"IF_ELSE":return uOo(e,t,r,n);case"WHILE_LOOP":return lOo(e,t,r,n);default:return[`${i}// Unknown statement type: ${e.type}`]}}function sOo(e,t,r,n){let i=" ".repeat(t),s=e.description?.trim()||"";if(!s)return[`${i}// ${r}: Skipping - no description`];if(n.noAgent)return[`${i}// ${r}: ${rp(s)}`,`${i}// DRAFT: ${rp(s)} (requires agent - skipped in hook)`];let o=JSON.stringify(s);return[`${i}// ${r}: ${rp(s)}`,`${i}// \u26A0 DRAFT: AI-resolved at runtime (~5-10s). Add a locator to make this <1s.`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.run(page, ${o}, '${r}');`]}function oOo(e,t,r,n){let i=" ".repeat(t),s=e.description,o=e.uid,u=n.actionEntityStore?.entries[e.uid]?.action_entity??e.action_entity;if(!u){if(!s)return[`${i}// ${r}: Skipping - no description`];if(n.noAgent)return[`${i}// ${r}: ${rp(s)}`,`${i}// DRAFT: ${rp(s)} (requires agent - skipped in hook)`];let S=JSON.stringify(s),T=!!e.use_pure_vision;return[`${i}// ${r}: ${rp(s)}`,`${i}// \u26A0 DRAFT: AI-resolved at runtime (~5-10s). Add a locator to make this <1s.`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.execute(page, ${S}, '${r}', ${T});`]}let l=e.locator?{...u,locator:e.locator}:u;s&&s!==l.action_description&&(l={...l,action_description:s});let c=l.action_data?.action_name||"",d=l.action_description||"",f=sBn(c);if(!f)return[`${i}// ${r}: Unknown action: ${c}`];let p={imports:n.imports},m=f(l,r,p);if(n.noAgent){if(Uvt(l))return[`${i}// ${r}: ${rp(d)}`,`${i}// AI action: ${rp(d)} (requires agent - skipped in hook)`];let S=cOo(l,c,i,r);return S||[`${i}// ${r}: ${rp(d)}`,...m.map(T=>`${i}${T}`)]}if(Uvt(l))return[`${i}// ${r}: ${rp(d)}`,`${i}page = agent.agentServices.validatePage(page);`,...m.map(S=>`${i}${S}`)];let y=JSON.stringify(d),b=m.map(S=>`${i} ${S}`),w=rBn(l),C=o?`'${o}'`:"undefined";return[`${i}// ${r}: ${rp(d)}`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.step(page, async () => {`,...b,`${i}}, ${y}, '${r}', ${C}, ${w});`]}function aOo(e,t,r,n){let i=" ".repeat(t),s=[];e.description&&e.description.trim()&&s.push(`${i}// Step: ${rp(e.description)}`);let o=DC(e.statements,t,n,r);return s.push(...o),s}function uOo(e,t,r,n){let i=" ".repeat(t),s=[];if(s.push(`${i}// ${r}: Conditional check`),e.condition.type==="JS_CODE")s.push(`${i}if (${e.condition.expression}) {`);else{s.push(`${i}// AI Condition: ${rp(e.condition.expression)}`);let a=JSON.stringify(e.condition.expression);s.push(`${i}if (await agent.evaluate(page, ${a}, "${r}")) {`)}let o=DC(e.then,t+1,n,`${r}.then`);if(s.push(...o),e.else&&e.else.length>0){s.push(`${i}} else {`);let a=DC(e.else,t+1,n,`${r}.else`);s.push(...a)}return s.push(`${i}}`),s}function lOo(e,t,r,n){let i=" ".repeat(t),s=[];s.push(`${i}// ${r}: Loop`);let o=e.timeout_ms??FD,a=o/1e3,u=e.timeout_ms?`While loop exceeded timeout of ${a}s`:`While loop exceeded default timeout of ${a}s`,l=`loop_${r.replace(/\./g,"_")}`;if(s.push(`${i}const ${l}_start = Date.now();`),s.push(`${i}const ${l}_timeout = ${o};`),s.push(`${i}const ${l}_check = () => {`),s.push(`${i} if (Date.now() - ${l}_start > ${l}_timeout) {`),s.push(`${i} throw new Error('${u}');`),s.push(`${i} }`),s.push(`${i} return true;`),s.push(`${i}};`),e.condition.type==="JS_CODE")s.push(`${i}while (${l}_check() && (${e.condition.expression})) {`);else{s.push(`${i}// AI Loop Condition: ${rp(e.condition.expression)}`);let d=JSON.stringify(e.condition.expression);s.push(`${i}while (${l}_check() && await agent.evaluate(page, ${d}, "${r}")) {`)}let c=DC(e.body,t+1,n,`${r}.body`);return s.push(...c),s.push(`${i}}`),s}function cOo(e,t,r,n){let i=e.action_description||"",s=e.action_data?.kwargs||{};switch(t){case"go_to_url":case"open_tab":{let o=s.url||"";return[`${r}// ${n}: ${rp(i)}`,`${r}await page.goto(${JSON.stringify(o)}, { waitUntil: 'domcontentloaded' });`]}case"go_back":return[`${r}// ${n}: ${rp(i)}`,`${r}await page.goBack();`];case"go_forward":return[`${r}// ${n}: ${rp(i)}`,`${r}await page.goForward();`];case"input_text":{let o=s.text||"",a=getPageLocatorExpression(e);return a?[`${r}// ${n}: ${rp(i)}`,`${r}await ${a}.fill(${JSON.stringify(o)}, { timeout: ${ACTION_TIMEOUT} });`]:null}case"select_dropdown_option":{let o=s.text||s.label||"",a=getPageLocatorExpression(e);return a?[`${r}// ${n}: ${rp(i)}`,`${r}await ${a}.selectOption({ label: ${JSON.stringify(o)} }, { timeout: ${ACTION_TIMEOUT} });`]:null}default:return null}}var qvt=k(()=>{"use strict";su();oBn();cse()});var uBn,aBn=k(()=>{uBn={name:"shiplightai",version:"0.1.14",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"}},files:["dist","README.md"],publishConfig:{registry:"https://registry.npmjs.org",access:"public"},scripts:{build:"tsup","build:cli":"tsup",clean:"rm -rf dist",dev:"tsup --watch",test:"playwright test",typecheck:"tsc --noEmit"},dependencies:{"@babel/plugin-transform-typescript":"^7.27.0","@babel/preset-env":"^7.26.9","@babel/preset-typescript":"^7.27.0","@anthropic-ai/claude-agent-sdk":"^0.1.72","@modelcontextprotocol/sdk":"^0.5.0",axios:"^1.6.0",dotenv:"^16.0.3",express:"^4.21.0",glob:"^13.0.0",open:"^10.1.0",sharp:"^0.34.5",uuid:"^11.1.0",yaml:"^2.8.0",zod:"^3.22.0","zod-to-json-schema":"^3.24.6"},devDependencies:{"@playwright/test":"1.55.0","@types/express":"^4.17.21","@types/node":"^24.0.0",copilot3:"workspace:*","mcp-tools":"workspace:*","sdk-core":"workspace:*","sdk-internal":"workspace:*","shiplight-types":"workspace:*",tsup:"^8.3.5",typescript:"5.5.4","web-session":"workspace:*"},peerDependencies:{"@playwright/test":">=1.40.0"},engines:{node:">=22.0.0"},keywords:["playwright","yaml","testing","automation","ai","shiplight","mcp"],author:"Shiplight",license:"MIT"}});var Hvt,lBn=k(()=>{"use strict";aBn();Hvt=uBn.version});import{stringify as dBn}from"yaml";function fBn(e,t){let r=[];r.push(`// @generated by shiplightai v${Hvt}`),r.push(...gBn()),r.push(""),t?.use&&Object.keys(t.use).length>0&&(r.push(`test.use(${JSON.stringify(t.use,null,2)});`),r.push(""));let n=new Set,i={imports:n};t?.beforeEach&&t.beforeEach.length>0&&(r.push(...cBn("beforeEach",t.beforeEach,i)),r.push(""));let s=t?.timeout||t?.skip!==void 0||t?.fail!==void 0||t?.only||t?.slow?{timeout:t.timeout,skip:t.skip,fail:t.fail,only:t.only,slow:t.slow}:void 0;if(t?.parameters&&t.parameters.length>0){let o=t?.testName||e.goal||"Generated test",a=jvt(t?.tags);for(let u of t.parameters){let l=mBn(e,u.values);r.push(...QRe(l,`${a}${Wx(o)} [${Wx(u.name)}]`,i,0,s)),r.push("")}}else{let o=t?.testName||e.goal||"Generated test",a=jvt(t?.tags);r.push(...QRe(e,`${a}${Wx(o)}`,i,0,s))}return t?.afterEach&&t.afterEach.length>0&&(r.push(""),r.push(...cBn("afterEach",t.afterEach,i))),ABn(r,n),r.join(`
8318
+ `);for(let i of n)r.push(` ${i}`);return r.push("}"),r});As("function",(e,t,r)=>{let n=e.action_data?.kwargs||{},i=n.functionName;if(i&&i.includes("#")){let[o,a]=i.split("#");if(o&&a){let u=o.replace(/\.(ts|js|mjs)$/,""),l=`import { ${a} } from '${u}';`;r?.imports?.add(l);let c={...n,functionName:a},d=nBn(c);return d?[d.endsWith(";")?d:`${d};`]:["// Skipping function: invalid export pattern"]}}let s=nBn(n);return s?[s.endsWith(";")?s:`${s};`]:["// Skipping function: missing functionName"]});As("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)} } },`,"});"]});As("upload_file",e=>{let t=e.action_data?.kwargs||{},r=[],n={};return t.paths?n.paths=t.paths:t.path&&(n.path=t.path),t.use_file_input&&(n.use_file_input=!0),r.push(`action_data: { kwargs: ${JSON.stringify(n)} }`),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},`),"});"]});As("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} } },`,"});"]);As("switch_tab",e=>['await agent.execAction("switch_tab", page, {',` action_data: { kwargs: { page_id: ${e.action_data?.kwargs?.page_id??0} } },`,"});"]);As("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} } },`,"});"]});As("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(n=>` ${n},`),"});"]});As("done",()=>["// Done - no action needed"])});function DC(e,t,r,n="main"){let i=[];for(let s=0;s<e.length;s++){let o=e[s],a=`${n}.${s}`,u=iOo(o,t,a,r);u.length>0&&(i.push(...u),s<e.length-1&&i.push(""))}return i}function iOo(e,t,r,n){let i=" ".repeat(t);switch(e.type){case"DRAFT":return sOo(e,t,r,n);case"ACTION":return oOo(e,t,r,n);case"STEP":return aOo(e,t,r,n);case"IF_ELSE":return uOo(e,t,r,n);case"WHILE_LOOP":return lOo(e,t,r,n);default:return[`${i}// Unknown statement type: ${e.type}`]}}function sOo(e,t,r,n){let i=" ".repeat(t),s=e.description?.trim()||"";if(!s)return[`${i}// ${r}: Skipping - no description`];if(n.noAgent)return[`${i}// ${r}: ${rp(s)}`,`${i}// DRAFT: ${rp(s)} (requires agent - skipped in hook)`];let o=JSON.stringify(s);return[`${i}// ${r}: ${rp(s)}`,`${i}// \u26A0 DRAFT: AI-resolved at runtime (~5-10s). Add a locator to make this <1s.`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.run(page, ${o}, '${r}');`]}function oOo(e,t,r,n){let i=" ".repeat(t),s=e.description,o=e.uid,u=n.actionEntityStore?.entries[e.uid]?.action_entity??e.action_entity;if(!u){if(!s)return[`${i}// ${r}: Skipping - no description`];if(n.noAgent)return[`${i}// ${r}: ${rp(s)}`,`${i}// DRAFT: ${rp(s)} (requires agent - skipped in hook)`];let S=JSON.stringify(s),T=!!e.use_pure_vision;return[`${i}// ${r}: ${rp(s)}`,`${i}// \u26A0 DRAFT: AI-resolved at runtime (~5-10s). Add a locator to make this <1s.`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.execute(page, ${S}, '${r}', ${T});`]}let l=e.locator?{...u,locator:e.locator}:u;s&&s!==l.action_description&&(l={...l,action_description:s});let c=l.action_data?.action_name||"",d=l.action_description||"",f=sBn(c);if(!f)return[`${i}// ${r}: Unknown action: ${c}`];let p={imports:n.imports},m=f(l,r,p);if(n.noAgent){if(Uvt(l))return[`${i}// ${r}: ${rp(d)}`,`${i}// AI action: ${rp(d)} (requires agent - skipped in hook)`];let S=cOo(l,c,i,r);return S||[`${i}// ${r}: ${rp(d)}`,...m.map(T=>`${i}${T}`)]}if(Uvt(l))return[`${i}// ${r}: ${rp(d)}`,`${i}page = agent.agentServices.validatePage(page);`,...m.map(S=>`${i}${S}`)];let y=JSON.stringify(d),b=m.map(S=>`${i} ${S}`),w=rBn(l),C=o?`'${o}'`:"undefined";return[`${i}// ${r}: ${rp(d)}`,`${i}page = agent.agentServices.validatePage(page);`,`${i}await agent.step(page, async () => {`,...b,`${i}}, ${y}, '${r}', ${C}, ${w});`]}function aOo(e,t,r,n){let i=" ".repeat(t),s=[];e.description&&e.description.trim()&&s.push(`${i}// Step: ${rp(e.description)}`);let o=DC(e.statements,t,n,r);return s.push(...o),s}function uOo(e,t,r,n){let i=" ".repeat(t),s=[];if(s.push(`${i}// ${r}: Conditional check`),e.condition.type==="JS_CODE")s.push(`${i}if (${e.condition.expression}) {`);else{s.push(`${i}// AI Condition: ${rp(e.condition.expression)}`);let a=JSON.stringify(e.condition.expression);s.push(`${i}if (await agent.evaluate(page, ${a}, "${r}")) {`)}let o=DC(e.then,t+1,n,`${r}.then`);if(s.push(...o),e.else&&e.else.length>0){s.push(`${i}} else {`);let a=DC(e.else,t+1,n,`${r}.else`);s.push(...a)}return s.push(`${i}}`),s}function lOo(e,t,r,n){let i=" ".repeat(t),s=[];s.push(`${i}// ${r}: Loop`);let o=e.timeout_ms??FD,a=o/1e3,u=e.timeout_ms?`While loop exceeded timeout of ${a}s`:`While loop exceeded default timeout of ${a}s`,l=`loop_${r.replace(/\./g,"_")}`;if(s.push(`${i}const ${l}_start = Date.now();`),s.push(`${i}const ${l}_timeout = ${o};`),s.push(`${i}const ${l}_check = () => {`),s.push(`${i} if (Date.now() - ${l}_start > ${l}_timeout) {`),s.push(`${i} throw new Error('${u}');`),s.push(`${i} }`),s.push(`${i} return true;`),s.push(`${i}};`),e.condition.type==="JS_CODE")s.push(`${i}while (${l}_check() && (${e.condition.expression})) {`);else{s.push(`${i}// AI Loop Condition: ${rp(e.condition.expression)}`);let d=JSON.stringify(e.condition.expression);s.push(`${i}while (${l}_check() && await agent.evaluate(page, ${d}, "${r}")) {`)}let c=DC(e.body,t+1,n,`${r}.body`);return s.push(...c),s.push(`${i}}`),s}function cOo(e,t,r,n){let i=e.action_description||"",s=e.action_data?.kwargs||{};switch(t){case"go_to_url":case"open_tab":{let o=s.url||"";return[`${r}// ${n}: ${rp(i)}`,`${r}await page.goto(${JSON.stringify(o)}, { waitUntil: 'domcontentloaded' });`]}case"go_back":return[`${r}// ${n}: ${rp(i)}`,`${r}await page.goBack();`];case"go_forward":return[`${r}// ${n}: ${rp(i)}`,`${r}await page.goForward();`];case"input_text":{let o=s.text||"",a=getPageLocatorExpression(e);return a?[`${r}// ${n}: ${rp(i)}`,`${r}await ${a}.fill(${JSON.stringify(o)}, { timeout: ${ACTION_TIMEOUT} });`]:null}case"select_dropdown_option":{let o=s.text||s.label||"",a=getPageLocatorExpression(e);return a?[`${r}// ${n}: ${rp(i)}`,`${r}await ${a}.selectOption({ label: ${JSON.stringify(o)} }, { timeout: ${ACTION_TIMEOUT} });`]:null}default:return null}}var qvt=k(()=>{"use strict";su();oBn();cse()});var uBn,aBn=k(()=>{uBn={name:"shiplightai",version:"0.1.15",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"}},files:["dist","README.md"],publishConfig:{registry:"https://registry.npmjs.org",access:"public"},scripts:{build:"tsup","build:cli":"tsup",clean:"rm -rf dist",dev:"tsup --watch",test:"playwright test",typecheck:"tsc --noEmit"},dependencies:{"@babel/plugin-transform-typescript":"^7.27.0","@babel/preset-env":"^7.26.9","@babel/preset-typescript":"^7.27.0","@anthropic-ai/claude-agent-sdk":"^0.1.72","@modelcontextprotocol/sdk":"^0.5.0",axios:"^1.6.0",dotenv:"^16.0.3",express:"^4.21.0",glob:"^13.0.0",open:"^10.1.0",sharp:"^0.34.5",uuid:"^11.1.0",yaml:"^2.8.0",zod:"^3.22.0","zod-to-json-schema":"^3.24.6"},devDependencies:{"@playwright/test":"1.55.0","@types/express":"^4.17.21","@types/node":"^24.0.0",copilot3:"workspace:*","mcp-tools":"workspace:*","sdk-core":"workspace:*","sdk-internal":"workspace:*","shiplight-types":"workspace:*",tsup:"^8.3.5",typescript:"5.5.4","web-session":"workspace:*"},peerDependencies:{"@playwright/test":">=1.40.0"},engines:{node:">=22.0.0"},keywords:["playwright","yaml","testing","automation","ai","shiplight","mcp"],author:"Shiplight",license:"MIT"}});var Hvt,lBn=k(()=>{"use strict";aBn();Hvt=uBn.version});import{stringify as dBn}from"yaml";function fBn(e,t){let r=[];r.push(`// @generated by shiplightai v${Hvt}`),r.push(...gBn()),r.push(""),t?.use&&Object.keys(t.use).length>0&&(r.push(`test.use(${JSON.stringify(t.use,null,2)});`),r.push(""));let n=new Set,i={imports:n};t?.beforeEach&&t.beforeEach.length>0&&(r.push(...cBn("beforeEach",t.beforeEach,i)),r.push(""));let s=t?.timeout||t?.skip!==void 0||t?.fail!==void 0||t?.only||t?.slow?{timeout:t.timeout,skip:t.skip,fail:t.fail,only:t.only,slow:t.slow}:void 0;if(t?.parameters&&t.parameters.length>0){let o=t?.testName||e.goal||"Generated test",a=jvt(t?.tags);for(let u of t.parameters){let l=mBn(e,u.values);r.push(...QRe(l,`${a}${Wx(o)} [${Wx(u.name)}]`,i,0,s)),r.push("")}}else{let o=t?.testName||e.goal||"Generated test",a=jvt(t?.tags);r.push(...QRe(e,`${a}${Wx(o)}`,i,0,s))}return t?.afterEach&&t.afterEach.length>0&&(r.push(""),r.push(...cBn("afterEach",t.afterEach,i))),ABn(r,n),r.join(`
8319
8319
  `)}function pBn(e,t){let r=[];r.push(`// @generated by shiplightai v${Hvt}`),r.push(...gBn()),r.push(""),t?.use&&Object.keys(t.use).length>0&&(r.push(`test.use(${JSON.stringify(t.use,null,2)});`),r.push(""));let n=new Set,i={imports:n},s=t?.testName||"Test Suite",o=jvt(t?.tags),a=e.serial?"test.describe.serial":"test.describe";r.push(`${a}('${o}${Wx(s)}', () => {`),e.beforeAll&&e.beforeAll.length>0&&(r.push(...LRe("beforeAll",e.beforeAll,i,1)),r.push("")),e.beforeEach&&e.beforeEach.length>0&&(r.push(...LRe("beforeEach",e.beforeEach,i,1)),r.push(""));for(let u=0;u<e.tests.length;u++){let l=e.tests[u],c=l.timeout||l.skip!==void 0||l.fail!==void 0||l.only||l.slow?{timeout:l.timeout,skip:l.skip,fail:l.fail,only:l.only,slow:l.slow}:void 0;if(l.parameters&&l.parameters.length>0)for(let d of l.parameters){let f=mBn(l.testFlow,d.values);r.push(...QRe(f,`${Wx(l.name)} [${Wx(d.name)}]`,i,1,c)),r.push("")}else r.push(...QRe(l.testFlow,Wx(l.name),i,1,c)),(u<e.tests.length-1||e.afterEach||e.afterAll)&&r.push("")}return e.afterEach&&e.afterEach.length>0&&(r.push(...LRe("afterEach",e.afterEach,i,1)),r.push("")),e.afterAll&&e.afterAll.length>0&&r.push(...LRe("afterAll",e.afterAll,i,1)),r.push("});"),ABn(r,n),r.join(`
8320
8320
  `)}function jvt(e){return e&&e.length>0?e.map(t=>`@${t}`).join(" ")+" ":""}function QRe(e,t,r,n=0,i){let s=" ".repeat(n),o=[],a=i?.only?"test.only":"test";o.push(`${s}${a}('${t}', async ({ page, agent }) => {`),i?.skip===!0?o.push(`${s} test.skip();`):typeof i?.skip=="string"&&o.push(`${s} test.skip(true, '${Wx(i.skip)}');`),i?.fail===!0?o.push(`${s} test.fail();`):typeof i?.fail=="string"&&o.push(`${s} test.fail(true, '${Wx(i.fail)}');`),i?.slow&&o.push(`${s} test.slow();`),i?.timeout&&o.push(`${s} test.setTimeout(${i.timeout});`);let u=e.teardown&&e.teardown.length>0,l=n+1;if(u){if(o.push(`${s} try {`),e.statements&&e.statements.length>0){o.push(`${s} // Test steps`);let d=DC(e.statements,l+1,r);o.push(...d)}o.push(`${s} } finally {`),o.push(`${s} // Teardown`);let c=DC(e.teardown,l+1,r,"teardown");o.push(...c),o.push(`${s} }`)}else if(e.statements&&e.statements.length>0){o.push(`${s} // Test steps`);let c=DC(e.statements,l,r);o.push(...c)}return o.push(`${s}});`),o}function cBn(e,t,r){let n=[],i=hBn(t);return n.push(`test.${e}(async ({ page, agent }) => {`),n.push(...DC(i,1,r,e)),n.push("});"),n}function LRe(e,t,r,n){let i=" ".repeat(n),s=[],o=hBn(t);if(e==="beforeAll"||e==="afterAll"){let u={...r,noAgent:!0};s.push(`${i}test.${e}(async ({ browser }, workerInfo) => {`),s.push(`${i} const page = await browser.newPage({ baseURL: workerInfo.project.use.baseURL });`),s.push(...DC(o,n+1,u,e)),s.push(`${i} await page.close();`),s.push(`${i}});`)}else s.push(`${i}test.${e}(async ({ page, agent }) => {`),s.push(...DC(o,n+1,r,e)),s.push(`${i}});`);return s}function hBn(e){let r=dBn({goal:"_hook",statements:e});return og(r).statements}function mBn(e,t){let r=dBn({goal:e.goal,statements:e.statements,teardown:e.teardown});for(let[n,i]of Object.entries(t))r=r.replaceAll(`<<${n}>>`,String(i));return og(r)}function gBn(){return["import { test, expect } from 'shiplightai/fixture';"]}function ABn(e,t){if(t.size>0){let r=0;for(let i=0;i<e.length;i++)e[i].startsWith("import ")&&(r=i+1);let n=Array.from(t);e.splice(r,0,...n)}}var yBn=k(()=>{"use strict";su();qvt();cse();lBn();cse();qvt()});var EBn={};bs(EBn,{runTranspile:()=>pOo});import*as URe from"fs";import*as dse from"path";import{glob as fOo}from"glob";async function pOo(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 locator 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(),n=await fOo(t,{cwd:r,ignore:["node_modules/**","*.yaml.spec.ts"]});n.length===0&&(console.log(`No files matched: ${t}`),process.exit(0));let i=0,s=0,o=0;for(let a of n.sort()){let u=dse.resolve(r,a),l=u.replace(/\.test\.yaml$/,".yaml.spec.ts"),c=URe.readFileSync(u,"utf-8"),d=gV(c);if(!d.valid){i++,console.log(`
8321
8321
  \u2717 ${a}`);for(let f of d.errors)console.log(` ERROR: ${f}`);continue}d.warnings.length>0&&s++;try{let f=ZTn(c,u),p;if(f.suite?p=pBn(f.suite,{testName:f.name,tags:f.tags,use:f.use}):p=fBn(f.testFlow,{testName:f.name,tags:f.tags,use:f.use,beforeEach:f.beforeEach,afterEach:f.afterEach,parameters:f.parameters,timeout:f.timeout,skip:f.skip,fail:f.fail,only:f.only,slow:f.slow}),URe.writeFileSync(l,p),o++,d.warnings.length>0){console.log(`\u26A0 ${a} \u2192 ${dse.basename(l)}`);for(let m of d.warnings)console.log(` WARNING: ${m}`)}else console.log(`\u2713 ${a} \u2192 ${dse.basename(l)}`)}catch(f){i++,console.log(`
8322
8322
  \u2717 ${a}`),console.log(` ERROR: ${f.message}`)}}console.log(`
8323
- ${n.length} file(s): ${o} transpiled, ${i} error(s), ${s} warning(s)`),process.exit(i>0?1:0)}var bBn=k(()=>{"use strict";su();tBn();yBn()});var wBn=D((RVu,hOo)=>{hOo.exports={name:"shiplightai",version:"0.1.14",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"}},files:["dist","README.md"],publishConfig:{registry:"https://registry.npmjs.org",access:"public"},scripts:{build:"tsup","build:cli":"tsup",clean:"rm -rf dist",dev:"tsup --watch",test:"playwright test",typecheck:"tsc --noEmit"},dependencies:{"@babel/plugin-transform-typescript":"^7.27.0","@babel/preset-env":"^7.26.9","@babel/preset-typescript":"^7.27.0","@anthropic-ai/claude-agent-sdk":"^0.1.72","@modelcontextprotocol/sdk":"^0.5.0",axios:"^1.6.0",dotenv:"^16.0.3",express:"^4.21.0",glob:"^13.0.0",open:"^10.1.0",sharp:"^0.34.5",uuid:"^11.1.0",yaml:"^2.8.0",zod:"^3.22.0","zod-to-json-schema":"^3.24.6"},devDependencies:{"@playwright/test":"1.55.0","@types/express":"^4.17.21","@types/node":"^24.0.0",copilot3:"workspace:*","mcp-tools":"workspace:*","sdk-core":"workspace:*","sdk-internal":"workspace:*","shiplight-types":"workspace:*",tsup:"^8.3.5",typescript:"5.5.4","web-session":"workspace:*"},peerDependencies:{"@playwright/test":">=1.40.0"},engines:{node:">=22.0.0"},keywords:["playwright","yaml","testing","automation","ai","shiplight","mcp"],author:"Shiplight",license:"MIT"}});import mOo from"dotenv";mOo.config();function CBn(){console.log(`
8323
+ ${n.length} file(s): ${o} transpiled, ${i} error(s), ${s} warning(s)`),process.exit(i>0?1:0)}var bBn=k(()=>{"use strict";su();tBn();yBn()});var wBn=D((RVu,hOo)=>{hOo.exports={name:"shiplightai",version:"0.1.15",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"}},files:["dist","README.md"],publishConfig:{registry:"https://registry.npmjs.org",access:"public"},scripts:{build:"tsup","build:cli":"tsup",clean:"rm -rf dist",dev:"tsup --watch",test:"playwright test",typecheck:"tsc --noEmit"},dependencies:{"@babel/plugin-transform-typescript":"^7.27.0","@babel/preset-env":"^7.26.9","@babel/preset-typescript":"^7.27.0","@anthropic-ai/claude-agent-sdk":"^0.1.72","@modelcontextprotocol/sdk":"^0.5.0",axios:"^1.6.0",dotenv:"^16.0.3",express:"^4.21.0",glob:"^13.0.0",open:"^10.1.0",sharp:"^0.34.5",uuid:"^11.1.0",yaml:"^2.8.0",zod:"^3.22.0","zod-to-json-schema":"^3.24.6"},devDependencies:{"@playwright/test":"1.55.0","@types/express":"^4.17.21","@types/node":"^24.0.0",copilot3:"workspace:*","mcp-tools":"workspace:*","sdk-core":"workspace:*","sdk-internal":"workspace:*","shiplight-types":"workspace:*",tsup:"^8.3.5",typescript:"5.5.4","web-session":"workspace:*"},peerDependencies:{"@playwright/test":">=1.40.0"},engines:{node:">=22.0.0"},keywords:["playwright","yaml","testing","automation","ai","shiplight","mcp"],author:"Shiplight",license:"MIT"}});import mOo from"dotenv";mOo.config();function CBn(){console.log(`
8324
8324
  Usage: shiplight <command> [options]
8325
8325
 
8326
8326
  Commands:
package/dist/index.js CHANGED
@@ -2,16 +2,16 @@ import { createRequire as __createRequire } from "module";
2
2
  const require = __createRequire(import.meta.url);
3
3
  import{r as ye,s as we}from"./chunk-NDYQF4WM.js";import"./chunk-JY6U4L7Q.js";import"./chunk-ESJGKHJ4.js";import"./chunk-VXL4KP4U.js";import"./chunk-YU3XZJIJ.js";import"./chunk-QU5HYOUM.js";import{l as $e}from"./chunk-4JBGAENP.js";import"./chunk-FL4TL6US.js";import"./chunk-BVOD5VWH.js";import{b as _e}from"./chunk-FBJSHHRD.js";import{Ka as G,ga as N}from"./chunk-SUZXLRAA.js";import"./chunk-CSINHOOD.js";import*as x from"fs";import*as S from"path";import Qe from"dotenv";import{globSync as Ze}from"glob";import{readFileSync as le,writeFileSync as De,statSync as Ge,existsSync as We}from"fs";import{resolve as Ye}from"path";import{globSync as Ve}from"glob";import{parse as Ee,stringify as K}from"yaml";import{readFileSync as Se}from"fs";import{resolve as V,dirname as be}from"path";import{parse as W,stringify as Ae}from"yaml";var Y=5;function J(e,t){let n={expandingPaths:new Set([V(t)]),depth:0,referencedPaths:new Set},s={...e};Array.isArray(s.statements)&&(s.statements=k(s.statements,t,n)),Array.isArray(s.teardown)&&(s.teardown=k(s.teardown,t,n));for(let r of["beforeAll","afterAll","beforeEach","afterEach"])Array.isArray(s[r])&&(s[r]=k(s[r],t,n));return{doc:s,referencedTemplatePaths:Array.from(n.referencedPaths)}}function k(e,t,n){let s=[];for(let r of e)if(xe(r)){let a=ke(r,t,n);s.push(...a)}else s.push(Te(r,t,n));return s}function xe(e){return typeof e=="object"&&e!==null&&typeof e.template=="string"}function ke(e,t,n){if(n.depth>=Y)throw new Error(`Template expansion exceeded maximum depth of ${Y}. Check for deeply nested or circular template references.`);let s=V(be(t),e.template);if(n.expandingPaths.has(s))throw new Error(`Circular template reference detected: ${s} is already being expanded. Stack: ${Array.from(n.expandingPaths).join(" \u2192 ")} \u2192 ${s}`);n.referencedPaths.add(s);let r;try{r=Se(s,"utf-8")}catch(u){throw new Error(`Failed to read template file: ${s} (referenced from ${t}): ${u.message}`)}let a=W(r);if(!a||typeof a!="object")throw new Error(`Invalid template file: ${s} \u2014 expected a YAML object`);let i=a.params||[],o=e.params||{};for(let u of i)if(!(u in o))throw new Error(`Template ${e.template} requires param "${u}" but it was not provided. Required params: [${i.join(", ")}]`);let l=a.statements;if(!Array.isArray(l))throw new Error(`Template ${e.template} must have a "statements" array`);if(Object.keys(o).length>0){let f=Ae(l);for(let[h,g]of Object.entries(o))f=f.replaceAll(`<<${h}>>`,String(g));l=W(f)}let c={expandingPaths:new Set([...n.expandingPaths,s]),depth:n.depth+1,referencedPaths:n.referencedPaths};return k(l,s,c)}function Te(e,t,n){if(typeof e!="object"||e===null)return e;let s={...e};return Array.isArray(s.statements)&&(s.statements=k(s.statements,t,n)),Array.isArray(s.THEN)&&(s.THEN=k(s.THEN,t,n)),Array.isArray(s.ELSE)&&(s.ELSE=k(s.ELSE,t,n)),Array.isArray(s.DO)&&(s.DO=k(s.DO,t,n)),s}function q(e,t){let n=Ee(e),s=n?.name,r=n?.tags,a=n?.use;if(n&&(n.name!==void 0||n.tags!==void 0||n.use!==void 0)&&(delete n.name,delete n.tags,delete n.use),n?.suite){if(n.goal||n.statements)throw new Error('YAML file cannot have both "suite" and top-level "goal"/"statements". Use either suite format or single-test format.');return ve(n,s,r,a,t)}return Oe(n,s,r,a,t)}function Oe(e,t,n,s,r){let a=e?.beforeEach,i=e?.afterEach,o=B(e?.parameters),l=e?.timeout,c=e?.skip,u=e?.fail,f=e?.only,h=e?.slow;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&&!e.goal&&t&&(e.goal=t);let g=[];if(r&&e&&typeof e=="object"){let b=J(e,r);e=b.doc,g=b.referencedTemplatePaths}let _=K(e);return{testFlow:N(_),name:t,tags:n,use:s,beforeEach:a,afterEach:i,parameters:o,timeout:l,skip:c,fail:u,only:f,slow:h,referencedTemplatePaths:g}}function ve(e,t,n,s,r){let a=e.suite;if(!Array.isArray(a.tests)||a.tests.length===0)throw new Error('Suite must have a non-empty "tests" array.');let i=a.serial,o=a.beforeAll,l=a.afterAll,c=a.beforeEach,u=a.afterEach,f=[],h=a.tests.map(g=>{if(!g.name)throw new Error('Each test in a suite must have a "name" field.');if(!Array.isArray(g.statements)||g.statements.length===0)throw new Error(`Suite test "${g.name}" must have a non-empty "statements" array.`);let _={goal:g.name,statements:g.statements};g.teardown&&(_.teardown=g.teardown);let T=[],b=_;if(r&&typeof _=="object"){let A=J(_,r);b=A.doc,T=A.referencedTemplatePaths,f.push(...T)}let P=K(b),L=N(P),y=B(g.parameters);return{testFlow:L,name:g.name,parameters:y,timeout:g.timeout,skip:g.skip,fail:g.fail,only:g.only,slow:g.slow}});return{suite:{serial:i,beforeAll:o,afterAll:l,beforeEach:c,afterEach:u,tests:h},name:t,tags:n,use:s,referencedTemplatePaths:f}}function B(e){if(!(!Array.isArray(e)||e.length===0))return e.map((t,n)=>{if(!t.name)throw new Error(`Parameter set at index ${n} 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}})}import{stringify as ne}from"yaml";function w(e){return e.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}function d(e){return e.replace(/\r\n/g," ").replace(/\n/g," ").replace(/\r/g," ").trim()}function Pe(e){let t=e.frame_path;return!t||t.length===0?"page":`page.frameLocator('${t[0]}')`}function Ne(e){let t=e.xpath;return typeof t=="string"&&t.trim()?!t.startsWith("xpath=")&&!t.startsWith("/")&&!t.startsWith("//")?`xpath=//${t}`:t.startsWith("xpath=")?t:`xpath=${t}`:null}function H(e){let t=Pe(e),n=e.locator;if(typeof n=="string"&&n.trim())return n=n.trim(),n.endsWith("first()")?`${t}.${n}`:`${t}.${n}.first()`;let s=Ne(e);if(s){let r=JSON.stringify(s);return`${t}.locator(${r}).first()`}return null}var Le=["ai_action","ai_step","ai_assert","ai_extract","ai_wait_until","verify","assert"],Ce=["js_code","function","wait","wait_for_download_complete","wait_for_page_ready","extract_email_content","extract_activation_code"];function M(e){let t=e.action_data?.action_name;return!t||(t==="verify"||t==="ai_assert"||t==="assert")&&e.action_data?.kwargs?.code?!1:Le.includes(t)}function z(e){let t=e.action_data?.action_name;return!t||(t==="verify"||t==="ai_assert"||t==="assert")&&e.action_data?.kwargs?.code?!1:!Ce.includes(t)}var m=new Map;function p(e,t){m.set(e,t)}function Z(e){return m.get(e)}function E(e,t,n=[]){let s=[...n];return t.locator?s.push(`locator: ${JSON.stringify(t.locator)}`):t.xpath&&s.push(`xpath: ${JSON.stringify(t.xpath)}`),t.frame_path&&t.frame_path.length>0&&s.push(`frame_path: ${JSON.stringify(t.frame_path)}`),s.length===0?[`await agent.execAction("${e}", page, {});`]:[`await agent.execAction("${e}", page, {`,...s.map(r=>` ${r},`),"});"]}p("click",e=>{let t=H(e);return t?[`await ${t}.click({ timeout: ${5e3} });`]:['await agent.execAction("click", page, {});']});p("click_element",m.get("click"));p("click_element_by_index",m.get("click"));p("double_click",e=>E("double_click",e));p("double_click_on_element",m.get("double_click"));p("right_click",e=>E("right_click",e));p("right_click_on_element",m.get("right_click"));p("hover",e=>E("hover",e));p("hover_element_by_index",m.get("hover"));p("input_text",e=>{let t=e.action_data?.kwargs?.text??e.action_data?.kwargs?.value??"";return E("input_text",e,[`action_data: { kwargs: { text: ${JSON.stringify(t)} } }`])});p("fill",m.get("input_text"));p("clear_input",e=>E("clear_input",e));p("press",e=>{let t=e.action_data?.kwargs?.keys;return[`await page.keyboard.press(${JSON.stringify(t)});`]});p("send_keys",m.get("press"));p("send_keys_on_element",e=>{let t=H(e),n=e.action_data?.kwargs?.keys||"";return t?[`await ${t}.press(${JSON.stringify(n)}, { timeout: ${5e3} });`]:['await agent.execAction("send_keys_on_element", page, {',` action_data: { kwargs: { keys: ${JSON.stringify(n)} } },`,"});"]});p("select_dropdown_option",e=>{let t=e.action_data?.kwargs?.text||e.action_data?.kwargs?.option||"";return E("select_dropdown_option",e,[`action_data: { kwargs: { text: ${JSON.stringify(t)} } }`])});p("scroll",e=>{let t=e.action_data?.kwargs?.down??!0;return[`await page.evaluate('window.scrollBy(0, window.innerHeight * ${(e.action_data?.kwargs?.num_pages??1)*(t?1:-1)})');`]});p("scroll_down",m.get("scroll"));p("scroll_up",m.get("scroll"));p("scroll_element",m.get("scroll"));p("scroll_to_text",e=>{let t=e.action_data?.kwargs?.text||"";return[`await page.getByText(${JSON.stringify(t)}, { exact: false }).first().scrollIntoViewIfNeeded();`]});p("scroll_on_element",e=>E("scroll_on_element",e,[`action_data: { kwargs: ${JSON.stringify(e.action_data?.kwargs||{})} }`]));p("go_to_url",e=>{let t=e.action_data?.kwargs?.url||"";return e.action_data?.kwargs?.new_tab===!0?['await agent.execAction("go_to_url", page, {',` action_data: { kwargs: { url: ${JSON.stringify(t)}, new_tab: true } },`,"});"]:['await agent.execAction("go_to_url", page, {',` action_data: { kwargs: { url: ${JSON.stringify(t)} } },`,"});"]});p("open_tab",m.get("go_to_url"));p("go_back",()=>['await agent.execAction("go_back", page, {});']);p("reload_page",()=>['await agent.execAction("reload_page", page, {});']);p("wait",e=>[`await page.waitForTimeout(${(e.action_data?.kwargs?.seconds||1)*1e3});`]);p("wait_for_page_ready",()=>["await page.waitForLoadState('domcontentloaded');"]);p("verify",(e,t)=>{let n=e.action_data?.kwargs;if(n?.code)return n.code.split(`
4
4
  `);let s=n?.statement||e.action_description;return s?[`await agent.assert(page, ${JSON.stringify(s)}, '${t||""}');`]:["// Skipping verify: missing statement or code"]});p("ai_assert",m.get("verify"));p("assert",m.get("verify"));p("ai_action",(e,t)=>{let n=e.action_data?.kwargs?.statement;if(!n)return["// Skipping ai_action: missing statement"];let s=JSON.stringify(n),r=e.action_data?.kwargs?.use_pure_vision;return[`await agent.execute(page, ${s}, '${t||""}', ${r});`]});p("ai_step",(e,t)=>{let n=e.action_data?.kwargs?.statement;return n?[`await agent.run(page, ${JSON.stringify(n)}, '${t||""}');`]:["// Skipping ai_step: missing statement"]});p("ai_extract",(e,t)=>{let n=e.action_data?.kwargs?.element_description,s=e.action_data?.kwargs?.variable_name;if(!n||!s)return["// Skipping ai_extract: missing element_description or variable_name"];let r=JSON.stringify(n),a=JSON.stringify(s);return[`await agent.extract(page, ${r}, ${a}, '${t||""}');`]});p("ai_wait_until",(e,t)=>{let n=e.action_data?.kwargs?.condition,s=e.action_data?.kwargs?.timeout_seconds||60;return n?[`await agent.waitUntilCondition(page, ${JSON.stringify(n)}, ${s}, '${t||""}');`]:["// Skipping ai_wait_until: missing condition"]});p("save_variable",e=>{let t=e.action_data?.kwargs?.name||"",n=e.action_data?.kwargs?.value;return['await agent.execAction("save_variable", page, {',` action_data: { kwargs: { name: ${JSON.stringify(t)}, value: ${JSON.stringify(n)} } },`,"});"]});p("js_code",e=>{let t=e.action_data?.kwargs?.code;if(!t)return["// Skipping js_code: missing code"];let n=["{"],s=t.split(`
5
- `);for(let r of s)n.push(` ${r}`);return n.push("}"),n});p("function",(e,t,n)=>{let s=e.action_data?.kwargs||{},r=s.functionName;if(r&&r.includes("#")){let[i,o]=r.split("#");if(i&&o){let l=i.replace(/\.(ts|js|mjs)$/,""),c=`import { ${o} } from '${l}';`;n?.imports?.add(c);let u={...s,functionName:o},f=X(u);return f?[f.endsWith(";")?f:`${f};`]:["// Skipping function: invalid export pattern"]}}let a=X(s);return a?[a.endsWith(";")?a:`${a};`]:["// Skipping function: missing functionName"]});p("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)} } },`,"});"]});p("upload_file",e=>{let t=e.action_data?.kwargs||{},n=[],s={};return t.paths?s.paths=t.paths:t.path&&(s.path=t.path),t.use_file_input&&(s.use_file_input=!0),n.push(`action_data: { kwargs: ${JSON.stringify(s)} }`),e.locator?n.push(`locator: ${JSON.stringify(e.locator)}`):e.xpath&&n.push(`xpath: ${JSON.stringify(e.xpath)}`),e.frame_path&&e.frame_path.length>0&&n.push(`frame_path: ${JSON.stringify(e.frame_path)}`),['await agent.execAction("upload_file", page, {',...n.map(r=>` ${r},`),"});"]});p("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} } },`,"});"]);p("switch_tab",e=>['await agent.execAction("switch_tab", page, {',` action_data: { kwargs: { page_id: ${e.action_data?.kwargs?.page_id??0} } },`,"});"]);p("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} } },`,"});"]});p("set_date_for_native_date_picker",e=>{let t=e.action_data?.kwargs?.date??"",n=[];return n.push(`action_data: { kwargs: { date: ${JSON.stringify(t)} } }`),e.locator?n.push(`locator: ${JSON.stringify(e.locator)}`):e.xpath&&n.push(`xpath: ${JSON.stringify(e.xpath)}`),e.frame_path&&e.frame_path.length>0&&n.push(`frame_path: ${JSON.stringify(e.frame_path)}`),['await agent.execAction("set_date_for_native_date_picker", page, {',...n.map(s=>` ${s},`),"});"]});p("done",()=>["// Done - no action needed"]);function X(e){let t=e.functionName;if(!t)return null;let n={},s=e.parameterNames||[],r=e.parameterValues||e.args||[];if(s.forEach((l,c)=>{c<r.length&&(n[l]=r[c])}),Object.keys(n).length===0)return`await ${t}()`;let a=["page","testContext","request","agentServices"],i=["undefined","null","true","false"],o=Object.entries(n).map(([l,c])=>{let u=String(c);return c==null?"undefined":a.includes(l)&&a.includes(u)||i.includes(u)||/^-?\d+(\.\d+)?$/.test(u)?u:u.startsWith("$")?`agent.agentServices.readVariable('${u.substring(1)}')`:`"${u}"`});return`await ${t}(${o.join(", ")})`}function $(e,t,n,s="main"){let r=[];for(let a=0;a<e.length;a++){let i=e[a],o=`${s}.${a}`,l=Ie(i,t,o,n);l.length>0&&(r.push(...l),a<e.length-1&&r.push(""))}return r}function Ie(e,t,n,s){let r=" ".repeat(t);switch(e.type){case"DRAFT":return je(e,t,n,s);case"ACTION":return Fe(e,t,n,s);case"STEP":return Re(e,t,n,s);case"IF_ELSE":return Je(e,t,n,s);case"WHILE_LOOP":return He(e,t,n,s);default:return[`${r}// Unknown statement type: ${e.type}`]}}function je(e,t,n,s){let r=" ".repeat(t),a=e.description?.trim()||"";if(!a)return[`${r}// ${n}: Skipping - no description`];if(s.noAgent)return[`${r}// ${n}: ${d(a)}`,`${r}// DRAFT: ${d(a)} (requires agent - skipped in hook)`];let i=JSON.stringify(a);return[`${r}// ${n}: ${d(a)}`,`${r}// \u26A0 DRAFT: AI-resolved at runtime (~5-10s). Add a locator to make this <1s.`,`${r}page = agent.agentServices.validatePage(page);`,`${r}await agent.run(page, ${i}, '${n}');`]}function Fe(e,t,n,s){let r=" ".repeat(t),a=e.description,i=e.uid,l=s.actionEntityStore?.entries[e.uid]?.action_entity??e.action_entity;if(!l){if(!a)return[`${r}// ${n}: Skipping - no description`];if(s.noAgent)return[`${r}// ${n}: ${d(a)}`,`${r}// DRAFT: ${d(a)} (requires agent - skipped in hook)`];let y=JSON.stringify(a),A=!!e.use_pure_vision;return[`${r}// ${n}: ${d(a)}`,`${r}// \u26A0 DRAFT: AI-resolved at runtime (~5-10s). Add a locator to make this <1s.`,`${r}page = agent.agentServices.validatePage(page);`,`${r}await agent.execute(page, ${y}, '${n}', ${A});`]}let c=e.locator?{...l,locator:e.locator}:l;a&&a!==c.action_description&&(c={...c,action_description:a});let u=c.action_data?.action_name||"",f=c.action_description||"",h=Z(u);if(!h)return[`${r}// ${n}: Unknown action: ${u}`];let g={imports:s.imports},_=h(c,n,g);if(s.noAgent){if(M(c))return[`${r}// ${n}: ${d(f)}`,`${r}// AI action: ${d(f)} (requires agent - skipped in hook)`];let y=Me(c,u,r,n);return y||[`${r}// ${n}: ${d(f)}`,..._.map(A=>`${r}${A}`)]}if(M(c))return[`${r}// ${n}: ${d(f)}`,`${r}page = agent.agentServices.validatePage(page);`,..._.map(y=>`${r}${y}`)];let T=JSON.stringify(f),b=_.map(y=>`${r} ${y}`),P=z(c),L=i?`'${i}'`:"undefined";return[`${r}// ${n}: ${d(f)}`,`${r}page = agent.agentServices.validatePage(page);`,`${r}await agent.step(page, async () => {`,...b,`${r}}, ${T}, '${n}', ${L}, ${P});`]}function Re(e,t,n,s){let r=" ".repeat(t),a=[];e.description&&e.description.trim()&&a.push(`${r}// Step: ${d(e.description)}`);let i=$(e.statements,t,s,n);return a.push(...i),a}function Je(e,t,n,s){let r=" ".repeat(t),a=[];if(a.push(`${r}// ${n}: Conditional check`),e.condition.type==="JS_CODE")a.push(`${r}if (${e.condition.expression}) {`);else{a.push(`${r}// AI Condition: ${d(e.condition.expression)}`);let o=JSON.stringify(e.condition.expression);a.push(`${r}if (await agent.evaluate(page, ${o}, "${n}")) {`)}let i=$(e.then,t+1,s,`${n}.then`);if(a.push(...i),e.else&&e.else.length>0){a.push(`${r}} else {`);let o=$(e.else,t+1,s,`${n}.else`);a.push(...o)}return a.push(`${r}}`),a}function He(e,t,n,s){let r=" ".repeat(t),a=[];a.push(`${r}// ${n}: Loop`);let i=e.timeout_ms??G,o=i/1e3,l=e.timeout_ms?`While loop exceeded timeout of ${o}s`:`While loop exceeded default timeout of ${o}s`,c=`loop_${n.replace(/\./g,"_")}`;if(a.push(`${r}const ${c}_start = Date.now();`),a.push(`${r}const ${c}_timeout = ${i};`),a.push(`${r}const ${c}_check = () => {`),a.push(`${r} if (Date.now() - ${c}_start > ${c}_timeout) {`),a.push(`${r} throw new Error('${l}');`),a.push(`${r} }`),a.push(`${r} return true;`),a.push(`${r}};`),e.condition.type==="JS_CODE")a.push(`${r}while (${c}_check() && (${e.condition.expression})) {`);else{a.push(`${r}// AI Loop Condition: ${d(e.condition.expression)}`);let f=JSON.stringify(e.condition.expression);a.push(`${r}while (${c}_check() && await agent.evaluate(page, ${f}, "${n}")) {`)}let u=$(e.body,t+1,s,`${n}.body`);return a.push(...u),a.push(`${r}}`),a}function Me(e,t,n,s){let r=e.action_description||"",a=e.action_data?.kwargs||{};switch(t){case"go_to_url":case"open_tab":{let i=a.url||"";return[`${n}// ${s}: ${d(r)}`,`${n}await page.goto(${JSON.stringify(i)}, { waitUntil: 'domcontentloaded' });`]}case"go_back":return[`${n}// ${s}: ${d(r)}`,`${n}await page.goBack();`];case"go_forward":return[`${n}// ${s}: ${d(r)}`,`${n}await page.goForward();`];case"input_text":{let i=a.text||"",o=getPageLocatorExpression(e);return o?[`${n}// ${s}: ${d(r)}`,`${n}await ${o}.fill(${JSON.stringify(i)}, { timeout: ${ACTION_TIMEOUT} });`]:null}case"select_dropdown_option":{let i=a.text||a.label||"",o=getPageLocatorExpression(e);return o?[`${n}// ${s}: ${d(r)}`,`${n}await ${o}.selectOption({ label: ${JSON.stringify(i)} }, { timeout: ${ACTION_TIMEOUT} });`]:null}default:return null}}var ee={name:"shiplightai",version:"0.1.14",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"}},files:["dist","README.md"],publishConfig:{registry:"https://registry.npmjs.org",access:"public"},scripts:{build:"tsup","build:cli":"tsup",clean:"rm -rf dist",dev:"tsup --watch",test:"playwright test",typecheck:"tsc --noEmit"},dependencies:{"@babel/plugin-transform-typescript":"^7.27.0","@babel/preset-env":"^7.26.9","@babel/preset-typescript":"^7.27.0","@anthropic-ai/claude-agent-sdk":"^0.1.72","@modelcontextprotocol/sdk":"^0.5.0",axios:"^1.6.0",dotenv:"^16.0.3",express:"^4.21.0",glob:"^13.0.0",open:"^10.1.0",sharp:"^0.34.5",uuid:"^11.1.0",yaml:"^2.8.0",zod:"^3.22.0","zod-to-json-schema":"^3.24.6"},devDependencies:{"@playwright/test":"1.55.0","@types/express":"^4.17.21","@types/node":"^24.0.0",copilot3:"workspace:*","mcp-tools":"workspace:*","sdk-core":"workspace:*","sdk-internal":"workspace:*","shiplight-types":"workspace:*",tsup:"^8.3.5",typescript:"5.5.4","web-session":"workspace:*"},peerDependencies:{"@playwright/test":">=1.40.0"},engines:{node:">=22.0.0"},keywords:["playwright","yaml","testing","automation","ai","shiplight","mcp"],author:"Shiplight",license:"MIT"};var C=ee.version;function re(e,t){let n=[];n.push(`// @generated by shiplightai v${C}`),n.push(...oe()),n.push(""),t?.use&&Object.keys(t.use).length>0&&(n.push(`test.use(${JSON.stringify(t.use,null,2)});`),n.push(""));let s=new Set,r={imports:s};t?.beforeEach&&t.beforeEach.length>0&&(n.push(...te("beforeEach",t.beforeEach,r)),n.push(""));let a=t?.timeout||t?.skip!==void 0||t?.fail!==void 0||t?.only||t?.slow?{timeout:t.timeout,skip:t.skip,fail:t.fail,only:t.only,slow:t.slow}:void 0;if(t?.parameters&&t.parameters.length>0){let i=t?.testName||e.goal||"Generated test",o=U(t?.tags);for(let l of t.parameters){let c=ie(e,l.values);n.push(...j(c,`${o}${w(i)} [${w(l.name)}]`,r,0,a)),n.push("")}}else{let i=t?.testName||e.goal||"Generated test",o=U(t?.tags);n.push(...j(e,`${o}${w(i)}`,r,0,a))}return t?.afterEach&&t.afterEach.length>0&&(n.push(""),n.push(...te("afterEach",t.afterEach,r))),ce(n,s),n.join(`
5
+ `);for(let r of s)n.push(` ${r}`);return n.push("}"),n});p("function",(e,t,n)=>{let s=e.action_data?.kwargs||{},r=s.functionName;if(r&&r.includes("#")){let[i,o]=r.split("#");if(i&&o){let l=i.replace(/\.(ts|js|mjs)$/,""),c=`import { ${o} } from '${l}';`;n?.imports?.add(c);let u={...s,functionName:o},f=X(u);return f?[f.endsWith(";")?f:`${f};`]:["// Skipping function: invalid export pattern"]}}let a=X(s);return a?[a.endsWith(";")?a:`${a};`]:["// Skipping function: missing functionName"]});p("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)} } },`,"});"]});p("upload_file",e=>{let t=e.action_data?.kwargs||{},n=[],s={};return t.paths?s.paths=t.paths:t.path&&(s.path=t.path),t.use_file_input&&(s.use_file_input=!0),n.push(`action_data: { kwargs: ${JSON.stringify(s)} }`),e.locator?n.push(`locator: ${JSON.stringify(e.locator)}`):e.xpath&&n.push(`xpath: ${JSON.stringify(e.xpath)}`),e.frame_path&&e.frame_path.length>0&&n.push(`frame_path: ${JSON.stringify(e.frame_path)}`),['await agent.execAction("upload_file", page, {',...n.map(r=>` ${r},`),"});"]});p("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} } },`,"});"]);p("switch_tab",e=>['await agent.execAction("switch_tab", page, {',` action_data: { kwargs: { page_id: ${e.action_data?.kwargs?.page_id??0} } },`,"});"]);p("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} } },`,"});"]});p("set_date_for_native_date_picker",e=>{let t=e.action_data?.kwargs?.date??"",n=[];return n.push(`action_data: { kwargs: { date: ${JSON.stringify(t)} } }`),e.locator?n.push(`locator: ${JSON.stringify(e.locator)}`):e.xpath&&n.push(`xpath: ${JSON.stringify(e.xpath)}`),e.frame_path&&e.frame_path.length>0&&n.push(`frame_path: ${JSON.stringify(e.frame_path)}`),['await agent.execAction("set_date_for_native_date_picker", page, {',...n.map(s=>` ${s},`),"});"]});p("done",()=>["// Done - no action needed"]);function X(e){let t=e.functionName;if(!t)return null;let n={},s=e.parameterNames||[],r=e.parameterValues||e.args||[];if(s.forEach((l,c)=>{c<r.length&&(n[l]=r[c])}),Object.keys(n).length===0)return`await ${t}()`;let a=["page","testContext","request","agentServices"],i=["undefined","null","true","false"],o=Object.entries(n).map(([l,c])=>{let u=String(c);return c==null?"undefined":a.includes(l)&&a.includes(u)||i.includes(u)||/^-?\d+(\.\d+)?$/.test(u)?u:u.startsWith("$")?`agent.agentServices.readVariable('${u.substring(1)}')`:`"${u}"`});return`await ${t}(${o.join(", ")})`}function $(e,t,n,s="main"){let r=[];for(let a=0;a<e.length;a++){let i=e[a],o=`${s}.${a}`,l=Ie(i,t,o,n);l.length>0&&(r.push(...l),a<e.length-1&&r.push(""))}return r}function Ie(e,t,n,s){let r=" ".repeat(t);switch(e.type){case"DRAFT":return je(e,t,n,s);case"ACTION":return Fe(e,t,n,s);case"STEP":return Re(e,t,n,s);case"IF_ELSE":return Je(e,t,n,s);case"WHILE_LOOP":return He(e,t,n,s);default:return[`${r}// Unknown statement type: ${e.type}`]}}function je(e,t,n,s){let r=" ".repeat(t),a=e.description?.trim()||"";if(!a)return[`${r}// ${n}: Skipping - no description`];if(s.noAgent)return[`${r}// ${n}: ${d(a)}`,`${r}// DRAFT: ${d(a)} (requires agent - skipped in hook)`];let i=JSON.stringify(a);return[`${r}// ${n}: ${d(a)}`,`${r}// \u26A0 DRAFT: AI-resolved at runtime (~5-10s). Add a locator to make this <1s.`,`${r}page = agent.agentServices.validatePage(page);`,`${r}await agent.run(page, ${i}, '${n}');`]}function Fe(e,t,n,s){let r=" ".repeat(t),a=e.description,i=e.uid,l=s.actionEntityStore?.entries[e.uid]?.action_entity??e.action_entity;if(!l){if(!a)return[`${r}// ${n}: Skipping - no description`];if(s.noAgent)return[`${r}// ${n}: ${d(a)}`,`${r}// DRAFT: ${d(a)} (requires agent - skipped in hook)`];let y=JSON.stringify(a),A=!!e.use_pure_vision;return[`${r}// ${n}: ${d(a)}`,`${r}// \u26A0 DRAFT: AI-resolved at runtime (~5-10s). Add a locator to make this <1s.`,`${r}page = agent.agentServices.validatePage(page);`,`${r}await agent.execute(page, ${y}, '${n}', ${A});`]}let c=e.locator?{...l,locator:e.locator}:l;a&&a!==c.action_description&&(c={...c,action_description:a});let u=c.action_data?.action_name||"",f=c.action_description||"",h=Z(u);if(!h)return[`${r}// ${n}: Unknown action: ${u}`];let g={imports:s.imports},_=h(c,n,g);if(s.noAgent){if(M(c))return[`${r}// ${n}: ${d(f)}`,`${r}// AI action: ${d(f)} (requires agent - skipped in hook)`];let y=Me(c,u,r,n);return y||[`${r}// ${n}: ${d(f)}`,..._.map(A=>`${r}${A}`)]}if(M(c))return[`${r}// ${n}: ${d(f)}`,`${r}page = agent.agentServices.validatePage(page);`,..._.map(y=>`${r}${y}`)];let T=JSON.stringify(f),b=_.map(y=>`${r} ${y}`),P=z(c),L=i?`'${i}'`:"undefined";return[`${r}// ${n}: ${d(f)}`,`${r}page = agent.agentServices.validatePage(page);`,`${r}await agent.step(page, async () => {`,...b,`${r}}, ${T}, '${n}', ${L}, ${P});`]}function Re(e,t,n,s){let r=" ".repeat(t),a=[];e.description&&e.description.trim()&&a.push(`${r}// Step: ${d(e.description)}`);let i=$(e.statements,t,s,n);return a.push(...i),a}function Je(e,t,n,s){let r=" ".repeat(t),a=[];if(a.push(`${r}// ${n}: Conditional check`),e.condition.type==="JS_CODE")a.push(`${r}if (${e.condition.expression}) {`);else{a.push(`${r}// AI Condition: ${d(e.condition.expression)}`);let o=JSON.stringify(e.condition.expression);a.push(`${r}if (await agent.evaluate(page, ${o}, "${n}")) {`)}let i=$(e.then,t+1,s,`${n}.then`);if(a.push(...i),e.else&&e.else.length>0){a.push(`${r}} else {`);let o=$(e.else,t+1,s,`${n}.else`);a.push(...o)}return a.push(`${r}}`),a}function He(e,t,n,s){let r=" ".repeat(t),a=[];a.push(`${r}// ${n}: Loop`);let i=e.timeout_ms??G,o=i/1e3,l=e.timeout_ms?`While loop exceeded timeout of ${o}s`:`While loop exceeded default timeout of ${o}s`,c=`loop_${n.replace(/\./g,"_")}`;if(a.push(`${r}const ${c}_start = Date.now();`),a.push(`${r}const ${c}_timeout = ${i};`),a.push(`${r}const ${c}_check = () => {`),a.push(`${r} if (Date.now() - ${c}_start > ${c}_timeout) {`),a.push(`${r} throw new Error('${l}');`),a.push(`${r} }`),a.push(`${r} return true;`),a.push(`${r}};`),e.condition.type==="JS_CODE")a.push(`${r}while (${c}_check() && (${e.condition.expression})) {`);else{a.push(`${r}// AI Loop Condition: ${d(e.condition.expression)}`);let f=JSON.stringify(e.condition.expression);a.push(`${r}while (${c}_check() && await agent.evaluate(page, ${f}, "${n}")) {`)}let u=$(e.body,t+1,s,`${n}.body`);return a.push(...u),a.push(`${r}}`),a}function Me(e,t,n,s){let r=e.action_description||"",a=e.action_data?.kwargs||{};switch(t){case"go_to_url":case"open_tab":{let i=a.url||"";return[`${n}// ${s}: ${d(r)}`,`${n}await page.goto(${JSON.stringify(i)}, { waitUntil: 'domcontentloaded' });`]}case"go_back":return[`${n}// ${s}: ${d(r)}`,`${n}await page.goBack();`];case"go_forward":return[`${n}// ${s}: ${d(r)}`,`${n}await page.goForward();`];case"input_text":{let i=a.text||"",o=getPageLocatorExpression(e);return o?[`${n}// ${s}: ${d(r)}`,`${n}await ${o}.fill(${JSON.stringify(i)}, { timeout: ${ACTION_TIMEOUT} });`]:null}case"select_dropdown_option":{let i=a.text||a.label||"",o=getPageLocatorExpression(e);return o?[`${n}// ${s}: ${d(r)}`,`${n}await ${o}.selectOption({ label: ${JSON.stringify(i)} }, { timeout: ${ACTION_TIMEOUT} });`]:null}default:return null}}var ee={name:"shiplightai",version:"0.1.15",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"}},files:["dist","README.md"],publishConfig:{registry:"https://registry.npmjs.org",access:"public"},scripts:{build:"tsup","build:cli":"tsup",clean:"rm -rf dist",dev:"tsup --watch",test:"playwright test",typecheck:"tsc --noEmit"},dependencies:{"@babel/plugin-transform-typescript":"^7.27.0","@babel/preset-env":"^7.26.9","@babel/preset-typescript":"^7.27.0","@anthropic-ai/claude-agent-sdk":"^0.1.72","@modelcontextprotocol/sdk":"^0.5.0",axios:"^1.6.0",dotenv:"^16.0.3",express:"^4.21.0",glob:"^13.0.0",open:"^10.1.0",sharp:"^0.34.5",uuid:"^11.1.0",yaml:"^2.8.0",zod:"^3.22.0","zod-to-json-schema":"^3.24.6"},devDependencies:{"@playwright/test":"1.55.0","@types/express":"^4.17.21","@types/node":"^24.0.0",copilot3:"workspace:*","mcp-tools":"workspace:*","sdk-core":"workspace:*","sdk-internal":"workspace:*","shiplight-types":"workspace:*",tsup:"^8.3.5",typescript:"5.5.4","web-session":"workspace:*"},peerDependencies:{"@playwright/test":">=1.40.0"},engines:{node:">=22.0.0"},keywords:["playwright","yaml","testing","automation","ai","shiplight","mcp"],author:"Shiplight",license:"MIT"};var C=ee.version;function re(e,t){let n=[];n.push(`// @generated by shiplightai v${C}`),n.push(...oe()),n.push(""),t?.use&&Object.keys(t.use).length>0&&(n.push(`test.use(${JSON.stringify(t.use,null,2)});`),n.push(""));let s=new Set,r={imports:s};t?.beforeEach&&t.beforeEach.length>0&&(n.push(...te("beforeEach",t.beforeEach,r)),n.push(""));let a=t?.timeout||t?.skip!==void 0||t?.fail!==void 0||t?.only||t?.slow?{timeout:t.timeout,skip:t.skip,fail:t.fail,only:t.only,slow:t.slow}:void 0;if(t?.parameters&&t.parameters.length>0){let i=t?.testName||e.goal||"Generated test",o=U(t?.tags);for(let l of t.parameters){let c=ie(e,l.values);n.push(...j(c,`${o}${w(i)} [${w(l.name)}]`,r,0,a)),n.push("")}}else{let i=t?.testName||e.goal||"Generated test",o=U(t?.tags);n.push(...j(e,`${o}${w(i)}`,r,0,a))}return t?.afterEach&&t.afterEach.length>0&&(n.push(""),n.push(...te("afterEach",t.afterEach,r))),ce(n,s),n.join(`
6
6
  `)}function se(e,t){let n=[];n.push(`// @generated by shiplightai v${C}`),n.push(...oe()),n.push(""),t?.use&&Object.keys(t.use).length>0&&(n.push(`test.use(${JSON.stringify(t.use,null,2)});`),n.push(""));let s=new Set,r={imports:s},a=t?.testName||"Test Suite",i=U(t?.tags),o=e.serial?"test.describe.serial":"test.describe";n.push(`${o}('${i}${w(a)}', () => {`),e.beforeAll&&e.beforeAll.length>0&&(n.push(...I("beforeAll",e.beforeAll,r,1)),n.push("")),e.beforeEach&&e.beforeEach.length>0&&(n.push(...I("beforeEach",e.beforeEach,r,1)),n.push(""));for(let l=0;l<e.tests.length;l++){let c=e.tests[l],u=c.timeout||c.skip!==void 0||c.fail!==void 0||c.only||c.slow?{timeout:c.timeout,skip:c.skip,fail:c.fail,only:c.only,slow:c.slow}:void 0;if(c.parameters&&c.parameters.length>0)for(let f of c.parameters){let h=ie(c.testFlow,f.values);n.push(...j(h,`${w(c.name)} [${w(f.name)}]`,r,1,u)),n.push("")}else n.push(...j(c.testFlow,w(c.name),r,1,u)),(l<e.tests.length-1||e.afterEach||e.afterAll)&&n.push("")}return e.afterEach&&e.afterEach.length>0&&(n.push(...I("afterEach",e.afterEach,r,1)),n.push("")),e.afterAll&&e.afterAll.length>0&&n.push(...I("afterAll",e.afterAll,r,1)),n.push("});"),ce(n,s),n.join(`
7
7
  `)}function U(e){return e&&e.length>0?e.map(t=>`@${t}`).join(" ")+" ":""}function j(e,t,n,s=0,r){let a=" ".repeat(s),i=[],o=r?.only?"test.only":"test";i.push(`${a}${o}('${t}', async ({ page, agent }) => {`),r?.skip===!0?i.push(`${a} test.skip();`):typeof r?.skip=="string"&&i.push(`${a} test.skip(true, '${w(r.skip)}');`),r?.fail===!0?i.push(`${a} test.fail();`):typeof r?.fail=="string"&&i.push(`${a} test.fail(true, '${w(r.fail)}');`),r?.slow&&i.push(`${a} test.slow();`),r?.timeout&&i.push(`${a} test.setTimeout(${r.timeout});`);let l=e.teardown&&e.teardown.length>0,c=s+1;if(l){if(i.push(`${a} try {`),e.statements&&e.statements.length>0){i.push(`${a} // Test steps`);let f=$(e.statements,c+1,n);i.push(...f)}i.push(`${a} } finally {`),i.push(`${a} // Teardown`);let u=$(e.teardown,c+1,n,"teardown");i.push(...u),i.push(`${a} }`)}else if(e.statements&&e.statements.length>0){i.push(`${a} // Test steps`);let u=$(e.statements,c,n);i.push(...u)}return i.push(`${a}});`),i}function te(e,t,n){let s=[],r=ae(t);return s.push(`test.${e}(async ({ page, agent }) => {`),s.push(...$(r,1,n,e)),s.push("});"),s}function I(e,t,n,s){let r=" ".repeat(s),a=[],i=ae(t);if(e==="beforeAll"||e==="afterAll"){let l={...n,noAgent:!0};a.push(`${r}test.${e}(async ({ browser }, workerInfo) => {`),a.push(`${r} const page = await browser.newPage({ baseURL: workerInfo.project.use.baseURL });`),a.push(...$(i,s+1,l,e)),a.push(`${r} await page.close();`),a.push(`${r}});`)}else a.push(`${r}test.${e}(async ({ page, agent }) => {`),a.push(...$(i,s+1,n,e)),a.push(`${r}});`);return a}function ae(e){let n=ne({goal:"_hook",statements:e});return N(n).statements}function ie(e,t){let n=ne({goal:e.goal,statements:e.statements,teardown:e.teardown});for(let[s,r]of Object.entries(t))n=n.replaceAll(`<<${s}>>`,String(r));return N(n)}function oe(){return["import { test, expect } from 'shiplightai/fixture';"]}function ce(e,t){if(t.size>0){let n=0;for(let r=0;r<e.length;r++)e[r].startsWith("import ")&&(n=r+1);let s=Array.from(t);e.splice(n,0,...s)}}function pe(e){try{return Ge(e).mtimeMs}catch{return 0}}var Ke=`// @generated by shiplightai v${C}`;function qe(e,t){if(!We(e)||le(e,"utf-8").split(`
8
8
  `,1)[0]!==Ke)return!1;let s=pe(e);for(let r of t)if(pe(r)>s)return!1;return!0}function ue(e){let t=Ve("**/*.test.yaml",{cwd:e.cwd,ignore:["**/node_modules/**"]}),n=[];for(let s of t){let r=Ye(e.cwd,s),a=r.replace(/\.test\.yaml$/,".yaml.spec.ts"),i=le(r,"utf-8");try{let o=q(i,r);if(qe(a,[r,...o.referencedTemplatePaths]))continue;let l;o.suite?l=se(o.suite,{testName:o.name,tags:o.tags,use:o.use}):l=re(o.testFlow,{testName:o.name,tags:o.tags,use:o.use,beforeEach:o.beforeEach,afterEach:o.afterEach,parameters:o.parameters,timeout:o.timeout,skip:o.skip,fail:o.fail,only:o.only,slow:o.slow}),De(a,l)}catch(o){console.error(`[shiplight] Failed to transpile ${s}:`,o),n.push({file:s,error:o})}}if(n.length>0)throw new Error(`[shiplight] Transpilation failed for ${n.length} file(s):
9
9
  `+n.map(s=>` - ${s.file}`).join(`
10
10
  `))}import*as v from"path";import*as de from"fs";import{mkdir as ze}from"fs/promises";import*as R from"fs";import*as O from"path";function D(e){let t=null,n=process.env.SHIPLIGHT_LOGIN_EMAIL,s=process.env.SHIPLIGHT_LOGIN_PASSWORD;return n&&s&&(t={username:n,password:s}),t||(t=Be(e)),t?(process.env.SHIPLIGHT_LOGIN_URL&&(t.loginUrl=process.env.SHIPLIGHT_LOGIN_URL),process.env.SHIPLIGHT_LOGIN_TOTP_SECRET&&(t.totpSecret=process.env.SHIPLIGHT_LOGIN_TOTP_SECRET),t):null}function F(e){if(e.startsWith("$")){let t=e.slice(1);return process.env[t]||e}return e}function Be(e){let t=O.resolve(e),n=O.resolve(process.cwd());for(;;){for(let r of["shiplight.config.json","login.config.json"]){let a=O.join(t,r);if(R.existsSync(a))try{let i=JSON.parse(R.readFileSync(a,"utf-8"));if(i.username&&i.password)return{username:F(i.username),password:F(i.password),loginUrl:i.url?F(i.url):void 0,totpSecret:i.totp_secret?F(i.totp_secret):void 0}}catch{}}if(t===n)break;let s=O.dirname(t);if(s===t)break;t=s}return null}var me="auth.setup.ts",fe=".auth",ge="storage-state.json";async function Xe(e,t){let n=v.resolve(t),s=v.join(n,fe,ge);if(de.existsSync(s)){console.log("[INFO] Storage state exists, skipping login. Delete",s,"to force re-auth.");return}let r=D(n);if(!r)return;let{WebAgent:a,createAgentContext:i,configureSdk:o,VariableStore:l,LoginType:c,TwoFactorAuthType:u}=await import("./dist-OOFTSMK3.js");o({env:{GOOGLE_API_KEY:process.env.GOOGLE_API_KEY??"",ANTHROPIC_API_KEY:process.env.ANTHROPIC_API_KEY??""}});let{resolveModelFromEnv:f}=await import("./dist-WQ66EMT6.js"),h=f(process.env);if(!h)throw new Error("No AI model configured. Set WEB_AGENT_MODEL, ANTHROPIC_API_KEY, or GOOGLE_API_KEY.");let g=new a(i({model:h,variableStore:new l})),{username:_,password:T,loginUrl:b,totpSecret:P}=r,L=b||e.url()||"about:blank";if(!(await g.loginPage(e,{site_url:L,num_verification_exprs:0,account:{type:c.PASSWORD,username:_,password:T,...P&&{two_factor_auth_config:{type:u.TOTP,data:P}}}})).success)throw new Error("Login failed.");let A=v.join(n,fe);await ze(A,{recursive:!0}),await e.context().storageState({path:v.join(A,ge)})}function he(){return`// @generated by shiplightai \u2014 do not edit
11
11
  import { test as setup } from '@playwright/test';
12
- import { authSetup } from 'shiplightai';
13
12
 
14
13
  setup('authenticate', async ({ page }) => {
15
- await authSetup(page, import.meta.dirname);
14
+ const { authSetup } = await import('shiplightai');
15
+ await authSetup(page, __dirname);
16
16
  });
17
17
  `}function et(e={}){e.dotenv!==!1&&tt(e.scanDir||process.cwd());let t=e.scanDir||process.cwd();return ue({cwd:t}),nt(t),e.apiKey&&(process.env.__SHIPLIGHT_API_KEY=e.apiKey),{}}function tt(e){let t=[],n=S.resolve(e),s=S.resolve(process.cwd());for(;;){let r=S.join(n,".env");if(x.existsSync(r)&&t.push(r),n===s)break;let a=S.dirname(n);if(a===n)break;n=a}for(let r of t)Qe.config({path:r})}function nt(e){let t=Ze("**/shiplight.config.json",{cwd:e,ignore:["**/node_modules/**"]});for(let n of t){let s=S.resolve(e,n),r=S.dirname(s),a=S.join(r,me),i=!1;try{let o=JSON.parse(x.readFileSync(s,"utf-8"));i=!!(o.username&&o.password)}catch{}if(!i&&process.env.SHIPLIGHT_LOGIN_EMAIL&&process.env.SHIPLIGHT_LOGIN_PASSWORD&&(i=!0),!!i){try{let o=x.statSync(s).mtimeMs;if(x.statSync(a).mtimeMs>o)continue}catch{}x.writeFileSync(a,he())}}}export{$e as VariableStore,ye as WebAgent,Xe as authSetup,_e as configureSdk,we as createAgentContext,D as resolveLoginConfig,et as shiplightConfig};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shiplightai",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "type": "module",
5
5
  "description": "Shiplight CLI for running and debugging .test.yaml files",
6
6
  "main": "dist/index.js",