@playword/core
Version:
Supercharge your web test automation experience with AI
410 lines (367 loc) • 54.4 kB
JavaScript
var At=Object.defineProperty;var Zt=Object.getOwnPropertyDescriptor;var Qt=(e,t)=>{for(var a in t)At(e,a,{get:t[a],enumerable:!0})};var Et=(e,t,a,n)=>{for(var o=n>1?void 0:n?Zt(t,a):t,r=e.length-1,c;r>=0;r--)(c=e[r])&&(o=(n?c(t,a,o):c(o))||o);return n&&o&&At(t,a,o),o};import{HumanMessage as pe}from"@langchain/core/messages";import{setTimeout as G}from"timers/promises";var k={};Qt(k,{assertElementContains:()=>X,assertElementContentEquals:()=>Q,assertElementContentNotEqual:()=>tt,assertElementNotContain:()=>Z,assertElementNotVisible:()=>at,assertElementVisible:()=>et,assertPageContains:()=>nt,assertPageNotContain:()=>ot,assertPageTitleEquals:()=>st,assertPageUrlMatches:()=>rt,click:()=>it,getText:()=>ct,goto:()=>lt,hover:()=>dt,input:()=>pt,pressKeys:()=>mt,scroll:()=>ut,select:()=>ht,sleep:()=>gt,switchFrame:()=>_,switchPage:()=>ft,waitForText:()=>yt});var Pt=`
.plwd-panel {
background: rgba(0, 0, 0, .7);
height: 100%;
opacity: 0;
transition: all .3s;
visibility: hidden;
width: 100%;
}
.plwd-banner {
color: #ffffff !important;
font-size: 32px !important;
font-weight: bold;
left: 4vw;
position: absolute;
top: 6vh;
}
.plwd-input {
background: transparent;
border: none;
border-bottom: 1px solid #ffffff;
color: #ffffff !important;
font-size: 20px !important;
font-weight: bold;
letter-spacing: 2px;
padding: 12px;
width: 90%;
}
.plwd-input[disabled] {
cursor: not-allowed;
opacity: 0.5;
}
.plwd-input-box {
margin: 10% auto 0 auto;
width: 90%;
}
.plwd-timeline {
max-height: 55vh;
overflow-x: hidden;
overflow-y: auto;
padding: 0;
position: relative;
width: 100%;
}
.plwd-preview {
margin: auto;
width: 80%;
text-align: left;
}
.plwd-preview-title {
color: #ffffff !important;
display: inline-block;
float: left;
font-size: 32px !important;
font-weight: bold;
height: 40px;
line-height: 40px;
margin: 0;
visibility: hidden;
}
.plwd-panel {
display: block;
left: 0;
position: fixed;
text-align: center;
top: 50%;
transform: translateY(-50%);
z-index: 2147483647;
}
.plwd-toast {
background: #333333;
border-radius: 25px;
bottom: 30px;
font-size: 24px !important;
font-weight: bold;
height: 50px;
left: 0;
line-height: 50px;
margin: auto;
position: fixed;
right: 0;
text-align: center;
visibility: hidden;
width: 50px;
z-index: 2147483647;
}
.plwd-toast-icon {
float: left;
width: 50px;
}
.plwd-toast-content {
overflow: hidden;
white-space: nowrap;
}
.plwd-toast.open {
animation: fade-in 0.5s, expand 0.5s 0.5s, stay 0.5s 1s, fade-out 0.5s 1.5s;
visibility: visible;
}
.plwd-input:focus {
outline: none;
}
.plwd-input::placeholder {
color: #ffffff !important;
font-size: 20px !important;
opacity: 0.4;
padding: 12px;
}
.plwd-loader-box {
display: inline-block;
height: 20px;
width: 20px;
}
.plwd-accept-btn {
border-radius: 25px;
color: #4db6ac !important;
font-size: 20px !important;
height: 45px;
line-height: 45px;
margin: 8px;
width: 150px;
}
.plwd-cancel-btn {
border-radius: 25px;
color: #e0e0e0 !important;
font-size: 20px !important;
height: 45px;
line-height: 45px;
margin: 8px;
width: 150px;
}
.plwd-dry-run-btn {
border-radius: 25px;
color: #e5c07b !important;
float: right;
font-size: 20px !important;
height: 40px;
line-height: 40px;
width: 100px;
visibility: hidden;
}
.plwd-clear-btn {
border-radius: 25px;
color: #e0e0e0 !important;
float: right;
font-size: 20px !important;
height: 40px;
line-height: 40px;
width: 100px;
visibility: hidden;
}
.plwd-delete-btn {
border-radius: 25px;
color: #ff6c6c !important;
height: 40px;
line-height: 40px;
margin: 0 8px;
width: 80px;
}
.plwd-accept-btn, .plwd-cancel-btn, .plwd-dry-run-btn, .plwd-clear-btn, .plwd-delete-btn {
background: transparent;
border: none;
box-sizing: border-box;
cursor: pointer;
font-weight: bold;
outline: none;
overflow: hidden;
position: relative;
text-align: center;
vertical-align: middle;
}
.plwd-accept-btn::before,
.plwd-cancel-btn::before,
.plwd-dry-run-btn::before,
.plwd-clear-btn::before,
.plwd-delete-btn::before {
background: currentColor;
bottom: 0;
content: '';
left: 0;
opacity: 0;
position: absolute;
right: 0;
top: 0;
transition: opacity .3s;
}
.plwd-accept-btn::after,
.plwd-cancel-btn::after,
.plwd-dry-run-btn::after,
.plwd-clear-btn::after,
.plwd-delete-btn::after {
background: currentColor;
border-radius: 25px;
content: '';
height: 6vh;
left: 50%;
opacity: 0;
padding: 50%;
position: absolute;
transform: translate(-50%, -50%) scale(1);
transition: opacity 1s, transform .5s;
}
.plwd-accept-btn:hover::before,
.plwd-cancel-btn:hover::before,
.plwd-dry-run-btn:hover::before,
.plwd-clear-btn:hover::before,
.plwd-delete-btn:hover::before {
opacity: .1;
}
.plwd-accept-btn:active::after,
.plwd-cancel-btn:active::after,
.plwd-dry-run-btn:active::after,
.plwd-clear-btn:active::after,
.plwd-delete-btn:active::after {
opacity: .2;
transform: translate(-50%, -50%) scale(0);
transition: transform 0s;
}
.plwd-panel.open, .plwd-preview-title.open, .plwd-dry-run-btn.open, .plwd-clear-btn.open {
opacity: 1;
visibility: visible;
}
.plwd-loader {
animation: loading .75s infinite linear;
border-bottom: 4px solid rgba(255, 255, 255, .5);
border-left: 4px solid rgba(255, 255, 255, .5);
border-right: 4px solid rgba(255, 255, 255, .5);
border-top: 4px solid rgba(255, 255, 255, 1);
border-radius: 100%;
height: inherit;
width: inherit;
}
.plwd-marker {
font-size: 16px !important;
font-weight: bold;
padding: 0 16px;
}
.plwd-timeline-item {
animation: draw-border 1s;
color: #ffffff !important;
content-visibility: auto;
border-color: #26a69a;
border-style: solid;
border-width: 2px;
border-right-width: 0px;
border-top-width: 0px;
font-size: 24px !important;
height: 100px;
line-height: 100px;
list-style-type: none;
overflow-x: auto;
overflow-y: hidden;
padding: 0 16px;
position: relative;
text-align: left;
white-space: nowrap;
width: 100%;
}
.plwd-timeline-item:last-child {
border-bottom: none;
}
.plwd-delete-btn::before {
background: currentColor;
bottom: 0;
content: '';
left: 0;
opacity: 0;
position: absolute;
right: 0;
top: 0;
transition: opacity .3s;
}
.plwd-trash-icon {
fill: #ff6c6c;
height: 40px;
width: 40%;
}
.plwd-trash-lid {
transform-origin: right bottom;
transition: transform .2s cubic-bezier(0.4, 0.0, 0.2, 1);
}
.plwd-delete-btn:hover .plwd-trash-lid {
transform: translateY(-1px) rotate(10deg);
}
@keyframes expand {
from {
min-width: 50px;
}
to {
min-width: 250px;
}
}
@keyframes fade-in {
from {
bottom: 0;
opacity: 0;
}
to {
bottom: 30px;
opacity: 1;
}
}
@keyframes stay {
from {
min-width: 250px;
}
to {
min-width: 250px;
}
}
@keyframes fade-out {
from {
bottom: 30px;
min-width: 250px;
opacity: 1;
}
to {
bottom: 45px;
min-width: 250px;
opacity: 0;
}
}
@keyframes draw-border {
0% {
max-height: 0;
width: 0;
}
30% {
max-height: 100px;
width: 0;
}
100% {
max-height: 100px;
width: 100%;
}
}
@keyframes loading {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
`;var q=(e,t)=>{e.classList.add(t)},St=async()=>{let e=await caches.keys();await Promise.all(e.map(t=>caches.delete(t)))},It=async()=>{(await indexedDB.databases()).filter(t=>t.name).map(t=>indexedDB.deleteDatabase(t.name))},Lt=()=>{localStorage.clear(),sessionStorage.clear()},Nt=async()=>{let e=await navigator.serviceWorker.getRegistrations();await Promise.all(e.map(t=>t.unregister()))},C=e=>{let t=document.querySelectorAll("*:not(head):not(script):not(style)"),a=[],n=r=>{let c=[];for(;r&&r.nodeType==1;r=r.parentNode){let s=1;for(let i=r.previousSibling;i;i=i.previousSibling)i.nodeType===1&&i.nodeName===r.nodeName&&s++;c.unshift(`${r.nodeName.toLowerCase()}[${s}]`)}return"//"+c.join("/")},o=r=>e.includes(r.nodeName.toLowerCase())?r?.checkVisibility?.({checkOpacity:!0,checkVisibilityCSS:!0,contentVisibilityAuto:!0})??!0:!1;for(let r of t){if(!o(r))continue;let c=r.cloneNode(!0);c.textContent=[...c.childNodes].filter(s=>s.nodeType===3).map(s=>s.nodeValue).join("").trim(),!(c.outerHTML.length>1e3)&&a.push({html:c.outerHTML,xpath:n(r)})}return a},Ot=(e,t)=>e.classList.contains(t),W=(e,t)=>{e.classList.remove(t)},K=(e,{name:t,value:a})=>{t==="value"&&e instanceof HTMLInputElement?e.value=a.toString():a?e.setAttribute(t,a.toString()):e.removeAttribute(t)},kt=()=>{window.__name=s=>s;let e,t=s=>{s.preventDefault(),s.stopImmediatePropagation()},a=s=>{let i=s.cloneNode(!0),d=[...i.childNodes].filter(l=>l.nodeType===3).map(l=>l.nodeValue),m=[...i.attributes].map(l=>`${l.name}="${l.value}"`),p=s.nodeName.toLowerCase();return{frameSrc:o(),html:`<${p} ${m.join(" ")}>${d.join(" ").trim()}</${p}>`,xpath:n(s)}},n=s=>{let i=[];for(;s&&s.nodeType==1;s=s.parentNode){let d=1;for(let m=s.previousSibling;m;m=m.previousSibling)m.nodeType===1&&m.nodeName===s.nodeName&&d++;i.unshift(`${s.nodeName.toLowerCase()}[${d}]`)}return"//"+i.join("/")},o=()=>{if(window.self===window.top)return;let{origin:s,pathname:i,search:d,hash:m}=new URL(document.location.href);return s+decodeURIComponent(i)+d+m},r=async s=>window.emit({name:"click",params:{...a(s)}}),c=async s=>{let i=["color","date","datetime-local","email","text","month","number","password","range","search","tel","time","url","week"];if(s.value)return i.includes(s.type)||s.nodeName==="TEXTAREA"?window.emit({name:"input",params:{...a(s),text:s.value}}):window.emit({name:"click",params:{...a(s)}})};document.addEventListener("change",s=>{clearTimeout(e);let i=s.target;if(i.nodeName==="SELECT")return window.emit({name:"select",params:{...a(i),option:i.value}});if(i.className==="plwd-input")return window.updateInput(i.value)},!0),document.addEventListener("click",s=>{let i=document.elementFromPoint(s.clientX,s.clientY);clearTimeout(e),i.className.startsWith("plwd")&&i.className!=="plwd-input"&&t(s)},!0),document.addEventListener("keydown",s=>{let i=document.querySelector(".plwd-panel:not(.open)"),{activeElement:d}=document;if(clearTimeout(e),s.key==="Escape")return window.stopDryRun();if(!(d?.className==="plwd-input"||i)){if(t(s),["A","a"].includes(s.key))return window.accept();if(["C","c"].includes(s.key))return window.cancel()}},!0),document.addEventListener("mousedown",s=>{let i=document.elementFromPoint(s.clientX,s.clientY);i.className.startsWith("plwd")&&i.className!=="plwd-input"&&t(s)}),document.addEventListener("mouseleave",s=>{clearTimeout(e),document.querySelector(".plwd-panel.open")&&t(s)},!0),document.addEventListener("mouseout",s=>{clearTimeout(e),document.querySelector(".plwd-panel.open")&&t(s)},!0),document.addEventListener("mouseover",s=>{clearTimeout(e),document.elementFromPoint(s.clientX,s.clientY).nodeName!=="IFRAME"&&(document.querySelector(".plwd-panel.open")&&t(s),e=setTimeout(async()=>{let d=document.elementFromPoint(s.clientX,s.clientY);if(!d.className.startsWith("plwd"))return window.emit({name:"hover",params:{...a(d),duration:1e3}})},3e3))}),document.addEventListener("mouseup",s=>{let i=document.activeElement,d=document.elementFromPoint(s.clientX,s.clientY);if(clearTimeout(e),d.className.startsWith("plwd")&&d.className!=="plwd-input"&&t(s),!(["SELECT","OPTION"].includes(d.nodeName)||!i))return["INPUT","TEXTAREA"].includes(i.nodeName)&&!["INPUT","TEXTAREA"].includes(d.nodeName)&&i.blur(),d.classList.contains("plwd-accept-btn")?window.accept():d.classList.contains("plwd-cancel-btn")?window.cancel():d.classList.contains("plwd-clear-btn")?window.clearAll():d.classList.contains("plwd-delete-btn")?window.deleteStep(parseInt(d.getAttribute("data-index"))):d.classList.contains("plwd-dry-run-btn")?window.dryRun():["INPUT","TEXTAREA"].includes(d.nodeName)?c(d):r(d)})},Rt=e=>{window.addEventListener("load",()=>{let t=document.createElement("style");t.textContent=e,document.body.appendChild(t);let a=document.createElement("div");a.classList.add("plwd-banner"),a.innerText="PlayWord";let n=document.createElement("div");n.classList.add("plwd-loader-box");let o=document.createElement("input");o.classList.add("plwd-input"),o.placeholder="Step Description";let r=document.createElement("button");r.classList.add("plwd-accept-btn"),r.innerText="\u2713 Accept (a)",r.setAttribute("title","Add the step to the test case");let c=document.createElement("button");c.classList.add("plwd-cancel-btn"),c.innerText="\u2715 Cancel (c)",c.setAttribute("title","Undo the step");let s=document.createElement("div");s.classList.add("plwd-input-box"),s.appendChild(o),s.appendChild(n),s.appendChild(c),s.appendChild(r);let i=document.createElement("ul");i.classList.add("plwd-timeline");let d=document.createElement("button");d.classList.add("plwd-dry-run-btn"),d.innerText="Dry Run";let m=document.createElement("button");m.classList.add("plwd-clear-btn"),m.innerText="Clear All";let p=document.createElement("p");p.classList.add("plwd-preview-title"),p.innerText="Test Case Preview";let l=document.createElement("div");l.classList.add("plwd-preview"),l.appendChild(p),l.appendChild(d),l.appendChild(m),l.appendChild(i);let x=document.createElement("div");x.classList.add("plwd-toast-icon");let M=document.createElement("div");M.classList.add("plwd-toast-content");let F=document.createElement("div");F.classList.add("plwd-panel"),F.appendChild(a),F.appendChild(s),F.appendChild(l),document.body.appendChild(F);let O=document.createElement("div");O.classList.add("plwd-toast"),O.appendChild(x),O.appendChild(M),document.body.appendChild(O)})},Ft=(e,t)=>{let a=n=>{let o=document.createElementNS("http://www.w3.org/2000/svg","path");o.classList.add("plwd-trash-lid"),o.setAttribute("d","M6 15l4 0 0-3 8 0 0 3 4 0 0 2 -16 0zM12 14l4 0 0 1 -4 0z"),o.setAttribute("fill-rule","evenodd");let r=document.createElementNS("http://www.w3.org/2000/svg","path");r.classList.add("plwd-trash-can"),r.setAttribute("d","M8 17h2v9h8v-9h2v9a2 2 0 0 1-2 2h-8a2 2 0 0 1-2-2z");let c=document.createElementNS("http://www.w3.org/2000/svg","svg");c.classList.add("plwd-trash-icon"),c.setAttribute("viewBox","3 6 24 28"),c.appendChild(o),c.appendChild(r);let s=document.createElement("button");return s.classList.add("plwd-delete-btn"),s.setAttribute("data-index",n.toString()),s.appendChild(c),s};e.replaceChildren();for(let[n,o]of t.entries()){let r=a(n),c=document.createElement("li"),s=document.createElement("span"),i=document.createTextNode(o.input);"success"in o.actions[0]&&(s.innerText=o.actions[0].success?"\u2713":"\u2715",s.style.color=o.actions[0].success?"#26a69a":"#f44336"),s.classList.add("plwd-marker"),c.classList.add("plwd-timeline-item"),c.appendChild(s),c.appendChild(i),c.appendChild(r),e.appendChild(c)}},Dt=e=>{let t=document.querySelector(".plwd-toast-content"),a=document.querySelector(".plwd-toast-icon"),n=document.querySelector(".plwd-toast:not(.open)");t&&a&&n&&(t.innerText=e.content,a.innerText=e.icon,n.style.color=e.color,n.classList.add("open"),setTimeout(()=>n.classList.remove("open"),1900))},Mt=(e,t)=>{if(e.replaceChildren(),!t)return;let a=document.createElement("div");a.classList.add("plwd-loader"),e.appendChild(a)};import te from"sanitize-html";var $=new RegExp(/^\[\b(?:ai)\b\]/i),Ht=new RegExp(/(?<={)[^{}]+(?=})/g),A=["a","button","div","h1","h2","h3","h4","h5","h6","img","input","label","li","option","p","select","span","strong","td","textarea","th","ul"];var E=e=>te(e,{allowedAttributes:{"*":["aria*","class","data*","href","id","name","placeholder","title","type","value"]},allowedStyles:{"*":{"*":[]}},allowedTags:A});var h=(e,t="none",a=!1)=>{if(process.env.PLWD_DEBUG!=="true")return;let n={green:32,magenta:35,red:31};return a&&console.log("\u2014".repeat(process.stdout.columns)),console.log(t==="none"?e:`\x1B[${n[t]}m${e}\x1B[0m`)},b=(e,t="none",a=!1)=>{let n={green:32,magenta:35,red:31};return a&&console.log("\u2014".repeat(process.stdout.columns)),console.log(t==="none"?e:`\x1B[${n[t]}m${e}\x1B[0m`)};import{setTimeout as ee}from"timers/promises";var ae=async(e,t,a=3e4)=>{let n=Date.now(),o=!1;for(;!o&&Date.now()-n<a;)o=!!e.page?.frames().some(r=>r.url()===t),await ee(500);return o},f=async(e,t={})=>{if(t.frameSrc&&await ae(e,t.frameSrc)){let n=e.page?.frames().find(o=>o.url()===t.frameSrc);e.frame=n}let a=e.frame||e.page;return await a.waitForLoadState("domcontentloaded"),a};var L=e=>{let t=e.match(Ht);return t&&process.env[t[0]]||e},X=async(e,t)=>{try{let n=(await f(e,t)).locator(t.xpath).first(),o=L(t.text);return await n.waitFor({state:"visible",timeout:5e3}),!!(await n.textContent())?.includes(o)}catch{return!1}},Z=async(e,t)=>{try{let n=(await f(e,t)).locator(t.xpath).first(),o=L(t.text);return await n.waitFor({state:"visible",timeout:5e3}),!(await n.textContent())?.includes(o)||!1}catch{return!1}},Q=async(e,t)=>{try{let n=(await f(e,t)).locator(t.xpath).first(),o=L(t.text);return await n.waitFor({state:"visible",timeout:5e3}),(await n.textContent())?.trim()===o.trim()}catch{return!1}},tt=async(e,t)=>{try{let n=(await f(e,t)).locator(t.xpath).first(),o=L(t.text);return await n.waitFor({state:"visible",timeout:5e3}),(await n.textContent())?.trim()!==o.trim()}catch{return!1}},et=async(e,t)=>{try{return await(await f(e,t)).locator(t.xpath).first().waitFor({state:"visible",timeout:5e3}),!0}catch{return!1}},at=async(e,t)=>{try{return await(await f(e,t)).locator(t.xpath).first().waitFor({state:"hidden",timeout:5e3}),!0}catch{return!1}},nt=async(e,t)=>{try{let a=await f(e,t),n=L(t.text),o=await a.getByText(n).all();return(await Promise.all(o.map(c=>c.isVisible()))).some(Boolean)}catch{return!1}},ot=async(e,t)=>{try{let a=await f(e,t),n=L(t.text),o=await a.getByText(n).all();return!(await Promise.all(o.map(c=>c.isVisible()))).some(Boolean)}catch{return!1}},st=async(e,t)=>{try{let a=L(t.text);return await e.page?.title()===a}catch{return!1}},rt=async(e,t)=>{try{let a=e.page.url();return new RegExp(t.pattern).test(a)}catch{return!1}},it=async(e,t)=>{try{let n=(await f(e,t)).locator(t.xpath).first();return await n.waitFor({state:"visible",timeout:5e3}),await n.click({timeout:5e3}),"Performed the click action"}catch(a){return b(a.message,"red"),"Failed to perform the action"}},ct=async(e,t)=>{try{let n="data:image/jpeg;base64,"+(await e.page.screenshot({type:"jpeg",quality:100})).toString("base64");return await e.ai.analyzeImage(n,t.input)}catch(a){return b(a.message,"red"),"Failed to perform the action"}},lt=async(e,t)=>{try{return await e.page?.goto(t.url),"Navigated to "+t.url}catch(a){return b(a.message,"red"),"Failed to perform the action"}},dt=async(e,t)=>{try{let n=(await f(e,t)).locator(t.xpath).first();return await n.waitFor({state:"visible",timeout:5e3}),await n.hover({timeout:5e3}),t.duration&&await e.page?.waitForTimeout(t.duration),"Performed the hover action"}catch(a){return b(a.message,"red"),"Failed to perform the action"}},pt=async(e,t)=>{try{let n=(await f(e,t)).locator(t.xpath).first(),o=L(t.text);return await n.waitFor({state:"visible",timeout:5e3}),await n.fill(o,{timeout:5e3}),"Performed the input action"}catch(a){return b(a.message,"red"),"Failed to perform the action"}},mt=async(e,t)=>{try{return await e.page?.keyboard.press(t.keys),"Pressed keys "+t.keys}catch(a){return b(a.message,"red"),"Failed to perform the action"}},ut=async(e,t)=>{try{let a=await f(e,t);switch(t.direction){case"up":return await a.evaluate(()=>window.scrollBy({top:window.innerHeight})),"scrolled up";case"down":return await a.evaluate(()=>window.scrollBy({top:window.innerHeight})),"scrolled down";case"top":return await a.evaluate(()=>window.scrollTo({top:0})),"scrolled to top";case"bottom":return await a.evaluate(()=>window.scrollTo({top:document.body.scrollHeight})),"scrolled to bottom";default:return`Unsupported scroll target ${t.direction}`}}catch(a){return b(a.message,"red"),"Failed to perform the action"}},ht=async(e,t)=>{try{let n=(await f(e,t)).locator(t.xpath).first();return await n.waitFor({state:"visible",timeout:5e3}),await n.selectOption({value:t.option},{timeout:5e3}),"Performed the select action"}catch(a){return b(a.message,"red"),"Failed to perform the action"}},gt=async(e,t)=>{try{return await e.page?.waitForTimeout(t.duration),"Slept for "+t.duration+" milliseconds"}catch(a){return b(a.message,"red"),"Failed to perform the action"}},_=async(e,t)=>{try{return e.frame=void 0,t.frameNumber!==void 0&&(e.frame=e.page?.frames()[t.frameNumber]),"Switched to frame"}catch(a){return b(a.message,"red"),"Failed to perform the action"}},ft=async(e,t)=>{try{return e.page=e.context.pages()[t.pageNumber||0],"Switched to page"}catch(a){return b(a.message,"red"),"Failed to perform the action"}},yt=async(e,t)=>{try{let a=await f(e,t),n=L(t.text);return await a.waitForSelector("text="+n,{state:"visible",timeout:3e4}),"Waited for text: "+n}catch(a){return b(a.message,"red"),"Failed to perform the action"}};import{access as ne,mkdir as oe,readFile as se,writeFile as re}from"fs/promises";import{dirname as ie}from"path";var j=class{constructor(t=""){this.recordPath=t}position=0;recordings=[];check=async t=>{try{return await ne(t),t.endsWith(".json")}catch{return!1}};removeProperty=(t,a)=>{if(!(!t||typeof t!="object")){if(Array.isArray(t))return t.forEach(n=>this.removeProperty(n,a));for(let n of Object.keys(t))n===a?delete t[n]:this.removeProperty(t[n],a)}};addAction(t){this.recordings[this.position].actions.push(t)}clear(){this.recordings=[],this.position=0}count(){return this.recordings.length}delete(t){t<0||t>=this.recordings.length||(this.recordings.splice(t,1),this.position>=t&&this.position--,this.position<0&&(this.position=0))}initStep(t,a){this.position=t,this.recordings[t]={input:a,actions:[]}}list(){return this.recordings}async load(){await this.check(this.recordPath)&&(this.recordings=JSON.parse(await se(this.recordPath,"utf-8")))}async save(t=[]){let a=structuredClone(this.recordings.slice(0,this.position+1));for(let n of t)this.removeProperty(a,n);await oe(ie(this.recordPath),{recursive:!0}),await re(this.recordPath,JSON.stringify(a,null,2))}};import{Document as ce}from"@langchain/core/documents";import{tool as P}from"@langchain/core/tools";import{z as y}from"zod";var wt=[P(async({thoughts:e},{configurable:t})=>{let{ref:a}=t,{ai:n,recorder:o}=a;h("Thoughts: "+e,"magenta");let s=(await(await f(a)).evaluate(C,A)).map(({html:p,xpath:l})=>({html:E(p),xpath:l}));await n.embedTexts(s.map(({html:p})=>p));let i=await n.searchDocuments(e),d=await n.getBestCandidate(e,i),{xpath:m}=s.find(({html:p})=>p===i[d].pageContent);return o?.addAction({name:"click",params:{xpath:m}}),it(a,{xpath:m})},{name:"Click",description:"Call to click on an element",schema:y.object({thoughts:y.string().describe("Thoughts to search for the relevant element from user input")})}),P(async({url:e},{configurable:t})=>{let{ref:a}=t;return h("Thoughts: Go to "+e,"magenta"),a.recorder?.addAction({name:"goto",params:{url:e}}),lt(a,{url:e})},{name:"GoTo",description:"Call to go to a specific URL",schema:y.object({url:y.string().describe("The full URL containing the protocol (e.g., http://example.com)")})}),P(async({duration:e,thoughts:t},{configurable:a})=>{let{ref:n}=a,{ai:o,recorder:r}=n;h("Thoughts: "+t,"magenta");let i=(await(await f(n)).evaluate(C,A)).map(({html:l,xpath:x})=>({html:E(l),xpath:x}));await o.embedTexts(i.map(({html:l})=>l));let d=await o.searchDocuments(t),m=await o.getBestCandidate(t,d),{xpath:p}=i.find(({html:l})=>l===d[m].pageContent);return r?.addAction({name:"hover",params:{duration:e,xpath:p}}),dt(n,{duration:e,xpath:p})},{name:"Hover",description:"Call to hover over an element",schema:y.object({duration:y.number().describe("The duration to hover over the element. Default is 1000ms"),thoughts:y.string().describe("Thoughts to search for the relevant element from user input")})}),P(async({thoughts:e,text:t},{configurable:a})=>{let{ref:n}=a,{ai:o,recorder:r}=n;h("Thoughts: "+e,"magenta");let i=(await(await f(n)).evaluate(C,["input","textarea"])).map(({html:l,xpath:x})=>({html:E(l),xpath:x}));await o.embedTexts(i.map(({html:l})=>l));let d=await o.searchDocuments(e),m=await o.getBestCandidate(e,d),{xpath:p}=i.find(({html:l})=>l===d[m].pageContent);return r?.addAction({name:"input",params:{text:t,xpath:p}}),pt(n,{text:t,xpath:p})},{name:"Input",description:"Call to type text into the input field or textarea",schema:y.object({thoughts:y.string().describe("Thoughts to search for the relevant element from user input"),text:y.string().describe("Text to input")})}),P(async({keys:e},{configurable:t})=>{let{ref:a}=t;return h("Thoughts: Press "+e,"magenta"),a.recorder?.addAction({name:"pressKeys",params:{keys:e}}),mt(a,{keys:e})},{name:"PressKeys",description:"Call to press a key or keys",schema:y.object({keys:y.string().describe("Keys to press. The format should match the Playwright API")})}),P(async({direction:e},{configurable:t})=>{let{ref:a}=t;return h("Thoughts: Scroll to "+e,"magenta"),a.recorder?.addAction({name:"scroll",params:{direction:e}}),ut(a,{direction:e})},{name:"Scroll",description:"Call to scroll the page",schema:y.object({direction:y.enum(["top","bottom","up","down"]).describe("The direction to scroll")})}),P(async({option:e,thoughts:t},{configurable:a})=>{let{ref:n}=a,{ai:o,recorder:r}=n;h("Thoughts: "+t,"magenta");let i=(await(await f(n)).evaluate(C,["select"])).map(({html:l,xpath:x})=>({html:E(l),xpath:x}));await o.embedTexts(i.map(({html:l})=>l));let d=await o.searchDocuments(t),m=await o.getBestCandidate(t,d),{xpath:p}=i.find(({html:l})=>l===d[m].pageContent);return r?.addAction({name:"select",params:{option:e,xpath:p}}),ht(n,{option:e,xpath:p})},{name:"Select",description:"Call to select an option from a select element",schema:y.object({option:y.string().describe("The option to select"),thoughts:y.string().describe("Thoughts to search for the relevant element from user input")})}),P(async({duration:e},{configurable:t})=>{let{ref:a}=t;return h("Thoughts: Sleep for"+e+"ms","magenta"),a.recorder?.addAction({name:"sleep",params:{duration:e}}),gt(a,{duration:e})},{name:"Sleep",description:"Call to wait for a certain amount of time",schema:y.object({duration:y.number().describe("The duration to wait in milliseconds")})}),P(async({enterFrame:e,thoughts:t},{configurable:a})=>{let{ref:n}=a,{ai:o,page:r,recorder:c}=n,s=r?.frames().map(i=>JSON.stringify({name:i.name(),url:i.url()}));if(e&&s?.length){h("Thoughts: Enter the frame","magenta");let i=s.map(m=>new ce({pageContent:m})),d=await o.getBestCandidate(t,i);return c?.addAction({name:"switchFrame",params:{frameNumber:d}}),_(n,{frameNumber:d})}return h("Thoughts: Leave the frame","magenta"),c?.addAction({name:"switchFrame",params:{}}),_(n,{})},{name:"SwitchFrame",description:"Call to switch, enter or return to a frame",schema:y.object({enterFrame:y.boolean().describe("Return true to enter the frame, false to return to the main page"),thoughts:y.string().describe("Thoughts to search for the relevant frame from user input")})}),P(async({pageNumber:e},{configurable:t})=>{let{ref:a}=t;return h("Thoughts: Switch to page "+e,"magenta"),ft(a,{pageNumber:e})},{name:"SwitchPage",description:"Call to switch to a different page or tab",schema:y.object({pageNumber:y.number().describe("The index of the page to switch to. Starts from 0")})}),P(async({text:e},{configurable:t})=>{let{ref:a}=t;return h('Thoughts: Wait for "'+e+'"',"magenta"),a.recorder?.addAction({name:"waitForText",params:{text:e}}),yt(a,{text:e})},{name:"WaitForText",description:"Call to wait for text to appear on the page",schema:y.object({text:y.string().describe("Text to wait for")})})];import{tool as S}from"@langchain/core/tools";import{z as w}from"zod";var bt=[S(async({text:e,thoughts:t},{configurable:a})=>{let{ref:n}=a,{ai:o,recorder:r}=n;h("Thoughts: "+t,"magenta");let i=(await(await f(n)).evaluate(C,A)).map(({html:l,xpath:x})=>({html:E(l),xpath:x}));await o.embedTexts(i.map(({html:l})=>l));let d=await o.searchDocuments(t),m=await o.getBestCandidate(t,d),{xpath:p}=i.find(({html:l})=>l===d[m].pageContent);return r?.addAction({name:"assertElementContains",params:{text:e,xpath:p}}),X(n,{text:e,xpath:p})},{name:"AssertElementContains",description:"Call to verify that an element contains specific text",schema:w.object({text:w.string().describe("The text to verify on the element"),thoughts:w.string().describe("Thoughts to search for the relevant element from user input")})}),S(async({text:e,thoughts:t},{configurable:a})=>{let{ref:n}=a,{ai:o,recorder:r}=n;h("Thoughts: "+t,"magenta");let i=(await(await f(n)).evaluate(C,A)).map(({html:l,xpath:x})=>({html:E(l),xpath:x}));await o.embedTexts(i.map(({html:l})=>l));let d=await o.searchDocuments(t),m=await o.getBestCandidate(t,d),{xpath:p}=i.find(({html:l})=>l===d[m].pageContent);return r?.addAction({name:"assertElementNotContain",params:{text:e,xpath:p}}),Z(n,{text:e,xpath:p})},{name:"AssertElementNotContain",description:"Call to verify that an element does not contain specific text",schema:w.object({text:w.string().describe("The text to verify on the element"),thoughts:w.string().describe("Thoughts to search for the relevant element from user input")})}),S(async({text:e,thoughts:t},{configurable:a})=>{let{ref:n}=a,{ai:o,recorder:r}=n;h("Thoughts: "+t,"magenta");let i=(await(await f(n)).evaluate(C,A)).map(({html:l,xpath:x})=>({html:E(l),xpath:x}));await o.embedTexts(i.map(({html:l})=>l));let d=await o.searchDocuments(t),m=await o.getBestCandidate(t,d),{xpath:p}=i.find(({html:l})=>l===d[m].pageContent);return r?.addAction({name:"assertElementContentEquals",params:{xpath:p,text:e}}),Q(n,{xpath:p,text:e})},{name:"AssertElementContentEquals",description:"Call to verify that an element has specific text",schema:w.object({text:w.string().describe("The text to verify on the element"),thoughts:w.string().describe("Thoughts to search for the relevant element from user input")})}),S(async({text:e,thoughts:t},{configurable:a})=>{let{ref:n}=a,{ai:o,recorder:r}=n;h("Thoughts: "+t,"magenta");let i=(await(await f(n)).evaluate(C,A)).map(({html:l,xpath:x})=>({html:E(l),xpath:x}));await o.embedTexts(i.map(({html:l})=>l));let d=await o.searchDocuments(t),m=await o.getBestCandidate(t,d),{xpath:p}=i.find(({html:l})=>l===d[m].pageContent);return r?.addAction({name:"assertElementContentNotEqual",params:{xpath:p,text:e}}),tt(n,{xpath:p,text:e})},{name:"AssertElementContentNotEqual",description:"Call to verify that an element does not have specific text",schema:w.object({text:w.string().describe("The text to verify on the element"),thoughts:w.string().describe("Thoughts to search for the relevant element from user input")})}),S(async({thoughts:e},{configurable:t})=>{let{ref:a}=t,{ai:n,recorder:o}=a;h("Thoughts: "+e,"magenta");let s=(await(await f(a)).evaluate(C,A)).map(({html:p,xpath:l})=>({html:E(p),xpath:l}));await n.embedTexts(s.map(({html:p})=>p));let i=await n.searchDocuments(e),d=await n.getBestCandidate(e,i),{xpath:m}=s.find(({html:p})=>p===i[d].pageContent);return o?.addAction({name:"assertElementVisible",params:{xpath:m}}),et(a,{xpath:m})},{name:"AssertElementVisible",description:"Call to verify that an element is visible",schema:w.object({thoughts:w.string().describe("Thoughts to search for the relevant element from user input")})}),S(async({thoughts:e},{configurable:t})=>{let{ref:a}=t,{ai:n,recorder:o}=a;h("Thoughts: "+e,"magenta");let s=(await(await f(a)).evaluate(C,A)).map(({html:p,xpath:l})=>({html:E(p),xpath:l}));await n.embedTexts(s.map(({html:p})=>p));let i=await n.searchDocuments(e),d=await n.getBestCandidate(e,i),{xpath:m}=s.find(({html:p})=>p===i[d].pageContent);return o?.addAction({name:"assertElementNotVisible",params:{xpath:m}}),at(a,{xpath:m})},{name:"AssertElementNotVisible",description:"Call to verify that an element is not visible",schema:w.object({thoughts:w.string().describe("Thoughts to search for the relevant element from user input")})}),S(async({text:e},{configurable:t})=>{let{ref:a}=t;return h('Thoughts: Verify if the page contains "'+e+'"',"magenta"),a.recorder?.addAction({name:"assertPageContains",params:{text:e}}),nt(a,{text:e})},{name:"AssertPageContains",description:"Call to verify that the page contains specific text",schema:w.object({text:w.string().describe("The text to verify on the page")})}),S(async({text:e},{configurable:t})=>{let{ref:a}=t;return h('Thoughts: Verify if the page does not contain "'+e+'"',"magenta"),a.recorder?.addAction({name:"assertPageNotContain",params:{text:e}}),ot(a,{text:e})},{name:"AssertPageNotContain",description:"Call to verify that the page does not contain specific text",schema:w.object({text:w.string().describe("The text to verify on the page")})}),S(async({text:e},{configurable:t})=>{let{ref:a}=t;return h('Thoughts: Verify if the page title is "'+e+'"',"magenta"),a.recorder?.addAction({name:"assertPageTitleEquals",params:{text:e}}),st(a,{text:e})},{name:"AssertPageTitleEquals",description:"Call to verify that the page title is equal to specific text",schema:w.object({text:w.string().describe("The text to verify on the page title")})}),S(async({pattern:e},{configurable:t})=>{let{ref:a}=t;return h('Thoughts: Verify if the page URL matches the pattern "'+e+'"',"magenta"),a.recorder?.addAction({name:"assertPageUrlMatches",params:{pattern:e}}),rt(a,{pattern:e})},{name:"AssertPageUrlMatches",description:"Call to verify that the page URL matches a specific pattern",schema:w.object({pattern:w.string().describe("The pattern to verify on the page URL")})})];import{tool as T}from"@langchain/core/tools";import{z as u}from"zod";var xt=[T(async({text:e},{configurable:t})=>JSON.stringify({name:"assertElementContains",params:{...t.action.params,text:e}}),{name:"AssertElementContains",description:"Call to verify that an element contains specific text",schema:u.object({text:u.string().describe("The text to verify")})}),T(async({text:e},{configurable:t})=>JSON.stringify({name:"assertElementNotContain",params:{...t.action.params,text:e}}),{name:"AssertElementNotContain",description:"Call to verify that an element does not contain specific text",schema:u.object({text:u.string().describe("The text to verify")})}),T(async({text:e},{configurable:t})=>JSON.stringify({name:"assertElementContentEquals",params:{...t.action.params,text:e}}),{name:"AssertElementContentEquals",description:"Call to verify that an element has specific text",schema:u.object({text:u.string().describe("The text to verify")})}),T(async({text:e},{configurable:t})=>JSON.stringify({name:"assertElementContentNotEqual",params:{...t.action.params,text:e}}),{name:"AssertElementContentNotEqual",description:"Call to verify that an element does not have specific text",schema:u.object({text:u.string().describe("The text to verify")})}),T(async(e,{configurable:t})=>JSON.stringify({name:"assertElementVisible",params:t.action.params}),{name:"AssertElementVisible",description:"Call to verify that an element is visible",schema:u.object({})}),T(async(e,{configurable:t})=>JSON.stringify({name:"assertElementNotVisible",params:t.action.params}),{name:"AssertElementNotVisible",description:"Call to verify that an element is not visible",schema:u.object({})}),T(async({text:e})=>JSON.stringify({name:"assertPageContains",params:{text:e}}),{name:"AssertPageContains",description:"Call to verify that the page contains specific text",schema:u.object({text:u.string().describe("The text to verify")})}),T(async({text:e})=>JSON.stringify({name:"assertPageNotContain",params:{text:e}}),{name:"AssertPageNotContain",description:"Call to verify that the page does not contain specific text",schema:u.object({text:u.string().describe("The text to verify")})}),T(async({text:e})=>JSON.stringify({name:"assertPageTitleEquals",params:{text:e}}),{name:"AssertPageTitleEquals",description:"Call to verify that the page title equals specific text",schema:u.object({text:u.string().describe("The text to verify")})}),T(async({pattern:e})=>JSON.stringify({name:"assertPageUrlMatches",params:{pattern:e}}),{name:"AssertPageUrlMatches",description:"Call to verify that the page URL matches a specific pattern",schema:u.object({pattern:u.string().describe("The pattern to match")})}),T(async(e,{configurable:t})=>JSON.stringify({name:"click",params:t.action.params}),{name:"Click",description:"Call to handle the click event",schema:u.object({})}),T(async({url:e})=>JSON.stringify({name:"goto",params:{url:e}}),{name:"GoTo",description:"Call to handle the navigation event",schema:u.object({url:u.string().describe("The URL to navigate to")})}),T(async({duration:e},{configurable:t})=>JSON.stringify({name:"hover",params:{...t.action.params,duration:e}}),{name:"Hover",description:"Call to handle the hover event",schema:u.object({duration:u.number().describe("How long the hover event should last. Default is 1000ms")})}),T(async({text:e},{configurable:t})=>JSON.stringify({name:"input",params:{text:e,...t.action.params}}),{name:"Input",description:"Call to handle the input event",schema:u.object({text:u.string().describe("The text to input")})}),T(async({direction:e},{configurable:t})=>JSON.stringify({name:"scroll",params:{...t.action.params,direction:e}}),{name:"Scroll",description:"Call to handle the scroll event",schema:u.object({direction:u.enum(["up","down","top","bottom"]).describe("The direction to scroll")})}),T(async({option:e},{configurable:t})=>JSON.stringify({name:"select",params:{option:e,...t.action.params}}),{name:"Select",description:"Call to handle the select event",schema:u.object({option:u.string().describe("The option to select")})}),T(async({duration:e})=>JSON.stringify({name:"sleep",params:{duration:e}}),{name:"Sleep",description:"Call to handle the sleep event",schema:u.object({duration:u.number().describe("The duration to sleep in milliseconds")})}),T(async({text:e})=>JSON.stringify({name:"waitForText",params:{text:e}}),{name:"WaitForText",description:"Call to handle the wait for text event",schema:u.object({text:u.string().describe("The text to wait for")})})];import{tool as le}from"@langchain/core/tools";import{z as de}from"zod";var vt=[le(async(e,{configurable:t})=>{let{ref:a}=t,{input:n,recorder:o}=a;return h("Thoughts: Extracting relevant information from the webpage","magenta"),o?.addAction({name:"getText",params:{input:n}}),ct(a,{input:n})},{name:"GetText",description:"Get specified information from the webpage",schema:de.object({})})];var qt=class{constructor(t,{delay:a=250,recordPath:n=".playword/recordings.json"}={}){this.playword=t;this.delay=Math.abs(a),this.recorder=new j(n),this.playword.recorder=void 0,this.observe=this.observe.bind(this)}action={name:"click",params:{}};delay;input="";recorder;state={dryRunning:!1,waitingForAI:!1,waitingForUserAction:!1};ai(){return this.playword.ai}context(){return this.playword.context}page(){return this.playword.page}async setPageListeners(){let t=async()=>{this.state.waitingForAI||(await Promise.all([i(),l("Accepted","\u2713","#4db6ac")]),this.recorder.initStep(this.recorder.count(),this.input),this.recorder.addAction(this.action),await this.recorder.save(["html","success"]),this.state.waitingForUserAction=!1)},a=async()=>{this.state.waitingForAI||(this.state.waitingForUserAction=!1)},n=async()=>{this.recorder.clear(),await Promise.all([this.recorder.save(),M()])},o=async()=>{await Promise.all([p(".plwd-preview-title").evaluate(W,"open"),p(".plwd-clear-btn").evaluate(W,"open"),p(".plwd-dry-run-btn").evaluate(W,"open"),p(".plwd-panel").evaluate(W,"open")])},r=async g=>{this.recorder.delete(g),await Promise.all([this.recorder.save(["html","success"]),M()])},c=async g=>{J(""),await Promise.all([O(),D(!0)]);let v=await this.ai().summarizeAction(JSON.stringify(g));J(v),await Promise.all([O(),D(!1)])},s=async()=>{h("Starting the dry run process...","green",!0),this.state.dryRunning=!0,this.state.waitingForUserAction=!1,await Promise.all([l("Dry Run","\u{1F680}","#e5c07b"),F()]);for(let g of this.recorder.list())if(this.state.dryRunning){let v=g.actions[0],I=await k[v.name](this.playword,v.params);v.success=!!(I!=="Failed to perform the action"&&I),h((v.success?"PASS: ":"FAIL: ")+g.input),await G(this.delay)}await l("Completed","\u{1F680}","#e5c07b"),this.state.dryRunning=!1,h("Dry Run Completed")},i=async()=>{await D(!0);let{tool_calls:g}=await this.ai().useTools(xt,[new pe(this.input)]);if(!g||!g.length)return D(!1);let v=xt.find(Y=>Y.name===g[0].name);if(!v)return D(!1);let{content:I}=await v.invoke(g[0],{configurable:{action:this.action}});return I&&(this.action=JSON.parse(I),h("Input: "+this.input+`
Action: `+JSON.stringify(this.action,null,2),"green",!0)),D(!1)},d=async g=>{if(!(this.state.dryRunning||this.state.waitingForAI||this.state.waitingForUserAction)){for(this.action=g,this.state.waitingForUserAction=!0,await G(500),c(g);this.state.waitingForUserAction;)await m()||await Promise.all([x(),M(),O()]),await G(200);await o()}},m=async()=>p(".plwd-panel").evaluate(Ot,"open"),p=g=>this.page().locator(g).first(),l=async(g,v,I)=>{await this.page().evaluate(Dt,{content:g,icon:v,color:I})},x=async()=>{await p(".plwd-panel").evaluate(q,"open")},M=async()=>{this.recorder.count()>0&&await Promise.all([p(".plwd-preview-title").evaluate(q,"open"),p(".plwd-clear-btn").evaluate(q,"open"),p(".plwd-dry-run-btn").evaluate(q,"open")]),await p(".plwd-timeline").evaluate(Ft,this.recorder.list())},F=async()=>{let g=()=>this.page().evaluate(St),v=()=>this.context().clearCookies(),I=()=>this.page().evaluate(It),Y=()=>this.page().evaluate(Lt),$t=()=>this.page().evaluate(Nt);await Promise.all([g(),v(),I(),$t(),Y()]),await G(2e3);for(let Xt of this.context().pages())await Xt.close();await this.context().newPage()},O=async()=>{await p(".plwd-input").evaluate(K,{name:"value",value:this.input})},Kt=()=>{this.state.dryRunning=!1},J=g=>{this.input=g},D=async g=>{await Promise.all([p(".plwd-input").evaluate(K,{name:"disabled",value:g}),p(".plwd-loader-box").evaluate(Mt,g)]),this.state.waitingForAI=g};this.page().on("framenavigated",g=>{let v=g.url();if(!(v==="about:blank"||v!==this.page().mainFrame().url()))return d({name:"goto",params:{url:v}})}),await Promise.all([this.page().addInitScript(kt),this.page().addInitScript(Rt,Pt)]),await Promise.all([this.page().exposeFunction("accept",t),this.page().exposeFunction("cancel",a),this.page().exposeFunction("clearAll",n),this.page().exposeFunction("deleteStep",r),this.page().exposeFunction("dryRun",s),this.page().exposeFunction("emit",d),this.page().exposeFunction("notify",l),this.page().exposeFunction("stopDryRun",Kt),this.page().exposeFunction("updateInput",J)])}async observe(){this.context().on("page",async()=>{await this.setPageListeners(),await this.page().reload()}),await this.recorder.load()}};import{HumanMessage as De}from"@langchain/core/messages";import{setTimeout as Me}from"timers/promises";import{Annotation as Wt,END as N,StateGraph as me,START as ue,messagesStateReducer as he}from"@langchain/langgraph";var Tt=async(e,t,a)=>{let{tool_calls:n}=t.messages[t.messages.length-1],o=[];for(let r of n){let s=await e.find(i=>i.name===r.name).invoke(r,a);o.push(s)}return{messages:o}},ge=async({messages:e},{configurable:t})=>{let{ai:a}=t?.ref;return{messages:[await a.useTools(bt,e)]}},fe=async({messages:e},t)=>Tt(bt,{messages:e},t),ye=async({messages:e},{configurable:t})=>{let{ai:a}=t?.ref;return{messages:[await a.useTools(wt,e)]}},we=async({messages:e},t)=>Tt(wt,{messages:e},t),be=async({messages:e},{configurable:t})=>{let{ai:a}=t?.ref;return{messages:[await a.useTools(vt,e)]}},xe=({messages:e},t)=>Tt(vt,{messages:e},t),ve=async({messages:e},{configurable:t})=>{let{ai:a}=t?.ref;return await a.classifyAction(e[e.length-1])},Te=async({messages:e})=>{let{tool_calls:t}=e[e.length-1];return t&&t.length?"assertionTools":N},Ce=async({messages:e})=>{let{tool_calls:t}=e[e.length-1];return t&&t.length?"operationTools":N},Ae=async({messages:e})=>{let{tool_calls:t}=e[e.length-1];return t&&t.length?"queryTools":N},Vt=()=>{let e=Wt.Root({messages:Wt({reducer:he})});return new me(e).addNode("assertion",ge).addNode("assertionTools",fe).addNode("operation",ye).addNode("operationTools",we).addNode("query",be).addNode("queryTools",xe).addConditionalEdges(ue,ve,["assertion","operation","query"]).addConditionalEdges("assertion",Te,["assertionTools",N]).addConditionalEdges("operation",Ce,["operationTools",N]).addConditionalEdges("query",Ae,["queryTools",N]).addEdge("assertionTools",N).addEdge("operationTools",N).addEdge("queryTools",N).compile()};import{ChatAnthropic as Ne}from"@langchain/anthropic";import{SystemMessage as Ct}from"@langchain/core/messages";import{ChatGoogleGenerativeAI as Oe,GoogleGenerativeAIEmbeddings as ke}from"@langchain/google-genai";import{ChatOpenAI as Re,OpenAIEmbeddings as Fe}from"@langchain/openai";import{z as R}from"zod";import{getEnvironmentVariable as Ee}from"@langchain/core/utils/env";import{Embeddings as Pe}from"@langchain/core/embeddings";import{chunkArray as Se}from"@langchain/core/utils/chunk_array";var z=class extends Pe{apiKey;headers={"Content-Type":"application/json"};batchSize;endpoint;inputType;model;outputDimension;outputDtype;truncation;constructor(t){if(super({...t}),this.apiKey=t?.apiKey||Ee("VOYAGEAI_API_KEY"),this.batchSize=t?.batchSize??8,this.endpoint=t?.endpoint??"https://api.voyageai.com/v1/embeddings",this.inputType=t?.inputType,this.model=t?.model??"voyage-3",this.outputDimension=t?.outputDimension,this.outputDtype=t?.outputDtype??"float",this.truncation=t?.truncation??!0,!this.apiKey)throw new Error("VoyageAI API key not found")}async callVoyageAPI(t){let a=async(r,c)=>await(await fetch(r,c)).json(),n=JSON.stringify(t),o={Authorization:"Bearer "+this.apiKey,...this.headers};return this.caller.call(a,this.endpoint,{body:n,headers:o,method:"POST"})}async embedDocuments(t){let n=Se(t,this.batchSize).map(c=>{let s={input:c,input_type:this.inputType,model:this.model,output_dimension:this.outputDimension,output_dtype:this.outputDtype,truncation:this.truncation};return this.callVoyageAPI(s)});return(await Promise.all(n)).flatMap(({data:c})=>c.map(({embedding:s})=>s))}async embedQuery(t){let a={input:t,input_type:this.inputType,model:this.model,output_dimension:this.outputDimension,output_dtype:this.outputDtype,truncation:this.truncation};return(await this.callVoyageAPI(a)).data[0].embedding}};var _t=`I will provide an image and a user input.
Your task is to analyze the image and retrieve the relevant information from it to fulfill the user input.
Just return the relevant information without any additional text and explanation.`,Gt=`Your goal is to find the most relevant element that user mentioned in the input from the list of elements provided.
When you find the element you believe to be the best match, return the index of that element.`,zt=`Classify the user's input into one of types: assertion, operation and query.
- "assertion": Indicates a request to verify a web element.
- "operation": Indicates the user wants to perform a specific operation in the browser like clicking a button or getting an attribute value.
- "query": Indicates the user wants to take, get, extract, find, search, retrieve or query something on the web page.`,Bt=`I will provide a JSON string that contains an action's name and its associated params.
Each JSON string represents a single test step within a test case.
Your tasks are as follows:
1. Operation Summary:
- Objective: Create a concise summary of the action described in the JSON.
- Guidelines:
- The summary should be brief, clear, and accurately reflect the intent of the action.
- The action in the summary should not be changed to a different action.
- If the action is performed on a password field, avoid including the actual password in the summary.
- If the action is a navigation step, the summary should be "Navigate to [URL]."
2. HTML Element Simplification:
- Objective: When the params include details about an HTML element, present the element's information without using attributes that are random, dynamic, or difficult to interpret.
- Guidelines:
- Exclude: Attributes that are likely to change frequently (e.g., dynamically generated IDs, timestamps or session-specific data).
- Include:
- Static and meaningful attributes that clearly identify or describe the element (e.g., class, id with meaningful names, data-* attributes relevant to the test).
- If the element has text content, prioritize including the text content in the description.`,Ut="Invoke the provided tools to execute every action listed in the input to fulfill the request.";import{Document as Jt}from"@langchain/core/documents";import{VectorStore as Le}from"@langchain/core/vectorstores";var V=class e extends Le{vectors=[];constructor(t){super(t,{})}_vectorstoreType(){return"memory"}static async fromDocuments(t,a){let n=new e(a);return await n.addDocuments(t),n}static async fromTexts(t,a){let n=t.filter(o=>o).map(o=>new Jt({pageContent:o}));return this.fromDocuments(n,a)}async _queryVectors(t,a){return this.vectors.map(({content:n,embedding:o},r)=>({index:r,content:n,embedding:o,similarity:this.cosine(t,o)})).sort((n,o)=>n.similarity>o.similarity?-1:0).slice(0,a)}cosine(t,a){let[n,o,r]=[0,0,0];for(let c=0;c<t.length;c++)n+=t[c]*a[c],o+=t[c]*t[c],