@floe-ai/sdk 0.1.0-dev.23 → 0.1.0-dev.24
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.
|
@@ -475,7 +475,7 @@ Error generating stack: `+o.message+`
|
|
|
475
475
|
[contenteditable="true"],
|
|
476
476
|
summary
|
|
477
477
|
`.replace(/\s+/g," ").trim()),L(Et,"SKIP_SELECTORS",["#onboarding-overlay","#onboarding-sdk-react-ui","#hse-highlight-element","script","style","noscript","template"]);let vd=Et;const Px=["#onboarding-overlay","#floe-cursor","#onboarding-sdk-react-ui","#hse-highlight-element","#floe-cursor-styles","#onboarding-animations"],Oi="data-floe-widget";function Ct(t){if(!t)return!1;if(t.hasAttribute(Oi))return!0;for(const e of Px)if(t.closest(e))return!0;return!1}function An(){return window.location.origin+window.location.pathname}function za(t){try{const e=new URL(t,window.location.origin);return e.origin+e.pathname}catch{return t}}function fy(t){return t&&t.replace(/\.ng-(untouched|touched|pristine|dirty|valid|invalid)/g,"")}function hy(t){try{const n=document.querySelector(t);if(n)return n}catch{}const e=fy(t);if(e!==t)try{const n=document.querySelector(e);if(n)return console.log(`[AngularFallback] Selector matched after stripping state classes: "${e}"`),n}catch{}return null}function Lx(t){let e=t,n=0;for(;e&&n<5;){const r=e.getAttribute("role");if(r==="dialog"||r==="alertdialog"||e.getAttribute("aria-modal")==="true"||e.tagName==="DIALOG")return!0;const i=e.tagName.toLowerCase();if(i.includes("modal")||i.includes("dialog"))return!0;const o=typeof e.className=="string"?e.className.toLowerCase():"";if(o.includes("modal")||o.includes("dialog")||o.includes("cdk-overlay"))return!0;e=e.parentElement,n++}return!1}function py(t,e={}){var h,b,y,g,S;const{focus:n=!0,includePointerEvents:r=!0,nativeClickFallback:i=!1,includeMouseEnter:o=!1}=e,s=t.getBoundingClientRect(),a=s.left+s.width/2,l=s.top+s.height/2,c=document.elementFromPoint(a,l);let d;if(c&&(c===t||t.contains(c)||c.contains(t)))d=c,d!==t&&console.log("[humanLikeClick] 🎯 Using element at point:",d.tagName,"instead of target:",t.tagName);else if(c){if(console.warn("[humanLikeClick] ⚠️ Element at point is unrelated:",c.tagName,(h=c.className)==null?void 0:h.toString().slice(0,50)),console.warn("[humanLikeClick] Expected target:",t.tagName,(b=t.className)==null?void 0:b.toString().slice(0,50)),Lx(c)){const v=`${c.tagName} (${(y=c.className)==null?void 0:y.toString().slice(0,80)})`;throw console.error("[humanLikeClick] ❌ BLOCKED: Modal/dialog overlay is covering the target element.",`Overlay: ${v}`,`Target: ${t.tagName} "${(g=t.textContent)==null?void 0:g.trim().slice(0,50)}"`),new Error(`Click blocked by modal overlay: ${v}. Target "${(S=t.textContent)==null?void 0:S.trim().slice(0,50)}" is behind the modal. Interact with the modal instead.`)}d=t}else console.warn("[humanLikeClick] ⚠️ No element at coordinates, falling back to target"),d=t;n&&typeof d.focus=="function"&&d.focus();const f={bubbles:!0,cancelable:!0,view:window,clientX:a,clientY:l,screenX:a+window.screenX,screenY:l+window.screenY,button:0,buttons:1};if(r){const v={...f,pointerType:"mouse",isPrimary:!0};d.dispatchEvent(new PointerEvent("pointerdown",v)),d.dispatchEvent(new PointerEvent("pointerup",v))}return o&&(d.dispatchEvent(new MouseEvent("mouseenter",{...f,bubbles:!1})),d.dispatchEvent(new MouseEvent("mouseover",f))),d.dispatchEvent(new MouseEvent("mousedown",f)),d.dispatchEvent(new MouseEvent("mouseup",f)),d.dispatchEvent(new MouseEvent("click",f)),i&&typeof d.click=="function"&&d.click(),console.log("[humanLikeClick] ✅ Completed on",d.tagName,"at (",Math.round(a),",",Math.round(l),")"),d}class gy{constructor(){L(this,"audioContext",null);L(this,"analyzerNode",null);L(this,"sourceNode",null);L(this,"dataArray",new Uint8Array(0));L(this,"isRunning",!1);L(this,"onLevelsCallback",null);L(this,"animationId",null);L(this,"analyze",()=>{if(!this.isRunning||!this.analyzerNode||this.dataArray.length===0)return;this.analyzerNode.getByteFrequencyData(this.dataArray);const e=[];for(let n=0;n<this.dataArray.length;n++)n>=2&&n<this.dataArray.length-2&&e.push(this.dataArray[n]/255);this.onLevelsCallback&&this.onLevelsCallback(e),this.animationId=requestAnimationFrame(this.analyze)})}start(e,n){try{this.audioContext||(this.audioContext=new(window.AudioContext||window.webkitAudioContext)),this.audioContext.state==="suspended"&&this.audioContext.resume(),this.analyzerNode=this.audioContext.createAnalyser(),this.analyzerNode.fftSize=64,this.analyzerNode.smoothingTimeConstant=.4,this.sourceNode=this.audioContext.createMediaStreamSource(e),this.sourceNode.connect(this.analyzerNode);const r=this.analyzerNode.frequencyBinCount;this.dataArray=new Uint8Array(r),this.onLevelsCallback=n,this.isRunning=!0,this.analyze(),console.log("[AudioAnalyzer] Started analyzing audio stream")}catch(r){console.error("[AudioAnalyzer] Failed to start:",r)}}stop(){this.isRunning=!1,this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null),this.sourceNode&&(this.sourceNode.disconnect(),this.sourceNode=null),this.analyzerNode=null,this.dataArray=new Uint8Array(0),this.onLevelsCallback=null,console.log("[AudioAnalyzer] Stopped")}destroy(){this.stop(),this.audioContext&&(this.audioContext.close(),this.audioContext=null)}}class Ix{constructor(){L(this,"events",{})}on(e,n){return this.events[e]||(this.events[e]=[]),this.events[e].push(n),this}off(e,n){if(!this.events[e])return this;const r=this.events[e].indexOf(n);return r>-1&&this.events[e].splice(r,1),this}emit(e,...n){if(!this.events[e])return!1;for(const r of this.events[e])r(...n);return!0}}class Rx{constructor(){L(this,"lastSnapshot",null);L(this,"lastSnapshotHash","");L(this,"snapshotInterval",null);L(this,"sendCallback",null);L(this,"correlationCounter",0);L(this,"INTERACTIVE_TAGS",new Set(["button","a","input","select","textarea","label","summary","details","option","menuitem"]));L(this,"INTERACTIVE_ROLES",new Set(["button","link","menuitem","option","tab","checkbox","radio","switch","textbox","combobox","listbox","slider"]));L(this,"mutationObserver",null);L(this,"mutationDebounceTimer",null)}startCapturing(e=1500,n){console.log(`[DOMIntrospector] Starting DOM capture every ${e}ms`),this.snapshotInterval&&(clearInterval(this.snapshotInterval),this.snapshotInterval=null),this.mutationDebounceTimer&&(clearTimeout(this.mutationDebounceTimer),this.mutationDebounceTimer=null),this.mutationObserver&&(this.mutationObserver.disconnect(),this.mutationObserver=null),this.sendCallback=n,this.captureAndSend(),this.snapshotInterval=window.setInterval(()=>{this.captureAndSend()},e),this.setupMutationObserver()}stopCapturing(){this.snapshotInterval&&(clearInterval(this.snapshotInterval),this.snapshotInterval=null),this.mutationDebounceTimer&&(clearTimeout(this.mutationDebounceTimer),this.mutationDebounceTimer=null),this.mutationObserver&&(this.mutationObserver.disconnect(),this.mutationObserver=null),console.log("[DOMIntrospector] Stopped DOM capture")}captureAndSendImmediate(e="immediate"){console.log(`[DOMIntrospector] Immediate capture triggered: ${e}`);const n=this.captureSnapshot(),r=this.computeSnapshotHash(n),i=r!==this.lastSnapshotHash,o={...n,correlationId:`dom-${Date.now()}-${++this.correlationCounter}`,captureReason:e,domChanged:i};return this.lastSnapshot=o,this.lastSnapshotHash=r,this.sendCallback&&(console.log(`[DOMIntrospector] Sending immediate snapshot (changed=${i}): ${n.elements.length} elements, corr=${o.correlationId}`),this.sendCallback(o)),o.correlationId}setupMutationObserver(){this.mutationObserver||(this.mutationObserver=new MutationObserver(e=>{this.mutationDebounceTimer&&clearTimeout(this.mutationDebounceTimer),e.some(r=>r.type==="childList"||r.type==="attributes"&&["href","src","hidden","disabled"].includes(r.attributeName||""))&&(this.mutationDebounceTimer=setTimeout(()=>{console.log("[DOMIntrospector] Significant DOM change detected"),this.captureAndSendImmediate("dom-mutation")},300))}),this.mutationObserver.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["hidden","disabled","aria-hidden","href","src"]}))}captureAndSend(){const e=this.captureSnapshot(),n=this.computeSnapshotHash(e);if(n!==this.lastSnapshotHash){const i={...e,correlationId:`dom-${Date.now()}-${++this.correlationCounter}`,captureReason:"periodic",domChanged:!0};this.lastSnapshot=i,this.lastSnapshotHash=n,this.sendCallback&&(console.log(`[DOMIntrospector] Sending snapshot (DOM changed): ${e.elements.length} elements, ${e.interactiveCount} interactive, corr=${i.correlationId}`),this.sendCallback(i))}else console.debug("[DOMIntrospector] Snapshot unchanged, skipping send")}computeSnapshotHash(e){const n=e.elements.length,r=e.interactiveCount||0,i=30,o=e.elements.slice(0,i),s=Math.max(0,Math.floor(n/2)-Math.floor(i/2)),a=e.elements.slice(s,s+i),l=e.elements.slice(-i),c=f=>f.map(h=>{var b;return`${h.tag}:${(b=h.text)==null?void 0:b.slice(0,20)}:${Math.round(h.rect.x)}:${Math.round(h.rect.y)}`}).join("|");return`count:${n}:${r}|`+c(o)+"||"+c(a)+"||"+c(l)}captureSnapshot(){const e=[],n={width:window.innerWidth,height:window.innerHeight},r=document.body.querySelectorAll("*");let i=0,o=0;return r.forEach(s=>{var h;const a=s;if(this.shouldSkipElement(a))return;const l=a.getBoundingClientRect();if(l.bottom<0||l.top>n.height||l.right<0||l.left>n.width||l.width<=0||l.height<=0)return;const c=this.isInteractiveElement(a);c&&o++;const d=this.getVisibleText(a);if(!c&&!d)return;const f={index:i++,tag:a.tagName.toLowerCase(),text:d,id:a.id||"",className:typeof a.className=="string"?a.className:"",ariaLabel:a.getAttribute("aria-label"),placeholder:a.getAttribute("placeholder"),role:a.getAttribute("role"),href:a.getAttribute("href"),type:a.getAttribute("type"),name:a.getAttribute("name"),rect:{x:Math.round(l.x),y:Math.round(l.y),width:Math.round(l.width),height:Math.round(l.height)},isVisible:!0,isInteractive:c,parentTag:((h=a.parentElement)==null?void 0:h.tagName.toLowerCase())||null,depth:this.getElementDepth(a)};e.push(f)}),{timestamp:Date.now(),url:An(),viewport:n,elements:e,totalElements:e.length,interactiveCount:o}}shouldSkipElement(e){if(Ct(e))return!0;const n=e.tagName.toLowerCase();if(["script","style","noscript","template","svg","path"].includes(n))return!0;const r=window.getComputedStyle(e);return r.display==="none"||r.visibility==="hidden"||r.opacity==="0"}isInteractiveElement(e){const n=e.tagName.toLowerCase();if(this.INTERACTIVE_TAGS.has(n))return!0;const r=e.getAttribute("role");if(r&&this.INTERACTIVE_ROLES.has(r)||e.onclick||e.getAttribute("onclick")||e.contentEditable==="true")return!0;const i=e.getAttribute("tabindex");return!!(i&&parseInt(i)>=0||window.getComputedStyle(e).cursor==="pointer")}getVisibleText(e){var r;return e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement?(e.value||e.placeholder||"").trim().slice(0,80):(((r=e.innerText)==null?void 0:r.trim())||"").slice(0,80)}getElementDepth(e){let n=0,r=e;for(;r&&r!==document.body;)n++,r=r.parentElement;return n}getLastSnapshot(){return this.lastSnapshot}findElementByIndex(e){if(!this.lastSnapshot)return null;const n=this.lastSnapshot.elements.find(r=>r.index===e);return n?this.findElementByBoundingBox(n.rect,n.tag,n.text):null}findElementByBoundingBox(e,n,r){var a;const o=[];if(document.body.querySelectorAll("*").forEach(l=>{var g;const c=l;if(this.shouldSkipElement(c))return;const d=c.getBoundingClientRect(),f=Math.abs(d.x-e.x)<=10,h=Math.abs(d.y-e.y)<=10,b=Math.abs(d.width-e.width)<=10*2,y=Math.abs(d.height-e.height)<=10*2;if(f&&h&&b&&y){let S=100,v=!1;if(n&&c.tagName.toLowerCase()===n.toLowerCase()&&(S+=30),r){const w=((g=c.innerText)==null?void 0:g.trim().toLowerCase())||"",k=r.toLowerCase();w.length===0?v=!1:w===k?(S+=50,v=!0):(w.includes(k)||k.includes(w))&&(S+=25,v=!0)}else v=!0;o.push({element:c,score:S,textMatch:v})}}),o.sort((l,c)=>c.score-l.score),o.length>0){const l=o[0],c=((a=l.element.innerText)==null?void 0:a.trim().slice(0,50))||"";return r&&!l.textMatch?(console.warn(`[DOMIntrospector] ⚠️ Bounding box match REJECTED - text mismatch! Expected: "${r}", Found: "${c}"`),console.warn(`[DOMIntrospector] Element at (${e.x}, ${e.y}) has text "${c}" which doesn't match expected "${r}" - page may have scrolled`),null):(console.log(`[DOMIntrospector] Found ${o.length} candidates by bounding box, best score: ${l.score}, text: "${c}"`),l.element)}return null}}const lr=class lr{static extractSelectorContext(e){if(!e)return{};const n=e.split(/\s*([>+~]|\s)\s*/);if(n.length<2)return{};const r=n[n.length-1],i=n.slice(0,-2),o=r.match(/^([a-zA-Z][a-zA-Z0-9-]*)/),s=o?o[1].toLowerCase():void 0,a=i.length>0?i.join(" "):void 0;let l;if(i.length>0){const d=i[i.length-1].match(/^([a-zA-Z][a-zA-Z0-9-]*)/);l=d?d[1].toLowerCase():void 0}return{expectedTag:s,parentSelector:a,parentTag:l}}static matchesSelectorContext(e,n){if(!n.parentTag&&!n.parentSelector)return .5;let r=0,i=0;if(n.parentTag&&(i++,e.closest(n.parentTag)&&(r+=1)),n.parentSelector){i++;try{e.closest(n.parentSelector)&&(r+=1)}catch{}}return i>0?r/i:.5}static setDOMIntrospector(e){lr.domIntrospector=e,console.log("[HybridTargetResolver] DOM Introspector set for enhanced targeting")}static safeStringify(e,n){const r=new WeakSet;return JSON.stringify(e,(i,o)=>{if(o&&typeof o=="object"){if(o instanceof HTMLElement){const s=o.tagName||"Unknown",a=o.id?`#${o.id}`:"",l=o.className&&typeof o.className=="string"?`.${o.className.split(" ").filter(Boolean).join(".")}`:"";return`[HTMLElement: ${s}${a}${l}]`}if(o instanceof Element)return`[Element: ${o.tagName||"Unknown"}]`;if(o instanceof Node)return`[Node: ${o.nodeName}]`;if(r.has(o))return"[Circular]";r.add(o)}return o},n)}static resolveTarget(e){if(!e)return console.warn("[HybridTargetResolver] ❌ No target provided"),null;console.log("[HybridTargetResolver] Target details:",this.safeStringify(e,2));const n=this.resolveTargetWithConsensus(e),r=n.element?`[HTMLElement: ${n.element.tagName}${n.element.id?`#${n.element.id}`:""}${n.element.className&&typeof n.element.className=="string"?`.${n.element.className.split(" ").filter(Boolean).join(".")}`:""}]`:null,i={...n,element:r};return console.log(`[HybridTargetResolver] consensus results (${n.confidence.toFixed(1)}% confidence)`,this.safeStringify(i,2)),n.element?n.element:null}static resolveTargetWithConsensus(e){var f;const n=performance.now(),r=this.getAvailableStrategies(e);if(r.length===0)return console.warn("[HybridTargetResolver] ⚠️ No strategies available for target"),{element:null,confidence:0,strategies:[],candidateCount:0,ambiguous:!1,duration:performance.now()-n};console.log(`[HybridTargetResolver] 🔄 Running ${r.length} strategies in parallel...`);const i=new Map;for(const h of r){const b=this.executeStrategyMulti(h,e);for(const y of b)Ct(y)||y.isConnected&&(i.has(y)?i.get(y).strategies.push(h):i.set(y,{element:y,strategies:[h],validationScore:0,interactable:!1,confidence:0}))}if(console.log(`[HybridTargetResolver] 📊 Found ${i.size} unique candidate(s)`),i.size===0)return{element:null,confidence:0,strategies:[],candidateCount:0,ambiguous:!1,duration:performance.now()-n};const o=[];for(const[h,b]of i){if(!h.isConnected){console.warn("[HybridTargetResolver] ⚠️ Candidate element was removed from DOM, skipping");continue}b.validationScore=this.computeValidationScore(h,e),b.interactable=this.checkInteractability(h).ok,b.confidence=this.computeConfidence(b,r.length,e),o.push(b),console.log(`[HybridTargetResolver] <${h.tagName.toLowerCase()}> "${(f=h.textContent)==null?void 0:f.slice(0,25)}..."`),console.log(`[HybridTargetResolver] Strategies: ${b.strategies.join(", ")} (${b.strategies.length}/${r.length})`),console.log(`[HybridTargetResolver] Confidence: ${b.confidence.toFixed(1)}%`)}if(o.length===0)return{element:null,confidence:0,strategies:[],candidateCount:i.size,ambiguous:!1,duration:performance.now()-n};o.sort((h,b)=>b.confidence-h.confidence);const s=o[0],a=o.length>1?o[1]:void 0,l=performance.now()-n,c=a!==void 0&&s.confidence-a.confidence<10;if(c&&console.warn("[HybridTargetResolver] ⚠️ AMBIGUOUS: Top candidates have similar confidence"),s.confidence<30)return console.warn(`[HybridTargetResolver] ❌ Best candidate confidence too low: ${s.confidence.toFixed(1)}%`),{element:null,confidence:s.confidence,strategies:s.strategies,candidateCount:i.size,ambiguous:c,duration:l};if(!s.interactable){const h=o.find(b=>b.interactable);if(h&&h.confidence>30)return console.log(`[HybridTargetResolver] ✅ Using interactable candidate (${h.confidence.toFixed(1)}%)`),{element:this.getClickableContainer(h.element),confidence:h.confidence,strategies:h.strategies,candidateCount:i.size,ambiguous:c,duration:l}}return console.log(`[HybridTargetResolver] ✅ Winner: ${s.confidence.toFixed(1)}% confidence (${l.toFixed(1)}ms)`),{element:this.getClickableContainer(s.element),confidence:s.confidence,strategies:s.strategies,candidateCount:i.size,ambiguous:c,duration:l}}static isValidCSSSelector(e){if(!e||typeof e!="string")return!1;if(/^(role|text|label|placeholder)=/.test(e))return console.warn(`[HybridTargetResolver] Skipping Playwright-style selector (not CSS): "${e.substring(0,50)}..."`),!1;try{return document.querySelector(e),!0}catch{return console.warn(`[HybridTargetResolver] Invalid CSS selector: "${e.substring(0,50)}..."`),!1}}static executeStrategyMulti(e,n){const r=[];try{switch(e){case"selector":{const i=new Set,o=[n.selector,...n.selectorFallbacks||[]].filter(a=>!!a),s=[];for(const a of o){this.isValidCSSSelector(a)&&s.push(a);const l=fy(a);l!==a&&this.isValidCSSSelector(l)&&!s.includes(l)&&s.push(l)}for(const a of s)try{document.querySelectorAll(a).forEach(l=>i.add(l))}catch{console.warn(`[HybridTargetResolver] querySelectorAll failed for: "${a.substring(0,50)}..."`)}r.push(...i);break}case"text":n.text&&r.push(...this.findAllByText(n.text));break;case"ariaLabel":n.ariaLabel&&document.querySelectorAll(`[aria-label*="${CSS.escape(n.ariaLabel)}"]`).forEach(i=>r.push(i));break;case"placeholder":n.placeholder&&document.querySelectorAll(`[placeholder*="${CSS.escape(n.placeholder)}"]`).forEach(i=>r.push(i));break;case"role":n.role&&document.querySelectorAll(`[role="${n.role}"]`).forEach(i=>r.push(i));break;case"labelText":{if(n.labelText){let i=n.selector||"";(!i||/react-select-\d+/.test(i))&&(n.role?i=`[role="${n.role}"]`:n.tag?i=n.tag:i="*");const o=this.findElementByLabelText(n.labelText,i);o&&r.push(o)}break}case"optionText":{if(n.optionText){const i=this.findDropdownOptionByText(n.optionText);i&&r.push(i)}break}case"removeChip":{if(n.removeChipText){const i=this.findMultiSelectChipRemoveButton(n.removeChipText);i&&r.push(i)}break}case"tag":{if(n.tag){const i=document.getElementsByTagName(n.tag);for(const o of i)(!n.text||(o.textContent||"").toLowerCase().includes(n.text.toLowerCase()))&&r.push(o)}break}case"domIndex":if(n.domIndex!==void 0){const i=this.findByDomIndex(n.domIndex);i&&r.push(i)}break;case"boundingBox":{if(n.boundingBox){const i=this.findByBoundingBox(n.boundingBox,n.tag,n.text);i&&r.push(i)}break}}}catch(i){console.warn(`[HybridTargetResolver] Strategy "${e}" threw error:`,i)}return r}static findAllByText(e,n){var b,y;const r=[],i=new Set;if(!e)return r;const o=e.trim();if(!o)return r;const s=n||"*",a=this.escapeXPathString(o),l=`//${s}[normalize-space(.)=${a}]`;try{const g=document.evaluate(l,document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);for(let S=0;S<g.snapshotLength;S++){const v=g.snapshotItem(S);v&&!this.isDropdownDisplayValue(v)&&!i.has(v)&&(r.push(v),i.add(v))}}catch{}const c=`//${s}[contains(normalize-space(.), ${a})]`;try{const g=document.evaluate(c,document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);for(let S=0;S<g.snapshotLength;S++){const v=g.snapshotItem(S);v&&!this.isDropdownDisplayValue(v)&&!i.has(v)&&(r.push(v),i.add(v))}}catch{}const d=[];for(const g of r)if(!this.isInteractiveElement(g)){const S=this.findNearbyInput(g);S&&!i.has(S)&&(console.log(`[HybridTargetResolver] → Found nearby input for label "${(b=g.textContent)==null?void 0:b.trim().substring(0,30)}": <${S.tagName.toLowerCase()}>`),d.push(S),i.add(S))}r.push(...d);const f=o.toLowerCase(),h=document.querySelectorAll("input, textarea");for(const g of h){const S=g;if(Ct(S)||i.has(S))continue;const v=((y=S.getAttribute("placeholder"))==null?void 0:y.trim().toLowerCase())||"";if(v===f||v&&v.includes(f)&&f.length/v.length>.6){const w=S.getBoundingClientRect();w.width>0&&w.height>0&&(r.push(S),i.add(S))}}return r}static isInteractiveElement(e){return!!(["INPUT","BUTTON","SELECT","TEXTAREA","A"].includes(e.tagName)||e.getAttribute("role")==="button"||e.getAttribute("role")==="combobox"||e.getAttribute("role")==="textbox"||e.getAttribute("role")==="listbox"||e.getAttribute("contenteditable")==="true"||e.getAttribute("tabindex")!==null&&e.getAttribute("tabindex")!=="-1")}static findNearbyInput(e){if(e.tagName==="LABEL"){const i=e.getAttribute("for");if(i){const o=document.getElementById(i);if(o)return o}}let n=e.nextElementSibling;for(let i=0;i<3&&n;i++){const o=this.findFirstInput(n);if(o)return o;n=n.nextElementSibling}const r=e.parentElement;if(r){const i=r.querySelectorAll('input, textarea, select, [role="combobox"], [role="listbox"], nz-select input, .ant-select input');for(const o of i)if(e.compareDocumentPosition(o)&Node.DOCUMENT_POSITION_FOLLOWING){const s=o.getBoundingClientRect();if(s.width>0&&s.height>0)return o}}return null}static findFirstInput(e){if(["INPUT","TEXTAREA","SELECT"].includes(e.tagName)||e.getAttribute("role")==="combobox"||e.getAttribute("role")==="listbox")return e;const n=e.querySelector('input, textarea, select, [role="combobox"], [role="listbox"]');if(n){const r=n.getBoundingClientRect();if(r.width>0&&r.height>0)return n}return null}static computeValidationScore(e,n){var c,d,f;let r=0,i=0,o=!1,s=!1;if(n.role){i+=25;const h=e.getAttribute("role");if(h===n.role)r+=25;else if(h)o=!0;else{const b=e.tagName.toLowerCase(),y=typeof e.className=="string"?e.className:"";b==="div"||b==="span"||e.classList.contains("container")||y.includes("control")||y.includes("wrapper")?r+=10:s=!0}}if(n.role==="combobox"&&e.querySelector('[role="combobox"]')&&(r+=10,i+=10),n.tag){i+=15;const h=e.tagName.toLowerCase(),b=n.tag.toLowerCase();h===b?r+=15:n.role==="combobox"&&(h==="input"||h==="div")&&(r+=10)}if(n.text&&!n.optionText){i+=20;const h=(e.textContent||"").toLowerCase().trim(),b=n.text.toLowerCase().trim();if(n.role==="combobox"&&e.tagName.toLowerCase()==="input"){const y=(c=e.closest('.css-6lmz24, [class*="value-container"], [class*="placeholder"]'))==null?void 0:c.parentElement,g=y==null?void 0:y.querySelector('[class*="placeholder"], [id*="placeholder"]'),S=((d=g==null?void 0:g.textContent)==null?void 0:d.toLowerCase().trim())||"";(S===b||S.includes(b))&&(r+=20)}else if(h===b)r+=20;else if(h.includes(b)){const y=b.length/h.length;y>.8?r+=15:y>.5?r+=8:(new RegExp(`\\b${lr.escapeRegex(b)}\\b`,"i").test(h)?r+=2:r+=0,console.log(`[HybridTargetResolver] Text length mismatch: "${b}" (${b.length}) in "${h.slice(0,30)}..." (${h.length}), ratio=${y.toFixed(2)}, points=${r}`))}else if(b.includes(h)){const y=h.length/b.length;r+=Math.round(15*y)}}if(n.ariaLabel){i+=15;const h=e.getAttribute("aria-label")||"";h.toLowerCase()===n.ariaLabel.toLowerCase()?r+=15:h.toLowerCase().includes(n.ariaLabel.toLowerCase())&&(r+=10)}if(n.placeholder){i+=15;const h=e.placeholder||"",b=n.placeholder.toLowerCase();if(h.toLowerCase().includes(b))r+=15;else if(n.role==="combobox"){const y=e.closest('[class*="container"]')||e.parentElement,g=y==null?void 0:y.querySelector('[class*="placeholder"], [id*="placeholder"]');(((f=g==null?void 0:g.textContent)==null?void 0:f.toLowerCase().trim())||"").includes(b)&&(r+=15)}}if(n.labelText){i+=20;const h=this.getAssociatedLabelText(e);if(h){const b=h.toLowerCase().trim().replace(/\*$/,"").trim(),y=n.labelText.toLowerCase().trim().replace(/\*$/,"").trim();b===y?r+=20:(b.includes(y)||y.includes(b))&&(r+=15)}}if(n.optionText){i+=15;const b=(e.textContent||"").trim().toLowerCase(),y=n.optionText.toLowerCase().trim();b===y?r+=15:b.includes(y)&&(r+=10)}if(i===0)return 100;let a=Math.round(r/i*100);if(o?(a=Math.round(a*.3),console.log(`[HybridTargetResolver] Role mismatch penalty (30%): ${e.tagName}[role="${e.getAttribute("role")}"] vs target role="${n.role}"`)):s&&(e.closest('[role="listbox"], [role="menu"], [role="tree"]')||(a=Math.round(a*.7),console.log(`[HybridTargetResolver] No role penalty (70%): ${e.tagName} expected role="${n.role}"`))),e.getAttribute("tabindex")==="-1"&&(e.closest('[role="listbox"], [role="menu"], [role="combobox"], .select, [class*="dropdown"]')||e.tagName.toLowerCase()==="input"&&(a=Math.round(a*.85),console.log("[HybridTargetResolver] tabindex=-1 input penalty (85%): likely hidden placeholder"))),n.selector){const h=this.extractSelectorContext(n.selector);if(h.parentTag||h.parentSelector){const b=this.matchesSelectorContext(e,h);b>.5?a=Math.min(100,Math.round(a*1.15)):b<.5&&n.text&&(a=Math.round(a*.7))}}if(n.text){const h=e.tagName.toLowerCase(),b=e.getAttribute("role"),y=["button","a","input","select","textarea"].includes(h),g=["button","link","menuitem","option","tab","checkbox","radio"].includes(b||""),S=e.onclick!==null||e.hasAttribute("onclick"),v=e.closest('button, a, [role="button"], [role="link"]');y||g?(a=Math.min(100,Math.round(a*1.25)),console.log(`[HybridTargetResolver] Interactive element bonus (25%): <${h}> is natively interactive`)):v?a=Math.min(100,Math.round(a*1.15)):S&&(a=Math.min(100,Math.round(a*1.1)))}return a}static computeConfidence(e,n,r){if(n===0)return console.warn("[HybridTargetResolver] computeConfidence: totalStrategies is 0, returning 0"),0;const i=e.strategies.length/n*100,o=e.validationScore;let s=100;try{const c=e.element.getBoundingClientRect();(c.width===0||c.height===0)&&(s=0),e.interactable||(s*=.5)}catch{s=0}let a=0;if(e.strategies.includes("selector"))if(r.text){const c=(e.element.textContent||"").toLowerCase().trim(),d=r.text.toLowerCase().trim();c===d?(a=100,console.log("[HybridTargetResolver] Selector + exact text match bonus applied")):c.includes(d)?(a=70,console.log("[HybridTargetResolver] Selector + partial text match bonus applied")):(a=20,console.log("[HybridTargetResolver] Selector match but NO text match - reduced bonus"))}else a=100,console.log("[HybridTargetResolver] Selector match bonus applied (no text to validate)");return i*.3+o*.4+s*.15+a*.15}static checkInteractability(e){try{if(!e.isConnected)return{ok:!1,reason:"Element is not connected to DOM"};let n;try{n=window.getComputedStyle(e)}catch{return{ok:!1,reason:"Cannot compute style (element may be in different document)"}}if(n.display==="none")return{ok:!1,reason:"Element has display: none"};if(n.visibility==="hidden")return{ok:!1,reason:"Element has visibility: hidden"};const r=parseFloat(n.opacity);if(isNaN(r)||r===0)return{ok:!1,reason:"Element has opacity: 0"};if(n.pointerEvents==="none")return{ok:!1,reason:"Element has pointer-events: none"};if(e.disabled)return{ok:!1,reason:"Element is disabled"};if(e.getAttribute("aria-disabled")==="true")return{ok:!1,reason:"Element has aria-disabled: true"};if(!e.offsetParent&&n.position!=="fixed"&&n.position!=="sticky"){let o=e.parentElement,s=!1;for(;o&&o!==document.body;){try{const a=window.getComputedStyle(o);if(a.position==="fixed"||a.position==="sticky"){s=!0;break}}catch{break}o=o.parentElement}if(!s)return{ok:!1,reason:"Element is not rendered (offsetParent is null)"}}let i;try{i=e.getBoundingClientRect()}catch{return{ok:!1,reason:"Cannot get bounding rect (element may be in different frame)"}}return i.width===0||i.height===0?{ok:!1,reason:"Element has zero dimensions"}:{ok:!0}}catch(n){return console.warn("[HybridTargetResolver] checkInteractability error:",n),{ok:!1,reason:`Error checking interactability: ${n}`}}}static getAvailableStrategies(e){const n=[];return e.labelText&&n.push("labelText"),e.optionText&&n.push("optionText"),e.removeChipText&&n.push("removeChip"),e.selector&&n.push("selector"),e.domIndex!==void 0&&n.push("domIndex"),e.boundingBox&&n.push("boundingBox"),e.placeholder&&n.push("placeholder"),e.ariaLabel&&n.push("ariaLabel"),e.text&&n.push("text"),e.role&&n.push("role"),e.tag&&n.push("tag"),console.log("[HybridTargetResolver] Auto-detected available strategies:",n.join(", ")),n}static findByDomIndex(e){return e===void 0?null:this.domIntrospector?this.domIntrospector.findElementByIndex(e):null}static findByBoundingBox(e,n,r){if(!e)return null;if(this.domIntrospector)return this.domIntrospector.findElementByBoundingBox(e,n,r);const i=10,o=document.body.querySelectorAll("*");let s=null,a=0;return o.forEach(l=>{var g;const c=l;if(Ct(c))return;const d=c.getBoundingClientRect(),f=Math.abs(d.x-e.x),h=Math.abs(d.y-e.y),b=Math.abs(d.width-e.width),y=Math.abs(d.height-e.height);if(f<=i&&h<=i&&b<=i*2&&y<=i*2){let S=100-f-h;n&&c.tagName.toLowerCase()===n.toLowerCase()&&(S+=30),r&&(((g=c.innerText)==null?void 0:g.trim().toLowerCase())||"").includes(r.toLowerCase())&&(S+=25),S>a&&(a=S,s=c)}}),s}static validateElementMatchesTarget(e,n){var o;if(!n.labelText&&!n.optionText&&!n.role&&!n.ariaLabel&&!n.placeholder&&!n.name&&!n.tag&&!n.text)return!0;const r=[];if(n.tag){const s=e.tagName.toLowerCase(),a=n.tag.toLowerCase();if(s!==a&&["input","select","textarea","button","a"].includes(a))return console.log(`[HybridTargetResolver] Validation failed: tag="${s}" !== expected "${a}"`),!1;r.push("tag")}if(n.text&&!n.optionText){const s=(e.textContent||"").trim().toLowerCase(),a=n.text.trim().toLowerCase(),l=s===a,c=s.includes(a)||a.includes(s);if(!l&&!c)return console.log(`[HybridTargetResolver] Validation failed: text="${s.slice(0,50)}" !== expected "${a}"`),!1;if(a.length<=10&&!l){const d=a.length/Math.max(s.length,1);if(d<.5)return console.log(`[HybridTargetResolver] Validation failed: text match ratio too low (${d.toFixed(2)})`),!1}r.push("text")}const i=(s,a)=>{const l=s.toLowerCase().trim().replace(/\*$/,"").trim(),c=a.toLowerCase().trim();return l===c?!0:new RegExp(`(^|\\s)${c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}($|\\s|[:\\*\\?\\.\\,])`,"i").test(s)};if(n.role){const s=e.getAttribute("role");if(s!==n.role)return console.log(`[HybridTargetResolver] Validation failed: role="${s}" !== expected "${n.role}"`),!1;r.push("role")}if(n.ariaLabel){const s=e.getAttribute("aria-label")||"";if(!i(s,n.ariaLabel))return console.log(`[HybridTargetResolver] Validation failed: aria-label="${s}" !== expected "${n.ariaLabel}"`),!1;r.push("ariaLabel")}if(n.placeholder){const s=e.placeholder||"";if(!i(s,n.placeholder))return console.log(`[HybridTargetResolver] Validation failed: placeholder="${s}" !== expected "${n.placeholder}"`),!1;r.push("placeholder")}if(n.name){const s=e.getAttribute("name")||"";if(s!==n.name)return console.log(`[HybridTargetResolver] Validation failed: name="${s}" !== expected "${n.name}"`),!1;r.push("name")}if(n.labelText){const s=this.getAssociatedLabelText(e);if(!s||!i(s,n.labelText))return console.log(`[HybridTargetResolver] Validation failed: associated label="${s}" !== expected "${n.labelText}"`),!1;console.log(`[HybridTargetResolver] ✓ Label validation passed: "${s}" matches "${n.labelText}"`),r.push("labelText")}if(n.optionText){const s=((o=e.textContent)==null?void 0:o.trim())||"";if(!i(s,n.optionText))return console.log(`[HybridTargetResolver] Validation failed: option text="${s}" !== expected "${n.optionText}"`),!1;r.push("optionText")}return r.length>0&&console.log(`[HybridTargetResolver] ✓ Validated: ${r.join(", ")}`),!0}static getAssociatedLabelText(e){var s,a,l,c;const n=e.getAttribute("id");if(n)try{const d=document.querySelector(`label[for="${CSS.escape(n)}"]`);if(d)return((s=d.textContent)==null?void 0:s.trim().replace(/\*$/,"").trim())||null}catch{}const r=e.getAttribute("aria-labelledby");if(r){const d=r.split(/\s+/).filter(f=>f.length>0);for(const f of d){const h=document.getElementById(f);if(h)return((a=h.textContent)==null?void 0:a.trim().replace(/\*$/,"").trim())||null}}let i=e.parentElement,o=0;for(;i&&o<8;){const d=i.querySelectorAll('label, .MuiFormLabel-root, [class*="FormLabel"], [class*="form-label"], [class*="field-label"], .label');for(const f of d){if(e.contains(f)||f.contains(e)||f.querySelector('input, select, textarea, [role="combobox"]'))continue;if(i.querySelectorAll('input, select, textarea, [role="combobox"]').length===1){const b=(l=f.textContent)==null?void 0:l.trim().replace(/\*$/,"").trim();if(b&&b.length>0&&b.length<50)return b}else if(this.isLabelForElement(f,e,i)){const b=(c=f.textContent)==null?void 0:c.trim().replace(/\*$/,"").trim();if(b&&b.length>0&&b.length<50)return b}}i=i.parentElement,o++}return null}static isLabelForElement(e,n,r){const i=e.getBoundingClientRect(),o=n.getBoundingClientRect(),s=i.bottom<=o.top+30,a=i.right<=o.left+30&&Math.abs(i.top-o.top)<60;if(!s&&!a)return!1;const l=r.querySelectorAll('input, select, textarea, [role="combobox"]');if(l.length<=1)return!0;for(const c of l){if(c===n)continue;const d=c.getBoundingClientRect();if(s&&(d.top>=i.bottom-5&&d.bottom<o.top||Math.abs(d.left-i.left)<Math.abs(o.left-i.left)&&d.top<o.top))return!1;if(a){const f=Math.abs(d.left-i.right),h=Math.abs(o.left-i.right);if(f<h&&Math.abs(d.top-i.top)<40)return!1}}return!0}static isTextNearElement(e,n,r){const i=e.getBoundingClientRect(),o=n.getBoundingClientRect();if(i.width===0||i.height===0||o.width===0||o.height===0)return(e.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_FOLLOWING)!==0;const s=i.bottom<=o.top+40,a=i.right<=o.left+20&&Math.abs(i.top-o.top)<50;if(!s&&!a)return!1;for(const l of r){if(l===n)continue;const c=l.getBoundingClientRect();if(!(c.width===0||c.height===0)){if(s&&c.top>=i.bottom-10&&c.bottom<o.top||s&&Math.abs(c.left-i.left)<Math.abs(o.left-i.left)-20&&c.top<o.top&&c.top>=i.bottom-50)return!1;if(a){const d=Math.abs(c.left-i.right),f=Math.abs(o.left-i.right);if(d<f-10&&Math.abs(c.top-i.top)<40)return!1}}}return!0}static isHiddenPlaceholderInput(e){const n=e.tagName.toLowerCase(),r=e.getAttribute("role");if(r==="option"||r==="menuitem"||r==="treeitem"||e.closest('[role="listbox"], [role="menu"], [role="tree"]')||n!=="input"&&!r)return!1;if(e.getAttribute("tabindex")==="-1"&&n==="input")return console.log('[HybridTargetResolver] → Input has tabindex="-1" (hidden placeholder)'),!0;try{const o=window.getComputedStyle(e);if(o.opacity==="0")return console.log("[HybridTargetResolver] → Element has opacity: 0 (hidden placeholder)"),!0;if(o.visibility==="hidden")return console.log("[HybridTargetResolver] → Element has visibility: hidden (hidden placeholder)"),!0;const s=e.getBoundingClientRect();if(s.width<=5&&s.height<=5)return console.log(`[HybridTargetResolver] → Element is too small (${s.width}x${s.height}) - hidden placeholder`),!0;if(o.position==="absolute"){const a=e.parentElement;if(a&&a.getBoundingClientRect().width>s.width*10&&s.width<20)return console.log("[HybridTargetResolver] → Element is tiny absolute-positioned (hidden placeholder)"),!0}}catch{}return!1}static getClickableContainer(e){var o,s;if(!this.isHiddenPlaceholderInput(e))return e;console.log("[HybridTargetResolver] → Looking for clickable container...");const n=['[class*="-control"]','[class*="control"]',".MuiSelect-select",".MuiInputBase-root",".MuiOutlinedInput-root",'[role="button"]','[role="combobox"]:not(input)','[aria-haspopup="listbox"]','[class*="select-container"]','[class*="dropdown-container"]','[class*="picker"]'];let r=e.parentElement,i=0;for(;r&&i<6;){for(const l of n)try{if(r.matches(l)){const c=r.getBoundingClientRect();if(c.width>50&&c.height>20)return console.log(`[HybridTargetResolver] → Found clickable container: ${r.tagName}.${(o=r.className)==null?void 0:o.split(" ").slice(0,2).join(".")}`),r}}catch{}const a=r.getBoundingClientRect();if(a.width>100&&a.height>30){const l=r.getAttribute("role"),c=r.onclick!==null||r.getAttribute("onclick")!==null||r.classList.contains("clickable");if(l==="button"||l==="combobox"||c||r.querySelector('input[role="combobox"]')===e)return console.log(`[HybridTargetResolver] → Found clickable container (generic): ${r.tagName}.${(s=r.className)==null?void 0:s.split(" ").slice(0,2).join(".")}`),r}r=r.parentElement,i++}return console.log("[HybridTargetResolver] → No clickable container found, using original element"),e}static findBySelector(e){if(!e)return null;const n=e.replace(/\\"/g,'"').replace(/\\ /g," ").replace(/\\\\/g,"\\");console.log(`[HybridTargetResolver] → Normalized selector: "${n}"`);const r=n.match(/\[data-option-text="([^"]+)"\]/);if(r){const l=r[1];return console.log(`[HybridTargetResolver] → Virtual selector - searching for option text: "${l}"`),this.findDropdownOptionByText(l)}const i=n.match(/\[data-label="([^"]+)"\]/);if(i){const l=i[1];return console.log(`[HybridTargetResolver] → Virtual selector - searching for combobox with label: "${l}"`),this.findComboboxByLabel(l)}const o=n.replace(/\[data-option-text="[^"]*"\]/g,"").replace(/\[data-label="[^"]*"\]/g,"").replace(/\[data-index="[^"]*"\]/g,"").trim();if(/#?react-select-\d+-(input|listbox|option|placeholder|live-region)/.test(o))return console.log(`[HybridTargetResolver] → Detected unstable React-Select ID pattern in "${o}", skipping selector strategy`),null;if(o==='input[role="combobox"]'||o==='[role="combobox"]'){const l=document.querySelectorAll(o);l.length>1&&(console.warn(`[HybridTargetResolver] ⚠️ AMBIGUOUS SELECTOR: "${o}" matches ${l.length} elements!`),console.warn("[HybridTargetResolver] ⚠️ Bot should send more specific targeting (text, label, boundingBox, domIndex)"),l.forEach((c,d)=>{const f=c,h=f.getAttribute("placeholder")||"",b=f.getAttribute("aria-label")||"",y=f.id||"";console.log(`[HybridTargetResolver] ${d}: id="${y}" placeholder="${h}" aria-label="${b}"`)}))}const a=document.querySelector(o);return a?this.isAccessibilityOnlyElement(a)?(console.log(`[HybridTargetResolver] → Selector matched a11y-only element (class: ${a.className}), skipping`),null):a:(console.log(`[HybridTargetResolver] → Selector "${o}" matched 0 elements`),null)}static isAccessibilityOnlyElement(e){const n=typeof e.className=="string"?e.className:"",r=(e.textContent||"").trim();if(n.includes("a11yText")&&!r||n.includes("sr-only")||n.includes("visually-hidden")||n.includes("screenreader")||n.includes("screen-reader")||e.getAttribute("aria-live")&&!r||e.getAttribute("role")==="log"&&!r)return!0;try{const i=getComputedStyle(e);if(i.position==="absolute"&&(i.width==="1px"||i.height==="1px"||i.clip==="rect(0px, 0px, 0px, 0px)"||i.clipPath==="inset(50%)"))return!0}catch{}return!1}static isDropdownDisplayValue(e){var a;const n=(e.className||"").toLowerCase(),r=(((a=e.parentElement)==null?void 0:a.className)||"").toLowerCase(),i=["singlevalue","single-value","selectedvalue","selected-value","placeholder","value-container","valuecontainer","muiselect-select","select__single-value"];for(const l of i)if(n.includes(l)||r.includes(l))return!0;const o=e.closest('[class*="-control"]:not([class*="-menu"])'),s=!e.closest('[role="listbox"], [role="menu"], [class*="-menu"]');return!!(o&&s)}static findDropdownOptionByText(e){var o,s,a;const n=e.toLowerCase().trim(),r=['[role="listbox"]','[role="menu"]','[class*="-menu"]:not([aria-hidden="true"])','[class*="listbox"]','[class*="options-container"]',".ant-select-dropdown","nz-option-container",".cdk-overlay-pane"],i=["singleValue","single-value","selectedValue","selected-value","placeholder","value-container","MuiSelect-select"];for(const l of r){let c;try{c=document.querySelectorAll(l)}catch{continue}for(const d of c){const f=d;if(!lr.isVisible(f)||f.getBoundingClientRect().height<20)continue;const b=d.querySelectorAll('[role="option"], [class*="option"]:not([class*="singleValue"]):not([class*="placeholder"]), nz-option-item, .ant-select-item-option, .ant-select-item-option-content');for(const y of b){const g=y,S=g.className||"";if(i.some(k=>S.toLowerCase().includes(k.toLowerCase()))){console.log(`[HybridTargetResolver] → Skipping display value: "${(o=g.textContent)==null?void 0:o.trim().substring(0,30)}..."`);continue}if(!g.closest('[role="listbox"], [role="menu"], [class*="-menu"]'))continue;const w=((s=g.textContent)==null?void 0:s.trim().toLowerCase())||"";if(w===n||w.includes(n))return console.log(`[HybridTargetResolver] → Found ACTUAL option in open menu: "${(a=g.textContent)==null?void 0:a.trim()}"`),g}}}return console.log(`[HybridTargetResolver] → No option "${e}" found in any open dropdown menu`),console.log("[HybridTargetResolver] → The dropdown may need to be opened first"),null}static findMultiSelectChipRemoveButton(e){var i;const n=e.toLowerCase().trim();console.log(`[HybridTargetResolver] → Searching for multi-select chip: "${e}"`);const r=['[class*="multiValue"]','[class*="multi-value"]','[class*="chip"]','[class*="tag"]',"[data-tag]"];for(const o of r){let s;try{s=document.querySelectorAll(o)}catch{continue}for(const a of s){const l=a;if(!this.isVisible(l))continue;const c=l.querySelector('[class*="label"], [class*="Label"], span:first-of-type'),d=c?(c.textContent||"").trim().toLowerCase():(l.textContent||"").replace(/×|✕|x/gi,"").trim().toLowerCase();if(d===n||d.includes(n)||n.includes(d)){console.log(`[HybridTargetResolver] → Found chip with text: "${(i=l.textContent)==null?void 0:i.trim().substring(0,30)}..."`);const f=['[role="button"]','[class*="remove"]','[class*="Remove"]','[class*="clear"]','[class*="delete"]','[aria-label*="Remove"]','[aria-label*="remove"]','[aria-label*="Delete"]','[aria-label*="delete"]',"button","svg"];for(const h of f){const b=l.querySelector(h);if(b&&this.isVisible(b))return console.log(`[HybridTargetResolver] → Found remove button: <${b.tagName.toLowerCase()}> with selector "${h}"`),b}return console.log("[HybridTargetResolver] → No specific remove button found, returning chip container"),l}}}return console.log(`[HybridTargetResolver] → No chip found with text: "${e}"`),null}static findComboboxByLabel(e){const n=e.toLowerCase().trim(),r=a=>a.toLowerCase().trim().replace(/\*$/,"").trim()===n?!0:new RegExp(`(^|\\s)${n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}($|\\s|[:\\*\\?\\.\\,])`,"i").test(a),i=document.querySelectorAll("label[for]");for(const a of i)if(r(a.textContent||"")){const l=a.getAttribute("for");if(l){const c=document.getElementById(l);if(c&&(c.getAttribute("role")==="combobox"||c.getAttribute("aria-haspopup")==="listbox"))return console.log(`[HybridTargetResolver] → Found combobox via label[for]: "${e}"`),c}}const o=document.querySelectorAll('input[role="combobox"], button[aria-haspopup="listbox"], [role="combobox"]');for(const a of o){const l=a.getAttribute("aria-labelledby");if(l){const c=document.getElementById(l.split(/\s+/)[0]);if(c&&r(c.textContent||""))return console.log(`[HybridTargetResolver] → Found combobox via aria-labelledby: "${e}"`),a}}const s=document.querySelectorAll("label");for(const a of s)if(r(a.textContent||"")){const l=a.closest('fieldset, [role="group"], form > div, [class*="form"], [class*="field"]')||a.parentElement;if(l){const c=l.querySelector('input[role="combobox"], button[aria-haspopup="listbox"], [role="combobox"]');if(c&&this.isElementVisible(c))return console.log(`[HybridTargetResolver] → Found combobox in label container: "${e}"`),c}}return null}static isElementVisible(e){const n=e.getBoundingClientRect();if(n.width===0||n.height===0)return!1;if(!e.offsetParent)try{const r=window.getComputedStyle(e);if(r.position!=="fixed"&&r.position!=="sticky")return!1}catch{return!1}return!0}static findElementByLabelText(e,n){var b,y,g;const i=n.replace(/\\"/g,'"').replace(/\\ /g," ").replace(/\\\\/g,"\\").replace(/\[data-label="[^"]*"\]/g,"").replace(/\[data-option-text="[^"]*"\]/g,"").replace(/\[data-index="[^"]*"\]/g,"").trim(),o=i.toLowerCase().trim(),s=["*","div","span","p","a","li","ul","section","article"],a=/\[role=/.test(i);if(s.includes(o)&&!a)return null;let l;try{l=document.querySelectorAll(i)}catch{return console.warn(`[HybridTargetResolver] → Invalid selector: "${i}"`),null}if(l.length===0)return null;console.log(`[HybridTargetResolver] → Looking for "${i}" associated with label "${e}"`),console.log(`[HybridTargetResolver] → Found ${l.length} elements matching selector`);const c=e.toLowerCase().trim();function d(S){return S.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}const f=S=>S.toLowerCase().trim().replace(/\*$/,"").trim()===c?!0:new RegExp(`(^|\\s)${d(c)}($|\\s|[:\\*\\?\\.\\,\\)\\]\\}\\-])`,"i").test(S),h=S=>{const v=S,w=v.getBoundingClientRect();if(w.width===0||w.height===0)return!1;if(!v.offsetParent)try{const C=window.getComputedStyle(v).position;if(C!=="fixed"&&C!=="sticky")return!1}catch{return!1}return!0};for(const S of l){if(!h(S))continue;const v=S.getAttribute("id");if(v)try{const D=document.querySelector(`label[for="${CSS.escape(v)}"]`);if(D&&f(D.textContent||""))return console.log("[HybridTargetResolver] → Found via label[for] attribute"),S}catch{}const w=S.getAttribute("aria-labelledby");if(w){const D=w.split(/\s+/).filter(F=>F.length>0);for(const F of D){const J=document.getElementById(F);if(J&&f(J.textContent||""))return console.log("[HybridTargetResolver] → Found via aria-labelledby"),S}}const k=S.getAttribute("aria-label")||"";if(k&&f(k))return console.log("[HybridTargetResolver] → Found via aria-label"),S;const C=S.getAttribute("placeholder")||"";if(C&&f(C))return console.log("[HybridTargetResolver] → Found via placeholder"),S;let M=S.parentElement,O=0;for(;M&&O<6;){const D=M.querySelectorAll('input, select, textarea, [role="combobox"], [role="listbox"]'),F=Array.from(D),J=F.includes(S),W=M.classList.contains("MuiFormControl-root")||M.tagName==="FIELDSET"||/form(-|_)?(field|group|control|item|row)/i.test(M.className)||M.childElementCount>=2&&M.childElementCount<=5,U=M.querySelectorAll('label, [class*="label"]:not(input):not(select):not(textarea):not([role="combobox"]), .MuiFormLabel-root, [class*="FormLabel"], [class*="form-label"], [class*="field-label"]');for(const V of U){if(S.contains(V)||V.contains(S)||V.querySelector('input, select, textarea, [role="combobox"]'))continue;const q=((b=V.textContent)==null?void 0:b.trim())||"";if(!(q.length>50)&&f(q)){if(D.length===1&&J)return console.log(`[HybridTargetResolver] → Found via label in container: "${q}"`),S;if(J&&this.isTextNearElement(V,S,F))return console.log(`[HybridTargetResolver] → Found via label position: "${q}"`),S}}if(W||O>=3){const V=M.querySelectorAll(":scope > div, :scope > span, :scope > p, :scope > div > div, :scope > div > span, :scope > div > p");for(const q of V){if(q.querySelector('input, select, textarea, [role="combobox"]')||q.contains(S)||S.contains(q))continue;const ie=S.value||"";if(ie&&((y=q.textContent)==null?void 0:y.trim())===ie)continue;const H=((g=q.textContent)==null?void 0:g.trim())||"";if(H.length>0&&H.length<=30&&f(H)){if(D.length===1&&J)return console.log(`[HybridTargetResolver] → Found via nearby text: "${H}"`),S;if(J&&this.isTextNearElement(q,S,F))return console.log(`[HybridTargetResolver] → Found via nearby text (position): "${H}"`),S}}}M=M.parentElement,O++}}return null}static escapeXPathString(e){const n=e.replace(/[\n\r\t]+/g," ").replace(/\s+/g," ").trim();if(n.includes('"')&&n.includes("'")){const r=n.split('"');return`concat(${r.map((o,s)=>s===r.length-1?`"${o}"`:`"${o}", '"'`).join(", ")})`}return n.includes('"')?`'${n}'`:`"${n}"`}static escapeRegex(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}static findByText(e,n,r){var C,M,O,D,F,J,W;if(!e)return null;const i=e.trim();if(!i)return null;const o=i.toLowerCase(),s=n||"*",a=this.escapeXPathString(i);if(r){const U=this.findElementByLabelText(i,r);if(U)return console.log(`[HybridTargetResolver] → Found element matching selector "${r}" associated with label "${i}"`),U}const l=`//${s}[normalize-space(.)=${a}]`;console.log(`[HybridTargetResolver] → XPath exact query: ${l}`);let c;try{c=document.evaluate(l,document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null)}catch(U){console.warn("[HybridTargetResolver] → XPath query failed:",U),c={snapshotLength:0,snapshotItem:()=>null}}if(c.snapshotLength>0){console.log(`[HybridTargetResolver] → Found ${c.snapshotLength} exact match(es), checking visibility...`);let U=null,V=null;for(let q=0;q<c.snapshotLength;q++){const ie=c.snapshotItem(q);if(V||(V=ie),this.isDropdownDisplayValue(ie)){console.log(`[HybridTargetResolver] → Skipping display value (not an option): "${(C=ie.textContent)==null?void 0:C.trim().substring(0,30)}..."`);continue}const H=ie.getBoundingClientRect();if(H.width>0&&H.height>0){U=ie,console.log(`[HybridTargetResolver] → Returning visible match ${q}: "${(M=ie.textContent)==null?void 0:M.trim().substring(0,30)}..."`);break}}if(U)return U;if(V&&!this.isDropdownDisplayValue(V))return console.log("[HybridTargetResolver] → No visible matches, returning first (possibly hidden) element"),V}console.log("[HybridTargetResolver] → No exact match, trying partial match...");const d=`//${s}[contains(normalize-space(.), ${a})]`;console.log(`[HybridTargetResolver] → XPath partial query: ${d}`);let f;try{f=document.evaluate(d,document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null)}catch(U){console.warn("[HybridTargetResolver] → XPath partial query failed:",U),f={snapshotLength:0,snapshotItem:()=>null}}if(f.snapshotLength>0){let U=null,V=-1;const q=r?this.extractSelectorContext(r):{},ie=!!(q.parentTag||q.parentSelector);console.log(`[HybridTargetResolver] → Selector context: parentTag="${q.parentTag||"none"}", expectedTag="${q.expectedTag||"none"}"`);for(let H=0;H<f.snapshotLength;H++){const G=f.snapshotItem(H),ne=(G.textContent||"").trim();if(ne.length===0)continue;const R=ne.toLowerCase(),j=o.length/R.length,Q=G.getBoundingClientRect();if(Q.width===0||Q.height===0||this.isDropdownDisplayValue(G))continue;let ae=j;if(new RegExp(`\\b${lr.escapeRegex(o)}\\b`,"i").test(R))ae+=.5;else if(j<.5)if(ie){if(this.matchesSelectorContext(G,q)<.5){console.log(`[HybridTargetResolver] → Skipping low ratio match that doesn't match selector context: "${ne.slice(0,30)}..."`);continue}}else{console.log(`[HybridTargetResolver] → Skipping low ratio match (${j.toFixed(2)}): "${ne.slice(0,30)}..."`);continue}if(ie){const m=this.matchesSelectorContext(G,q);ae+=m*.3}ae>V&&(V=ae,U=G)}if(U)return console.log(`[HybridTargetResolver] → XPath partial match found (score=${V.toFixed(2)})!`),U}console.log("[HybridTargetResolver] → XPath found nothing, trying fallback...");const h=document.querySelectorAll(n||"*");console.log(`[HybridTargetResolver] → Fallback: checking ${h.length} <${n||"*"}> elements for text "${i}"`);const b=U=>{const V=U;return Ct(V)?!0:V.id==="root"||V.id==="app"||V.id==="__next"||V.tagName==="BODY"||V.tagName==="HTML"};for(const U of h){if(b(U)||(((O=U.textContent)==null?void 0:O.trim().toLowerCase())||"")!==o)continue;const q=U.getBoundingClientRect();if(q.width>0&&q.height>0&&(((D=U.innerText)==null?void 0:D.trim().toLowerCase())||"")===o)return console.log("[HybridTargetResolver] → Found via exact text match"),U}let y=null,g=-1/0;for(const U of h){if(b(U))continue;const V=((F=U.textContent)==null?void 0:F.trim().toLowerCase())||"";if(V.length!==0&&V.includes(o)){const q=o.length/V.length,ie=U.getBoundingClientRect(),H=ie.width*ie.height;if(H>0&&H<5e5){const G=Math.max(0,50-H/1e4),ne=q*50,R=G+ne;R>g&&(g=R,y=U)}}}if(y){const U=y.getBoundingClientRect();return console.log(`[HybridTargetResolver] → Found via textContent (${U.width.toFixed(0)}x${U.height.toFixed(0)}px, score=${g.toFixed(0)})`),y}const S=n&&["input","textarea"].includes(n.toLowerCase())?n.toLowerCase():"input, textarea",v=document.querySelectorAll(S);console.log(`[HybridTargetResolver] → Checking ${v.length} input/textarea elements for placeholder "${i}"`);for(const U of v){const V=U;if(Ct(V))continue;const q=((J=V.getAttribute("placeholder"))==null?void 0:J.trim())||"";if(q.toLowerCase()===o){const ie=V.getBoundingClientRect();if(ie.width>0&&ie.height>0)return console.log(`[HybridTargetResolver] → Found via placeholder match: "${q}"`),V}}let w=null,k=0;for(const U of v){const V=U;if(Ct(V))continue;const q=((W=V.getAttribute("placeholder"))==null?void 0:W.trim().toLowerCase())||"";if(q&&q.includes(o)){const ie=o.length/q.length;if(ie>.6&&ie>k){const H=V.getBoundingClientRect();H.width>0&&H.height>0&&(w=V,k=ie)}}}return w?(console.log(`[HybridTargetResolver] → Found via partial placeholder match (ratio=${k.toFixed(2)})`),w):null}static findByAriaLabel(e){if(!e)return null;let n=document.querySelector(`[aria-label="${e}"]`);if(n)return console.log("[HybridTargetResolver] → Found via exact aria-label match"),n;const r=document.querySelectorAll("[aria-label]");console.log(`[HybridTargetResolver] → Checking ${r.length} elements with aria-label`);for(const i of r){const o=i.getAttribute("aria-label")||"";if(o.toLowerCase().includes(e.toLowerCase()))return console.log(`[HybridTargetResolver] → Found via partial aria-label match: "${o}"`),i}return null}static findByPlaceholder(e){if(!e)return null;let n=document.querySelector(`[placeholder="${e}"]`);if(n)return console.log("[HybridTargetResolver] → Found via exact placeholder match"),n;const r=document.querySelectorAll("input, textarea");console.log(`[HybridTargetResolver] → Checking ${r.length} input/textarea elements`);for(const i of r){const o=i.getAttribute("placeholder")||"";if(o.toLowerCase().includes(e.toLowerCase()))return console.log(`[HybridTargetResolver] → Found via partial placeholder match: "${o}"`),i}return null}static findByRole(e,n){var i;if(!e)return null;const r=document.querySelectorAll(`[role="${e}"]`);if(console.log(`[HybridTargetResolver] → Found ${r.length} elements with role="${e}"`),n){for(const o of r)if((((i=o.textContent)==null?void 0:i.trim())||"").toLowerCase().includes(n.toLowerCase()))return console.log("[HybridTargetResolver] → Found role element with matching text"),o}return r[0]||null}static findByTag(e,n){var i,o,s;if(!e)return null;const r=document.getElementsByTagName(e);if(console.log(`[HybridTargetResolver] → Found ${r.length} <${e}> elements`),n){const a=n.toLowerCase().trim();let l=null,c=null,d=0;for(const f of r){const h=f;if(h.id==="root"||h.id==="app"||h.tagName==="BODY"||h.tagName==="HTML"||!lr.isVisible(h)||(((i=h.innerText)==null?void 0:i.length)||0)>200)continue;const y=((o=h.innerText)==null?void 0:o.trim())||"",g=y.toLowerCase();if(g===a){console.log(`[HybridTargetResolver] → Found exact match: "${y.substring(0,50)}..."`),l=h;break}if(g.includes(a)){const S=a.length/g.length;S>.7&&S>d&&(c=h,d=S)}}if(l)return l;if(c){const f=((s=c.innerText)==null?void 0:s.trim().substring(0,50))||"";return console.log(`[HybridTargetResolver] → Found close match (${(d*100).toFixed(0)}%): "${f}..."`),c}return console.log(`[HybridTargetResolver] → No matching <${e}> found for text "${n}"`),null}if(e==="div"||e==="span")return console.log(`[HybridTargetResolver] → REFUSING to blindly return first <${e}> - too ambiguous without text`),null;for(const a of r){const l=a;if(l.id==="root"||l.id==="app"||l.tagName==="BODY"||l.tagName==="HTML"||l.classList.contains("App"))continue;const c=l.getBoundingClientRect();if(!(c.width>500&&c.height>500)&&c.width>0&&c.height>0)return l}return null}static isVisible(e){const n=e.getBoundingClientRect(),r=window.getComputedStyle(e);return n.width>0&&n.height>0&&r.display!=="none"&&r.visibility!=="hidden"&&r.opacity!=="0"}static scrollIntoView(e,n){console.log("[HybridTargetResolver] 📜 Scrolling element into view"),e.scrollIntoView({behavior:"smooth",block:"center",...n})}static async waitForPositionStability(e,n=1e3,r=50,i=2){console.log("[HybridTargetResolver] ⏳ Waiting for element position stability...");let o=e.getBoundingClientRect(),s=0;const a=3,l=Date.now();for(;Date.now()-l<n;){await new Promise(h=>setTimeout(h,r));const c=e.getBoundingClientRect();if(c.width===0||c.height===0)return console.warn("[HybridTargetResolver] ⚠️ Element disappeared during stability check"),null;const d=Math.abs(c.x-o.x),f=Math.abs(c.y-o.y);if(d<i&&f<i){if(s++,s>=a)return console.log(`[HybridTargetResolver] ✅ Element position stable at (${c.x.toFixed(0)}, ${c.y.toFixed(0)}) after ${Date.now()-l}ms`),c}else s=0,console.log(`[HybridTargetResolver] 📍 Element still moving: (${o.x.toFixed(0)}, ${o.y.toFixed(0)}) → (${c.x.toFixed(0)}, ${c.y.toFixed(0)})`);o=c}return console.warn(`[HybridTargetResolver] ⚠️ Position stability timeout after ${n}ms`),e.getBoundingClientRect()}static reResolveAndVerify(e,n){var a,l,c;const r={text:e.text,selector:e.selector,selectorFallbacks:e.selectorFallbacks,tag:e.tag,ariaLabel:e.ariaLabel,placeholder:e.placeholder,role:e.role,labelText:e.labelText,optionText:e.optionText,name:e.name,removeChipText:e.removeChipText,dropdownTriggerSelector:e.dropdownTriggerSelector,selectedValues:e.selectedValues,strategy:(a=e.strategy)==null?void 0:a.filter(d=>d!=="boundingBox"&&d!=="domIndex")};console.log("[HybridTargetResolver] 🔄 Re-resolving with position-independent target (no boundingBox/domIndex)");const i=this.resolveTarget(r);if(!i)return console.warn("[HybridTargetResolver] ⚠️ Re-resolution failed - element no longer found"),null;const o=((l=n.textContent)==null?void 0:l.trim().toLowerCase())||"",s=((c=i.textContent)==null?void 0:c.trim().toLowerCase())||"";return o!==s&&o&&s&&console.warn(`[HybridTargetResolver] ⚠️ Element changed during wait: "${o}" → "${s}"`),i}};L(lr,"domIntrospector",null);let xe=lr;class Nx{constructor(){L(this,"confirmationSound");L(this,"lastError",null);this.confirmationSound=new Audio("data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQAAAAA=")}humanLikeClick(e,n={}){return py(e,n)}async executeWithConsent(e,n=!0){try{if(n&&this.isDestructive(e)&&!await this.getConsent(e))return!1;const r=await this.execute(e);return r&&(this.confirmationSound.play().catch(()=>{}),console.log(`[ActionExecutor] Executed ${e.type} on ${e.selector}`)),r}catch(r){return console.error("[ActionExecutor] Failed to execute action:",r),!1}}async executeHybridAction(e,n=!0){this.lastError=null;try{if(console.log("[ActionExecutor] Executing hybrid action:",e),e.action==="navigate"){const s=e.value;if(!s)return console.warn("[ActionExecutor] Navigate action missing target URL"),this.lastError="Navigate action missing target URL",!1;let a;try{const l=new URL(s,window.location.origin);if(l.protocol!=="http:"&&l.protocol!=="https:")return console.warn("[ActionExecutor] Navigate blocked — disallowed scheme:",l.protocol),this.lastError=`Navigate blocked: disallowed URL scheme "${l.protocol}"`,!1;a=l.href}catch{return console.warn("[ActionExecutor] Navigate blocked — invalid URL:",s),this.lastError=`Navigate blocked: invalid URL "${s}"`,!1}return console.log("[ActionExecutor] 🧭 Navigating to URL:",a),window.location.href=a,!0}if(e.target.optionText&&e.action==="click"){console.log("[ActionExecutor] 🔽 Dropdown option click detected:",e.target.optionText);let s=xe.resolveTarget(e.target);if(!s){console.log("[ActionExecutor] Option not visible - dropdown may be closed, attempting to open...");let a=!1;if(e.target.dropdownTriggerSelector){console.log("[ActionExecutor] Using dropdownTriggerSelector:",e.target.dropdownTriggerSelector);const l=hy(e.target.dropdownTriggerSelector);l&&(this.handleComboboxClick(l),a=!0)}if(!a&&e.target.labelText){console.log("[ActionExecutor] Trying to find dropdown by label:",e.target.labelText);const l=this.findComboboxByLabel(e.target.labelText);l&&(this.handleComboboxClick(l),a=!0)}if(!a&&e.target.selector){console.log("[ActionExecutor] Trying to find dropdown by selector:",e.target.selector);const l={...e.target,optionText:void 0},c=xe.resolveTarget(l);if(c){const d=this.findComboboxInput(c);d&&(this.handleComboboxClick(d),a=!0)}}if(a){if(console.log("[ActionExecutor] Waiting for dropdown to open..."),await new Promise(l=>setTimeout(l,300)),s=xe.resolveTarget(e.target),!s)return console.warn("[ActionExecutor] ❌ Option still not found after opening dropdown:",e.target.optionText),!1;console.log("[ActionExecutor] ✅ Found option after opening dropdown")}else return console.warn("[ActionExecutor] ❌ Could not open dropdown - no trigger found. Add a separate task to open the dropdown first."),!1}return n&&this.isHybridActionDestructive(e)&&!await this.getHybridConsent(e)?!1:(xe.scrollIntoView(s),await new Promise(a=>setTimeout(a,100)),this.performClick(s),this.confirmationSound.play().catch(()=>{}),console.log(`[ActionExecutor] ✅ Successfully clicked dropdown option: "${e.target.optionText}"`),!0)}const r=xe.resolveTarget(e.target);if(!r)return console.warn("[ActionExecutor] Could not resolve target:",e.target),!1;if(n&&this.isHybridActionDestructive(e)&&!await this.getHybridConsent(e))return!1;const i=e.target.selector,o=await this.executeOnElement(e.action,r,e.value,i);return o&&(this.confirmationSound.play().catch(()=>{}),console.log(`[ActionExecutor] Successfully executed "${e.action}" on element`)),o}catch(r){return console.error("[ActionExecutor] Failed to execute hybrid action:",r),this.lastError=r instanceof Error?r.message:String(r),!1}}async executeOnElement(e,n,r,i){switch(xe.scrollIntoView(n),await new Promise(o=>setTimeout(o,300)),e){case"click":await this.expandCollapsedContainer(n),this.simulateClick(n,i);break;case"type":n instanceof HTMLInputElement||n instanceof HTMLTextAreaElement?(n.focus(),n.value=r||"",n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))):(n.focus(),n.textContent=r||"",n.dispatchEvent(new Event("input",{bubbles:!0})));break;case"focus":n.focus();break;case"hover":n.dispatchEvent(new MouseEvent("mouseenter",{bubbles:!0})),n.dispatchEvent(new MouseEvent("mouseover",{bubbles:!0}));break;case"scroll":n.scrollIntoView({behavior:"smooth",block:"center"});break;case"highlight":n.style.outline="3px solid #00aaff",n.style.outlineOffset="2px";break;default:return console.warn("[ActionExecutor] Unknown action type:",e),!1}return!0}async expandCollapsedContainer(e){const n=this.findCollapsedContainer(e);if(n){console.log("[ActionExecutor] Found collapsed container, hovering to expand...");const r=n.getBoundingClientRect(),i=r.left+r.width/2,o=r.top+r.height/2,s={bubbles:!0,cancelable:!0,view:window,clientX:i,clientY:o};n.dispatchEvent(new MouseEvent("mouseenter",s)),n.dispatchEvent(new MouseEvent("mouseover",s));const a=e.getBoundingClientRect(),l={bubbles:!0,cancelable:!0,view:window,clientX:a.left+a.width/2,clientY:a.top+a.height/2};e.dispatchEvent(new MouseEvent("mouseenter",l)),e.dispatchEvent(new MouseEvent("mouseover",l)),await new Promise(c=>setTimeout(c,400)),console.log("[ActionExecutor] Container expanded, proceeding with click")}}findCollapsedContainer(e){let n=e.parentElement;for(;n&&n!==document.body;){const r=window.getComputedStyle(n),i=n.getBoundingClientRect().width,o=r.transition.includes("width")||r.transitionProperty.includes("width")||r.transitionProperty==="all",s=i<80,a=n.offsetHeight>window.innerHeight*.7,l=typeof n.className=="string"?n.className:"",c=l.includes("sidebar")||l.includes("nav")||l.includes("menu");if(s&&(o||c)&&a)return console.log("[ActionExecutor] Detected collapsed container:",{width:i,hasTransition:o,isFullHeight:a,classes:n.className.substring(0,100)}),n;n=n.parentElement}return null}simulateClick(e,n){if(n){const d=this.parseOptionTextFromSelector(n);if(d){console.log("[ActionExecutor] 🎯 Detected dropdown option selector, searching for:",d);const h=this.findDropdownOption(d);if(h){console.log("[ActionExecutor] Found option by text, clicking it"),this.performClick(h);return}console.log("[ActionExecutor] Option not found by text, trying direct click")}const f=this.parseLabelFromSelector(n);if(f){console.log("[ActionExecutor] 🎯 Detected labeled combobox selector:",f);const h=this.findComboboxByLabel(f);if(h){console.log("[ActionExecutor] Found combobox by label, opening it"),this.handleComboboxClick(h);return}console.log("[ActionExecutor] Combobox not found by label, trying direct match")}}const r=this.findComboboxInput(e);if(r){console.log("[ActionExecutor] 🎯 Detected combobox/dropdown - using special handling"),this.handleComboboxClick(r);return}if(this.isDropdownOption(e)){console.log("[ActionExecutor] 🎯 Element is dropdown option - using React onClick + DOM events");const d=this.triggerReactOnClick(e);console.log(`[ActionExecutor] React onClick triggered: ${d}`),this.performClick(e);return}const i=this.findClickableElement(e),o=i.getBoundingClientRect(),s=o.left+o.width/2,a=o.top+o.height/2;if(i.focus&&i.focus(),this.hasReactOnClickHandler(i)){if(console.log("[ActionExecutor] 🎯 Element has React onClick - using direct call only"),this.triggerReactOnClick(i)){this.sendClickMetadata(i,e),console.log("[ActionExecutor] ✅ React onClick executed at",s,a,"on",i.tagName),i!==e&&console.log("[ActionExecutor] Note: Clicked parent",i.tagName,"instead of",e.tagName);return}console.log("[ActionExecutor] ⚠️ React onClick found but call failed, falling back to DOM events")}console.log("[ActionExecutor] Using humanLikeClick (no React onClick or fallback)");const c=this.humanLikeClick(i,{focus:!0,includePointerEvents:!0,nativeClickFallback:!1});c!==e&&c!==i&&console.log("[ActionExecutor] Note: humanLikeClick hit",c.tagName,"instead of element",e.tagName,"or clickTarget",i.tagName)}findComboboxInput(e){if(e.getAttribute("role")==="combobox")return console.log("[ActionExecutor] Element is combobox"),e;if(e.getAttribute("aria-haspopup")==="listbox"||e.getAttribute("aria-haspopup")==="true"){const o=e.querySelector('input[role="combobox"]');if(o)return console.log("[ActionExecutor] Found combobox via aria-haspopup container"),o;if(e.tagName==="BUTTON")return console.log("[ActionExecutor] Element is button with aria-haspopup"),e}let n=e,r=0;const i=5;for(;n&&r<i;){const o=typeof n.className=="string"?n.className:"",s=o.includes("css-")&&o.includes("control"),a=o.includes("css-")&&o.includes("ValueContainer"),l=o.includes("css-")&&o.includes("Indicator"),c=o.includes("MuiSelect-select")||o.includes("MuiAutocomplete-inputRoot"),d=(o.includes("headlessui")||o.includes("radix"))&&(o.includes("trigger")||o.includes("button"));if(s||a||l||c||d||o.includes("control")&&n.querySelector('input[role="combobox"]')||o.includes("trigger")&&n.getAttribute("aria-haspopup")){const h=n.querySelector('input[role="combobox"]');if(h)return console.log("[ActionExecutor] Found combobox input via control element"),h;const b=n.parentElement;if(b){const g=b.querySelector('input[role="combobox"]');if(g)return console.log("[ActionExecutor] Found combobox input in parent container"),g}const y=n.querySelector('button[aria-haspopup="listbox"]');if(y)return console.log("[ActionExecutor] Found listbox trigger button"),y}n=n.parentElement,r++}return null}parseOptionTextFromSelector(e){const r=e.replace(/\\"/g,'"').replace(/\\ /g," ").replace(/\\\\/g,"\\").match(/\[data-option-text="([^"]+)"\]/);return r?r[1]:null}parseLabelFromSelector(e){const r=e.replace(/\\"/g,'"').replace(/\\ /g," ").replace(/\\\\/g,"\\").match(/\[data-label="([^"]+)"\]/);return r?r[1]:null}stripVirtualAttributes(e){return e.replace(/\\"/g,'"').replace(/\\ /g," ").replace(/\\\\/g,"\\").replace(/\[data-option-text="[^"]*"\]/g,"").replace(/\[data-label="[^"]*"\]/g,"").replace(/\[data-index="[^"]*"\]/g,"").trim()}findComboboxByLabel(e){var r;const n=document.querySelectorAll("label");for(const i of n){const o=(r=i.textContent)==null?void 0:r.trim().replace(/\*$/,"").trim();if(o===e||o!=null&&o.includes(e)){const s=i.closest('div[class*="container"], div[aria-label], .MuiFormControl-root, form > div');if(s){const a=s.querySelector('input[role="combobox"], button[aria-haspopup="listbox"]');if(a)return console.log("[ActionExecutor] Found combobox by label:",e),a}}}return null}handleComboboxClick(e){console.log("[ActionExecutor] Opening combobox/dropdown with humanLikeClick");const r=e.closest('[class*="control"]')||e.closest('[class*="trigger"]')||e.closest("[aria-haspopup]")||e.parentElement||e,i=this.humanLikeClick(r,{focus:!0,includePointerEvents:!0,nativeClickFallback:!1});e.dispatchEvent(new FocusEvent("focus",{bubbles:!0})),e instanceof HTMLInputElement&&e.dispatchEvent(new Event("input",{bubbles:!0})),console.log("[ActionExecutor] ✅ Combobox/dropdown humanLikeClick complete, actual element:",i.tagName)}openDropdown(e){this.handleComboboxClick(e)}triggerReactOnClickPublic(e){return this.triggerReactOnClick(e)}findDropdownOption(e){var r;const n=['[role="listbox"]','[role="menu"]','[class*="menu"]:not([aria-hidden])','[class*="listbox"]','[class*="options"]',"[data-radix-popper-content-wrapper]",".MuiMenu-list",".MuiAutocomplete-listbox",".ant-select-dropdown","nz-option-container",".cdk-overlay-pane"];for(const i of n){const o=document.querySelectorAll(i);for(const s of o){if(!xe.isVisible(s))continue;const a=['[role="option"]','[class*="option"]','[class*="item"]',"nz-option-item",".ant-select-item-option",".ant-select-item-option-content","li"];for(const l of a){const c=s.querySelectorAll(l);for(const d of c){const f=(r=d.textContent)==null?void 0:r.trim();if(f===e||f!=null&&f.includes(e))return console.log("[ActionExecutor] Found dropdown option:",f),d}}}}return null}isDropdownOption(e){if(e.getAttribute("role")==="option")return!0;const n=typeof e.className=="string"?e.className:"";return n.includes("option")||n.includes("item")?e.closest('[role="listbox"], [role="menu"], [class*="menu"], [class*="listbox"]')!==null:!1}performClick(e){this.humanLikeClick(e,{focus:!0,includePointerEvents:!0,nativeClickFallback:!0})}hasReactOnClickHandler(e){const n=["__reactProps","__reactFiber","__reactEventHandlers"];try{const o=Object.keys(e);for(const s of o)if(n.some(a=>s.startsWith(a))){const a=e[s];if(a!=null&&a.onClick)return!0}}catch{}let r=e.parentElement,i=0;for(;r&&i<5;){try{const o=Object.keys(r);for(const s of o)if(n.some(a=>s.startsWith(a))){const a=r[s];if(a!=null&&a.onClick)return!0}}catch{}r=r.parentElement,i++}return!1}findClickableElement(e){var a;const n=["SPAN","LABEL","P","H1","H2","H3","H4","H5","H6","TEXT","SVG","PATH"],r=l=>l.className?typeof l.className=="string"?l.className:typeof l.className.baseVal=="string"?l.className.baseVal:"":"";if(console.log("[ActionExecutor] Finding clickable element for:",e.tagName,r(e).substring(0,50)),!n.includes(e.tagName))return console.log("[ActionExecutor] Element is already interactive"),e;let i=e.parentElement,o=e,s=0;for(;i&&i!==document.body&&s<10;){s++;const l=window.getComputedStyle(i),c=l.cursor==="pointer",d=r(i),f=d.includes("cursor-pointer"),h=(a=i.classList)==null?void 0:a.contains("cursor-pointer"),b=i.hasAttribute("onclick")||i.hasAttribute("data-onclick")||i.getAttribute("role")==="button"||i.getAttribute("role")==="menuitem",y=i.tagName==="BUTTON"||i.tagName==="A";if(console.log(`[ActionExecutor] Checking parent #${s}:`,i.tagName,"cursor:",l.cursor,"hasCursorClass:",f||h,"classes:",d.substring(0,60)),(c||f||h||b||y)&&(o=i,console.log("[ActionExecutor] ✅ Found clickable parent:",i.tagName,d.substring(0,80)),y||i.getAttribute("role")==="button"))break;i=i.parentElement}return console.log("[ActionExecutor] Final click target:",o.tagName,r(o).substring(0,60)),o}triggerReactOnClick(e){try{const n=Object.keys(e);for(const s of n)if(s.startsWith("__reactFiber")||s.startsWith("__reactProps")||s.startsWith("__reactEventHandlers")){const a=e[s];if(console.log("[ActionExecutor] Found React property:",s),a!=null&&a.onClick){console.log("[ActionExecutor] 🎯 Calling React onClick directly!");const l=new MouseEvent("click",{bubbles:!0,cancelable:!0}),c={type:"click",target:e,currentTarget:e,nativeEvent:l,bubbles:!0,cancelable:!0,defaultPrevented:!1,eventPhase:0,isTrusted:!1,timeStamp:Date.now(),preventDefault:()=>{c.defaultPrevented=!0},stopPropagation:()=>{},persist:()=>{},isDefaultPrevented:()=>c.defaultPrevented,isPropagationStopped:()=>!1};return a.onClick(c),!0}}const r=["__reactProps","__reactFiber","__reactEventHandlers"];let i=e.parentElement,o=0;for(;i&&o<5;){const s=Object.keys(i);for(const a of s)if(r.some(l=>a.startsWith(l))){const l=i[a];if(l!=null&&l.onClick){console.log("[ActionExecutor] 🎯 Found onClick on parent, calling directly!");const c=new MouseEvent("click",{bubbles:!0,cancelable:!0}),d={type:"click",target:e,currentTarget:i,nativeEvent:c,bubbles:!0,cancelable:!0,defaultPrevented:!1,eventPhase:0,isTrusted:!1,timeStamp:Date.now(),preventDefault:()=>{d.defaultPrevented=!0},stopPropagation:()=>{},persist:()=>{},isDefaultPrevented:()=>d.defaultPrevented,isPropagationStopped:()=>!1};return l.onClick(d),!0}}i=i.parentElement,o++}return console.log("[ActionExecutor] No React onClick handler found"),!1}catch(n){return console.log("[ActionExecutor] Error accessing React internals:",n),!1}}sendClickMetadata(e,n){const r=d=>d.className?typeof d.className=="string"?d.className:typeof d.className.baseVal=="string"?d.className.baseVal:"":"",i=[];let o=e;for(;o&&o!==document.body&&i.length<5;){let d=o.tagName.toLowerCase();if(o.id)d=`#${o.id}`;else{const f=r(o);if(f){const h=f.trim().split(/\s+/).slice(0,3).join(".");h&&(d+="."+h)}}i.unshift(d),o=o.parentElement}const s=d=>{var b;const f=d.querySelector("span, label, p");if((b=f==null?void 0:f.textContent)!=null&&b.trim())return f.textContent.trim().substring(0,50);let h="";for(const y of Array.from(d.childNodes))y.nodeType===Node.TEXT_NODE&&(h+=(y.textContent||"").trim()+" ");return h=h.trim(),!h&&d.textContent&&(h=d.textContent.trim().substring(0,50)),h},a=window.__onboardingSDK,l=(a==null?void 0:a._botActionDepth)>0,c={type:"click",selector:i.join(" > "),text:s(n),tagName:e.tagName.toLowerCase(),timestamp:Date.now(),source:l?"bot":"user",sourceDetail:"react_onclick"};console.log("[ActionExecutor] 📤 Sending React onClick metadata:",c.text,`(source: ${c.source})`),a!=null&&a.sendMetadata?a.sendMetadata(c):console.warn("[ActionExecutor] ⚠️ SDK not found on window, cannot send metadata")}isDestructive(e){const n=["submit","delete","remove","clear"],r=['[type="submit"]',".delete",".remove"];return n.some(i=>{var o;return(o=e.description)==null?void 0:o.toLowerCase().includes(i)})||r.some(i=>e.selector.includes(i))}isHybridActionDestructive(e){var o,s;const n=["submit","delete","remove","clear","confirm","proceed"],r=((o=e.description)==null?void 0:o.toLowerCase())||"",i=((s=e.target.text)==null?void 0:s.toLowerCase())||"";return n.some(a=>r.includes(a)||i.includes(a))}async getConsent(e){const n=`Allow action: ${e.description||e.type} on ${e.selector}?`;return confirm(n)}async getHybridConsent(e){const n=e.target.text||e.target.selector||"element",r=`Allow "${e.action}" on "${n}"?
|
|
478
|
-
${e.description||""}`;return confirm(r)}async execute(e){if(e.type==="click"){const i=this.parseOptionTextFromSelector(e.selector);if(i){console.log("[ActionExecutor] Virtual selector detected - finding option by text:",i);const s=this.findDropdownOption(i);return s?(this.performClick(s),!0):(console.warn("[ActionExecutor] Option not found by text:",i),!1)}const o=this.parseLabelFromSelector(e.selector);if(o){console.log("[ActionExecutor] Virtual selector detected - finding combobox by label:",o);const s=this.findComboboxByLabel(o);return s?(this.handleComboboxClick(s),!0):(console.warn("[ActionExecutor] Combobox not found by label:",o),!1)}}const n=this.stripVirtualAttributes(e.selector),r=document.querySelector(n);if(!r)return console.warn("[ActionExecutor] Element not found:",n),!1;switch(e.type){case"click":this.simulateClick(r,e.selector);break;case"type":(r instanceof HTMLInputElement||r instanceof HTMLTextAreaElement)&&(r.focus(),r.value=e.value||"",r.dispatchEvent(new Event("input",{bubbles:!0})),r.dispatchEvent(new Event("change",{bubbles:!0})));break;case"select":const i=this.findComboboxInput(r);if(i){if(this.handleComboboxClick(i),await new Promise(o=>setTimeout(o,200)),e.value){const o=this.findDropdownOption(e.value);o&&this.performClick(o)}}else r instanceof HTMLSelectElement&&(r.value=e.value||"",r.dispatchEvent(new Event("change",{bubbles:!0})));break;case"hover":r.dispatchEvent(new MouseEvent("mouseenter",{bubbles:!0})),r.dispatchEvent(new MouseEvent("mouseover",{bubbles:!0}));break;case"scroll":r.scrollIntoView({behavior:"smooth",block:"center"});break;default:return console.warn("[ActionExecutor] Unknown action type:",e.type),!1}return!0}}class $x{constructor(){L(this,"container",null);L(this,"highlightEl",null);L(this,"tooltipElement",null);L(this,"floeCursor",null)}inject(){this.container||(this.container=document.createElement("div"),this.container.id="onboarding-overlay",this.container.setAttribute(Oi,"overlay"),this.container.style.cssText=`
|
|
478
|
+
${e.description||""}`;return confirm(r)}async execute(e){if(e.type==="click"){const i=this.parseOptionTextFromSelector(e.selector);if(i){console.log("[ActionExecutor] Virtual selector detected - finding option by text:",i);const s=this.findDropdownOption(i);return s?(this.performClick(s),!0):(console.warn("[ActionExecutor] Option not found by text:",i),!1)}const o=this.parseLabelFromSelector(e.selector);if(o){console.log("[ActionExecutor] Virtual selector detected - finding combobox by label:",o);const s=this.findComboboxByLabel(o);return s?(this.handleComboboxClick(s),!0):(console.warn("[ActionExecutor] Combobox not found by label:",o),!1)}}const n=this.stripVirtualAttributes(e.selector),r=document.querySelector(n);if(!r)return console.warn("[ActionExecutor] Element not found:",n),!1;switch(e.type){case"click":this.simulateClick(r,e.selector);break;case"type":(r instanceof HTMLInputElement||r instanceof HTMLTextAreaElement)&&(r.focus(),r.value=e.value||"",r.dispatchEvent(new Event("input",{bubbles:!0})),r.dispatchEvent(new Event("change",{bubbles:!0})));break;case"select":const i=this.findComboboxInput(r);if(i){if(this.handleComboboxClick(i),await new Promise(o=>setTimeout(o,200)),e.value){const o=this.findDropdownOption(e.value);o&&this.performClick(o)}}else r instanceof HTMLSelectElement&&(r.value=e.value||"",r.dispatchEvent(new Event("change",{bubbles:!0})));break;case"hover":r.dispatchEvent(new MouseEvent("mouseenter",{bubbles:!0})),r.dispatchEvent(new MouseEvent("mouseover",{bubbles:!0}));break;case"scroll":r.scrollIntoView({behavior:"smooth",block:"center"});break;default:return console.warn("[ActionExecutor] Unknown action type:",e.type),!1}return!0}}class $x{constructor(){L(this,"container",null);L(this,"highlightEl",null);L(this,"tooltipElement",null);L(this,"floeCursor",null);L(this,"cursorHasBeenPositioned",!1)}inject(){this.container||(this.container=document.createElement("div"),this.container.id="onboarding-overlay",this.container.setAttribute(Oi,"overlay"),this.container.style.cssText=`
|
|
479
479
|
position: fixed;
|
|
480
480
|
top: 0;
|
|
481
481
|
left: 0;
|
|
@@ -549,7 +549,7 @@ ${e.description||""}`;return confirm(r)}async execute(e){if(e.type==="click"){co
|
|
|
549
549
|
30% { transform: scale(0.85); }
|
|
550
550
|
100% { transform: scale(1); }
|
|
551
551
|
}
|
|
552
|
-
`,document.head.appendChild(e),document.body.appendChild(this.floeCursor),console.log("[OverlaySystem] Floe cursor injected")}showFloeCursor(){this.floeCursor
|
|
552
|
+
`,document.head.appendChild(e),document.body.appendChild(this.floeCursor),console.log("[OverlaySystem] Floe cursor injected")}showFloeCursor(){if(this.floeCursor){if(!this.cursorHasBeenPositioned){const e=window.innerWidth-50,n=window.innerHeight-50;this.floeCursor.style.left=`${e}px`,this.floeCursor.style.top=`${n}px`,this.cursorHasBeenPositioned=!0,console.log("[OverlaySystem] Cursor initial position set to bot icon:",e,n)}this.floeCursor.style.opacity="1",this.floeCursor.style.transform="scale(1)"}}hideFloeCursor(){this.floeCursor&&(this.floeCursor.style.opacity="0",this.floeCursor.style.transform="scale(0.8)")}animateFloeCursorTo(e,n,r=400){return new Promise(i=>{if(!this.floeCursor){i();return}this.showFloeCursor();const o=parseFloat(this.floeCursor.style.top)||0,s=parseFloat(this.floeCursor.style.left)||0,a=performance.now(),l=s,c=o,d=f=>{const h=f-a,b=Math.min(h/r,1),y=1-Math.pow(1-b,3),g=l+(e-l)*y,S=c+(n-c)*y;this.floeCursor&&(this.floeCursor.style.left=`${g}px`,this.floeCursor.style.top=`${S}px`),b<1?requestAnimationFrame(d):i()};requestAnimationFrame(d)})}animateFloeCursorClick(){return new Promise(e=>{if(!this.floeCursor){e();return}const n=this.floeCursor.querySelector("svg");n?(n.style.animation="floeCursorClick 0.2s ease",setTimeout(()=>{n.style.animation="",e()},200)):e()})}async moveToElementAndClick(e){const n=e.getBoundingClientRect(),r=n.left+n.width/2-5,i=n.top+n.height/2-5;await this.animateFloeCursorTo(r,i,500),await new Promise(o=>setTimeout(o,100)),await this.animateFloeCursorClick()}showScreenShareModal(){return new Promise(e=>{const n=document.createElement("div");n.setAttribute(Oi,"consent-modal"),n.style.cssText=`
|
|
553
553
|
position: fixed;
|
|
554
554
|
top: 0;
|
|
555
555
|
left: 0;
|
|
@@ -801,13 +801,13 @@ ${e.description||""}`;return confirm(r)}async execute(e){if(e.type==="click"){co
|
|
|
801
801
|
max-width: 300px;
|
|
802
802
|
text-align: center;
|
|
803
803
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
804
|
-
`,this.tooltipElement.textContent=e}hideTooltip(){this.tooltipElement&&(this.tooltipElement.remove(),this.tooltipElement=null)}remove(){var r;const e=document.getElementById("floe-cursor-styles");e&&e.remove();const n=document.getElementById("onboarding-animations");n&&n.remove(),(r=this.container)==null||r.remove(),this.container=null,this.highlightEl=null,this.tooltipElement=null}}class yd{constructor(e){L(this,"piiPatterns");this.piiPatterns={email:/[\w.-]+@[\w.-]+\.\w+/,phone:/[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}/,ssn:/\d{3}-\d{2}-\d{4}/,creditCard:/\d{4}[\s.-]?\d{4}[\s.-]?\d{4}[\s.-]?\d{4}/,...e}}safeCanvasToDataURL(e,n,r){const i=`image/${n}`;try{return Promise.resolve(e.toDataURL(i,r))}catch(o){console.warn("[ScreenCapture] toDataURL failed (tainted canvas?), trying toBlob fallback:",o)}return new Promise((o,s)=>{try{e.toBlob(a=>{if(!a){s(new Error("[ScreenCapture] canvas.toBlob returned null — canvas may be tainted"));return}const l=new FileReader;l.onloadend=()=>{typeof l.result=="string"?o(l.result):s(new Error("[ScreenCapture] FileReader did not produce a string result"))},l.onerror=()=>{s(new Error("[ScreenCapture] FileReader failed to read blob"))},l.readAsDataURL(a)},i,r)}catch(a){s(new Error(`[ScreenCapture] Both toDataURL and toBlob failed for canvas export. toBlob error: ${a instanceof Error?a.message:String(a)}`))}})}static sanitizeClonedDocument(e){e.querySelectorAll("script").forEach(o=>{o.remove()});const r=e.querySelectorAll("*"),i=/^on/i;r.forEach(o=>{const s=Array.from(o.attributes);for(const a of s)i.test(a.name)&&o.removeAttribute(a.name)})}getAllTextNodes(){const e=[],n=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT,{acceptNode:i=>{const o=i.parentElement;if(!o)return NodeFilter.FILTER_REJECT;const s=window.getComputedStyle(o);return s.display==="none"||s.visibility==="hidden"||!i.textContent||!i.textContent.trim()?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}});let r;for(;r=n.nextNode();){const i=document.createRange();i.selectNode(r);const o=i.getBoundingClientRect();o.width>0&&o.height>0&&e.push({node:r,rect:o})}return e}containsPII(e){for(const[n,r]of Object.entries(this.piiPatterns))if(r.lastIndex=0,r.test(e))return{contains:!0,type:n};return{contains:!1}}applyBlur(e,n){const r=e.getImageData(n.x,n.y,n.width,n.height),i=r.data,o=5;for(let s=0;s<n.height;s++)for(let a=0;a<n.width;a++){let l=0,c=0,d=0,f=0,h=0;for(let y=-o;y<=o;y++)for(let g=-o;g<=o;g++){const S=a+g,v=s+y;if(S>=0&&S<n.width&&v>=0&&v<n.height){const w=(v*n.width+S)*4;l+=i[w],c+=i[w+1],d+=i[w+2],f+=i[w+3],h++}}const b=(s*n.width+a)*4;i[b]=l/h,i[b+1]=c/h,i[b+2]=d/h,i[b+3]=f/h}e.putImageData(r,n.x,n.y)}async captureWithRedaction(e={}){const{redact:n=!0,scale:r=.6,quality:i=.7,format:o="webp"}=e;if(!document.body)return console.warn("[ScreenCapture] Document body not available"),"";const s=[];if(n){const f=this.getAllTextNodes();for(const{node:h,rect:b}of f){const y=this.containsPII(h.textContent||"");y.contains&&s.push({x:b.left,y:b.top,width:b.width,height:b.height,type:y.type||"unknown"})}}const a=document.createElement("canvas"),l=a.getContext("2d");if(!l)return console.error("[ScreenCapture] Failed to get 2D canvas context"),Promise.reject(new Error("[ScreenCapture] Canvas 2D context unavailable"));const c=window.innerWidth*r,d=window.innerHeight*r;return a.width=c,a.height=d,new Promise((f,h)=>{const b=document.createElement("iframe");b.style.position="fixed",b.style.top="0",b.style.left="0",b.style.width="100%",b.style.height="100%",b.style.border="none",b.style.zIndex="-999999",document.body.appendChild(b);const y=b.contentDocument;if(y.open(),y.write(document.documentElement.outerHTML),y.close(),yd.sanitizeClonedDocument(y),n&&s.length>0){const S=y.createElement("style");if(S.textContent=`
|
|
804
|
+
`,this.tooltipElement.textContent=e}hideTooltip(){this.tooltipElement&&(this.tooltipElement.remove(),this.tooltipElement=null)}cleanup(){this.clearHighlight(),this.hideFloeCursor(),this.hideTooltip(),console.log("[OverlaySystem] Cleaned up all overlays")}resetCursorState(){this.cursorHasBeenPositioned=!1,this.floeCursor&&(this.floeCursor.style.top="-100px",this.floeCursor.style.left="-100px",this.floeCursor.style.opacity="0",this.floeCursor.style.transform="scale(0.8)"),console.log("[OverlaySystem] Cursor state reset")}remove(){var r;const e=document.getElementById("floe-cursor-styles");e&&e.remove();const n=document.getElementById("onboarding-animations");n&&n.remove(),this.floeCursor&&(this.floeCursor.remove(),this.floeCursor=null),this.cursorHasBeenPositioned=!1,(r=this.container)==null||r.remove(),this.container=null,this.highlightEl=null,this.tooltipElement=null}}class yd{constructor(e){L(this,"piiPatterns");this.piiPatterns={email:/[\w.-]+@[\w.-]+\.\w+/,phone:/[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}/,ssn:/\d{3}-\d{2}-\d{4}/,creditCard:/\d{4}[\s.-]?\d{4}[\s.-]?\d{4}[\s.-]?\d{4}/,...e}}safeCanvasToDataURL(e,n,r){const i=`image/${n}`;try{return Promise.resolve(e.toDataURL(i,r))}catch(o){console.warn("[ScreenCapture] toDataURL failed (tainted canvas?), trying toBlob fallback:",o)}return new Promise((o,s)=>{try{e.toBlob(a=>{if(!a){s(new Error("[ScreenCapture] canvas.toBlob returned null — canvas may be tainted"));return}const l=new FileReader;l.onloadend=()=>{typeof l.result=="string"?o(l.result):s(new Error("[ScreenCapture] FileReader did not produce a string result"))},l.onerror=()=>{s(new Error("[ScreenCapture] FileReader failed to read blob"))},l.readAsDataURL(a)},i,r)}catch(a){s(new Error(`[ScreenCapture] Both toDataURL and toBlob failed for canvas export. toBlob error: ${a instanceof Error?a.message:String(a)}`))}})}static sanitizeClonedDocument(e){e.querySelectorAll("script").forEach(o=>{o.remove()});const r=e.querySelectorAll("*"),i=/^on/i;r.forEach(o=>{const s=Array.from(o.attributes);for(const a of s)i.test(a.name)&&o.removeAttribute(a.name)})}getAllTextNodes(){const e=[],n=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT,{acceptNode:i=>{const o=i.parentElement;if(!o)return NodeFilter.FILTER_REJECT;const s=window.getComputedStyle(o);return s.display==="none"||s.visibility==="hidden"||!i.textContent||!i.textContent.trim()?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}});let r;for(;r=n.nextNode();){const i=document.createRange();i.selectNode(r);const o=i.getBoundingClientRect();o.width>0&&o.height>0&&e.push({node:r,rect:o})}return e}containsPII(e){for(const[n,r]of Object.entries(this.piiPatterns))if(r.lastIndex=0,r.test(e))return{contains:!0,type:n};return{contains:!1}}applyBlur(e,n){const r=e.getImageData(n.x,n.y,n.width,n.height),i=r.data,o=5;for(let s=0;s<n.height;s++)for(let a=0;a<n.width;a++){let l=0,c=0,d=0,f=0,h=0;for(let y=-o;y<=o;y++)for(let g=-o;g<=o;g++){const S=a+g,v=s+y;if(S>=0&&S<n.width&&v>=0&&v<n.height){const w=(v*n.width+S)*4;l+=i[w],c+=i[w+1],d+=i[w+2],f+=i[w+3],h++}}const b=(s*n.width+a)*4;i[b]=l/h,i[b+1]=c/h,i[b+2]=d/h,i[b+3]=f/h}e.putImageData(r,n.x,n.y)}async captureWithRedaction(e={}){const{redact:n=!0,scale:r=.6,quality:i=.7,format:o="webp"}=e;if(!document.body)return console.warn("[ScreenCapture] Document body not available"),"";const s=[];if(n){const f=this.getAllTextNodes();for(const{node:h,rect:b}of f){const y=this.containsPII(h.textContent||"");y.contains&&s.push({x:b.left,y:b.top,width:b.width,height:b.height,type:y.type||"unknown"})}}const a=document.createElement("canvas"),l=a.getContext("2d");if(!l)return console.error("[ScreenCapture] Failed to get 2D canvas context"),Promise.reject(new Error("[ScreenCapture] Canvas 2D context unavailable"));const c=window.innerWidth*r,d=window.innerHeight*r;return a.width=c,a.height=d,new Promise((f,h)=>{const b=document.createElement("iframe");b.style.position="fixed",b.style.top="0",b.style.left="0",b.style.width="100%",b.style.height="100%",b.style.border="none",b.style.zIndex="-999999",document.body.appendChild(b);const y=b.contentDocument;if(y.open(),y.write(document.documentElement.outerHTML),y.close(),yd.sanitizeClonedDocument(y),n&&s.length>0){const S=y.createElement("style");if(S.textContent=`
|
|
805
805
|
.pii-redacted {
|
|
806
806
|
filter: blur(5px);
|
|
807
807
|
background: #000;
|
|
808
808
|
color: transparent !important;
|
|
809
809
|
}
|
|
810
|
-
`,y.head.appendChild(S),!y.body){console.warn("[ScreenCapture] Cloned document has no body"),document.body.removeChild(b),this.safeCanvasToDataURL(a,o,i).then(f,h);return}const v=y.createTreeWalker(y.body,NodeFilter.SHOW_TEXT);let w;for(;w=v.nextNode();)this.containsPII(w.textContent||"").contains&&w.parentElement&&w.parentElement.classList.add("pii-redacted")}const g=()=>{try{document.body.removeChild(b)}catch{}};setTimeout(()=>{try{if(!b.contentWindow){console.warn("[ScreenCapture] iframe contentWindow not available"),g(),this.safeCanvasToDataURL(a,o,i).then(f,h);return}const w=new XMLSerializer().serializeToString(y.documentElement),k=`<svg xmlns="http://www.w3.org/2000/svg" width="${window.innerWidth}" height="${window.innerHeight}"><foreignObject width="100%" height="100%">`+w+"</foreignObject></svg>",C=new Blob([k],{type:"image/svg+xml;charset=utf-8"}),M=URL.createObjectURL(C),O=new Image;O.onload=()=>{if(l.save(),l.scale(r,r),l.drawImage(O,0,0),l.restore(),URL.revokeObjectURL(M),n&&s.length>0)for(const D of s)this.applyBlur(l,{x:D.x*r,y:D.y*r,width:D.width*r,height:D.height*r});g(),this.safeCanvasToDataURL(a,o,i).then(f,h)},O.onerror=()=>{URL.revokeObjectURL(M),console.warn("[ScreenCapture] SVG image render failed, returning blank canvas"),g(),this.safeCanvasToDataURL(a,o,i).then(f,h)},O.src=M}catch(S){console.error("[ScreenCapture] Failed to render iframe content:",S),g(),this.safeCanvasToDataURL(a,o,i).then(f,h)}},100)})}async captureSimple(e={}){return this.captureWithRedaction({...e,redact:!1})}}class Fx{constructor(e){L(this,"sdk");L(this,"domIntrospector",null);L(this,"lastUrl","");L(this,"clickHandler",null);L(this,"focusHandler",null);L(this,"blurHandler",null);L(this,"inputHandler",null);L(this,"keydownHandler",null);L(this,"inputDebounceTimers",new Map);L(this,"isTracking",!1);L(this,"scrollHandler",null);L(this,"scrollDebounceTimer",null);L(this,"urlCheckInterval",null);L(this,"popstateHandler",null);this.sdk=e,this.lastUrl=window.location.href}setDOMIntrospector(e){this.domIntrospector=e,console.log("[PageTracker] DOMIntrospector set for sync captures")}start(){this.isTracking||(this.isTracking=!0,console.log("[PageTracker] Starting page event tracking"),this.sendPageMetadata(),this.setupUrlTracking(),this.clickHandler=e=>{const n=e.target;if(!n||Ct(n))return;const r=this.getElementMetadata(n),i=this.sdk._botActionDepth>0?"bot":"user";this.sdk.sendMetadata({type:"click",selector:r.selector,text:r.text,tagName:r.tagName,role:r.role,ariaLabel:r.ariaLabel,placeholder:r.placeholder,labelText:r.labelText,timestamp:Date.now(),source:i}),console.log(`[PageTracker] Click (${i}):`,r.selector,r.labelText?`(label: ${r.labelText})`:""),this.domIntrospector&&setTimeout(()=>{var o;(o=this.domIntrospector)==null||o.captureAndSendImmediate("post-click")},100)},document.addEventListener("click",this.clickHandler,!0),this.scrollHandler=()=>{this.sdk.fastExecutionMode||(this.scrollDebounceTimer&&clearTimeout(this.scrollDebounceTimer),this.scrollDebounceTimer=setTimeout(()=>{this.sdk.fastExecutionMode||(console.log("[PageTracker] Scroll detected, capturing DOM"),this.sdk.sendMetadata({type:"scroll",scrollY:window.scrollY,scrollX:window.scrollX,viewportHeight:window.innerHeight,documentHeight:document.documentElement.scrollHeight,timestamp:Date.now()}),this.domIntrospector&&this.domIntrospector.captureAndSendImmediate("post-scroll"))},200))},window.addEventListener("scroll",this.scrollHandler,{passive:!0}),this.focusHandler=e=>{const n=e.target;if(!n||!this.isInteractiveElement(n)||Ct(n))return;const r=this.getElementMetadata(n),i=n.type||"";this.sdk.sendMetadata({type:"focus",selector:r.selector,tagName:r.tagName,inputType:i,role:r.role,ariaLabel:r.ariaLabel,placeholder:r.placeholder,labelText:r.labelText,timestamp:Date.now()}),console.log("[PageTracker] Focus:",r.tagName,r.labelText?`(label: ${r.labelText})`:""),this.domIntrospector&&this.isInputElement(n)&&setTimeout(()=>{var o;(o=this.domIntrospector)==null||o.captureAndSendImmediate("post-focus")},150)},document.addEventListener("focus",this.focusHandler,!0),this.blurHandler=e=>{const n=e.target;if(!n||!this.isInteractiveElement(n)||Ct(n))return;const r=n.tagName.toLowerCase();this.sdk.sendMetadata({type:"blur",selector:this.getSelector(n),tagName:r,timestamp:Date.now()}),console.log("[PageTracker] Blur:",r),this.domIntrospector&&this.isInputElement(n)&&setTimeout(()=>{var i;(i=this.domIntrospector)==null||i.captureAndSendImmediate("post-blur")},200)},document.addEventListener("blur",this.blurHandler,!0),this.inputHandler=e=>{const n=e.target;if(!n||Ct(n))return;const r=this.inputDebounceTimers.get(n);r&&clearTimeout(r);const i=setTimeout(()=>{const o=this.getElementMetadata(n),s=n.name||n.id||n.placeholder||o.labelText||"field";this.sdk.sendMetadata({type:"form_input",selector:o.selector,field:s,inputType:n.type||"text",hasValue:!!n.value,role:o.role,ariaLabel:o.ariaLabel,placeholder:o.placeholder,labelText:o.labelText,timestamp:Date.now()}),console.log("[PageTracker] Form input:",s,o.labelText?`(label: ${o.labelText})`:""),this.inputDebounceTimers.delete(n),this.domIntrospector&&this.domIntrospector.captureAndSendImmediate("post-input")},500);this.inputDebounceTimers.set(n,i)},document.addEventListener("input",this.inputHandler,!0),this.keydownHandler=e=>{const n=e.target;if(!n||!(n instanceof HTMLElement)||Ct(n)||!this.isInputElement(n)||!["Enter","Escape","Tab"].includes(e.key))return;const i=n.tagName.toLowerCase(),o=n.type||"";if(this.sdk.sendMetadata({type:"keydown",key:e.key,selector:this.getSelector(n),tagName:i,inputType:o,timestamp:Date.now()}),console.log("[PageTracker] Keydown:",e.key,"on",i),this.domIntrospector){const s=e.key==="Enter"?300:150;setTimeout(()=>{var a;(a=this.domIntrospector)==null||a.captureAndSendImmediate(`post-keydown-${e.key.toLowerCase()}`)},s)}},document.addEventListener("keydown",this.keydownHandler,!0),console.log("[PageTracker] Event listeners attached"))}stop(){this.isTracking&&(this.isTracking=!1,this.clickHandler&&(document.removeEventListener("click",this.clickHandler,!0),this.clickHandler=null),this.focusHandler&&(document.removeEventListener("focus",this.focusHandler,!0),this.focusHandler=null),this.blurHandler&&(document.removeEventListener("blur",this.blurHandler,!0),this.blurHandler=null),this.inputHandler&&(document.removeEventListener("input",this.inputHandler,!0),this.inputHandler=null),this.keydownHandler&&(document.removeEventListener("keydown",this.keydownHandler,!0),this.keydownHandler=null),this.scrollHandler&&(window.removeEventListener("scroll",this.scrollHandler),this.scrollHandler=null),this.scrollDebounceTimer&&(clearTimeout(this.scrollDebounceTimer),this.scrollDebounceTimer=null),this.urlCheckInterval&&(clearInterval(this.urlCheckInterval),this.urlCheckInterval=null),this.popstateHandler&&(window.removeEventListener("popstate",this.popstateHandler),this.popstateHandler=null),this.inputDebounceTimers.forEach(e=>{clearTimeout(e)}),this.inputDebounceTimers.clear(),console.log("[PageTracker] Stopped tracking"))}setupUrlTracking(){this.urlCheckInterval||(this.urlCheckInterval=setInterval(()=>{const e=window.location.href;e!==this.lastUrl&&(this.lastUrl=e,this.sendPageMetadata())},1e3),this.popstateHandler=()=>{setTimeout(()=>{const e=window.location.href;e!==this.lastUrl&&(this.lastUrl=e,this.sendPageMetadata())},100)},window.addEventListener("popstate",this.popstateHandler))}sendPageMetadata(){const e=An();this.sdk.sendMetadata({type:"page_metadata",url:e,title:document.title,pathname:window.location.pathname,timestamp:Date.now()}),console.log("[PageTracker] Page metadata sent:",e)}isInteractiveElement(e){const n=e.tagName.toLowerCase();return["input","textarea","select","button"].includes(n)||e.contentEditable==="true"}isInputElement(e){const n=e.tagName.toLowerCase();if(n==="textarea")return!0;if(n==="input"){const r=e.type||"text";return["text","search","email","password","tel","url","number"].includes(r)}return e.contentEditable==="true"}getSelector(e){if(e.id&&!e.id.match(/^(react-select-|:r|radix-)/))return`#${CSS.escape(e.id)}`;const n=e.getAttribute("role"),r=e.getAttribute("aria-label"),i=e.getAttribute("name"),o=e.getAttribute("data-testid")||e.getAttribute("data-test-id"),s=e.placeholder,a=e.tagName.toLowerCase();let l=a;if(o)return`[data-testid="${o}"]`;if(n)return l=`${a}[role="${n}"]`,r?l+=`[aria-label="${r}"]`:i&&(l+=`[name="${i}"]`),l;if(i)return`${a}[name="${i}"]`;if(s)return`${a}[placeholder="${s}"]`;if(r)return`${a}[aria-label="${r}"]`;const c=[];let d=e,f=0;for(;d&&d!==document.body&&f<5;){let h=d.tagName.toLowerCase();const b=d.getAttribute("role"),y=d.getAttribute("data-testid");if(y){c.unshift(`[data-testid="${y}"]`);break}if(b)h+=`[role="${b}"]`;else if(d.className&&typeof d.className=="string"){const g=d.className.split(" ").filter(S=>S&&!S.startsWith("css-")&&!S.startsWith("sc-")&&!S.startsWith("ng-")&&!S.startsWith("_")&&!S.match(/^[a-z]{6,}$/)&&!S.match(/^\d/)).slice(0,2);g.length>0&&(h+=`.${g.join(".")}`)}c.unshift(h),d=d.parentElement,f++}return c.join(" > ")}getElementMetadata(e){var h,b,y,g;const n=e,r=this.getSelector(e),i=((h=n.innerText)==null?void 0:h.trim().substring(0,100))||"",o=e.tagName.toLowerCase(),s=e.getAttribute("role")||void 0,a=e.getAttribute("aria-label")||void 0,l=e.placeholder||void 0;let c;const d=e.getAttribute("aria-labelledby");if(d){const S=document.getElementById(d.split(/\s+/)[0]);S&&(c=(b=S.textContent)==null?void 0:b.trim())}const f=e.getAttribute("id");if(!c&&f)try{const S=document.querySelector(`label[for="${CSS.escape(f)}"]`);S&&(c=(y=S.textContent)==null?void 0:y.trim().replace(/\*$/,"").trim())}catch{}if(!c){const S=e.closest('.MuiFormControl-root, fieldset, [class*="form-group"], [class*="form-field"], [class*="field-wrapper"]');if(S){const v=S.querySelector(":scope > label, :scope > .MuiFormLabel-root, :scope > div > label");if(v){const w=S.querySelectorAll('input, select, textarea, [role="combobox"]'),k=Array.from(w).some(C=>e.contains(C)||e===C);(w.length===1||k)&&(c=(g=v.textContent)==null?void 0:g.trim().replace(/\*$/,"").trim())}}}return{selector:r,text:i,tagName:o,role:s,ariaLabel:a,placeholder:l,labelText:c}}}class my{constructor(){L(this,"loadingSelectors",['[role="progressbar"]',".loading",".spinner",".loader",'[aria-busy="true"]','[class*="loading"]','[class*="spinner"]','svg[class*="animate-spin"]','[data-loading="true"]',".MuiCircularProgress-root",".MuiLinearProgress-root"])}isLoading(){for(const e of this.loadingSelectors)try{const n=document.querySelector(e);if(n&&this.isVisible(n))return console.log("[LoadingDetector] Found loading indicator:",e),!0}catch{}return!1}async waitForLoadingComplete(e=5e3){const n=Date.now();for(console.log("[LoadingDetector] Waiting for loading to complete...");Date.now()-n<e;){if(!this.isLoading()&&(await new Promise(r=>setTimeout(r,100)),!this.isLoading()))return console.log("[LoadingDetector] Loading complete"),!0;await new Promise(r=>setTimeout(r,50))}return console.warn("[LoadingDetector] Timed out waiting for loading"),!1}isVisible(e){const n=getComputedStyle(e);if(n.visibility==="hidden"||n.display==="none"||n.opacity==="0")return!1;if(e.offsetParent===null){const i=n.position;if(i!=="fixed"&&i!=="sticky")return!1}const r=e.getBoundingClientRect();return r.width>0&&r.height>0}}class jx{async waitForStable(e=300,n=5e3){return new Promise(r=>{let i,o;const s=()=>{clearTimeout(i),clearTimeout(o),a.disconnect()},a=new MutationObserver(()=>{clearTimeout(i),i=setTimeout(()=>{s(),console.log("[DOMStabilityChecker] DOM stable"),r()},e)});a.observe(document.body,{childList:!0,subtree:!0,attributes:!0}),i=setTimeout(()=>{s(),console.log("[DOMStabilityChecker] DOM stable (no mutations)"),r()},e),o=setTimeout(()=>{s(),console.warn("[DOMStabilityChecker] Max wait time reached, proceeding anyway"),r()},n)})}}class Bx{constructor(){L(this,"lastUrl","");L(this,"urlChangeCallback",null);L(this,"loadingDetector");L(this,"domStabilityChecker");L(this,"originalPushState",null);L(this,"originalReplaceState",null);L(this,"popstateHandler",null);L(this,"isStarted",!1);L(this,"handleUrlChange",async()=>{const e=window.location.href;if(e!==this.lastUrl){console.log("[NavigationCompleteDetector] URL changed:",e),this.lastUrl=e;try{await this.waitForPageStable()}catch(n){console.warn("[NavigationCompleteDetector] Error waiting for page stable:",n)}this.urlChangeCallback&&this.urlChangeCallback(An())}});this.lastUrl=window.location.href,this.loadingDetector=new my,this.domStabilityChecker=new jx}start(e){this.isStarted&&(console.warn("[NavigationCompleteDetector] Already started, stopping first"),this.stop()),console.log("[NavigationCompleteDetector] Starting navigation monitoring"),this.isStarted=!0,this.urlChangeCallback=e,this.lastUrl=window.location.href,this.setupUrlObserver(),this.popstateHandler=()=>this.handleUrlChange(),window.addEventListener("popstate",this.popstateHandler)}setupUrlObserver(){this.originalPushState||(this.originalPushState=history.pushState.bind(history)),this.originalReplaceState||(this.originalReplaceState=history.replaceState.bind(history));const e=this;history.pushState=function(...n){e.originalPushState(...n),e.handleUrlChange()},history.replaceState=function(...n){e.originalReplaceState(...n),e.handleUrlChange()}}async waitForPageStable(){console.log("[NavigationCompleteDetector] Waiting for page to stabilize...");const e=8e3,n=Date.now();await this.loadingDetector.waitForLoadingComplete(5e3);const r=e-(Date.now()-n);r>300&&await this.domStabilityChecker.waitForStable(300,Math.min(r,3e3)),console.log("[NavigationCompleteDetector] Page stable")}stop(){this.isStarted&&(console.log("[NavigationCompleteDetector] Stopping navigation monitoring"),this.isStarted=!1,this.popstateHandler&&(window.removeEventListener("popstate",this.popstateHandler),this.popstateHandler=null),this.originalPushState&&(history.pushState=this.originalPushState,this.originalPushState=null),this.originalReplaceState&&(history.replaceState=this.originalReplaceState,this.originalReplaceState=null),this.urlChangeCallback=null)}}class Ux{constructor(e,n){L(this,"overlay");L(this,"loadingDetector");L(this,"domIntrospector",null);L(this,"isExecuting",!1);this.overlay=e,this.loadingDetector=new my}setDOMIntrospector(e){this.domIntrospector=e,console.log("[BatchedActionExecutor] DOMIntrospector set for step captures")}get isBusy(){return this.isExecuting}async executeBatch(e){if(this.isExecuting)return console.warn("[BatchedActionExecutor] Already executing a batch"),{success:!1,completedSteps:0};this.isExecuting=!0;let n=0;console.log(`[BatchedActionExecutor] ⚡ Starting fast batch with ${e.steps.length} steps`);try{for(let r=0;r<e.steps.length;r++){const i=e.steps[r];if(console.log(`[BatchedActionExecutor] Step ${r+1}/${e.steps.length}: ${i.action}`),!await this.executeStep(i))return console.error(`[BatchedActionExecutor] ❌ Step ${r+1} failed, aborting batch (completed ${n} steps)`),{success:!1,completedSteps:n};n++;const s=i.action==="wait"?100:300;await new Promise(a=>setTimeout(a,s))}return console.log("[BatchedActionExecutor] ✅ Batch completed successfully"),e.completionCallback&&e.completionCallback(),{success:!0,completedSteps:n}}finally{this.isExecuting=!1,this.overlay.clearHighlight()}}async executeStep(e){switch(e.action){case"click":return await this.executeClickStep(e);case"wait":return await this.executeWaitStep(e);case"scroll":return await this.executeScrollStep(e);default:return console.warn(`[BatchedActionExecutor] Unknown action: ${e.action}`),!1}}async executeClickStep(e){var a,l,c,d,f;if(!e.target)return console.error("[BatchedActionExecutor] Click step missing target"),!1;const n=(a=e.target.text)==null?void 0:a.toLowerCase().trim(),r=(l=e.target.tag)==null?void 0:l.toLowerCase();console.log("[BatchedActionExecutor] Looking for element:",{text:e.target.text,tag:e.target.tag,selector:e.target.selector,ariaLabel:e.target.ariaLabel,role:e.target.role,labelText:e.target.labelText,selectorFallbacks:(c=e.target.selectorFallbacks)!=null&&c.length?`${e.target.selectorFallbacks.length} fallback(s)`:void 0});let i=null;const o=3,s=[300,500,800];for(let h=0;h<=o;h++)if(h>0&&(console.log(`[BatchedActionExecutor] Retry ${h}/${o} in ${s[h-1]}ms...`),await new Promise(b=>setTimeout(b,s[h-1]))),i=xe.resolveTarget(e.target),i){const b=((d=i.textContent)==null?void 0:d.trim().toLowerCase())||"",y=i.tagName.toLowerCase();if(n&&!b.includes(n)){console.warn(`[BatchedActionExecutor] ⚠️ Found element text "${b.slice(0,50)}" doesn't match expected "${n}"`),i=null;continue}r&&y!==r&&console.log(`[BatchedActionExecutor] Note: Found ${y} instead of expected ${r} (acceptable if it contains the text)`);break}if(!i){if(console.error("[BatchedActionExecutor] ❌ Could not find matching element after retries:",e.target),n){const h=Array.from(document.querySelectorAll("*")).filter(b=>{var y;return(y=b.textContent)==null?void 0:y.toLowerCase().includes(n)}).slice(0,5).map(b=>{var y;return`${b.tagName.toLowerCase()}: "${(y=b.textContent)==null?void 0:y.trim().slice(0,50)}"`});h.length>0&&console.log("[BatchedActionExecutor] Similar elements found:",h)}return!1}return console.log("[BatchedActionExecutor] ✓ Found element:",i.tagName,(f=i.textContent)==null?void 0:f.slice(0,30)),i.scrollIntoView({behavior:"auto",block:"center"}),await new Promise(h=>setTimeout(h,150)),this.overlay.highlightResolvedElement(i,{color:"rgba(124, 58, 237, 0.4)",padding:4}),await new Promise(h=>setTimeout(h,100)),this.simulateClick(i),await new Promise(h=>setTimeout(h,100)),this.overlay.clearHighlight(),this.domIntrospector&&(await new Promise(h=>setTimeout(h,100)),this.domIntrospector.captureAndSendImmediate("post-batch-step-click")),!0}simulateClick(e){var n,r;try{const i=py(e,{focus:!0,includePointerEvents:!0,includeMouseEnter:!0,nativeClickFallback:!1});i.tagName==="A"&&i.href&&console.log("[BatchedActionExecutor] Clicked link:",i.href)}catch(i){const o=((n=e.tagName)==null?void 0:n.toLowerCase())||"unknown",s=e.href||"",a=((r=e.textContent)==null?void 0:r.trim().slice(0,50))||"";console.error(`[BatchedActionExecutor] simulateClick failed on <${o}>${s?` href="${s}"`:""} "${a}":`,i);const l=i instanceof Error?i.message:String(i),c=new Error(`[BatchedActionExecutor] Click step failed on <${o}> "${a}": ${l}`);throw c.cause=i,c}}async executeWaitStep(e){const n=e.condition||"page_stable",r=e.waitMs||5e3;switch(n){case"page_stable":return await this.loadingDetector.waitForLoadingComplete(r),await new Promise(i=>setTimeout(i,400)),!0;case"loading_complete":return await this.loadingDetector.waitForLoadingComplete(r);case"element_visible":return e.target?await this.waitForElement(e.target,r):!0;default:return await new Promise(i=>setTimeout(i,e.waitMs||500)),!0}}async executeScrollStep(e){if(!e.target)return console.warn("[BatchedActionExecutor] Scroll step has no target"),!1;const n=xe.resolveTarget(e.target);return n?(n.scrollIntoView({behavior:"auto",block:"center"}),await new Promise(r=>setTimeout(r,100)),!0):(console.warn("[BatchedActionExecutor] Scroll target not found:",e.target),!0)}async waitForElement(e,n){const r=Date.now();for(;Date.now()-r<n;){if(xe.resolveTarget(e))return!0;await new Promise(o=>setTimeout(o,100))}return!1}}class vy extends Ix{constructor(n){super();L(this,"config");L(this,"sessionId");L(this,"overlay");L(this,"capture");L(this,"actionExecutor");L(this,"pipecatClient",null);L(this,"transport",null);L(this,"isInitialized",!1);L(this,"reactRoot",null);L(this,"reactContainer",null);L(this,"agentState","idle");L(this,"pausedSessionId",null);L(this,"pendingResumeSessionId",null);L(this,"botTranscript","");L(this,"userTranscript","");L(this,"transcriptHistory",[]);L(this,"lastUserTranscript","");L(this,"isConnected",!1);L(this,"connectInFlight",!1);L(this,"micEnabled",!0);L(this,"userIsSpeaking",!1);L(this,"botIsSpeaking",!1);L(this,"audioLevels",[]);L(this,"_discoveryPopupShown",!1);L(this,"_pendingDiscoveryStart",!1);L(this,"botAudioAnalyzer",null);L(this,"userAudioAnalyzer",null);L(this,"userMicStream",null);L(this,"userMicStreamRequestId",0);L(this,"audioElements",[]);L(this,"pageTracker");L(this,"screenShareEnabled",!1);L(this,"domIntrospector");L(this,"accessibleSnapshot");L(this,"fastExecutionMode",!1);L(this,"batchedActionExecutor",null);L(this,"navigationCompleteDetector",null);L(this,"_botActionDepth",0);L(this,"endUserStatus",null);L(this,"connectionProgress",null);L(this,"isReturningUser",!1);L(this,"hasSkippedOnboarding",!1);L(this,"_isMinimized",!1);L(this,"textModeEnabled",!1);L(this,"planProgress",null);if(!n.clientKey)throw new Error("Client key is required");const r="https://api.dev.floe.so";this.config={apiUrl:r,enableVideo:!1,enableAudio:!0,enableScreenCapture:!0,debug:!1,...n},this.micEnabled=this.config.enableAudio!==!1;try{localStorage.getItem("floe_text_mode")==="true"&&(this.textModeEnabled=!0)}catch{}this.sessionId=this.generateSessionId(),this.overlay=new $x,this.capture=new yd(this.config.redactionPatterns),this.actionExecutor=new Nx,this.pageTracker=new Fx(this),this.domIntrospector=new Rx,xe.setDOMIntrospector(this.domIntrospector),this.accessibleSnapshot=new vd,this.batchedActionExecutor=new Ux(this.overlay,this.actionExecutor),this.batchedActionExecutor.setDOMIntrospector(this.domIntrospector),window.__onboardingSDK=this,this.config.debug&&console.log("[OnboardingSDK] Initialized with config:",this.config)}generateSessionId(){return`session_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}async validateClientKeyAndBotStatus(){const n=new AbortController,r=setTimeout(()=>n.abort(),4e3);try{const i=await fetch(`${this.config.apiUrl}/sites/validate-client-key`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({clientKey:this.config.clientKey,origin:window.location.origin}),signal:n.signal});if(clearTimeout(r),!i.ok){let s=null;try{s=await i.json()}catch{}return{valid:!1,error:(s==null?void 0:s.error)||i.statusText||`HTTP ${i.status}`}}const o=await i.json();return o.valid?{valid:!0}:{valid:!1,error:o.error||"Validation failed"}}catch(i){return clearTimeout(r),i instanceof TypeError||i instanceof DOMException&&i.name==="AbortError"?(console.warn("[OnboardingSDK] Client key validation failed due to network/timeout, proceeding anyway:",i),{valid:!0}):(console.warn("[OnboardingSDK] Unexpected error during client key validation:",i),{valid:!1})}}async startScreenShare(){try{this.pipecatClient&&(await this.pipecatClient.enableScreenShare(!0),this.screenShareEnabled=!0,console.log("[OnboardingSDK] Screen share enabled"),this.sendMetadata({type:"screen_share_status",active:!0}),this.renderReactUI())}catch(n){throw console.error("[OnboardingSDK] Screen share failed:",n),this.screenShareEnabled=!1,n}}async init(){if(this.isInitialized){console.warn("[OnboardingSDK] Already initialized");return}try{const n=await this.validateClientKeyAndBotStatus();if(!n.valid){this.config.debug&&console.log("[OnboardingSDK] Bot is disabled or invalid:",n.error);return}this._finalizePendingNavigation(),this.overlay.inject(),this.initReactUI(),this.config.userInfo&&(this.config.userInfo.externalId||this.config.userInfo.email)&&await this.checkEndUserStatus();const r=this.shouldSkipOnboardingModal();let i=!0;if(r)console.log("[OnboardingSDK] 🔄 Skipping onboarding modal for returning user"),this._discoveryPopupShown=!0,this.isReturningUser=!0,i=!1,console.log("[OnboardingSDK] Bot will stay closed - user clicks to start");else if(this.config.enableDiscoveryPopup!==!1){console.log("[OnboardingSDK] 🎉 Showing welcome popup before connect");const a=await this.showWelcomePopupAsync();this._discoveryPopupShown=!0,this.markUserVisited(),a?(this._pendingDiscoveryStart=!0,console.log("[OnboardingSDK] User chose guided discovery - will start after connect"),i=!0):(console.log("[OnboardingSDK] User skipped onboarding - bot will stay closed"),this.hasSkippedOnboarding=!0,i=!1)}if(!i){console.log("[OnboardingSDK] 📍 Initialized in minimized state - user clicks to connect"),this._isMinimized=!0,this.agentState="idle",this.isInitialized=!0,this.renderReactUI(),this.emit("ready");return}this.transport=new yn,this.pipecatClient=new Ft({transport:this.transport,enableMic:this.textModeEnabled?!1:this.config.enableAudio!==!1,enableCam:this.config.enableVideo||!1,enableScreenShare:this.config.enableScreenCapture||!1,callbacks:this.createPipecatCallbacks()}),this.setupNavigationDetection(),await this.pipecatClient.initDevices(),console.log("[OnboardingSDK] Devices initialized"),this.setupAudioPlayback();const o=`${this.config.apiUrl}/sites/start-session`;console.log("[OnboardingSDK] Starting session via floe-api proxy:",o);const s={clientKey:this.config.clientKey,origin:window.location.origin,sessionData:{sessionId:this.sessionId,createDailyRoom:!0,dailyRoomProperties:{start_video_off:!0}}};if(this.config.userInfo&&(s.sessionData.userInfo=this.config.userInfo),await this.pipecatClient.startBotAndConnect({endpoint:o,requestData:s}),this.config.enableScreenCapture)if(await this.overlay.showScreenShareModal())try{await this.startScreenShare()}catch(l){console.error("[OnboardingSDK] Screen share failed:",l)}else console.log("[OnboardingSDK] Screen share declined by user");this.isInitialized=!0,this.emit("ready")}catch(n){throw console.error("[OnboardingSDK] Initialization failed:",n),this.emit("error",n),n}}setupNavigationDetection(){this.navigationCompleteDetector||(this.navigationCompleteDetector=new Bx),this.navigationCompleteDetector.start(n=>{console.log("[OnboardingSDK] Navigation complete detected:",n),this.sendMetadata({type:"navigation_complete",url:n,timestamp:Date.now()})}),console.log("[OnboardingSDK] NavigationCompleteDetector started")}setupAudioPlayback(){this.pipecatClient&&(this.botAudioAnalyzer||(this.botAudioAnalyzer=new gy),this.userAudioAnalyzer||(this.userAudioAnalyzer=new gy),this.textModeEnabled?console.log("[OnboardingSDK] ⌨️ Text mode — skipping user mic analysis"):this.setupUserMicAnalysis(),this.pipecatClient.on("trackStarted",(n,r)=>{if(!(r!=null&&r.local)&&n.kind==="audio"){console.log("[OnboardingSDK] 🔊 Bot audio track started");const i=new MediaStream([n]),o=document.createElement("audio");o.autoplay=!0,o.srcObject=i,document.body.appendChild(o),this.botAudioAnalyzer&&this.botAudioAnalyzer.start(i,s=>{this.botIsSpeaking&&(this.audioLevels=s,this.renderReactUI())}),this.audioElements||(this.audioElements=[]),this.audioElements.push(o)}}),this.pipecatClient.on("trackStopped",(n,r)=>{!(r!=null&&r.local)&&n.kind==="audio"&&(console.log("[OnboardingSDK] 🔇 Bot audio track stopped"),this.botAudioAnalyzer&&this.botAudioAnalyzer.stop(),this.audioLevels=[]),r!=null&&r.local&&n.kind==="video"&&this.screenShareEnabled&&(console.log("[OnboardingSDK] 🖥️ Screen share track stopped (browser stop button)"),this.screenShareEnabled=!1,this.sendMetadata({type:"screen_share_status",active:!1}),this.renderReactUI())}))}async setupUserMicAnalysis(){const n=++this.userMicStreamRequestId;try{const r=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0}});if(n!==this.userMicStreamRequestId||!this.userAudioAnalyzer){console.log("[OnboardingSDK] 🎤 Mic stream request invalidated (disconnect/reconnect occurred), stopping tracks"),r.getTracks().forEach(i=>i.stop());return}this.userMicStream&&this.userMicStream.getTracks().forEach(i=>i.stop()),this.userMicStream=r,console.log("[OnboardingSDK] 🎤 User mic stream captured for visualization"),this.userAudioAnalyzer&&this.userAudioAnalyzer.start(r,i=>{this.userIsSpeaking&&(this.audioLevels=i,this.renderReactUI())})}catch(r){console.warn("[OnboardingSDK] Could not capture mic for visualization:",r)}}initReactUI(){this.reactContainer=document.createElement("div"),this.reactContainer.id="onboarding-sdk-react-ui",this.reactContainer.setAttribute(Oi,"react-ui"),this.reactContainer.style.cssText=`
|
|
810
|
+
`,y.head.appendChild(S),!y.body){console.warn("[ScreenCapture] Cloned document has no body"),document.body.removeChild(b),this.safeCanvasToDataURL(a,o,i).then(f,h);return}const v=y.createTreeWalker(y.body,NodeFilter.SHOW_TEXT);let w;for(;w=v.nextNode();)this.containsPII(w.textContent||"").contains&&w.parentElement&&w.parentElement.classList.add("pii-redacted")}const g=()=>{try{document.body.removeChild(b)}catch{}};setTimeout(()=>{try{if(!b.contentWindow){console.warn("[ScreenCapture] iframe contentWindow not available"),g(),this.safeCanvasToDataURL(a,o,i).then(f,h);return}const w=new XMLSerializer().serializeToString(y.documentElement),k=`<svg xmlns="http://www.w3.org/2000/svg" width="${window.innerWidth}" height="${window.innerHeight}"><foreignObject width="100%" height="100%">`+w+"</foreignObject></svg>",C=new Blob([k],{type:"image/svg+xml;charset=utf-8"}),M=URL.createObjectURL(C),O=new Image;O.onload=()=>{if(l.save(),l.scale(r,r),l.drawImage(O,0,0),l.restore(),URL.revokeObjectURL(M),n&&s.length>0)for(const D of s)this.applyBlur(l,{x:D.x*r,y:D.y*r,width:D.width*r,height:D.height*r});g(),this.safeCanvasToDataURL(a,o,i).then(f,h)},O.onerror=()=>{URL.revokeObjectURL(M),console.warn("[ScreenCapture] SVG image render failed, returning blank canvas"),g(),this.safeCanvasToDataURL(a,o,i).then(f,h)},O.src=M}catch(S){console.error("[ScreenCapture] Failed to render iframe content:",S),g(),this.safeCanvasToDataURL(a,o,i).then(f,h)}},100)})}async captureSimple(e={}){return this.captureWithRedaction({...e,redact:!1})}}class Fx{constructor(e){L(this,"sdk");L(this,"domIntrospector",null);L(this,"lastUrl","");L(this,"clickHandler",null);L(this,"focusHandler",null);L(this,"blurHandler",null);L(this,"inputHandler",null);L(this,"keydownHandler",null);L(this,"inputDebounceTimers",new Map);L(this,"isTracking",!1);L(this,"scrollHandler",null);L(this,"scrollDebounceTimer",null);L(this,"urlCheckInterval",null);L(this,"popstateHandler",null);this.sdk=e,this.lastUrl=window.location.href}setDOMIntrospector(e){this.domIntrospector=e,console.log("[PageTracker] DOMIntrospector set for sync captures")}start(){this.isTracking||(this.isTracking=!0,console.log("[PageTracker] Starting page event tracking"),this.sendPageMetadata(),this.setupUrlTracking(),this.clickHandler=e=>{const n=e.target;if(!n||Ct(n))return;const r=this.getElementMetadata(n),i=this.sdk._botActionDepth>0?"bot":"user";this.sdk.sendMetadata({type:"click",selector:r.selector,text:r.text,tagName:r.tagName,role:r.role,ariaLabel:r.ariaLabel,placeholder:r.placeholder,labelText:r.labelText,timestamp:Date.now(),source:i}),console.log(`[PageTracker] Click (${i}):`,r.selector,r.labelText?`(label: ${r.labelText})`:""),this.domIntrospector&&setTimeout(()=>{var o;(o=this.domIntrospector)==null||o.captureAndSendImmediate("post-click")},100)},document.addEventListener("click",this.clickHandler,!0),this.scrollHandler=()=>{this.sdk.fastExecutionMode||(this.scrollDebounceTimer&&clearTimeout(this.scrollDebounceTimer),this.scrollDebounceTimer=setTimeout(()=>{this.sdk.fastExecutionMode||(console.log("[PageTracker] Scroll detected, capturing DOM"),this.sdk.sendMetadata({type:"scroll",scrollY:window.scrollY,scrollX:window.scrollX,viewportHeight:window.innerHeight,documentHeight:document.documentElement.scrollHeight,timestamp:Date.now()}),this.domIntrospector&&this.domIntrospector.captureAndSendImmediate("post-scroll"))},200))},window.addEventListener("scroll",this.scrollHandler,{passive:!0}),this.focusHandler=e=>{const n=e.target;if(!n||!this.isInteractiveElement(n)||Ct(n))return;const r=this.getElementMetadata(n),i=n.type||"";this.sdk.sendMetadata({type:"focus",selector:r.selector,tagName:r.tagName,inputType:i,role:r.role,ariaLabel:r.ariaLabel,placeholder:r.placeholder,labelText:r.labelText,timestamp:Date.now()}),console.log("[PageTracker] Focus:",r.tagName,r.labelText?`(label: ${r.labelText})`:""),this.domIntrospector&&this.isInputElement(n)&&setTimeout(()=>{var o;(o=this.domIntrospector)==null||o.captureAndSendImmediate("post-focus")},150)},document.addEventListener("focus",this.focusHandler,!0),this.blurHandler=e=>{const n=e.target;if(!n||!this.isInteractiveElement(n)||Ct(n))return;const r=n.tagName.toLowerCase();this.sdk.sendMetadata({type:"blur",selector:this.getSelector(n),tagName:r,timestamp:Date.now()}),console.log("[PageTracker] Blur:",r),this.domIntrospector&&this.isInputElement(n)&&setTimeout(()=>{var i;(i=this.domIntrospector)==null||i.captureAndSendImmediate("post-blur")},200)},document.addEventListener("blur",this.blurHandler,!0),this.inputHandler=e=>{const n=e.target;if(!n||Ct(n))return;const r=this.inputDebounceTimers.get(n);r&&clearTimeout(r);const i=setTimeout(()=>{const o=this.getElementMetadata(n),s=n.name||n.id||n.placeholder||o.labelText||"field";this.sdk.sendMetadata({type:"form_input",selector:o.selector,field:s,inputType:n.type||"text",hasValue:!!n.value,role:o.role,ariaLabel:o.ariaLabel,placeholder:o.placeholder,labelText:o.labelText,timestamp:Date.now()}),console.log("[PageTracker] Form input:",s,o.labelText?`(label: ${o.labelText})`:""),this.inputDebounceTimers.delete(n),this.domIntrospector&&this.domIntrospector.captureAndSendImmediate("post-input")},500);this.inputDebounceTimers.set(n,i)},document.addEventListener("input",this.inputHandler,!0),this.keydownHandler=e=>{const n=e.target;if(!n||!(n instanceof HTMLElement)||Ct(n)||!this.isInputElement(n)||!["Enter","Escape","Tab"].includes(e.key))return;const i=n.tagName.toLowerCase(),o=n.type||"";if(this.sdk.sendMetadata({type:"keydown",key:e.key,selector:this.getSelector(n),tagName:i,inputType:o,timestamp:Date.now()}),console.log("[PageTracker] Keydown:",e.key,"on",i),this.domIntrospector){const s=e.key==="Enter"?300:150;setTimeout(()=>{var a;(a=this.domIntrospector)==null||a.captureAndSendImmediate(`post-keydown-${e.key.toLowerCase()}`)},s)}},document.addEventListener("keydown",this.keydownHandler,!0),console.log("[PageTracker] Event listeners attached"))}stop(){this.isTracking&&(this.isTracking=!1,this.clickHandler&&(document.removeEventListener("click",this.clickHandler,!0),this.clickHandler=null),this.focusHandler&&(document.removeEventListener("focus",this.focusHandler,!0),this.focusHandler=null),this.blurHandler&&(document.removeEventListener("blur",this.blurHandler,!0),this.blurHandler=null),this.inputHandler&&(document.removeEventListener("input",this.inputHandler,!0),this.inputHandler=null),this.keydownHandler&&(document.removeEventListener("keydown",this.keydownHandler,!0),this.keydownHandler=null),this.scrollHandler&&(window.removeEventListener("scroll",this.scrollHandler),this.scrollHandler=null),this.scrollDebounceTimer&&(clearTimeout(this.scrollDebounceTimer),this.scrollDebounceTimer=null),this.urlCheckInterval&&(clearInterval(this.urlCheckInterval),this.urlCheckInterval=null),this.popstateHandler&&(window.removeEventListener("popstate",this.popstateHandler),this.popstateHandler=null),this.inputDebounceTimers.forEach(e=>{clearTimeout(e)}),this.inputDebounceTimers.clear(),console.log("[PageTracker] Stopped tracking"))}setupUrlTracking(){this.urlCheckInterval||(this.urlCheckInterval=setInterval(()=>{const e=window.location.href;e!==this.lastUrl&&(this.lastUrl=e,this.sendPageMetadata())},1e3),this.popstateHandler=()=>{setTimeout(()=>{const e=window.location.href;e!==this.lastUrl&&(this.lastUrl=e,this.sendPageMetadata())},100)},window.addEventListener("popstate",this.popstateHandler))}sendPageMetadata(){const e=An();this.sdk.sendMetadata({type:"page_metadata",url:e,title:document.title,pathname:window.location.pathname,timestamp:Date.now()}),console.log("[PageTracker] Page metadata sent:",e)}isInteractiveElement(e){const n=e.tagName.toLowerCase();return["input","textarea","select","button"].includes(n)||e.contentEditable==="true"}isInputElement(e){const n=e.tagName.toLowerCase();if(n==="textarea")return!0;if(n==="input"){const r=e.type||"text";return["text","search","email","password","tel","url","number"].includes(r)}return e.contentEditable==="true"}getSelector(e){if(e.id&&!e.id.match(/^(react-select-|:r|radix-)/))return`#${CSS.escape(e.id)}`;const n=e.getAttribute("role"),r=e.getAttribute("aria-label"),i=e.getAttribute("name"),o=e.getAttribute("data-testid")||e.getAttribute("data-test-id"),s=e.placeholder,a=e.tagName.toLowerCase();let l=a;if(o)return`[data-testid="${o}"]`;if(n)return l=`${a}[role="${n}"]`,r?l+=`[aria-label="${r}"]`:i&&(l+=`[name="${i}"]`),l;if(i)return`${a}[name="${i}"]`;if(s)return`${a}[placeholder="${s}"]`;if(r)return`${a}[aria-label="${r}"]`;const c=[];let d=e,f=0;for(;d&&d!==document.body&&f<5;){let h=d.tagName.toLowerCase();const b=d.getAttribute("role"),y=d.getAttribute("data-testid");if(y){c.unshift(`[data-testid="${y}"]`);break}if(b)h+=`[role="${b}"]`;else if(d.className&&typeof d.className=="string"){const g=d.className.split(" ").filter(S=>S&&!S.startsWith("css-")&&!S.startsWith("sc-")&&!S.startsWith("ng-")&&!S.startsWith("_")&&!S.match(/^[a-z]{6,}$/)&&!S.match(/^\d/)).slice(0,2);g.length>0&&(h+=`.${g.join(".")}`)}c.unshift(h),d=d.parentElement,f++}return c.join(" > ")}getElementMetadata(e){var h,b,y,g;const n=e,r=this.getSelector(e),i=((h=n.innerText)==null?void 0:h.trim().substring(0,100))||"",o=e.tagName.toLowerCase(),s=e.getAttribute("role")||void 0,a=e.getAttribute("aria-label")||void 0,l=e.placeholder||void 0;let c;const d=e.getAttribute("aria-labelledby");if(d){const S=document.getElementById(d.split(/\s+/)[0]);S&&(c=(b=S.textContent)==null?void 0:b.trim())}const f=e.getAttribute("id");if(!c&&f)try{const S=document.querySelector(`label[for="${CSS.escape(f)}"]`);S&&(c=(y=S.textContent)==null?void 0:y.trim().replace(/\*$/,"").trim())}catch{}if(!c){const S=e.closest('.MuiFormControl-root, fieldset, [class*="form-group"], [class*="form-field"], [class*="field-wrapper"]');if(S){const v=S.querySelector(":scope > label, :scope > .MuiFormLabel-root, :scope > div > label");if(v){const w=S.querySelectorAll('input, select, textarea, [role="combobox"]'),k=Array.from(w).some(C=>e.contains(C)||e===C);(w.length===1||k)&&(c=(g=v.textContent)==null?void 0:g.trim().replace(/\*$/,"").trim())}}}return{selector:r,text:i,tagName:o,role:s,ariaLabel:a,placeholder:l,labelText:c}}}class my{constructor(){L(this,"loadingSelectors",['[role="progressbar"]',".loading",".spinner",".loader",'[aria-busy="true"]','[class*="loading"]','[class*="spinner"]','svg[class*="animate-spin"]','[data-loading="true"]',".MuiCircularProgress-root",".MuiLinearProgress-root"])}isLoading(){for(const e of this.loadingSelectors)try{const n=document.querySelector(e);if(n&&this.isVisible(n))return console.log("[LoadingDetector] Found loading indicator:",e),!0}catch{}return!1}async waitForLoadingComplete(e=5e3){const n=Date.now();for(console.log("[LoadingDetector] Waiting for loading to complete...");Date.now()-n<e;){if(!this.isLoading()&&(await new Promise(r=>setTimeout(r,100)),!this.isLoading()))return console.log("[LoadingDetector] Loading complete"),!0;await new Promise(r=>setTimeout(r,50))}return console.warn("[LoadingDetector] Timed out waiting for loading"),!1}isVisible(e){const n=getComputedStyle(e);if(n.visibility==="hidden"||n.display==="none"||n.opacity==="0")return!1;if(e.offsetParent===null){const i=n.position;if(i!=="fixed"&&i!=="sticky")return!1}const r=e.getBoundingClientRect();return r.width>0&&r.height>0}}class jx{async waitForStable(e=300,n=5e3){return new Promise(r=>{let i,o;const s=()=>{clearTimeout(i),clearTimeout(o),a.disconnect()},a=new MutationObserver(()=>{clearTimeout(i),i=setTimeout(()=>{s(),console.log("[DOMStabilityChecker] DOM stable"),r()},e)});a.observe(document.body,{childList:!0,subtree:!0,attributes:!0}),i=setTimeout(()=>{s(),console.log("[DOMStabilityChecker] DOM stable (no mutations)"),r()},e),o=setTimeout(()=>{s(),console.warn("[DOMStabilityChecker] Max wait time reached, proceeding anyway"),r()},n)})}}class Bx{constructor(){L(this,"lastUrl","");L(this,"urlChangeCallback",null);L(this,"loadingDetector");L(this,"domStabilityChecker");L(this,"originalPushState",null);L(this,"originalReplaceState",null);L(this,"popstateHandler",null);L(this,"isStarted",!1);L(this,"handleUrlChange",async()=>{const e=window.location.href;if(e!==this.lastUrl){console.log("[NavigationCompleteDetector] URL changed:",e),this.lastUrl=e;try{await this.waitForPageStable()}catch(n){console.warn("[NavigationCompleteDetector] Error waiting for page stable:",n)}this.urlChangeCallback&&this.urlChangeCallback(An())}});this.lastUrl=window.location.href,this.loadingDetector=new my,this.domStabilityChecker=new jx}start(e){this.isStarted&&(console.warn("[NavigationCompleteDetector] Already started, stopping first"),this.stop()),console.log("[NavigationCompleteDetector] Starting navigation monitoring"),this.isStarted=!0,this.urlChangeCallback=e,this.lastUrl=window.location.href,this.setupUrlObserver(),this.popstateHandler=()=>this.handleUrlChange(),window.addEventListener("popstate",this.popstateHandler)}setupUrlObserver(){this.originalPushState||(this.originalPushState=history.pushState.bind(history)),this.originalReplaceState||(this.originalReplaceState=history.replaceState.bind(history));const e=this;history.pushState=function(...n){e.originalPushState(...n),e.handleUrlChange()},history.replaceState=function(...n){e.originalReplaceState(...n),e.handleUrlChange()}}async waitForPageStable(){console.log("[NavigationCompleteDetector] Waiting for page to stabilize...");const e=8e3,n=Date.now();await this.loadingDetector.waitForLoadingComplete(5e3);const r=e-(Date.now()-n);r>300&&await this.domStabilityChecker.waitForStable(300,Math.min(r,3e3)),console.log("[NavigationCompleteDetector] Page stable")}stop(){this.isStarted&&(console.log("[NavigationCompleteDetector] Stopping navigation monitoring"),this.isStarted=!1,this.popstateHandler&&(window.removeEventListener("popstate",this.popstateHandler),this.popstateHandler=null),this.originalPushState&&(history.pushState=this.originalPushState,this.originalPushState=null),this.originalReplaceState&&(history.replaceState=this.originalReplaceState,this.originalReplaceState=null),this.urlChangeCallback=null)}}class Ux{constructor(e,n){L(this,"overlay");L(this,"loadingDetector");L(this,"domIntrospector",null);L(this,"isExecuting",!1);this.overlay=e,this.loadingDetector=new my}setDOMIntrospector(e){this.domIntrospector=e,console.log("[BatchedActionExecutor] DOMIntrospector set for step captures")}get isBusy(){return this.isExecuting}async executeBatch(e){if(this.isExecuting)return console.warn("[BatchedActionExecutor] Already executing a batch"),{success:!1,completedSteps:0};this.isExecuting=!0;let n=0;console.log(`[BatchedActionExecutor] ⚡ Starting fast batch with ${e.steps.length} steps`);try{for(let r=0;r<e.steps.length;r++){const i=e.steps[r];if(console.log(`[BatchedActionExecutor] Step ${r+1}/${e.steps.length}: ${i.action}`),!await this.executeStep(i))return console.error(`[BatchedActionExecutor] ❌ Step ${r+1} failed, aborting batch (completed ${n} steps)`),{success:!1,completedSteps:n};n++;const s=i.action==="wait"?100:300;await new Promise(a=>setTimeout(a,s))}return console.log("[BatchedActionExecutor] ✅ Batch completed successfully"),e.completionCallback&&e.completionCallback(),{success:!0,completedSteps:n}}finally{this.isExecuting=!1,this.overlay.clearHighlight(),this.overlay.hideFloeCursor()}}async executeStep(e){switch(e.action){case"click":return await this.executeClickStep(e);case"wait":return await this.executeWaitStep(e);case"scroll":return await this.executeScrollStep(e);default:return console.warn(`[BatchedActionExecutor] Unknown action: ${e.action}`),!1}}async executeClickStep(e){var a,l,c,d,f;if(!e.target)return console.error("[BatchedActionExecutor] Click step missing target"),!1;const n=(a=e.target.text)==null?void 0:a.toLowerCase().trim(),r=(l=e.target.tag)==null?void 0:l.toLowerCase();console.log("[BatchedActionExecutor] Looking for element:",{text:e.target.text,tag:e.target.tag,selector:e.target.selector,ariaLabel:e.target.ariaLabel,role:e.target.role,labelText:e.target.labelText,selectorFallbacks:(c=e.target.selectorFallbacks)!=null&&c.length?`${e.target.selectorFallbacks.length} fallback(s)`:void 0});let i=null;const o=3,s=[300,500,800];for(let h=0;h<=o;h++)if(h>0&&(console.log(`[BatchedActionExecutor] Retry ${h}/${o} in ${s[h-1]}ms...`),await new Promise(b=>setTimeout(b,s[h-1]))),i=xe.resolveTarget(e.target),i){const b=((d=i.textContent)==null?void 0:d.trim().toLowerCase())||"",y=i.tagName.toLowerCase();if(n&&!b.includes(n)){console.warn(`[BatchedActionExecutor] ⚠️ Found element text "${b.slice(0,50)}" doesn't match expected "${n}"`),i=null;continue}r&&y!==r&&console.log(`[BatchedActionExecutor] Note: Found ${y} instead of expected ${r} (acceptable if it contains the text)`);break}if(!i){if(console.error("[BatchedActionExecutor] ❌ Could not find matching element after retries:",e.target),n){const h=Array.from(document.querySelectorAll("*")).filter(b=>{var y;return(y=b.textContent)==null?void 0:y.toLowerCase().includes(n)}).slice(0,5).map(b=>{var y;return`${b.tagName.toLowerCase()}: "${(y=b.textContent)==null?void 0:y.trim().slice(0,50)}"`});h.length>0&&console.log("[BatchedActionExecutor] Similar elements found:",h)}return!1}return console.log("[BatchedActionExecutor] ✓ Found element:",i.tagName,(f=i.textContent)==null?void 0:f.slice(0,30)),i.scrollIntoView({behavior:"auto",block:"center"}),await new Promise(h=>setTimeout(h,150)),this.overlay.highlightResolvedElement(i,{color:"rgba(124, 58, 237, 0.4)",padding:4}),await new Promise(h=>setTimeout(h,100)),this.simulateClick(i),await new Promise(h=>setTimeout(h,100)),this.overlay.clearHighlight(),this.domIntrospector&&(await new Promise(h=>setTimeout(h,100)),this.domIntrospector.captureAndSendImmediate("post-batch-step-click")),!0}simulateClick(e){var n,r;try{const i=py(e,{focus:!0,includePointerEvents:!0,includeMouseEnter:!0,nativeClickFallback:!1});i.tagName==="A"&&i.href&&console.log("[BatchedActionExecutor] Clicked link:",i.href)}catch(i){const o=((n=e.tagName)==null?void 0:n.toLowerCase())||"unknown",s=e.href||"",a=((r=e.textContent)==null?void 0:r.trim().slice(0,50))||"";console.error(`[BatchedActionExecutor] simulateClick failed on <${o}>${s?` href="${s}"`:""} "${a}":`,i);const l=i instanceof Error?i.message:String(i),c=new Error(`[BatchedActionExecutor] Click step failed on <${o}> "${a}": ${l}`);throw c.cause=i,c}}async executeWaitStep(e){const n=e.condition||"page_stable",r=e.waitMs||5e3;switch(n){case"page_stable":return await this.loadingDetector.waitForLoadingComplete(r),await new Promise(i=>setTimeout(i,400)),!0;case"loading_complete":return await this.loadingDetector.waitForLoadingComplete(r);case"element_visible":return e.target?await this.waitForElement(e.target,r):!0;default:return await new Promise(i=>setTimeout(i,e.waitMs||500)),!0}}async executeScrollStep(e){if(!e.target)return console.warn("[BatchedActionExecutor] Scroll step has no target"),!1;const n=xe.resolveTarget(e.target);return n?(n.scrollIntoView({behavior:"auto",block:"center"}),await new Promise(r=>setTimeout(r,100)),!0):(console.warn("[BatchedActionExecutor] Scroll target not found:",e.target),!0)}async waitForElement(e,n){const r=Date.now();for(;Date.now()-r<n;){if(xe.resolveTarget(e))return!0;await new Promise(o=>setTimeout(o,100))}return!1}}class vy extends Ix{constructor(n){super();L(this,"config");L(this,"sessionId");L(this,"overlay");L(this,"capture");L(this,"actionExecutor");L(this,"pipecatClient",null);L(this,"transport",null);L(this,"isInitialized",!1);L(this,"reactRoot",null);L(this,"reactContainer",null);L(this,"agentState","idle");L(this,"pausedSessionId",null);L(this,"pendingResumeSessionId",null);L(this,"botTranscript","");L(this,"userTranscript","");L(this,"transcriptHistory",[]);L(this,"lastUserTranscript","");L(this,"isConnected",!1);L(this,"connectInFlight",!1);L(this,"micEnabled",!0);L(this,"userIsSpeaking",!1);L(this,"botIsSpeaking",!1);L(this,"audioLevels",[]);L(this,"_discoveryPopupShown",!1);L(this,"_pendingDiscoveryStart",!1);L(this,"botAudioAnalyzer",null);L(this,"userAudioAnalyzer",null);L(this,"userMicStream",null);L(this,"userMicStreamRequestId",0);L(this,"audioElements",[]);L(this,"pageTracker");L(this,"screenShareEnabled",!1);L(this,"domIntrospector");L(this,"accessibleSnapshot");L(this,"fastExecutionMode",!1);L(this,"batchedActionExecutor",null);L(this,"navigationCompleteDetector",null);L(this,"_botActionDepth",0);L(this,"endUserStatus",null);L(this,"connectionProgress",null);L(this,"isReturningUser",!1);L(this,"hasSkippedOnboarding",!1);L(this,"_isMinimized",!1);L(this,"textModeEnabled",!1);L(this,"planProgress",null);if(!n.clientKey)throw new Error("Client key is required");const r="https://api.dev.floe.so";this.config={apiUrl:r,enableVideo:!1,enableAudio:!0,enableScreenCapture:!0,debug:!1,...n},this.micEnabled=this.config.enableAudio!==!1;try{localStorage.getItem("floe_text_mode")==="true"&&(this.textModeEnabled=!0)}catch{}this.sessionId=this.generateSessionId(),this.overlay=new $x,this.capture=new yd(this.config.redactionPatterns),this.actionExecutor=new Nx,this.pageTracker=new Fx(this),this.domIntrospector=new Rx,xe.setDOMIntrospector(this.domIntrospector),this.accessibleSnapshot=new vd,this.batchedActionExecutor=new Ux(this.overlay,this.actionExecutor),this.batchedActionExecutor.setDOMIntrospector(this.domIntrospector),window.__onboardingSDK=this,this.config.debug&&console.log("[OnboardingSDK] Initialized with config:",this.config)}generateSessionId(){return`session_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}async validateClientKeyAndBotStatus(){const n=new AbortController,r=setTimeout(()=>n.abort(),4e3);try{const i=await fetch(`${this.config.apiUrl}/sites/validate-client-key`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({clientKey:this.config.clientKey,origin:window.location.origin}),signal:n.signal});if(clearTimeout(r),!i.ok){let s=null;try{s=await i.json()}catch{}return{valid:!1,error:(s==null?void 0:s.error)||i.statusText||`HTTP ${i.status}`}}const o=await i.json();return o.valid?{valid:!0}:{valid:!1,error:o.error||"Validation failed"}}catch(i){return clearTimeout(r),i instanceof TypeError||i instanceof DOMException&&i.name==="AbortError"?(console.warn("[OnboardingSDK] Client key validation failed due to network/timeout, proceeding anyway:",i),{valid:!0}):(console.warn("[OnboardingSDK] Unexpected error during client key validation:",i),{valid:!1})}}async startScreenShare(){try{this.pipecatClient&&(await this.pipecatClient.enableScreenShare(!0),this.screenShareEnabled=!0,console.log("[OnboardingSDK] Screen share enabled"),this.sendMetadata({type:"screen_share_status",active:!0}),this.renderReactUI())}catch(n){throw console.error("[OnboardingSDK] Screen share failed:",n),this.screenShareEnabled=!1,n}}async init(){if(this.isInitialized){console.warn("[OnboardingSDK] Already initialized");return}try{const n=await this.validateClientKeyAndBotStatus();if(!n.valid){this.config.debug&&console.log("[OnboardingSDK] Bot is disabled or invalid:",n.error);return}this._finalizePendingNavigation(),this.overlay.inject(),this.initReactUI(),this.config.userInfo&&(this.config.userInfo.externalId||this.config.userInfo.email)&&await this.checkEndUserStatus();const r=this.shouldSkipOnboardingModal();let i=!0;if(r)console.log("[OnboardingSDK] 🔄 Skipping onboarding modal for returning user"),this._discoveryPopupShown=!0,this.isReturningUser=!0,i=!1,console.log("[OnboardingSDK] Bot will stay closed - user clicks to start");else if(this.config.enableDiscoveryPopup!==!1){console.log("[OnboardingSDK] 🎉 Showing welcome popup before connect");const a=await this.showWelcomePopupAsync();this._discoveryPopupShown=!0,this.markUserVisited(),a?(this._pendingDiscoveryStart=!0,console.log("[OnboardingSDK] User chose guided discovery - will start after connect"),i=!0):(console.log("[OnboardingSDK] User skipped onboarding - bot will stay closed"),this.hasSkippedOnboarding=!0,i=!1)}if(!i){console.log("[OnboardingSDK] 📍 Initialized in minimized state - user clicks to connect"),this._isMinimized=!0,this.agentState="idle",this.isInitialized=!0,this.renderReactUI(),this.emit("ready");return}this.transport=new yn,this.pipecatClient=new Ft({transport:this.transport,enableMic:this.textModeEnabled?!1:this.config.enableAudio!==!1,enableCam:this.config.enableVideo||!1,enableScreenShare:this.config.enableScreenCapture||!1,callbacks:this.createPipecatCallbacks()}),this.setupNavigationDetection(),await this.pipecatClient.initDevices(),console.log("[OnboardingSDK] Devices initialized"),this.setupAudioPlayback();const o=`${this.config.apiUrl}/sites/start-session`;console.log("[OnboardingSDK] Starting session via floe-api proxy:",o);const s={clientKey:this.config.clientKey,origin:window.location.origin,sessionData:{sessionId:this.sessionId,createDailyRoom:!0,dailyRoomProperties:{start_video_off:!0}}};if(this.config.userInfo&&(s.sessionData.userInfo=this.config.userInfo),await this.pipecatClient.startBotAndConnect({endpoint:o,requestData:s}),this.config.enableScreenCapture)if(await this.overlay.showScreenShareModal())try{await this.startScreenShare()}catch(l){console.error("[OnboardingSDK] Screen share failed:",l)}else console.log("[OnboardingSDK] Screen share declined by user");this.isInitialized=!0,this.emit("ready")}catch(n){throw console.error("[OnboardingSDK] Initialization failed:",n),this.emit("error",n),n}}setupNavigationDetection(){this.navigationCompleteDetector||(this.navigationCompleteDetector=new Bx),this.navigationCompleteDetector.start(n=>{console.log("[OnboardingSDK] Navigation complete detected:",n),this.overlay.clearHighlight(),this.overlay.hideFloeCursor(),this.sendMetadata({type:"navigation_complete",url:n,timestamp:Date.now()})}),console.log("[OnboardingSDK] NavigationCompleteDetector started")}setupAudioPlayback(){this.pipecatClient&&(this.botAudioAnalyzer||(this.botAudioAnalyzer=new gy),this.userAudioAnalyzer||(this.userAudioAnalyzer=new gy),this.textModeEnabled?console.log("[OnboardingSDK] ⌨️ Text mode — skipping user mic analysis"):this.setupUserMicAnalysis(),this.pipecatClient.on("trackStarted",(n,r)=>{if(!(r!=null&&r.local)&&n.kind==="audio"){console.log("[OnboardingSDK] 🔊 Bot audio track started");const i=new MediaStream([n]),o=document.createElement("audio");o.autoplay=!0,o.srcObject=i,document.body.appendChild(o),this.botAudioAnalyzer&&this.botAudioAnalyzer.start(i,s=>{this.botIsSpeaking&&(this.audioLevels=s,this.renderReactUI())}),this.audioElements||(this.audioElements=[]),this.audioElements.push(o)}}),this.pipecatClient.on("trackStopped",(n,r)=>{!(r!=null&&r.local)&&n.kind==="audio"&&(console.log("[OnboardingSDK] 🔇 Bot audio track stopped"),this.botAudioAnalyzer&&this.botAudioAnalyzer.stop(),this.audioLevels=[]),r!=null&&r.local&&n.kind==="video"&&this.screenShareEnabled&&(console.log("[OnboardingSDK] 🖥️ Screen share track stopped (browser stop button)"),this.screenShareEnabled=!1,this.sendMetadata({type:"screen_share_status",active:!1}),this.renderReactUI())}))}async setupUserMicAnalysis(){const n=++this.userMicStreamRequestId;try{const r=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0}});if(n!==this.userMicStreamRequestId||!this.userAudioAnalyzer){console.log("[OnboardingSDK] 🎤 Mic stream request invalidated (disconnect/reconnect occurred), stopping tracks"),r.getTracks().forEach(i=>i.stop());return}this.userMicStream&&this.userMicStream.getTracks().forEach(i=>i.stop()),this.userMicStream=r,console.log("[OnboardingSDK] 🎤 User mic stream captured for visualization"),this.userAudioAnalyzer&&this.userAudioAnalyzer.start(r,i=>{this.userIsSpeaking&&(this.audioLevels=i,this.renderReactUI())})}catch(r){console.warn("[OnboardingSDK] Could not capture mic for visualization:",r)}}initReactUI(){this.reactContainer=document.createElement("div"),this.reactContainer.id="onboarding-sdk-react-ui",this.reactContainer.setAttribute(Oi,"react-ui"),this.reactContainer.style.cssText=`
|
|
811
811
|
position: fixed;
|
|
812
812
|
top: 0;
|
|
813
813
|
left: 0;
|
|
@@ -815,7 +815,7 @@ ${e.description||""}`;return confirm(r)}async execute(e){if(e.type==="click"){co
|
|
|
815
815
|
height: 100%;
|
|
816
816
|
pointer-events: none;
|
|
817
817
|
z-index: 2147483646;
|
|
818
|
-
`,document.body.appendChild(this.reactContainer),this.reactRoot=cc.createRoot(this.reactContainer),this.renderReactUI()}renderReactUI(){var n,r,i;this.reactRoot&&this.reactRoot.render(eg.createElement(Dx,{connected:this.isConnected,voiceEnabled:this.micEnabled,agentState:this.agentState,botTranscript:this.botTranscript,userTranscript:this.userTranscript,transcriptHistory:[...this.transcriptHistory],screenShareEnabled:this.screenShareEnabled,userIsSpeaking:this.userIsSpeaking,botIsSpeaking:this.botIsSpeaking,audioLevels:[...this.audioLevels],onToggleConnection:()=>this.handleToggleConnection(),onToggleMute:()=>this.toggleMute(),onToggleScreenShare:()=>this.handleToggleScreenShare(),onResume:this.pausedSessionId?()=>this.resumeSession(this.pausedSessionId):void 0,pausedSessionId:this.pausedSessionId||void 0,onStop:this.agentState==="paused"?()=>this.stopSession():void 0,connectionProgress:this.connectionProgress||void 0,isReturningUser:this.isReturningUser,hasSkippedOnboarding:this.hasSkippedOnboarding,onMinimize:()=>this.handleMinimize(),onExpand:()=>this.handleExpand(),textModeEnabled:this.textModeEnabled,onToggleTextMode:()=>this.toggleTextMode(),onSendText:o=>this.sendTextMessage(o),nudgeText:(n=this.config.nudge)==null?void 0:n.text,nudgeAutoHideDelay:(r=this.config.nudge)==null?void 0:r.autoHideDelay,nudgeAutoShow:(i=this.config.nudge)==null?void 0:i.autoShow,planProgress:this.planProgress||void 0}))}handleMinimize(){this._isMinimized=!0,console.log("[OnboardingSDK] UI minimized"),this.renderReactUI(),this.emit("minimized")}handleExpand(){this._isMinimized=!1,console.log("[OnboardingSDK] UI expanded"),this.renderReactUI(),this.emit("expanded")}setConnectionProgress(n,r,i){this.connectionProgress={stage:n,message:r,progress:i},this.renderReactUI()}clearConnectionProgress(){this.connectionProgress=null,this.renderReactUI()}async handleToggleConnection(){if(this.isConnected){console.log("[OnboardingSDK] Disconnecting and minimizing...");try{await this.disconnectAndMinimize()}catch(n){console.error("[OnboardingSDK] Error during disconnect and minimize:",n),this.emit("error",n)}return}if(this.connectInFlight){console.log("[OnboardingSDK] Connection operation already in progress, ignoring...");return}try{await this.connectWithProgress()}catch(n){console.log("[OnboardingSDK] Connection error handled in handleToggleConnection:",n)}}async disconnectAndMinimize(){this.pageTracker.stop(),this.domIntrospector.stopCapturing(),this.navigationCompleteDetector&&this.navigationCompleteDetector.stop(),this.overlay.clearHighlight(),this.pipecatClient&&(await this.pipecatClient.disconnect(),this.pipecatClient=null),this.transport&&(this.transport=null),this.audioElements&&(this.audioElements.forEach(n=>{n.pause(),n.remove()}),this.audioElements=[]),this.botAudioAnalyzer&&(this.botAudioAnalyzer.destroy(),this.botAudioAnalyzer=null),this.userAudioAnalyzer&&(this.userAudioAnalyzer.destroy(),this.userAudioAnalyzer=null),this.userMicStreamRequestId++,this.userMicStream&&(this.userMicStream.getTracks().forEach(n=>n.stop()),this.userMicStream=null),this.audioLevels=[],this.isConnected=!1,this.agentState="idle",this._isMinimized=!0,this.botTranscript="",this.userTranscript="",this.renderReactUI(),console.log("[OnboardingSDK] Disconnected and minimized"),this.emit("disconnected"),this.emit("minimized")}async connectWithProgress(){if(this.connectInFlight){console.log("[OnboardingSDK] Connection already in progress, ignoring...");return}this.connectInFlight=!0;try{this.agentState="connecting",this._isMinimized=!1,this.setConnectionProgress("initializing","Initializing...",10),this.transport=new yn,this.setConnectionProgress("authenticating","Authenticating...",30),this.pipecatClient=new Ft({transport:this.transport,enableMic:this.textModeEnabled?!1:this.config.enableAudio!==!1,enableCam:this.config.enableVideo||!1,enableScreenShare:this.config.enableScreenCapture||!1,callbacks:this.createPipecatCallbacks()}),this.setupNavigationDetection(),await this.pipecatClient.initDevices(),console.log("[OnboardingSDK] Devices initialized"),this.setupAudioPlayback(),this.setConnectionProgress("connecting","Connecting to server...",50);const n=`${this.config.apiUrl}/sites/start-session`;console.log("[OnboardingSDK] Starting session via floe-api proxy:",n);const r={clientKey:this.config.clientKey,origin:window.location.origin,sessionData:{sessionId:this.sessionId,createDailyRoom:!0,dailyRoomProperties:{start_video_off:!0}}};this.config.userInfo&&(r.sessionData.userInfo=this.config.userInfo),this.setConnectionProgress("joining","Joining session...",70),await this.pipecatClient.startBotAndConnect({endpoint:n,requestData:r}),this.setConnectionProgress("ready","Connected!",100),setTimeout(()=>{this.clearConnectionProgress()},500)}catch(n){console.error("[OnboardingSDK] Connection failed:",n),this.setConnectionProgress("error","Connection failed",0),this.agentState="idle",setTimeout(()=>{this.clearConnectionProgress(),this.renderReactUI()},3e3),this.emit("error",n)}finally{this.connectInFlight=!1}}createPipecatCallbacks(){return{onConnected:()=>{var n;console.log("[OnboardingSDK] Connected to Pipecat"),this.isConnected=!0,this.agentState="listening",this.micEnabled=((n=this.pipecatClient)==null?void 0:n.isMicEnabled)??this.config.enableAudio!==!1,console.log("[OnboardingSDK] 🎤 Mic state on connect:",this.micEnabled?"ON":"MUTED"),this.textModeEnabled&&this.pipecatClient&&(this.pipecatClient.enableMic(!1),this.micEnabled=!1,console.log("[OnboardingSDK] ⌨️ Text mode active — mic muted on connect")),this.clearConnectionProgress(),this.renderReactUI(),this.emit("connected")},onDisconnected:()=>{console.log("[OnboardingSDK] Disconnected from Pipecat"),this.isConnected=!1,this.agentState="idle",this.pageTracker.stop(),this.domIntrospector.stopCapturing(),this.navigationCompleteDetector&&this.navigationCompleteDetector.stop(),this.overlay.clearHighlight(),this.audioElements&&(this.audioElements.forEach(n=>{n.pause(),n.remove()}),this.audioElements=[]),this.botAudioAnalyzer&&(this.botAudioAnalyzer.destroy(),this.botAudioAnalyzer=null),this.userAudioAnalyzer&&(this.userAudioAnalyzer.destroy(),this.userAudioAnalyzer=null),this.userMicStreamRequestId++,this.userMicStream&&(console.log("[OnboardingSDK] 🎤 Stopping user microphone stream"),this.userMicStream.getTracks().forEach(n=>n.stop()),this.userMicStream=null),this.audioLevels=[],this.renderReactUI(),this.emit("disconnected")},onBotReady:()=>{var n;if(console.log("[OnboardingSDK] Bot ready - transport is now in ready state"),this.domIntrospector.startCapturing(1500,r=>{const i=this.accessibleSnapshot.capture(r.captureReason);this.sendAccessibleSnapshot(i),this.sendDOMSnapshot(r)}),console.log("[OnboardingSDK] DOM Introspection Layer started (with Accessible Snapshot)"),this.pageTracker.setDOMIntrospector(this.domIntrospector),this.pageTracker.start(),console.log("[OnboardingSDK] PageTracker started"),this.config.clientKey){console.log("[OnboardingSDK] Sending site initialization with client key");const r={clientKey:this.config.clientKey,origin:window.location.origin,userInfo:this.config.userInfo};this.pendingResumeSessionId&&(r.resumeSessionId=this.pendingResumeSessionId,console.log(`[OnboardingSDK] Resuming session: ${this.pendingResumeSessionId}`),this.pendingResumeSessionId=null),(n=this.pipecatClient)==null||n.sendClientMessage("site_init",r)}this.emit("botReady"),this._pendingDiscoveryStart&&(console.log("[OnboardingSDK] 🔍 Starting pending guided discovery"),this._pendingDiscoveryStart=!1,setTimeout(()=>{this.isConnected&&this.startGuidedDiscovery()},500))},onUserTranscript:n=>{console.log("[OnboardingSDK] 🎤 User transcript:",n.text,n.final?"(final)":"(interim)"),n.text&&(this.userTranscript=n.text),n.final&&n.text&&(this.lastUserTranscript=n.text),this.emit("userTranscript",n),this.handleUserInput(n.text),this.renderReactUI()},onBotTtsText:n=>{this.textModeEnabled||(console.log("[OnboardingSDK] 🤖 Bot TTS text:",n.text),n.text&&(this.botTranscript&&!this.botTranscript.endsWith(" ")&&!n.text.startsWith(" ")&&(this.botTranscript+=" "),this.botTranscript+=n.text,this.renderReactUI()))},onBotLlmText:n=>{this.textModeEnabled&&n.text&&(this.botTranscript+=n.text,this.renderReactUI())},onBotLlmStarted:()=>{this.textModeEnabled&&(console.log("[OnboardingSDK] 🤖 Bot LLM started (text mode)"),this.agentState="speaking",this.botTranscript="",this.renderReactUI())},onBotLlmStopped:()=>{this.textModeEnabled&&(console.log("[OnboardingSDK] 🤖 Bot LLM stopped (text mode)"),this.agentState="listening",this.botTranscript&&(this.transcriptHistory.push({id:`assistant-${Date.now()}`,role:"assistant",content:this.botTranscript,timestamp:Date.now()}),console.log("[OnboardingSDK] 📝 Added assistant message to history (text mode):",this.botTranscript.substring(0,50)+"...")),this.botTranscript="",this.renderReactUI())},onUserStartedSpeaking:()=>{console.log("[OnboardingSDK] 🎤 User started speaking"),this.agentState="listening",this.userIsSpeaking=!0,this.renderReactUI(),this.emit("userSpeaking",!0)},onUserStoppedSpeaking:()=>{console.log("[OnboardingSDK] 🛑 User stopped speaking"),this.agentState="thinking",this.userIsSpeaking=!1,this.lastUserTranscript&&(this.transcriptHistory.push({id:`user-${Date.now()}`,role:"user",content:this.lastUserTranscript,timestamp:Date.now()}),console.log("[OnboardingSDK] 📝 Added user message to history:",this.lastUserTranscript),this.lastUserTranscript=""),this.userTranscript="",this.renderReactUI(),this.emit("userSpeaking",!1)},onBotStartedSpeaking:()=>{console.log("[OnboardingSDK] 🔊 Bot started speaking"),this.agentState="speaking",this.botIsSpeaking=!0,this.userTranscript="",this.botTranscript="",this.renderReactUI(),this.emit("botSpeaking",!0)},onBotStoppedSpeaking:()=>{console.log("[OnboardingSDK] 🔇 Bot stopped speaking"),this.agentState="listening",this.botIsSpeaking=!1,this.botTranscript&&(this.transcriptHistory.push({id:`assistant-${Date.now()}`,role:"assistant",content:this.botTranscript,timestamp:Date.now()}),console.log("[OnboardingSDK] 📝 Added assistant message to history:",this.botTranscript.substring(0,50)+"...")),this.botTranscript="",this.renderReactUI(),this.emit("botSpeaking",!1)},onServerMessage:n=>{console.log("[OnboardingSDK] Server message:",n),this.handleServerMessage(n)},onError:n=>{console.error("[OnboardingSDK] Error:",n),this.emit("error",n)}}}async resumeSession(n){console.log(`[OnboardingSDK] Resuming session: ${n}`),this.pendingResumeSessionId=n,this.agentState="idle",console.log("[OnboardingSDK] Forcing full reconnect for resume (bot pipeline was cancelled)"),this.isConnected&&await this.disconnect(),await new Promise(r=>setTimeout(r,100)),await this.init()}async stopSession(){console.log("[OnboardingSDK] Stopping paused session"),this.agentState="idle",this.pausedSessionId=null,this.pendingResumeSessionId=null,this.isConnected&&await this.disconnect(),this.renderReactUI(),this.emit("sessionStopped")}async handleToggleScreenShare(){if(!this.pipecatClient){console.warn("[OnboardingSDK] Cannot toggle screen share: client not initialized");return}try{this.screenShareEnabled?(console.log("[OnboardingSDK] Stopping screen share"),await this.pipecatClient.enableScreenShare(!1),this.screenShareEnabled=!1,this.sendMetadata({type:"screen_share_status",active:!1})):(console.log("[OnboardingSDK] Starting screen share"),await this.pipecatClient.enableScreenShare(!0),this.screenShareEnabled=!0,this.sendMetadata({type:"screen_share_status",active:!0})),this.renderReactUI()}catch(n){console.error("[OnboardingSDK] Failed to toggle screen share:",n),this.emit("error",n)}}sendMetadata(n){if(this.pipecatClient&&this.isConnected){const r=n.type||"metadata";console.log(`[OnboardingSDK] Sending metadata: ${r}`,n),this.pipecatClient.sendClientMessage(r,n)}else console.warn("[OnboardingSDK] Cannot send metadata - not connected")}sendDOMSnapshot(n){this.pipecatClient&&this.isConnected&&(Math.random()<.2&&console.log(`[OnboardingSDK] Sending DOM snapshot: ${n.totalElements} elements`),this.pipecatClient.sendClientMessage("dom_snapshot",{type:"dom_snapshot",...n}))}sendAccessibleSnapshot(n){this.pipecatClient&&this.isConnected&&(Math.random()<.3&&(console.log(`[OnboardingSDK] Sending accessible snapshot: ${n.elementCount} elements (reduced from DOM)`),this.config.debug&&console.log("[OnboardingSDK] Accessible elements:",n.elements.slice(0,5).map(r=>`${r.ref}: ${r.role} "${r.name}"`).join(", "),n.elements.length>5?"...":"")),this.pipecatClient.sendClientMessage("accessible_snapshot",{type:"accessible_snapshot",...n}))}async handleUserInput(n){await this.extractIntent(n),this.config.enableScreenCapture&&await this.captureContext()}handleServerMessage(n){console.log("[OnboardingSDK] 📥 Server message received:",JSON.stringify(n,null,2));let r=n;if(n.data&&typeof n.data=="object"&&(console.log("[OnboardingSDK] Unwrapping RTVIServerMessageFrame data"),r=n.data),r.type==="ui_action"&&r.action&&r.target){console.log("[OnboardingSDK] 🎯 Received UI action from bot:",r.action),console.log("[OnboardingSDK] Target:",JSON.stringify(r.target,null,2)),this.handleHybridAction({action:r.action,target:r.target,value:r.value,description:r.description,precondition:r.precondition});return}if(r.action&&r.target){console.log("[OnboardingSDK] 🎯 Received direct hybrid action:",r.action),this.handleHybridAction(r);return}r.type==="highlight"?(console.log("[OnboardingSDK] Handling highlight command"),r.target?this.overlay.highlightTarget(r.target,r.options):r.selector&&this.overlay.highlight(r.selector,r.options)):r.type==="tooltip"&&r.text?this.overlay.showTooltip(r.text,r.options):r.type==="action"?r.target?this.handleHybridAction(r):this.actionExecutor.executeWithConsent(r.action):r.type==="clear_highlight"?this.overlay.clearHighlight():r.type==="batched_navigation"?this.handleBatchedNavigation(r):r.type==="fast_action"?this.executeActionFast(r):r.type==="execute_api"||r.action==="execute_api"?this.handleExecuteApi(r):r.type==="session_paused"?(console.log("[OnboardingSDK] Session paused:",r),this.agentState="paused",this.pausedSessionId=r.session_id||null,this.overlay.clearHighlight(),this.renderReactUI(),this.emit("sessionPaused",r)):r.type==="plan_progress"?(console.log("[OnboardingSDK] Plan progress:",r),this.planProgress={planName:r.planName||"",currentStep:r.currentStep||0,totalSteps:r.totalSteps||0,progressPercent:r.progressPercent||0,currentTaskTitle:r.currentTaskTitle||""},this.renderReactUI(),this.emit("planProgress",this.planProgress)):r.type==="plan_started"?(console.log("[OnboardingSDK] Plan started:",r),this.emit("planStarted",{planName:r.planName,totalSteps:r.totalSteps})):r.type==="plan_complete"?(console.log("[OnboardingSDK] Plan complete:",r),this.planProgress=null,this.renderReactUI(),this.emit("planComplete",{planName:r.planName})):console.log("[OnboardingSDK] Unhandled server message type:",r.type||"unknown")}async handleHybridAction(n){switch(console.log("[OnboardingSDK] 🎯 Handling hybrid action:",n.action),console.log("[OnboardingSDK] Target strategies:",n.target.strategy||"auto-detect"),console.log("[OnboardingSDK] Target text:",n.target.text),console.log("[OnboardingSDK] Target selector:",n.target.selector),console.log("[OnboardingSDK] Target tag:",n.target.tag),n.action){case"highlight":console.log("[OnboardingSDK] 💡 Executing HIGHLIGHT action"),this.overlay.highlightTarget(n.target,{color:"rgba(0, 170, 255, 0.7)",padding:10})?(console.log("[OnboardingSDK] ✅ Element highlighted successfully"),n.description&&this.overlay.showTooltip(n.description,{}),this.emit("elementHighlighted",{target:n.target,description:n.description})):(console.warn("[OnboardingSDK] ⚠️ Failed to find element for highlight"),setTimeout(()=>{this.overlay.highlightTarget(n.target,{color:"rgba(255, 193, 7, 0.7)",padding:10})?(console.log("[OnboardingSDK] ✅ Element found on retry"),n.description&&this.overlay.showTooltip(n.description,{})):console.error("[OnboardingSDK] ❌ Element not found even after retry:",n.target)},500));break;case"click":console.log("[OnboardingSDK] 👆 Executing CLICK action with Floe cursor");const i=An();if(n.target.optionText){console.log("[OnboardingSDK] 🎯 Dropdown option selection detected:",n.target.optionText),await this.handleDropdownOptionClick(n);break}let o=xe.resolveTarget(n.target);if(!o){console.warn("[OnboardingSDK] ⚠️ Click target not found"),this.sendMetadata({type:"bot_action_complete",action:"click",success:!1,target:n.target.text||n.target.selector||"unknown",error:"Element not found",timestamp:Date.now()});break}xe.scrollIntoView(o),setTimeout(async()=>{var h,b;const a=this.findCollapsedSidebar(o);if(a){console.log("[OnboardingSDK] 🔍 Element is in collapsed sidebar, expanding first...");const y=a.getBoundingClientRect();await this.overlay.animateFloeCursorTo(y.left+y.width/2,y.top+y.height/3,400),a.dispatchEvent(new MouseEvent("mouseenter",{bubbles:!0})),a.dispatchEvent(new MouseEvent("mouseover",{bubbles:!0})),await new Promise(g=>setTimeout(g,450)),console.log("[OnboardingSDK] 📂 Sidebar expanded")}if(!await xe.waitForPositionStability(o,800)){console.error("[OnboardingSDK] ❌ Element disappeared during stability wait"),this.sendMetadata({type:"bot_action_complete",action:"click",success:!1,target:n.target.text||n.target.selector||"unknown",error:"Element disappeared during animation",timestamp:Date.now()});return}const c=xe.reResolveAndVerify(n.target,o);c?(o=c,console.log("[OnboardingSDK] 🔄 Re-resolved element after stability wait")):console.warn("[OnboardingSDK] ⚠️ Could not re-resolve element, using original"),await this.overlay.moveToElementAndClick(o),await new Promise(y=>setTimeout(y,150)),this._botActionDepth++;const d={...n,target:{text:n.target.text,selector:n.target.selector,selectorFallbacks:n.target.selectorFallbacks,tag:n.target.tag,ariaLabel:n.target.ariaLabel,placeholder:n.target.placeholder,role:n.target.role,strategy:(h=n.target.strategy)==null?void 0:h.filter(y=>y!=="boundingBox"&&y!=="domIndex")}};let f=!1;try{f=await this.actionExecutor.executeHybridAction(d,!1)}finally{this._botActionDepth--}if(f){console.log("[OnboardingSDK] ✅ Click executed successfully");const y=(n.target.text||"").toLowerCase().trim(),g=((b=o==null?void 0:o.textContent)==null?void 0:b.toLowerCase().trim())||"",S=(o==null?void 0:o.tagName.toLowerCase())||"unknown";let v=!1,w="";y&&g&&!g.includes(y)&&!y.includes(g)&&(v=!0,w=`Expected "${n.target.text}", but clicked "${g.slice(0,50)}"`,console.error(`[OnboardingSDK] ❌ CLICK MISMATCH: ${w}`)),this.domIntrospector&&(await new Promise(k=>setTimeout(k,150)),this.domIntrospector.captureAndSendImmediate("post-bot-click"),console.log("[OnboardingSDK] 📸 DOM snapshot sent after bot click")),this.sendMetadata({type:"bot_action_complete",action:"click",success:!v,target:n.target.text||n.target.selector||"unknown",actualClicked:v?g.slice(0,100):void 0,clickedTag:S,mismatch:v,mismatchDetails:w||void 0,previousUrl:i,currentUrl:An(),timestamp:Date.now()}),v?console.warn("[OnboardingSDK] ⚠️ Click mismatch reported to server"):console.log("[OnboardingSDK] 📤 Sent bot_action_complete for auto-advance")}else{const y=this.actionExecutor.lastError||"unknown";console.warn("[OnboardingSDK] ⚠️ Click action failed:",y),this.sendMetadata({type:"bot_action_complete",action:"click",success:!1,target:n.target.text||n.target.selector||"unknown",error:y,timestamp:Date.now()})}await new Promise(y=>setTimeout(y,100)),setTimeout(()=>{this.overlay.clearHighlight(),this.overlay.hideFloeCursor()},800)},350);break;case"type":console.log("[OnboardingSDK] ⌨️ Executing TYPE action, value:",n.value);const s=xe.resolveTarget(n.target);s&&this.overlay.highlightResolvedElement(s,{color:"rgba(76, 175, 80, 0.6)",padding:4}),setTimeout(async()=>{await this.actionExecutor.executeHybridAction(n,!1),setTimeout(()=>this.overlay.clearHighlight(),1500)},300);break;case"focus":console.log("[OnboardingSDK] 🎯 Executing FOCUS action"),await this.actionExecutor.executeHybridAction(n,!1);break;case"hover":console.log("[OnboardingSDK] 🖱️ Executing HOVER action"),await this.actionExecutor.executeHybridAction(n,!1);break;case"scroll":console.log("[OnboardingSDK] 📜 Executing SCROLL action"),await this.actionExecutor.executeHybridAction(n,!1);break;case"multi_select":console.log("[OnboardingSDK] 📋 Executing MULTI_SELECT action"),await this.handleMultiSelectAction(n);break;case"navigate":console.log("[OnboardingSDK] 🧭 Executing NAVIGATE action to URL:",n.value);{const a=n.value;if(!a){console.warn("[OnboardingSDK] ⚠️ Navigate action missing URL"),this.sendMetadata({type:"bot_action_complete",action:"navigate",success:!1,error:"Missing target URL",timestamp:Date.now()});break}let l;try{const y=new URL(a,window.location.href);if(y.protocol!=="http:"&&y.protocol!=="https:"){console.warn("[OnboardingSDK] ⚠️ Navigate blocked — disallowed scheme:",y.protocol),this.sendMetadata({type:"bot_action_complete",action:"navigate",success:!1,error:`Blocked: disallowed URL scheme "${y.protocol}"`,timestamp:Date.now()});break}l=y.href}catch{console.warn("[OnboardingSDK] ⚠️ Navigate blocked — invalid URL"),this.sendMetadata({type:"bot_action_complete",action:"navigate",success:!1,error:"Blocked: invalid URL",timestamp:Date.now()});break}const c=window.location.href,d=Date.now(),f={resolvedUrl:za(l),beforeUrl:za(c),timestamp:d};try{sessionStorage.setItem("floe_pending_navigation",JSON.stringify(f))}catch{}const h=()=>{const y={type:"bot_action_complete",action:"navigate",target:f.resolvedUrl,success:!0,previousUrl:f.beforeUrl,currentUrl:f.resolvedUrl,timestamp:d,beacon:!0};try{const g=this.config.apiUrl||"";g&&navigator.sendBeacon&&navigator.sendBeacon(`${g}/api/v1/events/beacon`,new Blob([JSON.stringify(y)],{type:"application/json"}))}catch{}};window.addEventListener("pagehide",h,{once:!0}),window.location.href=l;const b=await this.waitForNavigation(l,1e4);window.removeEventListener("pagehide",h);try{sessionStorage.removeItem("floe_pending_navigation")}catch{}this.sendMetadata({type:"bot_action_complete",action:"navigate",target:za(l),success:b,previousUrl:za(c),currentUrl:An(),...b?{}:{error:"Navigation timed out waiting for URL change"},timestamp:d})}break;case"check_precondition":console.log("[OnboardingSDK] 🔍 Checking precondition"),await this.handleCheckPrecondition(n);break;default:console.warn("[OnboardingSDK] ⚠️ Unknown hybrid action:",n.action)}}async waitForNavigation(n,r){const i=Date.now(),o=200,s=h=>h.length>1&&h.endsWith("/")?h.slice(0,-1):h;let a;try{a=new URL(n)}catch{return console.warn("[OnboardingSDK] ⚠️ waitForNavigation: could not parse expectedUrl, using exact match"),new Promise(h=>{const b=()=>{if(window.location.href===n){h(!0);return}if(Date.now()-i>=r){h(!1);return}setTimeout(b,o)};b()})}const l=a.origin,c=s(a.pathname),d=a.search,f=a.hash;return new Promise(h=>{const b=()=>{const y=Date.now()-i;try{const g=new URL(window.location.href);if(g.origin===l&&s(g.pathname)===c&&(!d||g.search===d)&&(!f||g.hash===f)){console.log(`[OnboardingSDK] ✅ Navigation completed to: ${window.location.href}`),h(!0);return}}catch{}if(y>=r){console.warn(`[OnboardingSDK] ⏱️ Navigation timeout after ${r}ms. Current: ${window.location.href}, Expected: ${n}`),h(!1);return}setTimeout(b,o)};b()})}_finalizePendingNavigation(){let n;try{n=sessionStorage.getItem("floe_pending_navigation")}catch{return}if(!n)return;let r;try{if(r=JSON.parse(n),!r.resolvedUrl||!r.timestamp)return}catch{try{sessionStorage.removeItem("floe_pending_navigation")}catch{}return}if(Date.now()-r.timestamp>6e4){try{sessionStorage.removeItem("floe_pending_navigation")}catch{}return}const i=An(),o=i===r.resolvedUrl,s={type:"bot_action_complete",action:"navigate",target:r.resolvedUrl,success:o,previousUrl:r.beforeUrl,currentUrl:i,...o?{}:{error:"Full-page navigation did not reach expected URL"},timestamp:r.timestamp,finalized:!0};try{sessionStorage.removeItem("floe_pending_navigation")}catch{}this.sendMetadata(s),setTimeout(()=>{this.isConnected&&this.sendMetadata(s)},3e3),console.log(`[OnboardingSDK] 🔄 Finalized pending navigation: ${r.resolvedUrl} (success=${o})`)}async handleCheckPrecondition(n){const r=n.precondition;if(!r){console.warn("[OnboardingSDK] ⚠️ No precondition specified"),this.sendMetadata({type:"precondition_result",preconditionType:"unknown",optionText:"",result:!1,details:"No precondition specified in action",timestamp:Date.now()});return}const{type:i,optionText:o,selector:s}=r;let a=!1,l="";switch(i){case"option_exists":{if(!o){l="No optionText provided for option_exists";break}const c=this.findDropdownTrigger(n.target);if(c){console.log("[OnboardingSDK] 🔍 Opening dropdown to check for option:",o),this._botActionDepth++;try{this.actionExecutor.openDropdown(c)}finally{this._botActionDepth--}await new Promise(f=>setTimeout(f,400)),a=!!this.findVisibleDropdownOption(o),a||(a=!!await this.scrollToDropdownOption(o)),l=a?`Option "${o}" found in dropdown`:`Option "${o}" NOT found in dropdown`,this._botActionDepth++;try{await new Promise(h=>setTimeout(h,100));const f=document.activeElement instanceof HTMLElement?document.activeElement:document.body;f&&f.dispatchEvent(new KeyboardEvent("keydown",{key:"Escape",bubbles:!0})),await new Promise(h=>setTimeout(h,100)),document.body.dispatchEvent(new MouseEvent("click",{bubbles:!0}))}finally{this._botActionDepth--}this.overlay.clearHighlight()}else l="Could not find dropdown trigger"}break;case"element_visible":{const c=s||n.target.selector;if(!c){l="No selector provided for element_visible";break}let d=null;try{d=document.querySelector(c)}catch{l=`Invalid selector for element_visible: "${c}"`;break}a=!!(d&&xe.isVisible(d)),l=a?`Element "${c}" is visible`:`Element "${c}" is NOT visible or not found`}break;case"element_enabled":{const c=s||n.target.selector;if(!c){l="No selector provided for element_enabled";break}let d=null;try{d=document.querySelector(c)}catch{l=`Invalid selector for element_enabled: "${c}"`;break}d?(a=!(d.hasAttribute("disabled")||d.getAttribute("aria-disabled")==="true"||d.classList.contains("disabled")||d.disabled===!0),l=a?`Element "${c}" is enabled`:`Element "${c}" is disabled`):l=`Element "${c}" not found`}break;default:l=`Unknown precondition type: ${i}`}console.log(`[OnboardingSDK] 🔍 Precondition check result: ${a} - ${l}`),this.sendMetadata({type:"precondition_result",preconditionType:i,optionText:o,result:a,details:l,timestamp:Date.now()})}async handleMultiSelectAction(n){const r=n.target.selectedValues||[];if(console.log("[OnboardingSDK] 📋 handleMultiSelectAction for:",r),r.length===0){console.warn("[OnboardingSDK] ⚠️ No values to select in multi_select action"),this.sendMetadata({type:"bot_action_complete",action:"multi_select",success:!1,target:n.target.text||n.target.selector||"unknown",error:"No values provided for multi-select",timestamp:Date.now()});return}const i=this.findDropdownTrigger(n.target);if(!i){console.error("[OnboardingSDK] ❌ Could not find dropdown trigger for multi-select"),this.sendMetadata({type:"bot_action_complete",action:"multi_select",success:!1,target:n.target.text||n.target.selector||"unknown",error:"Dropdown trigger not found",timestamp:Date.now()});return}xe.scrollIntoView(i),await new Promise(l=>setTimeout(l,200)),await this.overlay.moveToElementAndClick(i),console.log("[OnboardingSDK] 📂 Opening multi-select dropdown..."),this._botActionDepth++;try{this.actionExecutor.openDropdown(i)}finally{this._botActionDepth--}await new Promise(l=>setTimeout(l,300));const o=[],s=[];for(let l=0;l<r.length;l++){const c=r[l];console.log(`[OnboardingSDK] 📋 Selecting option ${l+1}/${r.length}: "${c}"`);let d=this.findVisibleDropdownOption(c);if(!d){console.log("[OnboardingSDK] ⚠️ Option not visible, checking if dropdown closed..."),this._botActionDepth++;try{this.actionExecutor.openDropdown(i)}finally{this._botActionDepth--}if(await new Promise(f=>setTimeout(f,300)),d=this.findVisibleDropdownOption(c),!d){const f=await this.scrollToDropdownOption(c);f&&(d=f)}}if(d)if(d.getAttribute("aria-selected")==="true"||d.classList.contains("selected")||d.closest('[aria-selected="true"]')!==null)o.push(c),console.log(`[OnboardingSDK] ✅ Already selected: "${c}"`);else{this._botActionDepth++;try{const h=d.getBoundingClientRect(),b=h.left+h.width/2,y=h.top+h.height/2,g={bubbles:!0,cancelable:!0,view:window,clientX:b,clientY:y};d.dispatchEvent(new MouseEvent("mousedown",g)),d.dispatchEvent(new MouseEvent("mouseup",g)),d.dispatchEvent(new MouseEvent("click",g)),await new Promise(S=>setTimeout(S,200)),o.push(c),console.log(`[OnboardingSDK] ✅ Selected: "${c}"`)}finally{this._botActionDepth--}}else s.push(c),console.warn(`[OnboardingSDK] ⚠️ Option not found after retries: "${c}"`)}await new Promise(l=>setTimeout(l,200)),this._botActionDepth++;try{const l=document.activeElement instanceof HTMLElement?document.activeElement:document.body;l&&l.dispatchEvent(new KeyboardEvent("keydown",{key:"Escape",bubbles:!0})),await new Promise(d=>setTimeout(d,100));const c=document.querySelector('[class*="backdrop"], [class*="overlay"], .MuiBackdrop-root');c&&c instanceof HTMLElement?c.click():document.body.dispatchEvent(new MouseEvent("click",{bubbles:!0}))}finally{this._botActionDepth--}this.overlay.clearHighlight();const a=o.length>0;console.log(`[OnboardingSDK] 📋 Multi-select complete: ${o.length} selected, ${s.length} failed`),this.sendMetadata({type:"bot_action_complete",action:"multi_select",success:a,target:n.target.text||n.target.selector||"unknown",selectedValues:o,failedValues:s,timestamp:Date.now()})}async handleDropdownOptionClick(n){const r=n.target.optionText;console.log("[OnboardingSDK] 🎯 handleDropdownOptionClick for:",r);let i=this.findVisibleDropdownOption(r);if(i){console.log("[OnboardingSDK] ✅ Option already visible, clicking directly"),await this.clickDropdownOption(i,n);return}console.log("[OnboardingSDK] 🔍 Option not visible, opening dropdown first");const o=this.findDropdownTrigger(n.target);if(!o){console.error("[OnboardingSDK] ❌ Could not find dropdown trigger"),this.sendMetadata({type:"bot_action_complete",action:"click",success:!1,target:r,error:"Dropdown trigger not found",timestamp:Date.now()});return}xe.scrollIntoView(o),await new Promise(c=>setTimeout(c,200)),await this.overlay.moveToElementAndClick(o),console.log("[OnboardingSDK] 📂 Opening dropdown..."),this._botActionDepth++;try{this.actionExecutor.openDropdown(o)}finally{this._botActionDepth--}await new Promise(c=>setTimeout(c,200));const s=3e3,a=150;let l=0;for(;l<s;){if(i=this.findVisibleDropdownOption(r),i){console.log("[OnboardingSDK] ✅ Option appeared after",l,"ms");break}await new Promise(c=>setTimeout(c,a)),l+=a}if(!i){console.error("[OnboardingSDK] ❌ Option did not appear after",s,"ms"),console.error("[OnboardingSDK] Looking for:",r);const c=document.querySelectorAll('[role="option"], [class*="option"]'),d=Array.from(c).slice(0,10).map(f=>{var h;return(h=f.textContent)==null?void 0:h.trim().slice(0,50)}).filter(Boolean);d.length>0?console.log("[OnboardingSDK] Available options:",d):console.log("[OnboardingSDK] No options visible - dropdown may not have opened"),this.sendMetadata({type:"bot_action_complete",action:"click",success:!1,target:r,error:`Option "${r}" not found in dropdown`,timestamp:Date.now()}),this.overlay.clearHighlight();return}await this.clickDropdownOption(i,n)}findVisibleDropdownOption(n){var a;const r=n.toLowerCase().trim(),i=['[role="listbox"]','[role="menu"]','[class*="-menu"]:not([aria-hidden="true"])','[class*="listbox"]','[class*="options-container"]',".ant-select-dropdown","nz-option-container",".cdk-overlay-pane"];let o=null,s=null;for(const l of i){let c;try{c=document.querySelectorAll(l)}catch{continue}for(const d of c){const f=d;if(!xe.isVisible(f)||f.getBoundingClientRect().height<20)continue;const b=d.querySelectorAll('[role="option"], [class*="option"]:not([class*="singleValue"]):not([class*="placeholder"]), nz-option-item, .ant-select-item-option, .ant-select-item-option-content');for(const y of b){const g=y,S=g.className||"";if(S.toLowerCase().includes("singlevalue")||S.toLowerCase().includes("placeholder"))continue;const v=((a=g.textContent)==null?void 0:a.trim().toLowerCase())||"";if(v===r){console.log(`[OnboardingSDK] Found EXACT match for option: "${n}"`),o=g;break}if(!s&&v.includes(r)){const w=r.length/v.length;w>.7&&(console.log(`[OnboardingSDK] Found partial match (${(w*100).toFixed(0)}%): "${v.slice(0,50)}"`),s=g)}}if(o)break}if(o)break}return o||(s?(console.warn(`[OnboardingSDK] ⚠️ Using partial match for "${n}" - verify this is correct`),s):(console.log(`[OnboardingSDK] No option found for: "${n}"`),null))}async scrollToDropdownOption(n){var o;const r=n.toLowerCase().trim();console.log(`[OnboardingSDK] 🔍 Scrolling dropdown to find: "${n}"`);const i=document.querySelectorAll('[role="listbox"], [class*="-menu"] [class*="menu-list"], [class*="options-container"], [class*="virtual-list"]');for(const s of i){const a=s;if(!xe.isVisible(a)||a.scrollHeight<=a.clientHeight)continue;console.log(`[OnboardingSDK] Found scrollable container, scrollHeight: ${a.scrollHeight}`);const l=200,c=Math.ceil(a.scrollHeight/l);for(let d=0;d<c;d++){a.scrollTop=d*l,await new Promise(h=>setTimeout(h,100));const f=a.querySelectorAll('[role="option"], [class*="option"]');for(const h of f){const b=h,y=((o=b.textContent)==null?void 0:o.trim().toLowerCase())||"";if(y===r||y.includes(r))return console.log(`[OnboardingSDK] ✅ Found option after scrolling: "${n}"`),b.scrollIntoView({block:"center"}),await new Promise(g=>setTimeout(g,100)),b}}}return console.log(`[OnboardingSDK] Option not found after scrolling: "${n}"`),null}isValidDropdownElement(n,r=!1){if(!n)return console.warn("[OnboardingSDK] ⚠️ Dropdown validation: element is null"),!1;if(Ct(n))return console.warn("[OnboardingSDK] ⚠️ Dropdown validation: element is inside SDK widget",{id:n.id,className:n.className,tagName:n.tagName}),!1;if(n.getAttribute("aria-hidden")==="true"||n.closest('[aria-hidden="true"]'))return console.warn('[OnboardingSDK] ⚠️ Dropdown validation: element or ancestor has aria-hidden="true"',{id:n.id,className:n.className}),!1;const i=window.getComputedStyle(n);if(i.display==="none")return console.warn("[OnboardingSDK] ⚠️ Dropdown validation: element has display:none",{id:n.id,className:n.className}),!1;if(i.visibility==="hidden")return console.warn("[OnboardingSDK] ⚠️ Dropdown validation: element has visibility:hidden",{id:n.id,className:n.className}),!1;if(i.pointerEvents==="none")return console.warn("[OnboardingSDK] ⚠️ Dropdown validation: element has pointer-events:none",{id:n.id,className:n.className}),!1;if(i.opacity==="0")return console.warn("[OnboardingSDK] ⚠️ Dropdown validation: element has opacity:0",{id:n.id,className:n.className}),!1;const o=i.position;if(n.offsetParent===null&&o!=="fixed"&&o!=="sticky"){let a=n.parentElement,l=!1;for(;a;){const c=window.getComputedStyle(a);if(c.position==="fixed"||c.position==="sticky"){l=!0;break}a=a.parentElement}if(!l)return console.warn("[OnboardingSDK] ⚠️ Dropdown validation: element has null offsetParent (not rendered)",{id:n.id,className:n.className}),!1}const s=n.getBoundingClientRect();return s.width<=0||s.height<=0?(console.warn("[OnboardingSDK] ⚠️ Dropdown validation: element has zero dimensions",{id:n.id,className:n.className,width:s.width,height:s.height}),!1):r&&!(n.closest('[role="combobox"]')!==null||n.closest('[aria-haspopup="listbox"]')!==null||n.closest('[aria-haspopup="true"]')!==null||n.closest('[class*="select"]')!==null||n.closest('[class*="Select"]')!==null||n.closest('[class*="dropdown"]')!==null||n.closest('[class*="Dropdown"]')!==null||n.closest("select")!==null)?(console.warn("[OnboardingSDK] ⚠️ Dropdown validation (Strategy 5): element lacks dropdown-like ancestor",{id:n.id,className:n.className,tagName:n.tagName}),!1):!0}findDropdownTrigger(n){var o;if(n.dropdownTriggerSelector){console.log("[OnboardingSDK] 🎯 Using dropdownTriggerSelector:",n.dropdownTriggerSelector);try{const s=hy(n.dropdownTriggerSelector);if(s){const a=this.getClickableDropdownContainer(s);if(this.isValidDropdownElement(a))return console.log("[OnboardingSDK] ✅ Found trigger via dropdownTriggerSelector"),a;console.warn("[OnboardingSDK] ⚠️ Strategy 1: dropdownTriggerSelector element failed validation")}}catch(s){console.warn("[OnboardingSDK] Invalid dropdownTriggerSelector:",s)}}if(n.labelText){console.log("[OnboardingSDK] 🔍 Finding dropdown by label:",n.labelText);const s=this.findDropdownByLabel(n.labelText);if(s)return console.log("[OnboardingSDK] ✅ Found trigger via labelText"),s}const r=document.querySelector('input[role="combobox"]:focus');if(r){const s=this.getClickableDropdownContainer(r);if(this.isValidDropdownElement(s))return console.log("[OnboardingSDK] ✅ Found focused combobox"),s;console.warn("[OnboardingSDK] ⚠️ Strategy 3: focused combobox failed validation")}const i=document.querySelector('input[role="combobox"][aria-expanded="true"]');if(i){const s=this.getClickableDropdownContainer(i);if(this.isValidDropdownElement(s))return console.log("[OnboardingSDK] ✅ Found expanded combobox"),s;console.warn("[OnboardingSDK] ⚠️ Strategy 3: expanded combobox failed validation")}if(n.selector){const a=n.selector.replace(/\\"/g,'"').replace(/\\ /g," ").replace(/\\\\/g,"\\").replace(/\[data-option-text="[^"]*"\]/g,"").replace(/\[data-label="[^"]*"\]/g,"").replace(/\[role="option"\]/g,"").trim();if(a&&a!=="")try{const l=document.querySelector(a);if(l){const c=this.getClickableDropdownContainer(l);if(this.isValidDropdownElement(c))return console.log("[OnboardingSDK] ✅ Found trigger via cleaned selector"),c;console.warn("[OnboardingSDK] ⚠️ Strategy 4: selector element failed validation")}}catch{console.warn("[OnboardingSDK] Invalid selector:",a)}}if(n.text||n.optionText){const s=(n.text||n.optionText||"").toLowerCase(),a=['[class*="singleValue"]','[class*="single-value"]','[class*="select__single-value"]',".MuiSelect-select",'[class*="placeholder"]'];for(const l of a){const c=document.querySelectorAll(l);for(const d of c){const f=((o=d.textContent)==null?void 0:o.trim().toLowerCase())||"";if(f===s||f.includes(s)){const h=this.getClickableDropdownContainer(d);if(this.isValidDropdownElement(h,!0))return console.log("[OnboardingSDK] ✅ Found trigger via display value match"),h;console.warn("[OnboardingSDK] ⚠️ Strategy 5: display value match element failed validation",{searchText:s,selector:l,elementText:f})}}}}return console.warn("[OnboardingSDK] ❌ Could not find dropdown trigger"),null}findDropdownByLabel(n){var o;const r=n.toLowerCase().trim(),i=["label",'[class*="label"]','[class*="Label"]','[class*="form-label"]',".MuiFormLabel-root",".MuiInputLabel-root"];for(const s of i){const a=document.querySelectorAll(s);for(const l of a){const c=((o=l.textContent)==null?void 0:o.trim().toLowerCase().replace(/\*$/,"").trim())||"";if(c===r||c.includes(r)){const d=l;if(d.tagName==="LABEL"&&d.htmlFor){const b=document.getElementById(d.htmlFor);if(b)return this.getClickableDropdownContainer(b)}const f=d.id;if(f){const b=document.querySelector(`[aria-labelledby="${f}"]`);if(b)return this.getClickableDropdownContainer(b)}const h=d.closest('[class*="field"], [class*="form-group"], [class*="FormControl"]')||d.parentElement;if(h){const b=h.querySelector('input[role="combobox"], select, [aria-haspopup="listbox"], [class*="control"]');if(b)return this.getClickableDropdownContainer(b)}}}}return null}getClickableDropdownContainer(n){var i;return n.closest('[class*="-control"]')||n.closest('[class*="control"]')||n.closest('[class*="trigger"]')||n.closest("[aria-haspopup]")||((i=n.closest(".MuiSelect-select"))==null?void 0:i.parentElement)||n.closest('[class*="select"]')||n}async clickDropdownOption(n,r){var i;await this.overlay.moveToElementAndClick(n),await new Promise(o=>setTimeout(o,150)),console.log("[OnboardingSDK] 👆 Clicking dropdown option:",(i=n.textContent)==null?void 0:i.trim()),this._botActionDepth++;try{if(this.actionExecutor.triggerReactOnClickPublic(n))console.log("[OnboardingSDK] ✅ React onClick triggered for option");else{const s=n.getBoundingClientRect(),a=s.left+s.width/2,l=s.top+s.height/2,c={bubbles:!0,cancelable:!0,view:window,clientX:a,clientY:l};n.dispatchEvent(new MouseEvent("mousedown",c)),n.dispatchEvent(new MouseEvent("mouseup",c)),n.dispatchEvent(new MouseEvent("click",c))}}finally{this._botActionDepth--}console.log("[OnboardingSDK] ✅ Dropdown option clicked successfully"),this.domIntrospector&&(await new Promise(o=>setTimeout(o,150)),this.domIntrospector.captureAndSendImmediate("post-dropdown-select"),console.log("[OnboardingSDK] 📸 DOM snapshot sent after dropdown selection")),this.sendMetadata({type:"bot_action_complete",action:"click",success:!0,target:r.target.optionText||r.target.text||"dropdown option",timestamp:Date.now()}),console.log("[OnboardingSDK] 📤 Sent bot_action_complete for auto-advance"),await new Promise(o=>setTimeout(o,200)),setTimeout(()=>{this.overlay.clearHighlight(),this.overlay.hideFloeCursor()},600)}findCollapsedSidebar(n){let r=n.parentElement;for(;r&&r!==document.body;){const i=window.getComputedStyle(r),o=r.getBoundingClientRect().width,s=r.getBoundingClientRect().height,a=i.transition.includes("width")||i.transitionProperty.includes("width")||i.transitionProperty==="all",l=o<80,c=s>window.innerHeight*.5,d=typeof r.className=="string"?r.className:"",f=d.includes("sidebar")||d.includes("nav")||d.includes("menu"),h=d.includes("w-12")||d.includes("w-14")||d.includes("w-16");if(l&&c&&(a||f)||h)return console.log("[OnboardingSDK] Detected collapsed sidebar:",{width:o,height:s,hasTransition:a,hasTailwindCollapsed:h,classes:r.className.substring(0,100)}),r;r=r.parentElement}return null}async executeActionFast(n){console.log("[OnboardingSDK] ⚡ Fast executing action:",n.action);let r=xe.resolveTarget(n.target);if(!r&&(await new Promise(o=>setTimeout(o,150)),r=xe.resolveTarget(n.target),!r))return console.warn("[OnboardingSDK] ⚠️ Fast action target not found"),!1;r.scrollIntoView({behavior:"auto",block:"center"}),await new Promise(o=>setTimeout(o,50)),this.overlay.highlightResolvedElement(r,{color:"rgba(124, 58, 237, 0.4)",padding:4}),await new Promise(o=>setTimeout(o,80)),this._botActionDepth++;let i=!1;try{i=await this.actionExecutor.executeHybridAction(n,!1)}finally{this._botActionDepth--}return await new Promise(o=>setTimeout(o,50)),this.overlay.clearHighlight(),i}async handleExecuteApi(n){var b;console.log("[OnboardingSDK] 🔌 Executing API call:",n.method,n.url);const{method:r="GET",url:i,base_url:o,body:s,query_params:a,success_indicator:l,result_extractor:c,error_message_path:d}=n;let f=i;if(o&&(f=`${o.replace(/\/$/,"")}/${i.replace(/^\//,"")}`),a&&r==="GET"){const y=new URLSearchParams(a);f=`${f}?${y.toString()}`}try{const y=new URL(f,window.location.href);if(y.origin!==window.location.origin){console.error("[OnboardingSDK] ❌ Cross-origin API request blocked:",y.origin),this.sendMetadata({type:"api_execution_result",success:!1,error:`Cross-origin request blocked: ${y.origin} does not match ${window.location.origin}`,url:f,method:r,timestamp:Date.now()});return}}catch{console.error("[OnboardingSDK] ❌ Invalid URL:",f),this.sendMetadata({type:"api_execution_result",success:!1,error:`Invalid URL: ${f}`,url:f,method:r,timestamp:Date.now()});return}if(!["GET","HEAD","POST","PUT","PATCH","DELETE"].includes(r.toUpperCase())){console.error("[OnboardingSDK] ❌ HTTP method not allowed:",r),this.sendMetadata({type:"api_execution_result",success:!1,error:`HTTP method not allowed: ${r}`,url:f,method:r,timestamp:Date.now()});return}try{const y={method:r.toUpperCase(),headers:{"Content-Type":"application/json",Accept:"application/json"},credentials:"include"};s&&r!=="GET"&&(y.body=JSON.stringify(s)),console.log("[OnboardingSDK] 📤 Making API request:",f);const g=await fetch(f,y);let S;const v=await g.text();try{S=JSON.parse(v)}catch{S={raw:v}}console.log("[OnboardingSDK] 📥 API response:",g.status,S);const w=g.ok&&this.evaluateJsonPathCondition(S,l),k=this.extractJsonPath(S,c);let C;w||(C=this.extractJsonPath(S,d)||((b=S.error)==null?void 0:b.message)||S.message||`Request failed with status ${g.status}`),this.sendMetadata({type:"api_execution_result",success:w,status_code:g.status,data:S,result_text:k,error:C,url:f,method:r,timestamp:Date.now()}),console.log(`[OnboardingSDK] ${w?"✅":"❌"} API execution ${w?"succeeded":"failed"}:`,k||C)}catch(y){console.error("[OnboardingSDK] ❌ API execution error:",y),this.sendMetadata({type:"api_execution_result",success:!1,error:y instanceof Error?y.message:"Unknown error",url:f,method:r,timestamp:Date.now()})}}evaluateJsonPathCondition(n,r){if(!r)return!0;try{if(r.includes(" == ")){const[i,o]=r.split(" == "),s=this.extractJsonPath(n,i.trim()),a=o.trim().replace(/^["']|["']$/g,"");return String(s)===a}return!!this.extractJsonPath(n,r)}catch{return!0}}extractJsonPath(n,r){if(!r||!n)return;const o=r.replace(/^\$\.?/,"").split(".");let s=n;for(const a of o){if(s==null)return;s=s[a]}return s}async handleBatchedNavigation(n){if(console.log("[OnboardingSDK] ⚡ Received batched navigation request"),!this.batchedActionExecutor){console.error("[OnboardingSDK] BatchedActionExecutor not initialized");return}const r=(n.steps||[]).map(i=>{const o=i.target||i,a=o.text||o.selector||o.tag?{text:o.text,tag:o.tag,selector:o.selector,ariaLabel:o.aria_label||o.ariaLabel,role:o.role,labelText:o.label_text||o.labelText,selectorFallbacks:o.selector_fallbacks||o.selectorFallbacks}:void 0;return{action:i.action,target:a,condition:i.condition,waitMs:i.wait_ms||i.waitMs}});if(r.length===0){console.warn("[OnboardingSDK] No steps in batched navigation request");return}this.fastExecutionMode=!0,this._botActionDepth++;try{console.log("[OnboardingSDK] ⚡ Executing batched navigation with steps:",r.map(o=>{var s;return`${o.action}${(s=o.target)!=null&&s.text?` "${o.target.text}"`:""}`}).join(" → "));const i=await this.batchedActionExecutor.executeBatch({steps:r});this.domIntrospector&&(await new Promise(o=>setTimeout(o,200)),this.domIntrospector.captureAndSendImmediate("post-batched-navigation"),console.log("[OnboardingSDK] 📸 DOM snapshot sent after batched navigation")),i.success?(console.log("[OnboardingSDK] ✅ Batched navigation complete, sending success"),this.sendMetadata({type:"batched_navigation_complete",success:!0,stepCount:r.length,completedSteps:i.completedSteps,timestamp:Date.now()})):(console.log(`[OnboardingSDK] ❌ Batched navigation failed at step ${i.completedSteps+1}, sending failure`),this.sendMetadata({type:"batched_navigation_complete",success:!1,error:`Step ${i.completedSteps+1} failed - check console for details`,stepCount:r.length,completedSteps:i.completedSteps,timestamp:Date.now()}))}finally{this.fastExecutionMode=!1,this._botActionDepth--}}startNavigationDetection(n){this.navigationCompleteDetector&&this.navigationCompleteDetector.start(r=>{console.log("[OnboardingSDK] Navigation complete detected:",r),this.sendMetadata({type:"navigation_complete",url:r,timestamp:Date.now()}),n(r)})}stopNavigationDetection(){this.navigationCompleteDetector&&this.navigationCompleteDetector.stop()}isInFastMode(){return this.fastExecutionMode}async extractIntent(n){const r={"get started":"onboarding",help:"assistance","show me":"demonstration","how do":"tutorial",where:"navigation",what:"information"},i=n.toLowerCase();for(const[o,s]of Object.entries(r))if(i.includes(o))return s;return"unknown"}async captureContext(){const n=this.config.enableScreenCapture?await this.capture.captureWithRedaction():void 0,r=this.extractPageStructure();return{screenshot:n,url:An(),structure:r,timestamp:Date.now()}}extractPageStructure(){const n=[];return["button","a","input","select","textarea",'[role="button"]',"[onclick]"].forEach(i=>{document.querySelectorAll(i).forEach(o=>{const s=o.getBoundingClientRect(),a=s.width>0&&s.height>0&&s.top<window.innerHeight&&s.bottom>0;a&&n.push({selector:this.getSelector(o),type:o.tagName.toLowerCase(),text:(o.textContent||"").trim().substring(0,100),visible:a,position:s,attributes:this.getAttributes(o)})})}),{title:document.title,url:An(),elements:n,viewport:{width:window.innerWidth,height:window.innerHeight}}}getSelector(n){if(n.id)return`#${n.id}`;const r=[];let i=n;for(;i&&i!==document.body;){let o=i.tagName.toLowerCase();if(i.className){const s=Array.from(i.classList).slice(0,2).join(".");s&&(o+=`.${s}`)}r.unshift(o),i=i.parentElement}return r.join(" > ")}getAttributes(n){const r={};return["href","type","name","placeholder","aria-label","role"].forEach(o=>{const s=n.getAttribute(o);s&&(r[o]=s)}),r}async sendText(n){this.pipecatClient&&this.isConnected&&await this.pipecatClient.sendText(n)}toggleTextMode(){var n,r;this.textModeEnabled=!this.textModeEnabled,this.textModeEnabled?((n=this.pipecatClient)==null||n.enableMic(!1),this.micEnabled=!1,console.log("[OnboardingSDK] ⌨️ Text mode enabled — mic muted")):((r=this.pipecatClient)==null||r.enableMic(!0),this.micEnabled=!0,console.log("[OnboardingSDK] 🎤 Voice mode enabled — mic unmuted"),this.isConnected&&this.setupUserMicAnalysis());try{localStorage.setItem("floe_text_mode",String(this.textModeEnabled))}catch{}this.renderReactUI()}async sendTextMessage(n){n.trim()&&(this.transcriptHistory.push({id:`user-${Date.now()}`,role:"user",content:n.trim(),timestamp:Date.now()}),this.renderReactUI(),this.pipecatClient&&this.isConnected&&this.pipecatClient.sendClientMessage("text_message",{text:n.trim(),audio_response:!this.textModeEnabled}))}toggleMute(){if(this.pipecatClient){const r=!this.pipecatClient.isMicEnabled;return this.pipecatClient.enableMic(r),this.micEnabled=r,console.log("[OnboardingSDK] 🎤 Mic toggled:",r?"ON":"MUTED"),this.renderReactUI(),r}return!1}highlight(n,r){this.overlay.highlight(n,r)}clearHighlight(){this.overlay.clearHighlight()}showTooltip(n,r){this.overlay.showTooltip(n,r)}hideTooltip(){this.overlay.hideTooltip()}async executeAction(n){return this.actionExecutor.executeWithConsent(n)}async takeScreenshot(n){return this.capture.captureWithRedaction(n)}getSessionId(){return this.sessionId}getStatus(){return{initialized:this.isInitialized,connected:this.isConnected,sessionId:this.sessionId,microphoneMuted:this.pipecatClient?!this.pipecatClient.isMicEnabled:!1}}startGuidedDiscovery(){return!this.pipecatClient||!this.isConnected?(console.warn("[OnboardingSDK] Cannot start discovery - not connected"),!1):(console.log("[OnboardingSDK] 🔍 Starting guided discovery mode"),this.pipecatClient.sendClientMessage("start_discovery",{type:"start_discovery",timestamp:Date.now()}),this.hideWelcomePopup(),!0)}skipDiscovery(){console.log("[OnboardingSDK] Skipping discovery - standard greeting flow"),this.hideWelcomePopup()}showWelcomePopupAsync(){return new Promise(n=>{if(document.getElementById("floe-welcome-popup")){n(!1);return}const r=document.createElement("div");r.id="floe-welcome-popup",r.setAttribute("data-floe-widget","true"),r.style.cssText=`
|
|
818
|
+
`,document.body.appendChild(this.reactContainer),this.reactRoot=cc.createRoot(this.reactContainer),this.renderReactUI()}renderReactUI(){var n,r,i;this.reactRoot&&this.reactRoot.render(eg.createElement(Dx,{connected:this.isConnected,voiceEnabled:this.micEnabled,agentState:this.agentState,botTranscript:this.botTranscript,userTranscript:this.userTranscript,transcriptHistory:[...this.transcriptHistory],screenShareEnabled:this.screenShareEnabled,userIsSpeaking:this.userIsSpeaking,botIsSpeaking:this.botIsSpeaking,audioLevels:[...this.audioLevels],onToggleConnection:()=>this.handleToggleConnection(),onToggleMute:()=>this.toggleMute(),onToggleScreenShare:()=>this.handleToggleScreenShare(),onResume:this.pausedSessionId?()=>this.resumeSession(this.pausedSessionId):void 0,pausedSessionId:this.pausedSessionId||void 0,onStop:this.agentState==="paused"?()=>this.stopSession():void 0,connectionProgress:this.connectionProgress||void 0,isReturningUser:this.isReturningUser,hasSkippedOnboarding:this.hasSkippedOnboarding,onMinimize:()=>this.handleMinimize(),onExpand:()=>this.handleExpand(),textModeEnabled:this.textModeEnabled,onToggleTextMode:()=>this.toggleTextMode(),onSendText:o=>this.sendTextMessage(o),nudgeText:(n=this.config.nudge)==null?void 0:n.text,nudgeAutoHideDelay:(r=this.config.nudge)==null?void 0:r.autoHideDelay,nudgeAutoShow:(i=this.config.nudge)==null?void 0:i.autoShow,planProgress:this.planProgress||void 0}))}handleMinimize(){this._isMinimized=!0,console.log("[OnboardingSDK] UI minimized"),this.renderReactUI(),this.emit("minimized")}handleExpand(){this._isMinimized=!1,console.log("[OnboardingSDK] UI expanded"),this.renderReactUI(),this.emit("expanded")}setConnectionProgress(n,r,i){this.connectionProgress={stage:n,message:r,progress:i},this.renderReactUI()}clearConnectionProgress(){this.connectionProgress=null,this.renderReactUI()}async handleToggleConnection(){if(this.isConnected){console.log("[OnboardingSDK] Disconnecting and minimizing...");try{await this.disconnectAndMinimize()}catch(n){console.error("[OnboardingSDK] Error during disconnect and minimize:",n),this.emit("error",n)}return}if(this.connectInFlight){console.log("[OnboardingSDK] Connection operation already in progress, ignoring...");return}try{await this.connectWithProgress()}catch(n){console.log("[OnboardingSDK] Connection error handled in handleToggleConnection:",n)}}async disconnectAndMinimize(){this.pageTracker.stop(),this.domIntrospector.stopCapturing(),this.navigationCompleteDetector&&this.navigationCompleteDetector.stop(),this.overlay.cleanup(),this.overlay.resetCursorState(),this.pipecatClient&&(await this.pipecatClient.disconnect(),this.pipecatClient=null),this.transport&&(this.transport=null),this.audioElements&&(this.audioElements.forEach(n=>{n.pause(),n.remove()}),this.audioElements=[]),this.botAudioAnalyzer&&(this.botAudioAnalyzer.destroy(),this.botAudioAnalyzer=null),this.userAudioAnalyzer&&(this.userAudioAnalyzer.destroy(),this.userAudioAnalyzer=null),this.userMicStreamRequestId++,this.userMicStream&&(this.userMicStream.getTracks().forEach(n=>n.stop()),this.userMicStream=null),this.audioLevels=[],this.isConnected=!1,this.agentState="idle",this._isMinimized=!0,this.botTranscript="",this.userTranscript="",this.renderReactUI(),console.log("[OnboardingSDK] Disconnected and minimized"),this.emit("disconnected"),this.emit("minimized")}async connectWithProgress(){if(this.connectInFlight){console.log("[OnboardingSDK] Connection already in progress, ignoring...");return}this.connectInFlight=!0;try{this.agentState="connecting",this._isMinimized=!1,this.setConnectionProgress("initializing","Initializing...",10),this.transport=new yn,this.setConnectionProgress("authenticating","Authenticating...",30),this.pipecatClient=new Ft({transport:this.transport,enableMic:this.textModeEnabled?!1:this.config.enableAudio!==!1,enableCam:this.config.enableVideo||!1,enableScreenShare:this.config.enableScreenCapture||!1,callbacks:this.createPipecatCallbacks()}),this.setupNavigationDetection(),await this.pipecatClient.initDevices(),console.log("[OnboardingSDK] Devices initialized"),this.setupAudioPlayback(),this.setConnectionProgress("connecting","Connecting to server...",50);const n=`${this.config.apiUrl}/sites/start-session`;console.log("[OnboardingSDK] Starting session via floe-api proxy:",n);const r={clientKey:this.config.clientKey,origin:window.location.origin,sessionData:{sessionId:this.sessionId,createDailyRoom:!0,dailyRoomProperties:{start_video_off:!0}}};this.config.userInfo&&(r.sessionData.userInfo=this.config.userInfo),this.setConnectionProgress("joining","Joining session...",70),await this.pipecatClient.startBotAndConnect({endpoint:n,requestData:r}),this.setConnectionProgress("ready","Connected!",100),setTimeout(()=>{this.clearConnectionProgress()},500)}catch(n){console.error("[OnboardingSDK] Connection failed:",n),this.setConnectionProgress("error","Connection failed",0),this.agentState="idle",setTimeout(()=>{this.clearConnectionProgress(),this.renderReactUI()},3e3),this.emit("error",n)}finally{this.connectInFlight=!1}}createPipecatCallbacks(){return{onConnected:()=>{var n;console.log("[OnboardingSDK] Connected to Pipecat"),this.isConnected=!0,this.agentState="listening",this.micEnabled=((n=this.pipecatClient)==null?void 0:n.isMicEnabled)??this.config.enableAudio!==!1,console.log("[OnboardingSDK] 🎤 Mic state on connect:",this.micEnabled?"ON":"MUTED"),this.textModeEnabled&&this.pipecatClient&&(this.pipecatClient.enableMic(!1),this.micEnabled=!1,console.log("[OnboardingSDK] ⌨️ Text mode active — mic muted on connect")),this.clearConnectionProgress(),this.renderReactUI(),this.emit("connected")},onDisconnected:()=>{console.log("[OnboardingSDK] Disconnected from Pipecat"),this.isConnected=!1,this.agentState="idle",this.pageTracker.stop(),this.domIntrospector.stopCapturing(),this.navigationCompleteDetector&&this.navigationCompleteDetector.stop(),this.overlay.cleanup(),this.overlay.resetCursorState(),this.audioElements&&(this.audioElements.forEach(n=>{n.pause(),n.remove()}),this.audioElements=[]),this.botAudioAnalyzer&&(this.botAudioAnalyzer.destroy(),this.botAudioAnalyzer=null),this.userAudioAnalyzer&&(this.userAudioAnalyzer.destroy(),this.userAudioAnalyzer=null),this.userMicStreamRequestId++,this.userMicStream&&(console.log("[OnboardingSDK] 🎤 Stopping user microphone stream"),this.userMicStream.getTracks().forEach(n=>n.stop()),this.userMicStream=null),this.audioLevels=[],this.renderReactUI(),this.emit("disconnected")},onBotReady:()=>{var n;if(console.log("[OnboardingSDK] Bot ready - transport is now in ready state"),this.domIntrospector.startCapturing(1500,r=>{const i=this.accessibleSnapshot.capture(r.captureReason);this.sendAccessibleSnapshot(i),this.sendDOMSnapshot(r)}),console.log("[OnboardingSDK] DOM Introspection Layer started (with Accessible Snapshot)"),this.pageTracker.setDOMIntrospector(this.domIntrospector),this.pageTracker.start(),console.log("[OnboardingSDK] PageTracker started"),this.config.clientKey){console.log("[OnboardingSDK] Sending site initialization with client key");const r={clientKey:this.config.clientKey,origin:window.location.origin,userInfo:this.config.userInfo};this.pendingResumeSessionId&&(r.resumeSessionId=this.pendingResumeSessionId,console.log(`[OnboardingSDK] Resuming session: ${this.pendingResumeSessionId}`),this.pendingResumeSessionId=null),(n=this.pipecatClient)==null||n.sendClientMessage("site_init",r)}this.emit("botReady"),this._pendingDiscoveryStart&&(console.log("[OnboardingSDK] 🔍 Starting pending guided discovery"),this._pendingDiscoveryStart=!1,setTimeout(()=>{this.isConnected&&this.startGuidedDiscovery()},500))},onUserTranscript:n=>{console.log("[OnboardingSDK] 🎤 User transcript:",n.text,n.final?"(final)":"(interim)"),n.text&&(this.userTranscript=n.text),n.final&&n.text&&(this.lastUserTranscript=n.text),this.emit("userTranscript",n),this.handleUserInput(n.text),this.renderReactUI()},onBotTtsText:n=>{this.textModeEnabled||(console.log("[OnboardingSDK] 🤖 Bot TTS text:",n.text),n.text&&(this.botTranscript&&!this.botTranscript.endsWith(" ")&&!n.text.startsWith(" ")&&(this.botTranscript+=" "),this.botTranscript+=n.text,this.renderReactUI()))},onBotLlmText:n=>{this.textModeEnabled&&n.text&&(this.botTranscript+=n.text,this.renderReactUI())},onBotLlmStarted:()=>{this.textModeEnabled&&(console.log("[OnboardingSDK] 🤖 Bot LLM started (text mode)"),this.agentState="speaking",this.botTranscript="",this.renderReactUI())},onBotLlmStopped:()=>{this.textModeEnabled&&(console.log("[OnboardingSDK] 🤖 Bot LLM stopped (text mode)"),this.agentState="listening",this.botTranscript&&(this.transcriptHistory.push({id:`assistant-${Date.now()}`,role:"assistant",content:this.botTranscript,timestamp:Date.now()}),console.log("[OnboardingSDK] 📝 Added assistant message to history (text mode):",this.botTranscript.substring(0,50)+"...")),this.botTranscript="",this.renderReactUI())},onUserStartedSpeaking:()=>{console.log("[OnboardingSDK] 🎤 User started speaking"),this.agentState="listening",this.userIsSpeaking=!0,this.renderReactUI(),this.emit("userSpeaking",!0)},onUserStoppedSpeaking:()=>{console.log("[OnboardingSDK] 🛑 User stopped speaking"),this.agentState="thinking",this.userIsSpeaking=!1,this.lastUserTranscript&&(this.transcriptHistory.push({id:`user-${Date.now()}`,role:"user",content:this.lastUserTranscript,timestamp:Date.now()}),console.log("[OnboardingSDK] 📝 Added user message to history:",this.lastUserTranscript),this.lastUserTranscript=""),this.userTranscript="",this.renderReactUI(),this.emit("userSpeaking",!1)},onBotStartedSpeaking:()=>{console.log("[OnboardingSDK] 🔊 Bot started speaking"),this.agentState="speaking",this.botIsSpeaking=!0,this.userTranscript="",this.botTranscript="",this.renderReactUI(),this.emit("botSpeaking",!0)},onBotStoppedSpeaking:()=>{console.log("[OnboardingSDK] 🔇 Bot stopped speaking"),this.agentState="listening",this.botIsSpeaking=!1,this.botTranscript&&(this.transcriptHistory.push({id:`assistant-${Date.now()}`,role:"assistant",content:this.botTranscript,timestamp:Date.now()}),console.log("[OnboardingSDK] 📝 Added assistant message to history:",this.botTranscript.substring(0,50)+"...")),this.botTranscript="",this.renderReactUI(),this.emit("botSpeaking",!1)},onServerMessage:n=>{console.log("[OnboardingSDK] Server message:",n),this.handleServerMessage(n)},onError:n=>{console.error("[OnboardingSDK] Error:",n),this.emit("error",n)}}}async resumeSession(n){console.log(`[OnboardingSDK] Resuming session: ${n}`),this.pendingResumeSessionId=n,this.agentState="idle",console.log("[OnboardingSDK] Forcing full reconnect for resume (bot pipeline was cancelled)"),this.isConnected&&await this.disconnect(),await new Promise(r=>setTimeout(r,100)),await this.init()}async stopSession(){console.log("[OnboardingSDK] Stopping paused session"),this.agentState="idle",this.pausedSessionId=null,this.pendingResumeSessionId=null,this.isConnected&&await this.disconnect(),this.renderReactUI(),this.emit("sessionStopped")}async handleToggleScreenShare(){if(!this.pipecatClient){console.warn("[OnboardingSDK] Cannot toggle screen share: client not initialized");return}try{this.screenShareEnabled?(console.log("[OnboardingSDK] Stopping screen share"),await this.pipecatClient.enableScreenShare(!1),this.screenShareEnabled=!1,this.sendMetadata({type:"screen_share_status",active:!1})):(console.log("[OnboardingSDK] Starting screen share"),await this.pipecatClient.enableScreenShare(!0),this.screenShareEnabled=!0,this.sendMetadata({type:"screen_share_status",active:!0})),this.renderReactUI()}catch(n){console.error("[OnboardingSDK] Failed to toggle screen share:",n),this.emit("error",n)}}sendMetadata(n){if(this.pipecatClient&&this.isConnected){const r=n.type||"metadata";console.log(`[OnboardingSDK] Sending metadata: ${r}`,n),this.pipecatClient.sendClientMessage(r,n)}else console.warn("[OnboardingSDK] Cannot send metadata - not connected")}sendDOMSnapshot(n){this.pipecatClient&&this.isConnected&&(Math.random()<.2&&console.log(`[OnboardingSDK] Sending DOM snapshot: ${n.totalElements} elements`),this.pipecatClient.sendClientMessage("dom_snapshot",{type:"dom_snapshot",...n}))}sendAccessibleSnapshot(n){this.pipecatClient&&this.isConnected&&(Math.random()<.3&&(console.log(`[OnboardingSDK] Sending accessible snapshot: ${n.elementCount} elements (reduced from DOM)`),this.config.debug&&console.log("[OnboardingSDK] Accessible elements:",n.elements.slice(0,5).map(r=>`${r.ref}: ${r.role} "${r.name}"`).join(", "),n.elements.length>5?"...":"")),this.pipecatClient.sendClientMessage("accessible_snapshot",{type:"accessible_snapshot",...n}))}async handleUserInput(n){await this.extractIntent(n),this.config.enableScreenCapture&&await this.captureContext()}handleServerMessage(n){console.log("[OnboardingSDK] 📥 Server message received:",JSON.stringify(n,null,2));let r=n;if(n.data&&typeof n.data=="object"&&(console.log("[OnboardingSDK] Unwrapping RTVIServerMessageFrame data"),r=n.data),r.type==="ui_action"&&r.action&&r.target){console.log("[OnboardingSDK] 🎯 Received UI action from bot:",r.action),console.log("[OnboardingSDK] Target:",JSON.stringify(r.target,null,2)),this.handleHybridAction({action:r.action,target:r.target,value:r.value,description:r.description,precondition:r.precondition});return}if(r.action&&r.target){console.log("[OnboardingSDK] 🎯 Received direct hybrid action:",r.action),this.handleHybridAction(r);return}r.type==="highlight"?(console.log("[OnboardingSDK] Handling highlight command"),r.target?this.overlay.highlightTarget(r.target,r.options):r.selector&&this.overlay.highlight(r.selector,r.options)):r.type==="tooltip"&&r.text?this.overlay.showTooltip(r.text,r.options):r.type==="action"?r.target?this.handleHybridAction(r):this.actionExecutor.executeWithConsent(r.action):r.type==="clear_highlight"?this.overlay.clearHighlight():r.type==="batched_navigation"?this.handleBatchedNavigation(r):r.type==="fast_action"?this.executeActionFast(r):r.type==="execute_api"||r.action==="execute_api"?this.handleExecuteApi(r):r.type==="session_paused"?(console.log("[OnboardingSDK] Session paused:",r),this.agentState="paused",this.pausedSessionId=r.session_id||null,this.overlay.clearHighlight(),this.overlay.hideFloeCursor(),this.renderReactUI(),this.emit("sessionPaused",r)):r.type==="plan_progress"?(console.log("[OnboardingSDK] Plan progress:",r),this.planProgress={planName:r.planName||"",currentStep:r.currentStep||0,totalSteps:r.totalSteps||0,progressPercent:r.progressPercent||0,currentTaskTitle:r.currentTaskTitle||""},this.renderReactUI(),this.emit("planProgress",this.planProgress)):r.type==="plan_started"?(console.log("[OnboardingSDK] Plan started:",r),this.emit("planStarted",{planName:r.planName,totalSteps:r.totalSteps})):r.type==="plan_complete"?(console.log("[OnboardingSDK] Plan complete:",r),this.planProgress=null,this.overlay.clearHighlight(),this.overlay.hideFloeCursor(),this.renderReactUI(),this.emit("planComplete",{planName:r.planName})):console.log("[OnboardingSDK] Unhandled server message type:",r.type||"unknown")}async handleHybridAction(n){switch(console.log("[OnboardingSDK] 🎯 Handling hybrid action:",n.action),console.log("[OnboardingSDK] Target strategies:",n.target.strategy||"auto-detect"),console.log("[OnboardingSDK] Target text:",n.target.text),console.log("[OnboardingSDK] Target selector:",n.target.selector),console.log("[OnboardingSDK] Target tag:",n.target.tag),n.action){case"highlight":console.log("[OnboardingSDK] 💡 Executing HIGHLIGHT action"),this.overlay.highlightTarget(n.target,{color:"rgba(0, 170, 255, 0.7)",padding:10})?(console.log("[OnboardingSDK] ✅ Element highlighted successfully"),n.description&&this.overlay.showTooltip(n.description,{}),this.emit("elementHighlighted",{target:n.target,description:n.description})):(console.warn("[OnboardingSDK] ⚠️ Failed to find element for highlight"),setTimeout(()=>{this.overlay.highlightTarget(n.target,{color:"rgba(255, 193, 7, 0.7)",padding:10})?(console.log("[OnboardingSDK] ✅ Element found on retry"),n.description&&this.overlay.showTooltip(n.description,{})):console.error("[OnboardingSDK] ❌ Element not found even after retry:",n.target)},500));break;case"click":console.log("[OnboardingSDK] 👆 Executing CLICK action with Floe cursor");const i=An();if(n.target.optionText){console.log("[OnboardingSDK] 🎯 Dropdown option selection detected:",n.target.optionText),await this.handleDropdownOptionClick(n);break}let o=xe.resolveTarget(n.target);if(!o){console.warn("[OnboardingSDK] ⚠️ Click target not found"),this.overlay.clearHighlight(),this.overlay.hideFloeCursor(),this.sendMetadata({type:"bot_action_complete",action:"click",success:!1,target:n.target.text||n.target.selector||"unknown",error:"Element not found",timestamp:Date.now()});break}xe.scrollIntoView(o),setTimeout(async()=>{var h,b;const a=this.findCollapsedSidebar(o);if(a){console.log("[OnboardingSDK] 🔍 Element is in collapsed sidebar, expanding first...");const y=a.getBoundingClientRect();await this.overlay.animateFloeCursorTo(y.left+y.width/2,y.top+y.height/3,400),a.dispatchEvent(new MouseEvent("mouseenter",{bubbles:!0})),a.dispatchEvent(new MouseEvent("mouseover",{bubbles:!0})),await new Promise(g=>setTimeout(g,450)),console.log("[OnboardingSDK] 📂 Sidebar expanded")}if(!await xe.waitForPositionStability(o,800)){console.error("[OnboardingSDK] ❌ Element disappeared during stability wait"),this.overlay.clearHighlight(),this.overlay.hideFloeCursor(),this.sendMetadata({type:"bot_action_complete",action:"click",success:!1,target:n.target.text||n.target.selector||"unknown",error:"Element disappeared during animation",timestamp:Date.now()});return}const c=xe.reResolveAndVerify(n.target,o);c?(o=c,console.log("[OnboardingSDK] 🔄 Re-resolved element after stability wait")):console.warn("[OnboardingSDK] ⚠️ Could not re-resolve element, using original"),await this.overlay.moveToElementAndClick(o),await new Promise(y=>setTimeout(y,150)),this._botActionDepth++;const d={...n,target:{text:n.target.text,selector:n.target.selector,selectorFallbacks:n.target.selectorFallbacks,tag:n.target.tag,ariaLabel:n.target.ariaLabel,placeholder:n.target.placeholder,role:n.target.role,strategy:(h=n.target.strategy)==null?void 0:h.filter(y=>y!=="boundingBox"&&y!=="domIndex")}};let f=!1;try{f=await this.actionExecutor.executeHybridAction(d,!1)}finally{this._botActionDepth--}if(f){console.log("[OnboardingSDK] ✅ Click executed successfully");const y=(n.target.text||"").toLowerCase().trim(),g=((b=o==null?void 0:o.textContent)==null?void 0:b.toLowerCase().trim())||"",S=(o==null?void 0:o.tagName.toLowerCase())||"unknown";let v=!1,w="";y&&g&&!g.includes(y)&&!y.includes(g)&&(v=!0,w=`Expected "${n.target.text}", but clicked "${g.slice(0,50)}"`,console.error(`[OnboardingSDK] ❌ CLICK MISMATCH: ${w}`)),this.domIntrospector&&(await new Promise(k=>setTimeout(k,150)),this.domIntrospector.captureAndSendImmediate("post-bot-click"),console.log("[OnboardingSDK] 📸 DOM snapshot sent after bot click")),this.sendMetadata({type:"bot_action_complete",action:"click",success:!v,target:n.target.text||n.target.selector||"unknown",actualClicked:v?g.slice(0,100):void 0,clickedTag:S,mismatch:v,mismatchDetails:w||void 0,previousUrl:i,currentUrl:An(),timestamp:Date.now()}),v?console.warn("[OnboardingSDK] ⚠️ Click mismatch reported to server"):console.log("[OnboardingSDK] 📤 Sent bot_action_complete for auto-advance")}else{const y=this.actionExecutor.lastError||"unknown";console.warn("[OnboardingSDK] ⚠️ Click action failed:",y),this.sendMetadata({type:"bot_action_complete",action:"click",success:!1,target:n.target.text||n.target.selector||"unknown",error:y,timestamp:Date.now()})}await new Promise(y=>setTimeout(y,100)),setTimeout(()=>{this.overlay.clearHighlight(),this.overlay.hideFloeCursor()},800)},350);break;case"type":console.log("[OnboardingSDK] ⌨️ Executing TYPE action, value:",n.value);const s=xe.resolveTarget(n.target);s&&this.overlay.highlightResolvedElement(s,{color:"rgba(76, 175, 80, 0.6)",padding:4}),setTimeout(async()=>{await this.actionExecutor.executeHybridAction(n,!1),setTimeout(()=>this.overlay.clearHighlight(),1500)},300);break;case"focus":console.log("[OnboardingSDK] 🎯 Executing FOCUS action"),await this.actionExecutor.executeHybridAction(n,!1);break;case"hover":console.log("[OnboardingSDK] 🖱️ Executing HOVER action"),await this.actionExecutor.executeHybridAction(n,!1);break;case"scroll":console.log("[OnboardingSDK] 📜 Executing SCROLL action"),await this.actionExecutor.executeHybridAction(n,!1);break;case"multi_select":console.log("[OnboardingSDK] 📋 Executing MULTI_SELECT action"),await this.handleMultiSelectAction(n);break;case"navigate":console.log("[OnboardingSDK] 🧭 Executing NAVIGATE action to URL:",n.value),this.overlay.clearHighlight(),this.overlay.hideFloeCursor();{const a=n.value;if(!a){console.warn("[OnboardingSDK] ⚠️ Navigate action missing URL"),this.sendMetadata({type:"bot_action_complete",action:"navigate",success:!1,error:"Missing target URL",timestamp:Date.now()});break}let l;try{const y=new URL(a,window.location.href);if(y.protocol!=="http:"&&y.protocol!=="https:"){console.warn("[OnboardingSDK] ⚠️ Navigate blocked — disallowed scheme:",y.protocol),this.sendMetadata({type:"bot_action_complete",action:"navigate",success:!1,error:`Blocked: disallowed URL scheme "${y.protocol}"`,timestamp:Date.now()});break}l=y.href}catch{console.warn("[OnboardingSDK] ⚠️ Navigate blocked — invalid URL"),this.sendMetadata({type:"bot_action_complete",action:"navigate",success:!1,error:"Blocked: invalid URL",timestamp:Date.now()});break}const c=window.location.href,d=Date.now(),f={resolvedUrl:za(l),beforeUrl:za(c),timestamp:d};try{sessionStorage.setItem("floe_pending_navigation",JSON.stringify(f))}catch{}const h=()=>{const y={type:"bot_action_complete",action:"navigate",target:f.resolvedUrl,success:!0,previousUrl:f.beforeUrl,currentUrl:f.resolvedUrl,timestamp:d,beacon:!0};try{const g=this.config.apiUrl||"";g&&navigator.sendBeacon&&navigator.sendBeacon(`${g}/api/v1/events/beacon`,new Blob([JSON.stringify(y)],{type:"application/json"}))}catch{}};window.addEventListener("pagehide",h,{once:!0}),window.location.href=l;const b=await this.waitForNavigation(l,1e4);window.removeEventListener("pagehide",h);try{sessionStorage.removeItem("floe_pending_navigation")}catch{}this.sendMetadata({type:"bot_action_complete",action:"navigate",target:za(l),success:b,previousUrl:za(c),currentUrl:An(),...b?{}:{error:"Navigation timed out waiting for URL change"},timestamp:d})}break;case"check_precondition":console.log("[OnboardingSDK] 🔍 Checking precondition"),await this.handleCheckPrecondition(n);break;default:console.warn("[OnboardingSDK] ⚠️ Unknown hybrid action:",n.action)}}async waitForNavigation(n,r){const i=Date.now(),o=200,s=h=>h.length>1&&h.endsWith("/")?h.slice(0,-1):h;let a;try{a=new URL(n)}catch{return console.warn("[OnboardingSDK] ⚠️ waitForNavigation: could not parse expectedUrl, using exact match"),new Promise(h=>{const b=()=>{if(window.location.href===n){h(!0);return}if(Date.now()-i>=r){h(!1);return}setTimeout(b,o)};b()})}const l=a.origin,c=s(a.pathname),d=a.search,f=a.hash;return new Promise(h=>{const b=()=>{const y=Date.now()-i;try{const g=new URL(window.location.href);if(g.origin===l&&s(g.pathname)===c&&(!d||g.search===d)&&(!f||g.hash===f)){console.log(`[OnboardingSDK] ✅ Navigation completed to: ${window.location.href}`),h(!0);return}}catch{}if(y>=r){console.warn(`[OnboardingSDK] ⏱️ Navigation timeout after ${r}ms. Current: ${window.location.href}, Expected: ${n}`),h(!1);return}setTimeout(b,o)};b()})}_finalizePendingNavigation(){let n;try{n=sessionStorage.getItem("floe_pending_navigation")}catch{return}if(!n)return;let r;try{if(r=JSON.parse(n),!r.resolvedUrl||!r.timestamp)return}catch{try{sessionStorage.removeItem("floe_pending_navigation")}catch{}return}if(Date.now()-r.timestamp>6e4){try{sessionStorage.removeItem("floe_pending_navigation")}catch{}return}const i=An(),o=i===r.resolvedUrl,s={type:"bot_action_complete",action:"navigate",target:r.resolvedUrl,success:o,previousUrl:r.beforeUrl,currentUrl:i,...o?{}:{error:"Full-page navigation did not reach expected URL"},timestamp:r.timestamp,finalized:!0};try{sessionStorage.removeItem("floe_pending_navigation")}catch{}this.sendMetadata(s),setTimeout(()=>{this.isConnected&&this.sendMetadata(s)},3e3),console.log(`[OnboardingSDK] 🔄 Finalized pending navigation: ${r.resolvedUrl} (success=${o})`)}async handleCheckPrecondition(n){const r=n.precondition;if(!r){console.warn("[OnboardingSDK] ⚠️ No precondition specified"),this.sendMetadata({type:"precondition_result",preconditionType:"unknown",optionText:"",result:!1,details:"No precondition specified in action",timestamp:Date.now()});return}const{type:i,optionText:o,selector:s}=r;let a=!1,l="";switch(i){case"option_exists":{if(!o){l="No optionText provided for option_exists";break}const c=this.findDropdownTrigger(n.target);if(c){console.log("[OnboardingSDK] 🔍 Opening dropdown to check for option:",o),this._botActionDepth++;try{this.actionExecutor.openDropdown(c)}finally{this._botActionDepth--}await new Promise(f=>setTimeout(f,400)),a=!!this.findVisibleDropdownOption(o),a||(a=!!await this.scrollToDropdownOption(o)),l=a?`Option "${o}" found in dropdown`:`Option "${o}" NOT found in dropdown`,this._botActionDepth++;try{await new Promise(h=>setTimeout(h,100));const f=document.activeElement instanceof HTMLElement?document.activeElement:document.body;f&&f.dispatchEvent(new KeyboardEvent("keydown",{key:"Escape",bubbles:!0})),await new Promise(h=>setTimeout(h,100)),document.body.dispatchEvent(new MouseEvent("click",{bubbles:!0}))}finally{this._botActionDepth--}this.overlay.clearHighlight()}else l="Could not find dropdown trigger"}break;case"element_visible":{const c=s||n.target.selector;if(!c){l="No selector provided for element_visible";break}let d=null;try{d=document.querySelector(c)}catch{l=`Invalid selector for element_visible: "${c}"`;break}a=!!(d&&xe.isVisible(d)),l=a?`Element "${c}" is visible`:`Element "${c}" is NOT visible or not found`}break;case"element_enabled":{const c=s||n.target.selector;if(!c){l="No selector provided for element_enabled";break}let d=null;try{d=document.querySelector(c)}catch{l=`Invalid selector for element_enabled: "${c}"`;break}d?(a=!(d.hasAttribute("disabled")||d.getAttribute("aria-disabled")==="true"||d.classList.contains("disabled")||d.disabled===!0),l=a?`Element "${c}" is enabled`:`Element "${c}" is disabled`):l=`Element "${c}" not found`}break;default:l=`Unknown precondition type: ${i}`}console.log(`[OnboardingSDK] 🔍 Precondition check result: ${a} - ${l}`),this.sendMetadata({type:"precondition_result",preconditionType:i,optionText:o,result:a,details:l,timestamp:Date.now()})}async handleMultiSelectAction(n){const r=n.target.selectedValues||[];if(console.log("[OnboardingSDK] 📋 handleMultiSelectAction for:",r),r.length===0){console.warn("[OnboardingSDK] ⚠️ No values to select in multi_select action"),this.sendMetadata({type:"bot_action_complete",action:"multi_select",success:!1,target:n.target.text||n.target.selector||"unknown",error:"No values provided for multi-select",timestamp:Date.now()});return}const i=this.findDropdownTrigger(n.target);if(!i){console.error("[OnboardingSDK] ❌ Could not find dropdown trigger for multi-select"),this.sendMetadata({type:"bot_action_complete",action:"multi_select",success:!1,target:n.target.text||n.target.selector||"unknown",error:"Dropdown trigger not found",timestamp:Date.now()});return}xe.scrollIntoView(i),await new Promise(l=>setTimeout(l,200)),await this.overlay.moveToElementAndClick(i),console.log("[OnboardingSDK] 📂 Opening multi-select dropdown..."),this._botActionDepth++;try{this.actionExecutor.openDropdown(i)}finally{this._botActionDepth--}await new Promise(l=>setTimeout(l,300));const o=[],s=[];for(let l=0;l<r.length;l++){const c=r[l];console.log(`[OnboardingSDK] 📋 Selecting option ${l+1}/${r.length}: "${c}"`);let d=this.findVisibleDropdownOption(c);if(!d){console.log("[OnboardingSDK] ⚠️ Option not visible, checking if dropdown closed..."),this._botActionDepth++;try{this.actionExecutor.openDropdown(i)}finally{this._botActionDepth--}if(await new Promise(f=>setTimeout(f,300)),d=this.findVisibleDropdownOption(c),!d){const f=await this.scrollToDropdownOption(c);f&&(d=f)}}if(d)if(d.getAttribute("aria-selected")==="true"||d.classList.contains("selected")||d.closest('[aria-selected="true"]')!==null)o.push(c),console.log(`[OnboardingSDK] ✅ Already selected: "${c}"`);else{this._botActionDepth++;try{const h=d.getBoundingClientRect(),b=h.left+h.width/2,y=h.top+h.height/2,g={bubbles:!0,cancelable:!0,view:window,clientX:b,clientY:y};d.dispatchEvent(new MouseEvent("mousedown",g)),d.dispatchEvent(new MouseEvent("mouseup",g)),d.dispatchEvent(new MouseEvent("click",g)),await new Promise(S=>setTimeout(S,200)),o.push(c),console.log(`[OnboardingSDK] ✅ Selected: "${c}"`)}finally{this._botActionDepth--}}else s.push(c),console.warn(`[OnboardingSDK] ⚠️ Option not found after retries: "${c}"`)}await new Promise(l=>setTimeout(l,200)),this._botActionDepth++;try{const l=document.activeElement instanceof HTMLElement?document.activeElement:document.body;l&&l.dispatchEvent(new KeyboardEvent("keydown",{key:"Escape",bubbles:!0})),await new Promise(d=>setTimeout(d,100));const c=document.querySelector('[class*="backdrop"], [class*="overlay"], .MuiBackdrop-root');c&&c instanceof HTMLElement?c.click():document.body.dispatchEvent(new MouseEvent("click",{bubbles:!0}))}finally{this._botActionDepth--}this.overlay.clearHighlight();const a=o.length>0;console.log(`[OnboardingSDK] 📋 Multi-select complete: ${o.length} selected, ${s.length} failed`),this.sendMetadata({type:"bot_action_complete",action:"multi_select",success:a,target:n.target.text||n.target.selector||"unknown",selectedValues:o,failedValues:s,timestamp:Date.now()})}async handleDropdownOptionClick(n){const r=n.target.optionText;console.log("[OnboardingSDK] 🎯 handleDropdownOptionClick for:",r);let i=this.findVisibleDropdownOption(r);if(i){console.log("[OnboardingSDK] ✅ Option already visible, clicking directly"),await this.clickDropdownOption(i,n);return}console.log("[OnboardingSDK] 🔍 Option not visible, opening dropdown first");const o=this.findDropdownTrigger(n.target);if(!o){console.error("[OnboardingSDK] ❌ Could not find dropdown trigger"),this.sendMetadata({type:"bot_action_complete",action:"click",success:!1,target:r,error:"Dropdown trigger not found",timestamp:Date.now()});return}xe.scrollIntoView(o),await new Promise(c=>setTimeout(c,200)),await this.overlay.moveToElementAndClick(o),console.log("[OnboardingSDK] 📂 Opening dropdown..."),this._botActionDepth++;try{this.actionExecutor.openDropdown(o)}finally{this._botActionDepth--}await new Promise(c=>setTimeout(c,200));const s=3e3,a=150;let l=0;for(;l<s;){if(i=this.findVisibleDropdownOption(r),i){console.log("[OnboardingSDK] ✅ Option appeared after",l,"ms");break}await new Promise(c=>setTimeout(c,a)),l+=a}if(!i){console.error("[OnboardingSDK] ❌ Option did not appear after",s,"ms"),console.error("[OnboardingSDK] Looking for:",r);const c=document.querySelectorAll('[role="option"], [class*="option"]'),d=Array.from(c).slice(0,10).map(f=>{var h;return(h=f.textContent)==null?void 0:h.trim().slice(0,50)}).filter(Boolean);d.length>0?console.log("[OnboardingSDK] Available options:",d):console.log("[OnboardingSDK] No options visible - dropdown may not have opened"),this.sendMetadata({type:"bot_action_complete",action:"click",success:!1,target:r,error:`Option "${r}" not found in dropdown`,timestamp:Date.now()}),this.overlay.clearHighlight();return}await this.clickDropdownOption(i,n)}findVisibleDropdownOption(n){var a;const r=n.toLowerCase().trim(),i=['[role="listbox"]','[role="menu"]','[class*="-menu"]:not([aria-hidden="true"])','[class*="listbox"]','[class*="options-container"]',".ant-select-dropdown","nz-option-container",".cdk-overlay-pane"];let o=null,s=null;for(const l of i){let c;try{c=document.querySelectorAll(l)}catch{continue}for(const d of c){const f=d;if(!xe.isVisible(f)||f.getBoundingClientRect().height<20)continue;const b=d.querySelectorAll('[role="option"], [class*="option"]:not([class*="singleValue"]):not([class*="placeholder"]), nz-option-item, .ant-select-item-option, .ant-select-item-option-content');for(const y of b){const g=y,S=g.className||"";if(S.toLowerCase().includes("singlevalue")||S.toLowerCase().includes("placeholder"))continue;const v=((a=g.textContent)==null?void 0:a.trim().toLowerCase())||"";if(v===r){console.log(`[OnboardingSDK] Found EXACT match for option: "${n}"`),o=g;break}if(!s&&v.includes(r)){const w=r.length/v.length;w>.7&&(console.log(`[OnboardingSDK] Found partial match (${(w*100).toFixed(0)}%): "${v.slice(0,50)}"`),s=g)}}if(o)break}if(o)break}return o||(s?(console.warn(`[OnboardingSDK] ⚠️ Using partial match for "${n}" - verify this is correct`),s):(console.log(`[OnboardingSDK] No option found for: "${n}"`),null))}async scrollToDropdownOption(n){var o;const r=n.toLowerCase().trim();console.log(`[OnboardingSDK] 🔍 Scrolling dropdown to find: "${n}"`);const i=document.querySelectorAll('[role="listbox"], [class*="-menu"] [class*="menu-list"], [class*="options-container"], [class*="virtual-list"]');for(const s of i){const a=s;if(!xe.isVisible(a)||a.scrollHeight<=a.clientHeight)continue;console.log(`[OnboardingSDK] Found scrollable container, scrollHeight: ${a.scrollHeight}`);const l=200,c=Math.ceil(a.scrollHeight/l);for(let d=0;d<c;d++){a.scrollTop=d*l,await new Promise(h=>setTimeout(h,100));const f=a.querySelectorAll('[role="option"], [class*="option"]');for(const h of f){const b=h,y=((o=b.textContent)==null?void 0:o.trim().toLowerCase())||"";if(y===r||y.includes(r))return console.log(`[OnboardingSDK] ✅ Found option after scrolling: "${n}"`),b.scrollIntoView({block:"center"}),await new Promise(g=>setTimeout(g,100)),b}}}return console.log(`[OnboardingSDK] Option not found after scrolling: "${n}"`),null}isValidDropdownElement(n,r=!1){if(!n)return console.warn("[OnboardingSDK] ⚠️ Dropdown validation: element is null"),!1;if(Ct(n))return console.warn("[OnboardingSDK] ⚠️ Dropdown validation: element is inside SDK widget",{id:n.id,className:n.className,tagName:n.tagName}),!1;if(n.getAttribute("aria-hidden")==="true"||n.closest('[aria-hidden="true"]'))return console.warn('[OnboardingSDK] ⚠️ Dropdown validation: element or ancestor has aria-hidden="true"',{id:n.id,className:n.className}),!1;const i=window.getComputedStyle(n);if(i.display==="none")return console.warn("[OnboardingSDK] ⚠️ Dropdown validation: element has display:none",{id:n.id,className:n.className}),!1;if(i.visibility==="hidden")return console.warn("[OnboardingSDK] ⚠️ Dropdown validation: element has visibility:hidden",{id:n.id,className:n.className}),!1;if(i.pointerEvents==="none")return console.warn("[OnboardingSDK] ⚠️ Dropdown validation: element has pointer-events:none",{id:n.id,className:n.className}),!1;if(i.opacity==="0")return console.warn("[OnboardingSDK] ⚠️ Dropdown validation: element has opacity:0",{id:n.id,className:n.className}),!1;const o=i.position;if(n.offsetParent===null&&o!=="fixed"&&o!=="sticky"){let a=n.parentElement,l=!1;for(;a;){const c=window.getComputedStyle(a);if(c.position==="fixed"||c.position==="sticky"){l=!0;break}a=a.parentElement}if(!l)return console.warn("[OnboardingSDK] ⚠️ Dropdown validation: element has null offsetParent (not rendered)",{id:n.id,className:n.className}),!1}const s=n.getBoundingClientRect();return s.width<=0||s.height<=0?(console.warn("[OnboardingSDK] ⚠️ Dropdown validation: element has zero dimensions",{id:n.id,className:n.className,width:s.width,height:s.height}),!1):r&&!(n.closest('[role="combobox"]')!==null||n.closest('[aria-haspopup="listbox"]')!==null||n.closest('[aria-haspopup="true"]')!==null||n.closest('[class*="select"]')!==null||n.closest('[class*="Select"]')!==null||n.closest('[class*="dropdown"]')!==null||n.closest('[class*="Dropdown"]')!==null||n.closest("select")!==null)?(console.warn("[OnboardingSDK] ⚠️ Dropdown validation (Strategy 5): element lacks dropdown-like ancestor",{id:n.id,className:n.className,tagName:n.tagName}),!1):!0}findDropdownTrigger(n){var o;if(n.dropdownTriggerSelector){console.log("[OnboardingSDK] 🎯 Using dropdownTriggerSelector:",n.dropdownTriggerSelector);try{const s=hy(n.dropdownTriggerSelector);if(s){const a=this.getClickableDropdownContainer(s);if(this.isValidDropdownElement(a))return console.log("[OnboardingSDK] ✅ Found trigger via dropdownTriggerSelector"),a;console.warn("[OnboardingSDK] ⚠️ Strategy 1: dropdownTriggerSelector element failed validation")}}catch(s){console.warn("[OnboardingSDK] Invalid dropdownTriggerSelector:",s)}}if(n.labelText){console.log("[OnboardingSDK] 🔍 Finding dropdown by label:",n.labelText);const s=this.findDropdownByLabel(n.labelText);if(s)return console.log("[OnboardingSDK] ✅ Found trigger via labelText"),s}const r=document.querySelector('input[role="combobox"]:focus');if(r){const s=this.getClickableDropdownContainer(r);if(this.isValidDropdownElement(s))return console.log("[OnboardingSDK] ✅ Found focused combobox"),s;console.warn("[OnboardingSDK] ⚠️ Strategy 3: focused combobox failed validation")}const i=document.querySelector('input[role="combobox"][aria-expanded="true"]');if(i){const s=this.getClickableDropdownContainer(i);if(this.isValidDropdownElement(s))return console.log("[OnboardingSDK] ✅ Found expanded combobox"),s;console.warn("[OnboardingSDK] ⚠️ Strategy 3: expanded combobox failed validation")}if(n.selector){const a=n.selector.replace(/\\"/g,'"').replace(/\\ /g," ").replace(/\\\\/g,"\\").replace(/\[data-option-text="[^"]*"\]/g,"").replace(/\[data-label="[^"]*"\]/g,"").replace(/\[role="option"\]/g,"").trim();if(a&&a!=="")try{const l=document.querySelector(a);if(l){const c=this.getClickableDropdownContainer(l);if(this.isValidDropdownElement(c))return console.log("[OnboardingSDK] ✅ Found trigger via cleaned selector"),c;console.warn("[OnboardingSDK] ⚠️ Strategy 4: selector element failed validation")}}catch{console.warn("[OnboardingSDK] Invalid selector:",a)}}if(n.text||n.optionText){const s=(n.text||n.optionText||"").toLowerCase(),a=['[class*="singleValue"]','[class*="single-value"]','[class*="select__single-value"]',".MuiSelect-select",'[class*="placeholder"]'];for(const l of a){const c=document.querySelectorAll(l);for(const d of c){const f=((o=d.textContent)==null?void 0:o.trim().toLowerCase())||"";if(f===s||f.includes(s)){const h=this.getClickableDropdownContainer(d);if(this.isValidDropdownElement(h,!0))return console.log("[OnboardingSDK] ✅ Found trigger via display value match"),h;console.warn("[OnboardingSDK] ⚠️ Strategy 5: display value match element failed validation",{searchText:s,selector:l,elementText:f})}}}}return console.warn("[OnboardingSDK] ❌ Could not find dropdown trigger"),null}findDropdownByLabel(n){var o;const r=n.toLowerCase().trim(),i=["label",'[class*="label"]','[class*="Label"]','[class*="form-label"]',".MuiFormLabel-root",".MuiInputLabel-root"];for(const s of i){const a=document.querySelectorAll(s);for(const l of a){const c=((o=l.textContent)==null?void 0:o.trim().toLowerCase().replace(/\*$/,"").trim())||"";if(c===r||c.includes(r)){const d=l;if(d.tagName==="LABEL"&&d.htmlFor){const b=document.getElementById(d.htmlFor);if(b)return this.getClickableDropdownContainer(b)}const f=d.id;if(f){const b=document.querySelector(`[aria-labelledby="${f}"]`);if(b)return this.getClickableDropdownContainer(b)}const h=d.closest('[class*="field"], [class*="form-group"], [class*="FormControl"]')||d.parentElement;if(h){const b=h.querySelector('input[role="combobox"], select, [aria-haspopup="listbox"], [class*="control"]');if(b)return this.getClickableDropdownContainer(b)}}}}return null}getClickableDropdownContainer(n){var i;return n.closest('[class*="-control"]')||n.closest('[class*="control"]')||n.closest('[class*="trigger"]')||n.closest("[aria-haspopup]")||((i=n.closest(".MuiSelect-select"))==null?void 0:i.parentElement)||n.closest('[class*="select"]')||n}async clickDropdownOption(n,r){var i;await this.overlay.moveToElementAndClick(n),await new Promise(o=>setTimeout(o,150)),console.log("[OnboardingSDK] 👆 Clicking dropdown option:",(i=n.textContent)==null?void 0:i.trim()),this._botActionDepth++;try{if(this.actionExecutor.triggerReactOnClickPublic(n))console.log("[OnboardingSDK] ✅ React onClick triggered for option");else{const s=n.getBoundingClientRect(),a=s.left+s.width/2,l=s.top+s.height/2,c={bubbles:!0,cancelable:!0,view:window,clientX:a,clientY:l};n.dispatchEvent(new MouseEvent("mousedown",c)),n.dispatchEvent(new MouseEvent("mouseup",c)),n.dispatchEvent(new MouseEvent("click",c))}}finally{this._botActionDepth--}console.log("[OnboardingSDK] ✅ Dropdown option clicked successfully"),this.domIntrospector&&(await new Promise(o=>setTimeout(o,150)),this.domIntrospector.captureAndSendImmediate("post-dropdown-select"),console.log("[OnboardingSDK] 📸 DOM snapshot sent after dropdown selection")),this.sendMetadata({type:"bot_action_complete",action:"click",success:!0,target:r.target.optionText||r.target.text||"dropdown option",timestamp:Date.now()}),console.log("[OnboardingSDK] 📤 Sent bot_action_complete for auto-advance"),await new Promise(o=>setTimeout(o,200)),setTimeout(()=>{this.overlay.clearHighlight(),this.overlay.hideFloeCursor()},600)}findCollapsedSidebar(n){let r=n.parentElement;for(;r&&r!==document.body;){const i=window.getComputedStyle(r),o=r.getBoundingClientRect().width,s=r.getBoundingClientRect().height,a=i.transition.includes("width")||i.transitionProperty.includes("width")||i.transitionProperty==="all",l=o<80,c=s>window.innerHeight*.5,d=typeof r.className=="string"?r.className:"",f=d.includes("sidebar")||d.includes("nav")||d.includes("menu"),h=d.includes("w-12")||d.includes("w-14")||d.includes("w-16");if(l&&c&&(a||f)||h)return console.log("[OnboardingSDK] Detected collapsed sidebar:",{width:o,height:s,hasTransition:a,hasTailwindCollapsed:h,classes:r.className.substring(0,100)}),r;r=r.parentElement}return null}async executeActionFast(n){console.log("[OnboardingSDK] ⚡ Fast executing action:",n.action);let r=xe.resolveTarget(n.target);if(!r&&(await new Promise(o=>setTimeout(o,150)),r=xe.resolveTarget(n.target),!r))return console.warn("[OnboardingSDK] ⚠️ Fast action target not found"),!1;r.scrollIntoView({behavior:"auto",block:"center"}),await new Promise(o=>setTimeout(o,50)),this.overlay.highlightResolvedElement(r,{color:"rgba(124, 58, 237, 0.4)",padding:4}),await new Promise(o=>setTimeout(o,80)),this._botActionDepth++;let i=!1;try{i=await this.actionExecutor.executeHybridAction(n,!1)}finally{this._botActionDepth--}return await new Promise(o=>setTimeout(o,50)),this.overlay.clearHighlight(),i}async handleExecuteApi(n){var b;console.log("[OnboardingSDK] 🔌 Executing API call:",n.method,n.url);const{method:r="GET",url:i,base_url:o,body:s,query_params:a,success_indicator:l,result_extractor:c,error_message_path:d}=n;let f=i;if(o&&(f=`${o.replace(/\/$/,"")}/${i.replace(/^\//,"")}`),a&&r==="GET"){const y=new URLSearchParams(a);f=`${f}?${y.toString()}`}try{const y=new URL(f,window.location.href);if(y.origin!==window.location.origin){console.error("[OnboardingSDK] ❌ Cross-origin API request blocked:",y.origin),this.sendMetadata({type:"api_execution_result",success:!1,error:`Cross-origin request blocked: ${y.origin} does not match ${window.location.origin}`,url:f,method:r,timestamp:Date.now()});return}}catch{console.error("[OnboardingSDK] ❌ Invalid URL:",f),this.sendMetadata({type:"api_execution_result",success:!1,error:`Invalid URL: ${f}`,url:f,method:r,timestamp:Date.now()});return}if(!["GET","HEAD","POST","PUT","PATCH","DELETE"].includes(r.toUpperCase())){console.error("[OnboardingSDK] ❌ HTTP method not allowed:",r),this.sendMetadata({type:"api_execution_result",success:!1,error:`HTTP method not allowed: ${r}`,url:f,method:r,timestamp:Date.now()});return}try{const y={method:r.toUpperCase(),headers:{"Content-Type":"application/json",Accept:"application/json"},credentials:"include"};s&&r!=="GET"&&(y.body=JSON.stringify(s)),console.log("[OnboardingSDK] 📤 Making API request:",f);const g=await fetch(f,y);let S;const v=await g.text();try{S=JSON.parse(v)}catch{S={raw:v}}console.log("[OnboardingSDK] 📥 API response:",g.status,S);const w=g.ok&&this.evaluateJsonPathCondition(S,l),k=this.extractJsonPath(S,c);let C;w||(C=this.extractJsonPath(S,d)||((b=S.error)==null?void 0:b.message)||S.message||`Request failed with status ${g.status}`),this.sendMetadata({type:"api_execution_result",success:w,status_code:g.status,data:S,result_text:k,error:C,url:f,method:r,timestamp:Date.now()}),console.log(`[OnboardingSDK] ${w?"✅":"❌"} API execution ${w?"succeeded":"failed"}:`,k||C)}catch(y){console.error("[OnboardingSDK] ❌ API execution error:",y),this.sendMetadata({type:"api_execution_result",success:!1,error:y instanceof Error?y.message:"Unknown error",url:f,method:r,timestamp:Date.now()})}}evaluateJsonPathCondition(n,r){if(!r)return!0;try{if(r.includes(" == ")){const[i,o]=r.split(" == "),s=this.extractJsonPath(n,i.trim()),a=o.trim().replace(/^["']|["']$/g,"");return String(s)===a}return!!this.extractJsonPath(n,r)}catch{return!0}}extractJsonPath(n,r){if(!r||!n)return;const o=r.replace(/^\$\.?/,"").split(".");let s=n;for(const a of o){if(s==null)return;s=s[a]}return s}async handleBatchedNavigation(n){if(console.log("[OnboardingSDK] ⚡ Received batched navigation request"),!this.batchedActionExecutor){console.error("[OnboardingSDK] BatchedActionExecutor not initialized");return}const r=(n.steps||[]).map(i=>{const o=i.target||i,a=o.text||o.selector||o.tag?{text:o.text,tag:o.tag,selector:o.selector,ariaLabel:o.aria_label||o.ariaLabel,role:o.role,labelText:o.label_text||o.labelText,selectorFallbacks:o.selector_fallbacks||o.selectorFallbacks}:void 0;return{action:i.action,target:a,condition:i.condition,waitMs:i.wait_ms||i.waitMs}});if(r.length===0){console.warn("[OnboardingSDK] No steps in batched navigation request");return}this.fastExecutionMode=!0,this._botActionDepth++;try{console.log("[OnboardingSDK] ⚡ Executing batched navigation with steps:",r.map(o=>{var s;return`${o.action}${(s=o.target)!=null&&s.text?` "${o.target.text}"`:""}`}).join(" → "));const i=await this.batchedActionExecutor.executeBatch({steps:r});this.domIntrospector&&(await new Promise(o=>setTimeout(o,200)),this.domIntrospector.captureAndSendImmediate("post-batched-navigation"),console.log("[OnboardingSDK] 📸 DOM snapshot sent after batched navigation")),i.success?(console.log("[OnboardingSDK] ✅ Batched navigation complete, sending success"),this.sendMetadata({type:"batched_navigation_complete",success:!0,stepCount:r.length,completedSteps:i.completedSteps,timestamp:Date.now()})):(console.log(`[OnboardingSDK] ❌ Batched navigation failed at step ${i.completedSteps+1}, sending failure`),this.sendMetadata({type:"batched_navigation_complete",success:!1,error:`Step ${i.completedSteps+1} failed - check console for details`,stepCount:r.length,completedSteps:i.completedSteps,timestamp:Date.now()}))}finally{this.fastExecutionMode=!1,this._botActionDepth--}}startNavigationDetection(n){this.navigationCompleteDetector&&this.navigationCompleteDetector.start(r=>{console.log("[OnboardingSDK] Navigation complete detected:",r),this.sendMetadata({type:"navigation_complete",url:r,timestamp:Date.now()}),n(r)})}stopNavigationDetection(){this.navigationCompleteDetector&&this.navigationCompleteDetector.stop()}isInFastMode(){return this.fastExecutionMode}async extractIntent(n){const r={"get started":"onboarding",help:"assistance","show me":"demonstration","how do":"tutorial",where:"navigation",what:"information"},i=n.toLowerCase();for(const[o,s]of Object.entries(r))if(i.includes(o))return s;return"unknown"}async captureContext(){const n=this.config.enableScreenCapture?await this.capture.captureWithRedaction():void 0,r=this.extractPageStructure();return{screenshot:n,url:An(),structure:r,timestamp:Date.now()}}extractPageStructure(){const n=[];return["button","a","input","select","textarea",'[role="button"]',"[onclick]"].forEach(i=>{document.querySelectorAll(i).forEach(o=>{const s=o.getBoundingClientRect(),a=s.width>0&&s.height>0&&s.top<window.innerHeight&&s.bottom>0;a&&n.push({selector:this.getSelector(o),type:o.tagName.toLowerCase(),text:(o.textContent||"").trim().substring(0,100),visible:a,position:s,attributes:this.getAttributes(o)})})}),{title:document.title,url:An(),elements:n,viewport:{width:window.innerWidth,height:window.innerHeight}}}getSelector(n){if(n.id)return`#${n.id}`;const r=[];let i=n;for(;i&&i!==document.body;){let o=i.tagName.toLowerCase();if(i.className){const s=Array.from(i.classList).slice(0,2).join(".");s&&(o+=`.${s}`)}r.unshift(o),i=i.parentElement}return r.join(" > ")}getAttributes(n){const r={};return["href","type","name","placeholder","aria-label","role"].forEach(o=>{const s=n.getAttribute(o);s&&(r[o]=s)}),r}async sendText(n){this.pipecatClient&&this.isConnected&&await this.pipecatClient.sendText(n)}toggleTextMode(){var n,r;this.textModeEnabled=!this.textModeEnabled,this.textModeEnabled?((n=this.pipecatClient)==null||n.enableMic(!1),this.micEnabled=!1,console.log("[OnboardingSDK] ⌨️ Text mode enabled — mic muted")):((r=this.pipecatClient)==null||r.enableMic(!0),this.micEnabled=!0,console.log("[OnboardingSDK] 🎤 Voice mode enabled — mic unmuted"),this.isConnected&&this.setupUserMicAnalysis());try{localStorage.setItem("floe_text_mode",String(this.textModeEnabled))}catch{}this.renderReactUI()}async sendTextMessage(n){n.trim()&&(this.transcriptHistory.push({id:`user-${Date.now()}`,role:"user",content:n.trim(),timestamp:Date.now()}),this.renderReactUI(),this.pipecatClient&&this.isConnected&&this.pipecatClient.sendClientMessage("text_message",{text:n.trim(),audio_response:!this.textModeEnabled}))}toggleMute(){if(this.pipecatClient){const r=!this.pipecatClient.isMicEnabled;return this.pipecatClient.enableMic(r),this.micEnabled=r,console.log("[OnboardingSDK] 🎤 Mic toggled:",r?"ON":"MUTED"),this.renderReactUI(),r}return!1}highlight(n,r){this.overlay.highlight(n,r)}clearHighlight(){this.overlay.clearHighlight()}showTooltip(n,r){this.overlay.showTooltip(n,r)}hideTooltip(){this.overlay.hideTooltip()}async executeAction(n){return this.actionExecutor.executeWithConsent(n)}async takeScreenshot(n){return this.capture.captureWithRedaction(n)}getSessionId(){return this.sessionId}getStatus(){return{initialized:this.isInitialized,connected:this.isConnected,sessionId:this.sessionId,microphoneMuted:this.pipecatClient?!this.pipecatClient.isMicEnabled:!1}}startGuidedDiscovery(){return!this.pipecatClient||!this.isConnected?(console.warn("[OnboardingSDK] Cannot start discovery - not connected"),!1):(console.log("[OnboardingSDK] 🔍 Starting guided discovery mode"),this.pipecatClient.sendClientMessage("start_discovery",{type:"start_discovery",timestamp:Date.now()}),this.hideWelcomePopup(),!0)}skipDiscovery(){console.log("[OnboardingSDK] Skipping discovery - standard greeting flow"),this.hideWelcomePopup()}showWelcomePopupAsync(){return new Promise(n=>{if(document.getElementById("floe-welcome-popup")){n(!1);return}const r=document.createElement("div");r.id="floe-welcome-popup",r.setAttribute("data-floe-widget","true"),r.style.cssText=`
|
|
819
819
|
position: fixed;
|
|
820
820
|
top: 0;
|
|
821
821
|
left: 0;
|
|
@@ -973,5 +973,5 @@ ${e.description||""}`;return confirm(r)}async execute(e){if(e.type==="click"){co
|
|
|
973
973
|
">
|
|
974
974
|
I'll explore on my own
|
|
975
975
|
</button>
|
|
976
|
-
`,r.appendChild(i),document.body.appendChild(r);const o=r.querySelector("#floe-start-guided"),s=r.querySelector("#floe-skip-guided");o&&(o.onmouseenter=()=>{o.style.background="rgba(255, 255, 255, 1)",o.style.transform="translateY(-1px)",o.style.boxShadow="0 8px 24px rgba(0, 0, 0, 0.3)"},o.onmouseleave=()=>{o.style.background="rgba(255, 255, 255, 0.95)",o.style.transform="translateY(0)",o.style.boxShadow="0 4px 12px rgba(0, 0, 0, 0.2)"},o.onclick=()=>{r.style.animation="welcomeFadeOut 0.2s ease",setTimeout(()=>{r.remove(),n(!0)},200)}),s&&(s.onmouseenter=()=>{s.style.color="rgba(255, 255, 255, 0.8)"},s.onmouseleave=()=>{s.style.color="rgba(255, 255, 255, 0.4)"},s.onclick=()=>{r.style.animation="welcomeFadeOut 0.2s ease",setTimeout(()=>{r.remove(),n(!1)},200)}),console.log("[OnboardingSDK] Welcome popup shown (async)")})}showWelcomePopup(){this.showWelcomePopupAsync().then(n=>{n?this.startGuidedDiscovery():this.skipDiscovery()})}hideWelcomePopup(){const n=document.getElementById("floe-welcome-popup");n&&(n.style.animation="welcomeFadeOut 0.2s ease",setTimeout(()=>n.remove(),200)),console.log("[OnboardingSDK] Welcome popup hidden")}shouldShowDiscoveryPrompt(){const n=localStorage.getItem("floe_has_visited"),r=localStorage.getItem("floe_onboarding_complete");return!n||!r}async checkEndUserStatus(){var n,r,i,o,s;try{const a=`${this.config.apiUrl}/end-users/check-status`,l={clientKey:this.config.clientKey,origin:window.location.origin};(n=this.config.userInfo)!=null&&n.externalId&&(l.externalId=this.config.userInfo.externalId),(r=this.config.userInfo)!=null&&r.email&&(l.email=this.config.userInfo.email),this.config.debug&&console.log("[OnboardingSDK] Checking EndUser status...",{externalId:l.externalId?"***":void 0,email:l.email?"***":void 0});const c=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)});if(!c.ok){console.warn(`[OnboardingSDK] EndUser status check failed: ${c.status}`);return}this.endUserStatus=await c.json(),console.log(`[OnboardingSDK] EndUser status: found=${(i=this.endUserStatus)==null?void 0:i.found}, isNewUser=${(o=this.endUserStatus)==null?void 0:o.isNewUser}, hasPreferences=${(s=this.endUserStatus)==null?void 0:s.hasPreferences}`)}catch(a){console.warn("[OnboardingSDK] Error checking EndUser status:",a)}}getEndUserPreferences(){var n;return((n=this.endUserStatus)==null?void 0:n.preferences)||null}shouldSkipOnboardingModal(){var o,s;if(typeof this.config.skipOnboardingModal=="boolean")return console.log(`[OnboardingSDK] skipOnboardingModal explicitly set to: ${this.config.skipOnboardingModal}`),this.config.skipOnboardingModal;if(((o=this.endUserStatus)==null?void 0:o.isNewUser)===!0)return console.log("[OnboardingSDK] Showing modal: API indicates isNewUser=true"),!1;if((s=this.endUserStatus)!=null&&s.found&&this.endUserStatus.isNewUser===!1)return console.log("[OnboardingSDK] Skipping modal: existing EndUser (isNewUser=false)"),!0;const n=localStorage.getItem("floe_has_visited")==="true",r=localStorage.getItem("floe_onboarding_complete")==="true",i=n&&r;return console.log(`[OnboardingSDK] Fallback to localStorage: skip=${i} (hasVisited: ${n}, hasCompletedOnboarding: ${r})`),i}markUserVisited(){localStorage.setItem("floe_has_visited","true")}markOnboardingComplete(){localStorage.setItem("floe_onboarding_complete","true")}async disconnect(){this.pageTracker.stop(),this.domIntrospector.stopCapturing(),this.navigationCompleteDetector&&this.navigationCompleteDetector.stop(),this.overlay.
|
|
976
|
+
`,r.appendChild(i),document.body.appendChild(r);const o=r.querySelector("#floe-start-guided"),s=r.querySelector("#floe-skip-guided");o&&(o.onmouseenter=()=>{o.style.background="rgba(255, 255, 255, 1)",o.style.transform="translateY(-1px)",o.style.boxShadow="0 8px 24px rgba(0, 0, 0, 0.3)"},o.onmouseleave=()=>{o.style.background="rgba(255, 255, 255, 0.95)",o.style.transform="translateY(0)",o.style.boxShadow="0 4px 12px rgba(0, 0, 0, 0.2)"},o.onclick=()=>{r.style.animation="welcomeFadeOut 0.2s ease",setTimeout(()=>{r.remove(),n(!0)},200)}),s&&(s.onmouseenter=()=>{s.style.color="rgba(255, 255, 255, 0.8)"},s.onmouseleave=()=>{s.style.color="rgba(255, 255, 255, 0.4)"},s.onclick=()=>{r.style.animation="welcomeFadeOut 0.2s ease",setTimeout(()=>{r.remove(),n(!1)},200)}),console.log("[OnboardingSDK] Welcome popup shown (async)")})}showWelcomePopup(){this.showWelcomePopupAsync().then(n=>{n?this.startGuidedDiscovery():this.skipDiscovery()})}hideWelcomePopup(){const n=document.getElementById("floe-welcome-popup");n&&(n.style.animation="welcomeFadeOut 0.2s ease",setTimeout(()=>n.remove(),200)),console.log("[OnboardingSDK] Welcome popup hidden")}shouldShowDiscoveryPrompt(){const n=localStorage.getItem("floe_has_visited"),r=localStorage.getItem("floe_onboarding_complete");return!n||!r}async checkEndUserStatus(){var n,r,i,o,s;try{const a=`${this.config.apiUrl}/end-users/check-status`,l={clientKey:this.config.clientKey,origin:window.location.origin};(n=this.config.userInfo)!=null&&n.externalId&&(l.externalId=this.config.userInfo.externalId),(r=this.config.userInfo)!=null&&r.email&&(l.email=this.config.userInfo.email),this.config.debug&&console.log("[OnboardingSDK] Checking EndUser status...",{externalId:l.externalId?"***":void 0,email:l.email?"***":void 0});const c=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)});if(!c.ok){console.warn(`[OnboardingSDK] EndUser status check failed: ${c.status}`);return}this.endUserStatus=await c.json(),console.log(`[OnboardingSDK] EndUser status: found=${(i=this.endUserStatus)==null?void 0:i.found}, isNewUser=${(o=this.endUserStatus)==null?void 0:o.isNewUser}, hasPreferences=${(s=this.endUserStatus)==null?void 0:s.hasPreferences}`)}catch(a){console.warn("[OnboardingSDK] Error checking EndUser status:",a)}}getEndUserPreferences(){var n;return((n=this.endUserStatus)==null?void 0:n.preferences)||null}shouldSkipOnboardingModal(){var o,s;if(typeof this.config.skipOnboardingModal=="boolean")return console.log(`[OnboardingSDK] skipOnboardingModal explicitly set to: ${this.config.skipOnboardingModal}`),this.config.skipOnboardingModal;if(((o=this.endUserStatus)==null?void 0:o.isNewUser)===!0)return console.log("[OnboardingSDK] Showing modal: API indicates isNewUser=true"),!1;if((s=this.endUserStatus)!=null&&s.found&&this.endUserStatus.isNewUser===!1)return console.log("[OnboardingSDK] Skipping modal: existing EndUser (isNewUser=false)"),!0;const n=localStorage.getItem("floe_has_visited")==="true",r=localStorage.getItem("floe_onboarding_complete")==="true",i=n&&r;return console.log(`[OnboardingSDK] Fallback to localStorage: skip=${i} (hasVisited: ${n}, hasCompletedOnboarding: ${r})`),i}markUserVisited(){localStorage.setItem("floe_has_visited","true")}markOnboardingComplete(){localStorage.setItem("floe_onboarding_complete","true")}async disconnect(){this.pageTracker.stop(),this.domIntrospector.stopCapturing(),this.navigationCompleteDetector&&this.navigationCompleteDetector.stop(),this.overlay.cleanup(),this.pipecatClient&&(await this.pipecatClient.disconnect(),this.pipecatClient=null),this.transport&&(this.transport=null),this.audioElements&&(this.audioElements.forEach(n=>{n.pause(),n.remove()}),this.audioElements=[]),this.botAudioAnalyzer&&(this.botAudioAnalyzer.destroy(),this.botAudioAnalyzer=null),this.userAudioAnalyzer&&(this.userAudioAnalyzer.destroy(),this.userAudioAnalyzer=null),this.userMicStreamRequestId++,this.userMicStream&&(this.userMicStream.getTracks().forEach(n=>n.stop()),this.userMicStream=null),this.audioLevels=[],this.reactRoot&&(this.reactRoot.unmount(),this.reactRoot=null),this.reactContainer&&(this.reactContainer.remove(),this.reactContainer=null),this.overlay.remove(),this.isInitialized=!1,this.isConnected=!1,this.agentState="idle",console.log("[OnboardingSDK] Disconnected"),this.emit("disconnected")}}typeof window<"u"&&(window.OnboardingSDK=vy);function zx(t){return{clientKey:t.clientKey,...t.apiUrl!==void 0&&{apiUrl:t.apiUrl},enableVideo:!1,enableAudio:t.enableAudio??!0,enableScreenCapture:t.enableScreenCapture??!0,debug:t.debug??!1,industry:t.industry,useCase:t.useCase,companyName:t.companyName,companySize:t.companySize,role:t.role,userInfo:t.userInfo,skipOnboardingModal:t.skipOnboardingModal,enableDiscoveryPopup:!0,nudge:t.nudge?{text:t.nudge.text??"Hi 👋 How can I help you today?",autoShow:t.nudge.autoShow??!0,autoHideDelay:t.nudge.autoHideDelay??0}:void 0}}function yy(t){if(!t.clientKey)throw new Error("[Floe] clientKey is required");const e=zx(t),n=new vy(e);return n.ready=n.init().catch(r=>{throw console.error("[Floe] Initialization failed:",r),r}),n}return typeof window<"u"&&(window.Floe=yy),dn.Floe=yy,Object.defineProperty(dn,Symbol.toStringTag,{value:"Module"}),dn}({});
|
|
977
977
|
//# sourceMappingURL=floe-sdk.iife.js.map
|