@zibby/core 0.1.34 → 0.1.37

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.
Files changed (48) hide show
  1. package/dist/agents/base.js +157 -190
  2. package/dist/backend-client.js +1 -1
  3. package/dist/constants/zibby-scratch.js +1 -1
  4. package/dist/enrichment/enrichers/accessibility-enricher.js +1 -1
  5. package/dist/enrichment/index.js +2 -2
  6. package/dist/enrichment/mcp-integration.js +2 -2
  7. package/dist/enrichment/trace-text-enricher.js +2 -2
  8. package/dist/framework/agents/assistant-strategy.js +3 -3
  9. package/dist/framework/agents/claude-strategy.js +53 -54
  10. package/dist/framework/agents/codex-strategy.js +1 -1
  11. package/dist/framework/agents/cursor-strategy.js +51 -83
  12. package/dist/framework/agents/gemini-strategy.js +2 -2
  13. package/dist/framework/agents/index.js +131 -164
  14. package/dist/framework/agents/utils/auth-resolver.js +1 -1
  15. package/dist/framework/agents/utils/openai-proxy-formatter.js +25 -57
  16. package/dist/framework/code-generator.js +143 -176
  17. package/dist/framework/context-loader.js +1 -1
  18. package/dist/framework/function-bridge.js +2 -2
  19. package/dist/framework/graph-compiler.js +150 -183
  20. package/dist/framework/graph.js +149 -182
  21. package/dist/framework/index.js +152 -185
  22. package/dist/framework/mcp-client.js +2 -2
  23. package/dist/framework/node-registry.js +134 -167
  24. package/dist/framework/node.js +146 -179
  25. package/dist/index.js +199 -232
  26. package/dist/package.json +1 -1
  27. package/dist/runtime/generation/index.js +2 -2
  28. package/dist/runtime/generation/mcp-ref-strategy.js +1 -1
  29. package/dist/runtime/generation/stable-id-strategy.js +1 -1
  30. package/dist/runtime/verification/index.js +1 -1
  31. package/dist/runtime/verification/playwright-json-strategy.js +1 -1
  32. package/dist/tools/run-playwright-test.js +1 -1
  33. package/dist/utils/ci-setup.js +1 -1
  34. package/dist/utils/cursor-mcp-isolated-home.js +1 -1
  35. package/dist/utils/cursor-utils.js +1 -1
  36. package/dist/utils/live-frame-discovery.js +1 -1
  37. package/dist/utils/mcp-config-writer.js +1 -1
  38. package/dist/utils/post-process-events.js +2 -2
  39. package/dist/utils/repo-clone.js +1 -1
  40. package/dist/utils/result-handler.js +1 -1
  41. package/dist/utils/run-capacity-coordinator.js +2 -2
  42. package/dist/utils/run-capacity-queue.js +2 -2
  43. package/dist/utils/run-index-post-cli.js +2 -2
  44. package/dist/utils/run-registry.js +1 -1
  45. package/dist/utils/run-state-session.js +1 -1
  46. package/dist/utils/trace-parser.js +1 -1
  47. package/dist/utils/video-organizer.js +1 -1
  48. package/package.json +1 -1
@@ -1 +1 @@
1
- import{existsSync as f,readFileSync as u}from"fs";import{homedir as l}from"os";import{join as h}from"path";var o=new Map;function w(){if(process.env.ZIBBY_USER_TOKEN)return process.env.ZIBBY_USER_TOKEN;try{let t=h(l(),".zibby","config.json");return f(t)&&JSON.parse(u(t,"utf-8")).sessionToken||null}catch{return null}}function k(){return process.env.ZIBBY_ACCOUNT_API_URL?process.env.ZIBBY_ACCOUNT_API_URL.replace(/\/$/,""):(process.env.ZIBBY_ENV||"prod")==="local"?"http://localhost:3001":process.env.ZIBBY_PROD_ACCOUNT_API_URL||"https://account-api-prod.zibby.app"}async function y(t){let s=Date.now(),r=o.get(t);if(r&&r.expiresAt>s)return r.data;let i=w();if(!i)throw new Error("No session token. Run `zibby login` first.");let c=`${k()}/integrations/token/${t}`,n=await fetch(c,{method:"GET",headers:{Authorization:`Bearer ${i}`}});if(!n.ok){let p=await n.text().catch(()=>"");throw n.status===404?new Error(`${t} is not connected. Connect it at https://studio.zibby.app/integrations`):n.status===401||n.status===403?new Error("Session expired. Run `zibby login` to re-authenticate."):new Error(`Failed to resolve ${t} token (${n.status}): ${p}`)}let e=await n.json();if(!e||typeof e!="object")throw new Error(`Invalid response from ${t} token endpoint: expected object, got ${typeof e}`);if(t==="jira"){if(!e.token||typeof e.token!="string")throw new Error(`Invalid jira token response: token is ${typeof e.token}, expected string`);if(!e.cloudId)throw new Error("Invalid jira token response: missing cloudId")}else if(t==="github"&&(!e.token||typeof e.token!="string"))throw new Error(`Invalid github token response: token is ${typeof e.token}, expected string`);let a=((e.expiresInSec||3e3)-120)*1e3;return o.set(t,{data:e,expiresAt:s+a}),e}function b(t){t?o.delete(t):o.clear()}export{b as clearTokenCache,y as resolveIntegrationToken};
1
+ import{existsSync as f,readFileSync as u}from"node:fs";import{homedir as l}from"node:os";import{join as h}from"node:path";var o=new Map;function w(){if(process.env.ZIBBY_USER_TOKEN)return process.env.ZIBBY_USER_TOKEN;try{let t=h(l(),".zibby","config.json");return f(t)&&JSON.parse(u(t,"utf-8")).sessionToken||null}catch{return null}}function k(){return process.env.ZIBBY_ACCOUNT_API_URL?process.env.ZIBBY_ACCOUNT_API_URL.replace(/\/$/,""):(process.env.ZIBBY_ENV||"prod")==="local"?"http://localhost:3001":process.env.ZIBBY_PROD_ACCOUNT_API_URL||"https://account-api-prod.zibby.app"}async function y(t){let s=Date.now(),r=o.get(t);if(r&&r.expiresAt>s)return r.data;let i=w();if(!i)throw new Error("No session token. Run `zibby login` first.");let c=`${k()}/integrations/token/${t}`,n=await fetch(c,{method:"GET",headers:{Authorization:`Bearer ${i}`}});if(!n.ok){let p=await n.text().catch(()=>"");throw n.status===404?new Error(`${t} is not connected. Connect it at https://studio.zibby.app/integrations`):n.status===401||n.status===403?new Error("Session expired. Run `zibby login` to re-authenticate."):new Error(`Failed to resolve ${t} token (${n.status}): ${p}`)}let e=await n.json();if(!e||typeof e!="object")throw new Error(`Invalid response from ${t} token endpoint: expected object, got ${typeof e}`);if(t==="jira"){if(!e.token||typeof e.token!="string")throw new Error(`Invalid jira token response: token is ${typeof e.token}, expected string`);if(!e.cloudId)throw new Error("Invalid jira token response: missing cloudId")}else if(t==="github"&&(!e.token||typeof e.token!="string"))throw new Error(`Invalid github token response: token is ${typeof e.token}, expected string`);let a=((e.expiresInSec||3e3)-120)*1e3;return o.set(t,{data:e,expiresAt:s+a}),e}function b(t){t?o.delete(t):o.clear()}export{b as clearTokenCache,y as resolveIntegrationToken};
@@ -1 +1 @@
1
- import{resolve as c}from"path";var t=".zibby/scratch/specs";function o(r){return c(String(r||process.cwd()),t)}export{t as ZIBBY_SCRATCH_SPECS_REL,o as zibbyScratchSpecsDir};
1
+ import{resolve as c}from"node:path";var t=".zibby/scratch/specs";function o(r){return c(String(r||process.cwd()),t)}export{t as ZIBBY_SCRATCH_SPECS_REL,o as zibbyScratchSpecsDir};
@@ -1 +1 @@
1
- var s=class{constructor(e={}){this.config=e,this.enabled=e.enabled!==!1,this.priority=e.priority||50}getName(){throw new Error("EventEnricher.getName() must be implemented")}canEnrich(e){return this.enabled}async enrich(e,r){throw new Error("EventEnricher.enrich() must be implemented")}handleError(e,r){return console.warn(`[${this.getName()}] Enrichment failed for event ${r.type}:`,e.message),null}};import o from"crypto";var h=class extends s{getName(){return"AccessibilityEnricher"}getPriority(){return 100}canEnrich(e){return!this.enabled||!e.element||!e.event?!1:["click","fill","type","selectOption","hover"].includes(e.event.type)}async enrich(e,r){try{let{page:t,element:n}=r,i=await t.accessibility.snapshot(),a=await this.findAxNode(n,i);if(!a)return null;let l=await this.getAxContext(a,i),u=this.hashAxSubtree(a),f=this.hashAxPath(l.path);return{accessibility:{role:a.role,name:a.name||"",level:l.level,parent:l.parent,siblings:l.siblings,axTreeHash:u,axPathHash:f}}}catch(t){return this.handleError(t,e)}}async findAxNode(e,r){let t=await e.evaluate(n=>({role:n.getAttribute("role")||n.tagName.toLowerCase(),name:n.getAttribute("aria-label")||n.textContent?.trim()||"",tagName:n.tagName.toLowerCase()}));return this.searchAxTree(r,t)}searchAxTree(e,r){if(!e)return null;if(e.role===r.role&&(e.name||"").includes(r.name.substring(0,20)))return e;if(e.children)for(let t of e.children){let n=this.searchAxTree(t,r);if(n)return n}return null}getAxContext(e,r){let t={level:0,parent:null,siblings:[],path:[]},n=this.findParent(e,r);return n&&(t.parent={role:n.role,name:n.name},t.siblings=(n.children||[]).filter(i=>i!==e).map(i=>({role:i.role,name:i.name})).slice(0,3)),t.level=this.calculateLevel(e,r),t.path=this.buildPath(e,r),t}findParent(e,r,t=r){if(!t||!t.children)return null;if(t.children.includes(e))return t;for(let n of t.children){let i=this.findParent(e,r,n);if(i)return i}return null}calculateLevel(e,r,t=r,n=0){if(t===e)return n;if(t.children)for(let i of t.children){let a=this.calculateLevel(e,r,i,n+1);if(a>=0)return a}return-1}buildPath(e,r,t=r,n=[]){if(t===e)return[...n,{role:t.role,name:t.name}];if(t.children)for(let i of t.children){let a=this.buildPath(e,r,i,[...n,{role:t.role,name:t.name}]);if(a)return a}return null}hashAxSubtree(e){let r=JSON.stringify({role:e.role,name:e.name,children:(e.children||[]).map(t=>({role:t.role,name:t.name}))});return o.createHash("md5").update(r).digest("hex").substring(0,12)}hashAxPath(e){let r=e.map(t=>`${t.role}:${t.name}`).join("/");return o.createHash("md5").update(r).digest("hex").substring(0,12)}},p=h;export{h as AccessibilityEnricher,p as default};
1
+ var s=class{constructor(e={}){this.config=e,this.enabled=e.enabled!==!1,this.priority=e.priority||50}getName(){throw new Error("EventEnricher.getName() must be implemented")}canEnrich(e){return this.enabled}async enrich(e,r){throw new Error("EventEnricher.enrich() must be implemented")}handleError(e,r){return console.warn(`[${this.getName()}] Enrichment failed for event ${r.type}:`,e.message),null}};import o from"node:crypto";var h=class extends s{getName(){return"AccessibilityEnricher"}getPriority(){return 100}canEnrich(e){return!this.enabled||!e.element||!e.event?!1:["click","fill","type","selectOption","hover"].includes(e.event.type)}async enrich(e,r){try{let{page:t,element:n}=r,i=await t.accessibility.snapshot(),a=await this.findAxNode(n,i);if(!a)return null;let l=await this.getAxContext(a,i),u=this.hashAxSubtree(a),f=this.hashAxPath(l.path);return{accessibility:{role:a.role,name:a.name||"",level:l.level,parent:l.parent,siblings:l.siblings,axTreeHash:u,axPathHash:f}}}catch(t){return this.handleError(t,e)}}async findAxNode(e,r){let t=await e.evaluate(n=>({role:n.getAttribute("role")||n.tagName.toLowerCase(),name:n.getAttribute("aria-label")||n.textContent?.trim()||"",tagName:n.tagName.toLowerCase()}));return this.searchAxTree(r,t)}searchAxTree(e,r){if(!e)return null;if(e.role===r.role&&(e.name||"").includes(r.name.substring(0,20)))return e;if(e.children)for(let t of e.children){let n=this.searchAxTree(t,r);if(n)return n}return null}getAxContext(e,r){let t={level:0,parent:null,siblings:[],path:[]},n=this.findParent(e,r);return n&&(t.parent={role:n.role,name:n.name},t.siblings=(n.children||[]).filter(i=>i!==e).map(i=>({role:i.role,name:i.name})).slice(0,3)),t.level=this.calculateLevel(e,r),t.path=this.buildPath(e,r),t}findParent(e,r,t=r){if(!t||!t.children)return null;if(t.children.includes(e))return t;for(let n of t.children){let i=this.findParent(e,r,n);if(i)return i}return null}calculateLevel(e,r,t=r,n=0){if(t===e)return n;if(t.children)for(let i of t.children){let a=this.calculateLevel(e,r,i,n+1);if(a>=0)return a}return-1}buildPath(e,r,t=r,n=[]){if(t===e)return[...n,{role:t.role,name:t.name}];if(t.children)for(let i of t.children){let a=this.buildPath(e,r,i,[...n,{role:t.role,name:t.name}]);if(a)return a}return null}hashAxSubtree(e){let r=JSON.stringify({role:e.role,name:e.name,children:(e.children||[]).map(t=>({role:t.role,name:t.name}))});return o.createHash("md5").update(r).digest("hex").substring(0,12)}hashAxPath(e){let r=e.map(t=>`${t.role}:${t.name}`).join("/");return o.createHash("md5").update(r).digest("hex").substring(0,12)}},p=h;export{h as AccessibilityEnricher,p as default};
@@ -1,4 +1,4 @@
1
1
  var g=class{constructor(e={}){this.config=e,this.enabled=e.enabled!==!1,this.priority=e.priority||50}getName(){throw new Error("EventEnricher.getName() must be implemented")}canEnrich(e){return this.enabled}async enrich(e,r){throw new Error("EventEnricher.enrich() must be implemented")}handleError(e,r){return console.warn(`[${this.getName()}] Enrichment failed for event ${r.type}:`,e.message),null}};var S=class{constructor(e={}){this.enrichers=[],this.config=e,this.stats={totalEvents:0,enrichedEvents:0,skippedEvents:0,errors:{}}}register(e){return this.enrichers.push(e),this.enrichers.sort((r,t)=>t.getPriority()-r.getPriority()),this}unregister(e){return this.enrichers=this.enrichers.filter(r=>r.getName()!==e),this}get(e){return this.enrichers.find(r=>r.getName()===e)}setEnabled(e,r){let t=this.get(e);return t&&(t.enabled=r),this}async enrich(e,r){this.stats.totalEvents++;let t={...e},i=[],n=[],s=[];for(let o of this.enrichers)try{if(!o.canEnrich(r)){n.push(o.getName());continue}let l=Date.now(),a=await o.enrich(e,r),f=Date.now()-l;a?(Object.assign(t,a),i.push({name:o.getName(),duration:f})):n.push(o.getName())}catch(l){console.warn(`[EnrichmentPipeline] ${o.getName()} failed:`,l.message),s.push(o.getName()),this.stats.errors[o.getName()]=(this.stats.errors[o.getName()]||0)+1}return t._enrichment={version:"1.0",timestamp:new Date().toISOString(),enrichers:{run:i,skipped:n,failed:s}},i.length>0?this.stats.enrichedEvents++:this.stats.skippedEvents++,t}async enrichBatch(e,r){let t=[];for(let i of e){let n=await this.enrich(i,r);t.push(n)}return t}getStats(){return{...this.stats,enrichers:this.enrichers.map(e=>({name:e.getName(),enabled:e.enabled,priority:e.getPriority(),errors:this.stats.errors[e.getName()]||0}))}}resetStats(){this.stats={totalEvents:0,enrichedEvents:0,skippedEvents:0,errors:{}}}logStatus(){console.log(`
2
2
  \u{1F4CA} Enrichment Pipeline Status:`),console.log(` Total events: ${this.stats.totalEvents}`),console.log(` Enriched: ${this.stats.enrichedEvents}`),console.log(` Skipped: ${this.stats.skippedEvents}`),console.log(`
3
- Registered enrichers (${this.enrichers.length}):`);for(let e of this.enrichers){let r=e.enabled?"\u2713":"\u2717",t=this.stats.errors[e.getName()]||0,i=t>0?` (${t} errors)`:"";console.log(` ${r} ${e.getName()} (priority: ${e.getPriority()})${i}`)}console.log()}};var R=class extends g{getName(){return"PositionEnricher"}getPriority(){return 90}canEnrich(e){return!this.enabled||!e.element||!e.event?!1:["click","fill","type","selectOption","hover"].includes(e.event.type)}async enrich(e,r){try{let{page:t,element:i}=r,n=await i.boundingBox();if(!n)return null;let s=await t.evaluate(()=>({scrollX:window.scrollX,scrollY:window.scrollY,width:window.innerWidth,height:window.innerHeight})),o=n.y>=s.scrollY&&n.y+n.height<=s.scrollY+s.height&&n.x>=0&&n.x+n.width<=s.width;return{position:{boundingBox:n,viewport:s,inViewport:o,centerPoint:{x:Math.round(n.x+n.width/2),y:Math.round(n.y+n.height/2)}}}}catch(t){return this.handleError(t,e)}}};import _ from"crypto";var P=class extends g{getName(){return"AccessibilityEnricher"}getPriority(){return 100}canEnrich(e){return!this.enabled||!e.element||!e.event?!1:["click","fill","type","selectOption","hover"].includes(e.event.type)}async enrich(e,r){try{let{page:t,element:i}=r,n=await t.accessibility.snapshot(),s=await this.findAxNode(i,n);if(!s)return null;let o=await this.getAxContext(s,n),l=this.hashAxSubtree(s),a=this.hashAxPath(o.path);return{accessibility:{role:s.role,name:s.name||"",level:o.level,parent:o.parent,siblings:o.siblings,axTreeHash:l,axPathHash:a}}}catch(t){return this.handleError(t,e)}}async findAxNode(e,r){let t=await e.evaluate(i=>({role:i.getAttribute("role")||i.tagName.toLowerCase(),name:i.getAttribute("aria-label")||i.textContent?.trim()||"",tagName:i.tagName.toLowerCase()}));return this.searchAxTree(r,t)}searchAxTree(e,r){if(!e)return null;if(e.role===r.role&&(e.name||"").includes(r.name.substring(0,20)))return e;if(e.children)for(let t of e.children){let i=this.searchAxTree(t,r);if(i)return i}return null}getAxContext(e,r){let t={level:0,parent:null,siblings:[],path:[]},i=this.findParent(e,r);return i&&(t.parent={role:i.role,name:i.name},t.siblings=(i.children||[]).filter(n=>n!==e).map(n=>({role:n.role,name:n.name})).slice(0,3)),t.level=this.calculateLevel(e,r),t.path=this.buildPath(e,r),t}findParent(e,r,t=r){if(!t||!t.children)return null;if(t.children.includes(e))return t;for(let i of t.children){let n=this.findParent(e,r,i);if(n)return n}return null}calculateLevel(e,r,t=r,i=0){if(t===e)return i;if(t.children)for(let n of t.children){let s=this.calculateLevel(e,r,n,i+1);if(s>=0)return s}return-1}buildPath(e,r,t=r,i=[]){if(t===e)return[...i,{role:t.role,name:t.name}];if(t.children)for(let n of t.children){let s=this.buildPath(e,r,n,[...i,{role:t.role,name:t.name}]);if(s)return s}return null}hashAxSubtree(e){let r=JSON.stringify({role:e.role,name:e.name,children:(e.children||[]).map(t=>({role:t.role,name:t.name}))});return _.createHash("md5").update(r).digest("hex").substring(0,12)}hashAxPath(e){let r=e.map(t=>`${t.role}:${t.name}`).join("/");return _.createHash("md5").update(r).digest("hex").substring(0,12)}};var M=class extends g{constructor(e={}){super(e),this.pendingRequests=new Set,this.setupNetworkTracking=!1}getName(){return"PageStateEnricher"}getPriority(){return 95}canEnrich(e){return this.enabled&&e.page}async setupTracking(e){this.setupNetworkTracking||(e.on("request",r=>{["document","xhr","fetch"].includes(r.resourceType())&&this.pendingRequests.add(r.url())}),e.on("requestfinished",r=>{this.pendingRequests.delete(r.url())}),e.on("requestfailed",r=>{this.pendingRequests.delete(r.url())}),this.setupNetworkTracking=!0)}async enrich(e,r){try{let{page:t}=r;await this.setupTracking(t);let i=await t.evaluate(()=>({readyState:document.readyState,domContentLoaded:document.readyState!=="loading",loadComplete:document.readyState==="complete",url:document.location.href})),n=await this.checkDOMStability(t);return{page:{networkIdle:this.pendingRequests.size===0,pendingRequests:this.pendingRequests.size,domStable:n,...i}}}catch(t){return this.handleError(t,e)}}async checkDOMStability(e,r=500){try{return await e.evaluate(i=>new Promise(n=>{let s,o=0,l=new MutationObserver(()=>{o++,clearTimeout(s),s=setTimeout(()=>{l.disconnect(),n(o===0)},i)});l.observe(document.body,{childList:!0,subtree:!0,attributes:!0}),s=setTimeout(()=>{l.disconnect(),n(!0)},i)}),r)}catch{return!1}}reset(){this.pendingRequests.clear(),this.setupNetworkTracking=!1}};var k=class extends g{getName(){return"DOMEnricher"}getPriority(){return 85}canEnrich(e){return!this.enabled||!e.element||!e.event?!1:["click","fill","type","selectOption","hover"].includes(e.event.type)}async enrich(e,r){try{let{element:t}=r,i=await t.evaluate(n=>{let s=c=>{let d=[],u=c;for(;u&&u!==document.body;){let x=u.tagName.toLowerCase(),b=u.parentElement;if(b){let y=Array.from(b.children).filter(T=>T.tagName===u.tagName);if(y.length>1){let T=y.indexOf(u)+1;x+=`:nth-child(${T})`}}d.unshift(x),u=u.parentElement}return`body > ${d.join(" > ")}`},o=c=>{let d=[],u=c;for(;u&&u!==document.body;){let x=1,b=u.previousSibling;for(;b;)b.nodeType===1&&b.tagName===u.tagName&&x++,b=b.previousSibling;let y=u.tagName.toLowerCase();d.unshift(`${y}[${x}]`),u=u.parentElement}return`/html/body/${d.join("/")}`},l={};for(let c of n.attributes)l[c.name]=c.value;let a=window.getComputedStyle(n),f={display:a.display,visibility:a.visibility,opacity:a.opacity,pointerEvents:a.pointerEvents},m=0,w=n.parentElement;for(;w;)m++,w=w.parentElement;return{path:s(n),xpath:o(n),depth:m,parent:n.parentElement?n.parentElement.tagName.toLowerCase():null,tagName:n.tagName.toLowerCase(),attributes:l,state:{visible:a.display!=="none"&&a.visibility!=="hidden",enabled:!n.disabled,focused:document.activeElement===n,...f}}});return{dom:{path:i.path,xpath:i.xpath,depth:i.depth,parent:i.parent,selector:this.buildSmartSelector(i)},attributes:i.attributes,state:i.state}}catch(t){return this.handleError(t,e)}}buildSmartSelector(e){let r=e.tagName;if(e.attributes.id)return`#${e.attributes.id}`;if(e.attributes["data-test-id"])return`[data-test-id="${e.attributes["data-test-id"]}"]`;if(e.attributes.class){let t=e.attributes.class.split(" ").filter(i=>i&&!i.match(/^(active|focus|hover|disabled)/));t.length>0&&(r+=`.${t.slice(0,2).join(".")}`)}return e.parent&&(r=`${e.parent} > ${r}`),r}};var L=class extends g{constructor(e={}){super(e),this.priority=200}getName(){return"MCPRef"}getPriority(){return this.priority}async enrich(e,r){let t=e.data?.params?.ref,i=e.data?.params?.element;if(!t&&!i)return null;let n=null,s=null,o=null;if(r?.element)try{let l=await r.element.evaluate(a=>({text:a.textContent?.trim()||"",innerText:a.innerText?.trim()||"",value:a.value||"",label:a.getAttribute("aria-label")||a.getAttribute("label")||"",role:a.getAttribute("role")||a.tagName.toLowerCase(),placeholder:a.getAttribute("placeholder")||"",title:a.getAttribute("title")||""}));n=l.text||l.innerText||l.value||l.placeholder,s=l.role,o=l.label||l.title,console.log(`[MCPRefEnricher] \u2705 Captured actual text: "${n}" (AI said: "${i}")`)}catch(l){console.log(`[MCPRefEnricher] \u26A0\uFE0F Could not extract actual text: ${l.message}`)}return{mcpRef:t,mcpElement:i,actualText:n,actualRole:s,actualLabel:o,recordedSelector:n||i}}};import{readFileSync as X,existsSync as I,readdirSync as H}from"fs";import{join as j}from"path";import{execSync as Z}from"child_process";import{tmpdir as K}from"os";var z=class{static async parseTraceZip(e){let r;if(e.endsWith(".zip")&&I(e)){let t=j(K(),`trace-${Date.now()}`);Z(`unzip -q "${e}" -d "${t}"`,{stdio:"pipe"});let n=H(t).find(s=>s.endsWith(".trace"));if(!n)throw new Error("No .trace file found in zip");r=j(t,n)}else if(I(e)){let i=H(e).find(n=>n.endsWith(".trace"));if(!i)throw new Error("No .trace file found");r=j(e,i)}else throw new Error(`Trace not found at ${e}`);try{let i=X(r,"utf-8").trim().split(`
4
- `),n=[],s=new Map,o=new Map;for(let l of i)try{let a=JSON.parse(l);if(a.type==="snapshot"&&a.snapshot&&a.snapshot.accessibility){let f=new Map;for(let m of a.snapshot.accessibility)m.ref&&f.set(m.ref,m);s.set(a.snapshotName,f)}if(a.type==="frame-snapshot"&&a.snapshot){let f=Buffer.from(a.snapshot.html||"","base64").toString("utf-8");f&&f.length>100&&o.set(a.pageId||"default",f)}}catch{}for(let l of i)try{let a=JSON.parse(l);if(a.type==="before"&&a.params&&a.params.selector){let f=a.method;if(["click","fill","type","selectOption"].includes(f)){let m=a.params.selector,w=a.params.text||a.params.value||"",c=[],d=null,u=null,x=null,b=m.match(/aria-ref=([a-z0-9]+)/i);if(b&&a.snapshotName){let p=b[1],E=s.get(a.snapshotName);if(E&&E.has(p)){let v=E.get(p);d=v.name||null,u=v.role||null,x=v.label||null,console.log(`[TraceParser] \u2705 Found ACTUAL element data: text="${d}", role="${u}"`)}}let y=m.match(/internal:text="([^"]+)"/i),T=m.match(/internal:label="([^"]+)"/i),F=m.match(/internal:placeholder="([^"]+)"/i),D=m.match(/internal:role=([^ ]+)/i),A=m.match(/internal:describe="([^"]+)"/i),B=m.match(/name="([^"]+)"/i);if(y){c.push({type:"text",text:y[1]});let p=y[1].split(" ");p.length>1&&(c.push({type:"text",text:p[0],fuzzy:!0}),c.push({type:"text",text:p[p.length-1],fuzzy:!0}))}if(T&&c.push({type:"label",label:T[1]}),F&&c.push({type:"placeholder",placeholder:F[1]}),d){c.unshift({type:"text",text:d,source:"accessibility-tree"});let p=d.split(" ");p.length>1&&c.push({type:"text",text:p[0],fuzzy:!0,source:"accessibility-tree"})}if(u||D){let p=u||D[1],E=d||(B?B[1]:y?y[1]:null);c.unshift({type:"role",role:p,name:E,source:d?"accessibility-tree":"selector"})}if(x&&c.unshift({type:"label",label:x,source:"accessibility-tree"}),A){let p=A[1],E=["link","button","textbox","menuitem","submenu","combobox","checkbox","radio","tab","treeitem","menu item"],v=null,C=p;for(let N of E)if(p.toLowerCase().endsWith(` ${N}`)){v=N.replace(" ",""),C=p.substring(0,p.length-N.length-1);break}if(v){c.push({type:"role",role:v,name:C});let N=C.replace(/\s*\([^)]+\)\s*$/,"");c.push({type:"text",text:N}),c.push({type:"text",text:C});let q=C.split(" ");q.length>1&&(c.push({type:"text",text:q[0],fuzzy:!0}),c.push({type:"text",text:q.slice(0,2).join(" "),fuzzy:!0}))}else{let N=p.replace(/\s*\([^)]+\)\s*$/,"");c.push({type:"text",text:N}),c.push({type:"text",text:p})}}let Y=this.extractDOMStrategies(m,o,y?.[1]||A?.[1],a.pageId);c.push(...Y);let $=this.extractStructuralContext(m);($.parent||$.sibling)&&c.forEach(p=>{["role","text","label","testid"].includes(p.type)&&($.parent&&(p.parent=$.parent),$.sibling&&(p.sibling=$.sibling))}),c.push({type:"css",value:m});let J=d||y?y[1]:A?A[1].replace(/\s*\([^)]+\)\s*$/,""):`Action ${n.length}`;n.push({method:f,name:J,action:f==="type"?"fill":f,value:w,strategies:c,timestamp:a.startTime,actualText:d,actualRole:u,actualAriaLabel:x})}}}catch{}return n}catch(t){throw new Error(`Failed to parse trace: ${t.message}`,{cause:t})}}static extractDOMStrategies(e,r,t,i){let n=[];if(!r||r.size===0||!t)return n;try{let s=r.get(i);if(!s)return n;let o=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),l=new RegExp(`data-testid=["']([^"']+)["'][^>]*>[^<]*${o}`,"i"),a=s.match(l);a&&n.push({type:"testid",value:a[1],priority:"high"});let f=new RegExp(`class=["']([^"']+)["'][^>]*>[^<]*${o}`,"gi"),m=s.matchAll(f);for(let d of m){let u=d[1].split(/\s+/).filter(x=>x&&!x.match(/^(css|jss|makeStyles|MuiBox|MuiStack)-\w+/)&&x.length>2);u.length>0&&(n.push({type:"class",value:u.join("."),priority:"medium"}),u.length===1&&n.push({type:"class",value:u[0],priority:"medium"}))}let w=new RegExp(`id=["']([^"']+)["'][^>]*>[^<]*${o}`,"i"),c=s.match(w);c&&!c[1].match(/^(root|app|\d+|[a-f0-9-]{20,})$/i)&&n.push({type:"id",value:c[1],priority:"high"})}catch(s){console.warn(`[TraceParser] DOM extraction failed: ${s.message}`)}return n}static extractStructuralContext(e){let r={parent:null,sibling:null},t=e.split(">>").map(s=>s.trim());if(t.length>1){let o=t[t.length-2].replace(/internal:text="[^"]+"\s*/gi,"").replace(/internal:role=\S+\s*/gi,"").replace(/internal:label="[^"]+"\s*/gi,"").trim();o&&(o.match(/^(form|section|nav|header|aside|main|article)\b/)||o.includes("[")||o.match(/[#.]\w/))&&(r.parent=o)}let n=t[t.length-1].match(/([^+~]+)\s*[+~]\s*(.+)/);return n&&(r.sibling=n[1].trim()),r}};import{existsSync as U}from"fs";import{join as W}from"path";var O=class extends g{constructor(e={}){super(e),this.priority=190,this.traceData=null}getName(){return"TraceText"}getPriority(){return this.priority}async loadTrace(e){if(this.traceData)return;let r=W(e,"traces"),t=W(e,"trace.zip");if(U(t))try{this.traceData=await z.parseTraceZip(t),console.log(`[TraceTextEnricher] \u2705 Loaded trace with ${this.traceData.length} actions`)}catch(i){console.log(`[TraceTextEnricher] \u26A0\uFE0F Failed to parse trace: ${i.message}`)}}async enrich(e,r){let t=e.data?.params?.ref,i=e.id;if(t===void 0&&i===void 0||(!this.traceData&&r.sessionPath&&await this.loadTrace(r.sessionPath),!this.traceData))return null;let n=this.traceData[i];if(!n)return console.log(`[TraceTextEnricher] \u26A0\uFE0F No trace action for event ${i}`),null;let s=n.actualText||this._extractTextFromSelector(n.selector),o=n.actualRole,l=n.actualAriaLabel;return s||o||l?(console.log(`[TraceTextEnricher] \u2705 Event ${i}: text="${s}", role="${o}", label="${l}"`),{traceActualText:s,traceActualRole:o,traceActualAriaLabel:l,traceSelector:n.selector,traceStrategies:n.strategies}):null}_extractTextFromSelector(e){if(!e)return null;let r=e.match(/internal:label="([^"]+)"/);if(r)return r[1];let t=e.match(/internal:text="([^"]+)"/);if(t)return t[1];let i=e.match(/getByText\(['"]([^'"]+)['"]\)/);if(i)return i[1];let n=e.match(/name:\s*['"]([^'"]+)['"]/);return n?n[1]:null}};function Pe(h={}){let e=new S(h);return h.enableMCPRef!==!1&&e.register(new L(h)),h.enableTraceText!==!1&&e.register(new O(h)),h.enableAccessibility!==!1&&e.register(new P(h)),h.enablePageState!==!1&&e.register(new M(h)),h.enablePosition!==!1&&e.register(new R(h)),h.enableDOM!==!1&&e.register(new k(h)),e}function Me(h={}){let e=new S(h);return e.register(new P(h)),e.register(new M(h)),e}function Ae(h,e={}){let r=new S(e);for(let t of h)r.register(t);return r}export{P as AccessibilityEnricher,k as DOMEnricher,S as EnrichmentPipeline,g as EventEnricher,L as MCPRefEnricher,M as PageStateEnricher,R as PositionEnricher,O as TraceTextEnricher,Ae as createCustomPipeline,Pe as createDefaultPipeline,Me as createMinimalPipeline};
3
+ Registered enrichers (${this.enrichers.length}):`);for(let e of this.enrichers){let r=e.enabled?"\u2713":"\u2717",t=this.stats.errors[e.getName()]||0,i=t>0?` (${t} errors)`:"";console.log(` ${r} ${e.getName()} (priority: ${e.getPriority()})${i}`)}console.log()}};var R=class extends g{getName(){return"PositionEnricher"}getPriority(){return 90}canEnrich(e){return!this.enabled||!e.element||!e.event?!1:["click","fill","type","selectOption","hover"].includes(e.event.type)}async enrich(e,r){try{let{page:t,element:i}=r,n=await i.boundingBox();if(!n)return null;let s=await t.evaluate(()=>({scrollX:window.scrollX,scrollY:window.scrollY,width:window.innerWidth,height:window.innerHeight})),o=n.y>=s.scrollY&&n.y+n.height<=s.scrollY+s.height&&n.x>=0&&n.x+n.width<=s.width;return{position:{boundingBox:n,viewport:s,inViewport:o,centerPoint:{x:Math.round(n.x+n.width/2),y:Math.round(n.y+n.height/2)}}}}catch(t){return this.handleError(t,e)}}};import _ from"node:crypto";var P=class extends g{getName(){return"AccessibilityEnricher"}getPriority(){return 100}canEnrich(e){return!this.enabled||!e.element||!e.event?!1:["click","fill","type","selectOption","hover"].includes(e.event.type)}async enrich(e,r){try{let{page:t,element:i}=r,n=await t.accessibility.snapshot(),s=await this.findAxNode(i,n);if(!s)return null;let o=await this.getAxContext(s,n),l=this.hashAxSubtree(s),a=this.hashAxPath(o.path);return{accessibility:{role:s.role,name:s.name||"",level:o.level,parent:o.parent,siblings:o.siblings,axTreeHash:l,axPathHash:a}}}catch(t){return this.handleError(t,e)}}async findAxNode(e,r){let t=await e.evaluate(i=>({role:i.getAttribute("role")||i.tagName.toLowerCase(),name:i.getAttribute("aria-label")||i.textContent?.trim()||"",tagName:i.tagName.toLowerCase()}));return this.searchAxTree(r,t)}searchAxTree(e,r){if(!e)return null;if(e.role===r.role&&(e.name||"").includes(r.name.substring(0,20)))return e;if(e.children)for(let t of e.children){let i=this.searchAxTree(t,r);if(i)return i}return null}getAxContext(e,r){let t={level:0,parent:null,siblings:[],path:[]},i=this.findParent(e,r);return i&&(t.parent={role:i.role,name:i.name},t.siblings=(i.children||[]).filter(n=>n!==e).map(n=>({role:n.role,name:n.name})).slice(0,3)),t.level=this.calculateLevel(e,r),t.path=this.buildPath(e,r),t}findParent(e,r,t=r){if(!t||!t.children)return null;if(t.children.includes(e))return t;for(let i of t.children){let n=this.findParent(e,r,i);if(n)return n}return null}calculateLevel(e,r,t=r,i=0){if(t===e)return i;if(t.children)for(let n of t.children){let s=this.calculateLevel(e,r,n,i+1);if(s>=0)return s}return-1}buildPath(e,r,t=r,i=[]){if(t===e)return[...i,{role:t.role,name:t.name}];if(t.children)for(let n of t.children){let s=this.buildPath(e,r,n,[...i,{role:t.role,name:t.name}]);if(s)return s}return null}hashAxSubtree(e){let r=JSON.stringify({role:e.role,name:e.name,children:(e.children||[]).map(t=>({role:t.role,name:t.name}))});return _.createHash("md5").update(r).digest("hex").substring(0,12)}hashAxPath(e){let r=e.map(t=>`${t.role}:${t.name}`).join("/");return _.createHash("md5").update(r).digest("hex").substring(0,12)}};var M=class extends g{constructor(e={}){super(e),this.pendingRequests=new Set,this.setupNetworkTracking=!1}getName(){return"PageStateEnricher"}getPriority(){return 95}canEnrich(e){return this.enabled&&e.page}async setupTracking(e){this.setupNetworkTracking||(e.on("request",r=>{["document","xhr","fetch"].includes(r.resourceType())&&this.pendingRequests.add(r.url())}),e.on("requestfinished",r=>{this.pendingRequests.delete(r.url())}),e.on("requestfailed",r=>{this.pendingRequests.delete(r.url())}),this.setupNetworkTracking=!0)}async enrich(e,r){try{let{page:t}=r;await this.setupTracking(t);let i=await t.evaluate(()=>({readyState:document.readyState,domContentLoaded:document.readyState!=="loading",loadComplete:document.readyState==="complete",url:document.location.href})),n=await this.checkDOMStability(t);return{page:{networkIdle:this.pendingRequests.size===0,pendingRequests:this.pendingRequests.size,domStable:n,...i}}}catch(t){return this.handleError(t,e)}}async checkDOMStability(e,r=500){try{return await e.evaluate(i=>new Promise(n=>{let s,o=0,l=new MutationObserver(()=>{o++,clearTimeout(s),s=setTimeout(()=>{l.disconnect(),n(o===0)},i)});l.observe(document.body,{childList:!0,subtree:!0,attributes:!0}),s=setTimeout(()=>{l.disconnect(),n(!0)},i)}),r)}catch{return!1}}reset(){this.pendingRequests.clear(),this.setupNetworkTracking=!1}};var k=class extends g{getName(){return"DOMEnricher"}getPriority(){return 85}canEnrich(e){return!this.enabled||!e.element||!e.event?!1:["click","fill","type","selectOption","hover"].includes(e.event.type)}async enrich(e,r){try{let{element:t}=r,i=await t.evaluate(n=>{let s=c=>{let d=[],u=c;for(;u&&u!==document.body;){let x=u.tagName.toLowerCase(),b=u.parentElement;if(b){let y=Array.from(b.children).filter(T=>T.tagName===u.tagName);if(y.length>1){let T=y.indexOf(u)+1;x+=`:nth-child(${T})`}}d.unshift(x),u=u.parentElement}return`body > ${d.join(" > ")}`},o=c=>{let d=[],u=c;for(;u&&u!==document.body;){let x=1,b=u.previousSibling;for(;b;)b.nodeType===1&&b.tagName===u.tagName&&x++,b=b.previousSibling;let y=u.tagName.toLowerCase();d.unshift(`${y}[${x}]`),u=u.parentElement}return`/html/body/${d.join("/")}`},l={};for(let c of n.attributes)l[c.name]=c.value;let a=window.getComputedStyle(n),f={display:a.display,visibility:a.visibility,opacity:a.opacity,pointerEvents:a.pointerEvents},m=0,w=n.parentElement;for(;w;)m++,w=w.parentElement;return{path:s(n),xpath:o(n),depth:m,parent:n.parentElement?n.parentElement.tagName.toLowerCase():null,tagName:n.tagName.toLowerCase(),attributes:l,state:{visible:a.display!=="none"&&a.visibility!=="hidden",enabled:!n.disabled,focused:document.activeElement===n,...f}}});return{dom:{path:i.path,xpath:i.xpath,depth:i.depth,parent:i.parent,selector:this.buildSmartSelector(i)},attributes:i.attributes,state:i.state}}catch(t){return this.handleError(t,e)}}buildSmartSelector(e){let r=e.tagName;if(e.attributes.id)return`#${e.attributes.id}`;if(e.attributes["data-test-id"])return`[data-test-id="${e.attributes["data-test-id"]}"]`;if(e.attributes.class){let t=e.attributes.class.split(" ").filter(i=>i&&!i.match(/^(active|focus|hover|disabled)/));t.length>0&&(r+=`.${t.slice(0,2).join(".")}`)}return e.parent&&(r=`${e.parent} > ${r}`),r}};var L=class extends g{constructor(e={}){super(e),this.priority=200}getName(){return"MCPRef"}getPriority(){return this.priority}async enrich(e,r){let t=e.data?.params?.ref,i=e.data?.params?.element;if(!t&&!i)return null;let n=null,s=null,o=null;if(r?.element)try{let l=await r.element.evaluate(a=>({text:a.textContent?.trim()||"",innerText:a.innerText?.trim()||"",value:a.value||"",label:a.getAttribute("aria-label")||a.getAttribute("label")||"",role:a.getAttribute("role")||a.tagName.toLowerCase(),placeholder:a.getAttribute("placeholder")||"",title:a.getAttribute("title")||""}));n=l.text||l.innerText||l.value||l.placeholder,s=l.role,o=l.label||l.title,console.log(`[MCPRefEnricher] \u2705 Captured actual text: "${n}" (AI said: "${i}")`)}catch(l){console.log(`[MCPRefEnricher] \u26A0\uFE0F Could not extract actual text: ${l.message}`)}return{mcpRef:t,mcpElement:i,actualText:n,actualRole:s,actualLabel:o,recordedSelector:n||i}}};import{readFileSync as X,existsSync as I,readdirSync as H}from"node:fs";import{join as j}from"node:path";import{execSync as Z}from"node:child_process";import{tmpdir as K}from"node:os";var z=class{static async parseTraceZip(e){let r;if(e.endsWith(".zip")&&I(e)){let t=j(K(),`trace-${Date.now()}`);Z(`unzip -q "${e}" -d "${t}"`,{stdio:"pipe"});let n=H(t).find(s=>s.endsWith(".trace"));if(!n)throw new Error("No .trace file found in zip");r=j(t,n)}else if(I(e)){let i=H(e).find(n=>n.endsWith(".trace"));if(!i)throw new Error("No .trace file found");r=j(e,i)}else throw new Error(`Trace not found at ${e}`);try{let i=X(r,"utf-8").trim().split(`
4
+ `),n=[],s=new Map,o=new Map;for(let l of i)try{let a=JSON.parse(l);if(a.type==="snapshot"&&a.snapshot&&a.snapshot.accessibility){let f=new Map;for(let m of a.snapshot.accessibility)m.ref&&f.set(m.ref,m);s.set(a.snapshotName,f)}if(a.type==="frame-snapshot"&&a.snapshot){let f=Buffer.from(a.snapshot.html||"","base64").toString("utf-8");f&&f.length>100&&o.set(a.pageId||"default",f)}}catch{}for(let l of i)try{let a=JSON.parse(l);if(a.type==="before"&&a.params&&a.params.selector){let f=a.method;if(["click","fill","type","selectOption"].includes(f)){let m=a.params.selector,w=a.params.text||a.params.value||"",c=[],d=null,u=null,x=null,b=m.match(/aria-ref=([a-z0-9]+)/i);if(b&&a.snapshotName){let p=b[1],E=s.get(a.snapshotName);if(E&&E.has(p)){let v=E.get(p);d=v.name||null,u=v.role||null,x=v.label||null,console.log(`[TraceParser] \u2705 Found ACTUAL element data: text="${d}", role="${u}"`)}}let y=m.match(/internal:text="([^"]+)"/i),T=m.match(/internal:label="([^"]+)"/i),F=m.match(/internal:placeholder="([^"]+)"/i),D=m.match(/internal:role=([^ ]+)/i),A=m.match(/internal:describe="([^"]+)"/i),B=m.match(/name="([^"]+)"/i);if(y){c.push({type:"text",text:y[1]});let p=y[1].split(" ");p.length>1&&(c.push({type:"text",text:p[0],fuzzy:!0}),c.push({type:"text",text:p[p.length-1],fuzzy:!0}))}if(T&&c.push({type:"label",label:T[1]}),F&&c.push({type:"placeholder",placeholder:F[1]}),d){c.unshift({type:"text",text:d,source:"accessibility-tree"});let p=d.split(" ");p.length>1&&c.push({type:"text",text:p[0],fuzzy:!0,source:"accessibility-tree"})}if(u||D){let p=u||D[1],E=d||(B?B[1]:y?y[1]:null);c.unshift({type:"role",role:p,name:E,source:d?"accessibility-tree":"selector"})}if(x&&c.unshift({type:"label",label:x,source:"accessibility-tree"}),A){let p=A[1],E=["link","button","textbox","menuitem","submenu","combobox","checkbox","radio","tab","treeitem","menu item"],v=null,C=p;for(let N of E)if(p.toLowerCase().endsWith(` ${N}`)){v=N.replace(" ",""),C=p.substring(0,p.length-N.length-1);break}if(v){c.push({type:"role",role:v,name:C});let N=C.replace(/\s*\([^)]+\)\s*$/,"");c.push({type:"text",text:N}),c.push({type:"text",text:C});let q=C.split(" ");q.length>1&&(c.push({type:"text",text:q[0],fuzzy:!0}),c.push({type:"text",text:q.slice(0,2).join(" "),fuzzy:!0}))}else{let N=p.replace(/\s*\([^)]+\)\s*$/,"");c.push({type:"text",text:N}),c.push({type:"text",text:p})}}let Y=this.extractDOMStrategies(m,o,y?.[1]||A?.[1],a.pageId);c.push(...Y);let $=this.extractStructuralContext(m);($.parent||$.sibling)&&c.forEach(p=>{["role","text","label","testid"].includes(p.type)&&($.parent&&(p.parent=$.parent),$.sibling&&(p.sibling=$.sibling))}),c.push({type:"css",value:m});let J=d||y?y[1]:A?A[1].replace(/\s*\([^)]+\)\s*$/,""):`Action ${n.length}`;n.push({method:f,name:J,action:f==="type"?"fill":f,value:w,strategies:c,timestamp:a.startTime,actualText:d,actualRole:u,actualAriaLabel:x})}}}catch{}return n}catch(t){throw new Error(`Failed to parse trace: ${t.message}`,{cause:t})}}static extractDOMStrategies(e,r,t,i){let n=[];if(!r||r.size===0||!t)return n;try{let s=r.get(i);if(!s)return n;let o=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),l=new RegExp(`data-testid=["']([^"']+)["'][^>]*>[^<]*${o}`,"i"),a=s.match(l);a&&n.push({type:"testid",value:a[1],priority:"high"});let f=new RegExp(`class=["']([^"']+)["'][^>]*>[^<]*${o}`,"gi"),m=s.matchAll(f);for(let d of m){let u=d[1].split(/\s+/).filter(x=>x&&!x.match(/^(css|jss|makeStyles|MuiBox|MuiStack)-\w+/)&&x.length>2);u.length>0&&(n.push({type:"class",value:u.join("."),priority:"medium"}),u.length===1&&n.push({type:"class",value:u[0],priority:"medium"}))}let w=new RegExp(`id=["']([^"']+)["'][^>]*>[^<]*${o}`,"i"),c=s.match(w);c&&!c[1].match(/^(root|app|\d+|[a-f0-9-]{20,})$/i)&&n.push({type:"id",value:c[1],priority:"high"})}catch(s){console.warn(`[TraceParser] DOM extraction failed: ${s.message}`)}return n}static extractStructuralContext(e){let r={parent:null,sibling:null},t=e.split(">>").map(s=>s.trim());if(t.length>1){let o=t[t.length-2].replace(/internal:text="[^"]+"\s*/gi,"").replace(/internal:role=\S+\s*/gi,"").replace(/internal:label="[^"]+"\s*/gi,"").trim();o&&(o.match(/^(form|section|nav|header|aside|main|article)\b/)||o.includes("[")||o.match(/[#.]\w/))&&(r.parent=o)}let n=t[t.length-1].match(/([^+~]+)\s*[+~]\s*(.+)/);return n&&(r.sibling=n[1].trim()),r}};import{existsSync as U}from"node:fs";import{join as W}from"node:path";var O=class extends g{constructor(e={}){super(e),this.priority=190,this.traceData=null}getName(){return"TraceText"}getPriority(){return this.priority}async loadTrace(e){if(this.traceData)return;let r=W(e,"traces"),t=W(e,"trace.zip");if(U(t))try{this.traceData=await z.parseTraceZip(t),console.log(`[TraceTextEnricher] \u2705 Loaded trace with ${this.traceData.length} actions`)}catch(i){console.log(`[TraceTextEnricher] \u26A0\uFE0F Failed to parse trace: ${i.message}`)}}async enrich(e,r){let t=e.data?.params?.ref,i=e.id;if(t===void 0&&i===void 0||(!this.traceData&&r.sessionPath&&await this.loadTrace(r.sessionPath),!this.traceData))return null;let n=this.traceData[i];if(!n)return console.log(`[TraceTextEnricher] \u26A0\uFE0F No trace action for event ${i}`),null;let s=n.actualText||this._extractTextFromSelector(n.selector),o=n.actualRole,l=n.actualAriaLabel;return s||o||l?(console.log(`[TraceTextEnricher] \u2705 Event ${i}: text="${s}", role="${o}", label="${l}"`),{traceActualText:s,traceActualRole:o,traceActualAriaLabel:l,traceSelector:n.selector,traceStrategies:n.strategies}):null}_extractTextFromSelector(e){if(!e)return null;let r=e.match(/internal:label="([^"]+)"/);if(r)return r[1];let t=e.match(/internal:text="([^"]+)"/);if(t)return t[1];let i=e.match(/getByText\(['"]([^'"]+)['"]\)/);if(i)return i[1];let n=e.match(/name:\s*['"]([^'"]+)['"]/);return n?n[1]:null}};function Pe(h={}){let e=new S(h);return h.enableMCPRef!==!1&&e.register(new L(h)),h.enableTraceText!==!1&&e.register(new O(h)),h.enableAccessibility!==!1&&e.register(new P(h)),h.enablePageState!==!1&&e.register(new M(h)),h.enablePosition!==!1&&e.register(new R(h)),h.enableDOM!==!1&&e.register(new k(h)),e}function Me(h={}){let e=new S(h);return e.register(new P(h)),e.register(new M(h)),e}function Ae(h,e={}){let r=new S(e);for(let t of h)r.register(t);return r}export{P as AccessibilityEnricher,k as DOMEnricher,S as EnrichmentPipeline,g as EventEnricher,L as MCPRefEnricher,M as PageStateEnricher,R as PositionEnricher,O as TraceTextEnricher,Ae as createCustomPipeline,Pe as createDefaultPipeline,Me as createMinimalPipeline};
@@ -1,4 +1,4 @@
1
1
  var g=class{constructor(e={}){this.config=e,this.enabled=e.enabled!==!1,this.priority=e.priority||50}getName(){throw new Error("EventEnricher.getName() must be implemented")}canEnrich(e){return this.enabled}async enrich(e,n){throw new Error("EventEnricher.enrich() must be implemented")}handleError(e,n){return console.warn(`[${this.getName()}] Enrichment failed for event ${n.type}:`,e.message),null}};var T=class{constructor(e={}){this.enrichers=[],this.config=e,this.stats={totalEvents:0,enrichedEvents:0,skippedEvents:0,errors:{}}}register(e){return this.enrichers.push(e),this.enrichers.sort((n,t)=>t.getPriority()-n.getPriority()),this}unregister(e){return this.enrichers=this.enrichers.filter(n=>n.getName()!==e),this}get(e){return this.enrichers.find(n=>n.getName()===e)}setEnabled(e,n){let t=this.get(e);return t&&(t.enabled=n),this}async enrich(e,n){this.stats.totalEvents++;let t={...e},i=[],r=[],s=[];for(let o of this.enrichers)try{if(!o.canEnrich(n)){r.push(o.getName());continue}let c=Date.now(),a=await o.enrich(e,n),f=Date.now()-c;a?(Object.assign(t,a),i.push({name:o.getName(),duration:f})):r.push(o.getName())}catch(c){console.warn(`[EnrichmentPipeline] ${o.getName()} failed:`,c.message),s.push(o.getName()),this.stats.errors[o.getName()]=(this.stats.errors[o.getName()]||0)+1}return t._enrichment={version:"1.0",timestamp:new Date().toISOString(),enrichers:{run:i,skipped:r,failed:s}},i.length>0?this.stats.enrichedEvents++:this.stats.skippedEvents++,t}async enrichBatch(e,n){let t=[];for(let i of e){let r=await this.enrich(i,n);t.push(r)}return t}getStats(){return{...this.stats,enrichers:this.enrichers.map(e=>({name:e.getName(),enabled:e.enabled,priority:e.getPriority(),errors:this.stats.errors[e.getName()]||0}))}}resetStats(){this.stats={totalEvents:0,enrichedEvents:0,skippedEvents:0,errors:{}}}logStatus(){console.log(`
2
2
  \u{1F4CA} Enrichment Pipeline Status:`),console.log(` Total events: ${this.stats.totalEvents}`),console.log(` Enriched: ${this.stats.enrichedEvents}`),console.log(` Skipped: ${this.stats.skippedEvents}`),console.log(`
3
- Registered enrichers (${this.enrichers.length}):`);for(let e of this.enrichers){let n=e.enabled?"\u2713":"\u2717",t=this.stats.errors[e.getName()]||0,i=t>0?` (${t} errors)`:"";console.log(` ${n} ${e.getName()} (priority: ${e.getPriority()})${i}`)}console.log()}};var k=class extends g{getName(){return"PositionEnricher"}getPriority(){return 90}canEnrich(e){return!this.enabled||!e.element||!e.event?!1:["click","fill","type","selectOption","hover"].includes(e.event.type)}async enrich(e,n){try{let{page:t,element:i}=n,r=await i.boundingBox();if(!r)return null;let s=await t.evaluate(()=>({scrollX:window.scrollX,scrollY:window.scrollY,width:window.innerWidth,height:window.innerHeight})),o=r.y>=s.scrollY&&r.y+r.height<=s.scrollY+s.height&&r.x>=0&&r.x+r.width<=s.width;return{position:{boundingBox:r,viewport:s,inViewport:o,centerPoint:{x:Math.round(r.x+r.width/2),y:Math.round(r.y+r.height/2)}}}}catch(t){return this.handleError(t,e)}}};import J from"crypto";var P=class extends g{getName(){return"AccessibilityEnricher"}getPriority(){return 100}canEnrich(e){return!this.enabled||!e.element||!e.event?!1:["click","fill","type","selectOption","hover"].includes(e.event.type)}async enrich(e,n){try{let{page:t,element:i}=n,r=await t.accessibility.snapshot(),s=await this.findAxNode(i,r);if(!s)return null;let o=await this.getAxContext(s,r),c=this.hashAxSubtree(s),a=this.hashAxPath(o.path);return{accessibility:{role:s.role,name:s.name||"",level:o.level,parent:o.parent,siblings:o.siblings,axTreeHash:c,axPathHash:a}}}catch(t){return this.handleError(t,e)}}async findAxNode(e,n){let t=await e.evaluate(i=>({role:i.getAttribute("role")||i.tagName.toLowerCase(),name:i.getAttribute("aria-label")||i.textContent?.trim()||"",tagName:i.tagName.toLowerCase()}));return this.searchAxTree(n,t)}searchAxTree(e,n){if(!e)return null;if(e.role===n.role&&(e.name||"").includes(n.name.substring(0,20)))return e;if(e.children)for(let t of e.children){let i=this.searchAxTree(t,n);if(i)return i}return null}getAxContext(e,n){let t={level:0,parent:null,siblings:[],path:[]},i=this.findParent(e,n);return i&&(t.parent={role:i.role,name:i.name},t.siblings=(i.children||[]).filter(r=>r!==e).map(r=>({role:r.role,name:r.name})).slice(0,3)),t.level=this.calculateLevel(e,n),t.path=this.buildPath(e,n),t}findParent(e,n,t=n){if(!t||!t.children)return null;if(t.children.includes(e))return t;for(let i of t.children){let r=this.findParent(e,n,i);if(r)return r}return null}calculateLevel(e,n,t=n,i=0){if(t===e)return i;if(t.children)for(let r of t.children){let s=this.calculateLevel(e,n,r,i+1);if(s>=0)return s}return-1}buildPath(e,n,t=n,i=[]){if(t===e)return[...i,{role:t.role,name:t.name}];if(t.children)for(let r of t.children){let s=this.buildPath(e,n,r,[...i,{role:t.role,name:t.name}]);if(s)return s}return null}hashAxSubtree(e){let n=JSON.stringify({role:e.role,name:e.name,children:(e.children||[]).map(t=>({role:t.role,name:t.name}))});return J.createHash("md5").update(n).digest("hex").substring(0,12)}hashAxPath(e){let n=e.map(t=>`${t.role}:${t.name}`).join("/");return J.createHash("md5").update(n).digest("hex").substring(0,12)}};var M=class extends g{constructor(e={}){super(e),this.pendingRequests=new Set,this.setupNetworkTracking=!1}getName(){return"PageStateEnricher"}getPriority(){return 95}canEnrich(e){return this.enabled&&e.page}async setupTracking(e){this.setupNetworkTracking||(e.on("request",n=>{["document","xhr","fetch"].includes(n.resourceType())&&this.pendingRequests.add(n.url())}),e.on("requestfinished",n=>{this.pendingRequests.delete(n.url())}),e.on("requestfailed",n=>{this.pendingRequests.delete(n.url())}),this.setupNetworkTracking=!0)}async enrich(e,n){try{let{page:t}=n;await this.setupTracking(t);let i=await t.evaluate(()=>({readyState:document.readyState,domContentLoaded:document.readyState!=="loading",loadComplete:document.readyState==="complete",url:document.location.href})),r=await this.checkDOMStability(t);return{page:{networkIdle:this.pendingRequests.size===0,pendingRequests:this.pendingRequests.size,domStable:r,...i}}}catch(t){return this.handleError(t,e)}}async checkDOMStability(e,n=500){try{return await e.evaluate(i=>new Promise(r=>{let s,o=0,c=new MutationObserver(()=>{o++,clearTimeout(s),s=setTimeout(()=>{c.disconnect(),r(o===0)},i)});c.observe(document.body,{childList:!0,subtree:!0,attributes:!0}),s=setTimeout(()=>{c.disconnect(),r(!0)},i)}),n)}catch{return!1}}reset(){this.pendingRequests.clear(),this.setupNetworkTracking=!1}};var R=class extends g{getName(){return"DOMEnricher"}getPriority(){return 85}canEnrich(e){return!this.enabled||!e.element||!e.event?!1:["click","fill","type","selectOption","hover"].includes(e.event.type)}async enrich(e,n){try{let{element:t}=n,i=await t.evaluate(r=>{let s=l=>{let d=[],u=l;for(;u&&u!==document.body;){let x=u.tagName.toLowerCase(),b=u.parentElement;if(b){let y=Array.from(b.children).filter(N=>N.tagName===u.tagName);if(y.length>1){let N=y.indexOf(u)+1;x+=`:nth-child(${N})`}}d.unshift(x),u=u.parentElement}return`body > ${d.join(" > ")}`},o=l=>{let d=[],u=l;for(;u&&u!==document.body;){let x=1,b=u.previousSibling;for(;b;)b.nodeType===1&&b.tagName===u.tagName&&x++,b=b.previousSibling;let y=u.tagName.toLowerCase();d.unshift(`${y}[${x}]`),u=u.parentElement}return`/html/body/${d.join("/")}`},c={};for(let l of r.attributes)c[l.name]=l.value;let a=window.getComputedStyle(r),f={display:a.display,visibility:a.visibility,opacity:a.opacity,pointerEvents:a.pointerEvents},m=0,w=r.parentElement;for(;w;)m++,w=w.parentElement;return{path:s(r),xpath:o(r),depth:m,parent:r.parentElement?r.parentElement.tagName.toLowerCase():null,tagName:r.tagName.toLowerCase(),attributes:c,state:{visible:a.display!=="none"&&a.visibility!=="hidden",enabled:!r.disabled,focused:document.activeElement===r,...f}}});return{dom:{path:i.path,xpath:i.xpath,depth:i.depth,parent:i.parent,selector:this.buildSmartSelector(i)},attributes:i.attributes,state:i.state}}catch(t){return this.handleError(t,e)}}buildSmartSelector(e){let n=e.tagName;if(e.attributes.id)return`#${e.attributes.id}`;if(e.attributes["data-test-id"])return`[data-test-id="${e.attributes["data-test-id"]}"]`;if(e.attributes.class){let t=e.attributes.class.split(" ").filter(i=>i&&!i.match(/^(active|focus|hover|disabled)/));t.length>0&&(n+=`.${t.slice(0,2).join(".")}`)}return e.parent&&(n=`${e.parent} > ${n}`),n}};var O=class extends g{constructor(e={}){super(e),this.priority=200}getName(){return"MCPRef"}getPriority(){return this.priority}async enrich(e,n){let t=e.data?.params?.ref,i=e.data?.params?.element;if(!t&&!i)return null;let r=null,s=null,o=null;if(n?.element)try{let c=await n.element.evaluate(a=>({text:a.textContent?.trim()||"",innerText:a.innerText?.trim()||"",value:a.value||"",label:a.getAttribute("aria-label")||a.getAttribute("label")||"",role:a.getAttribute("role")||a.tagName.toLowerCase(),placeholder:a.getAttribute("placeholder")||"",title:a.getAttribute("title")||""}));r=c.text||c.innerText||c.value||c.placeholder,s=c.role,o=c.label||c.title,console.log(`[MCPRefEnricher] \u2705 Captured actual text: "${r}" (AI said: "${i}")`)}catch(c){console.log(`[MCPRefEnricher] \u26A0\uFE0F Could not extract actual text: ${c.message}`)}return{mcpRef:t,mcpElement:i,actualText:r,actualRole:s,actualLabel:o,recordedSelector:r||i}}};import{readFileSync as G,existsSync as H,readdirSync as W}from"fs";import{join as j}from"path";import{execSync as Q}from"child_process";import{tmpdir as ee}from"os";var z=class{static async parseTraceZip(e){let n;if(e.endsWith(".zip")&&H(e)){let t=j(ee(),`trace-${Date.now()}`);Q(`unzip -q "${e}" -d "${t}"`,{stdio:"pipe"});let r=W(t).find(s=>s.endsWith(".trace"));if(!r)throw new Error("No .trace file found in zip");n=j(t,r)}else if(H(e)){let i=W(e).find(r=>r.endsWith(".trace"));if(!i)throw new Error("No .trace file found");n=j(e,i)}else throw new Error(`Trace not found at ${e}`);try{let i=G(n,"utf-8").trim().split(`
4
- `),r=[],s=new Map,o=new Map;for(let c of i)try{let a=JSON.parse(c);if(a.type==="snapshot"&&a.snapshot&&a.snapshot.accessibility){let f=new Map;for(let m of a.snapshot.accessibility)m.ref&&f.set(m.ref,m);s.set(a.snapshotName,f)}if(a.type==="frame-snapshot"&&a.snapshot){let f=Buffer.from(a.snapshot.html||"","base64").toString("utf-8");f&&f.length>100&&o.set(a.pageId||"default",f)}}catch{}for(let c of i)try{let a=JSON.parse(c);if(a.type==="before"&&a.params&&a.params.selector){let f=a.method;if(["click","fill","type","selectOption"].includes(f)){let m=a.params.selector,w=a.params.text||a.params.value||"",l=[],d=null,u=null,x=null,b=m.match(/aria-ref=([a-z0-9]+)/i);if(b&&a.snapshotName){let p=b[1],v=s.get(a.snapshotName);if(v&&v.has(p)){let E=v.get(p);d=E.name||null,u=E.role||null,x=E.label||null,console.log(`[TraceParser] \u2705 Found ACTUAL element data: text="${d}", role="${u}"`)}}let y=m.match(/internal:text="([^"]+)"/i),N=m.match(/internal:label="([^"]+)"/i),_=m.match(/internal:placeholder="([^"]+)"/i),B=m.match(/internal:role=([^ ]+)/i),A=m.match(/internal:describe="([^"]+)"/i),I=m.match(/name="([^"]+)"/i);if(y){l.push({type:"text",text:y[1]});let p=y[1].split(" ");p.length>1&&(l.push({type:"text",text:p[0],fuzzy:!0}),l.push({type:"text",text:p[p.length-1],fuzzy:!0}))}if(N&&l.push({type:"label",label:N[1]}),_&&l.push({type:"placeholder",placeholder:_[1]}),d){l.unshift({type:"text",text:d,source:"accessibility-tree"});let p=d.split(" ");p.length>1&&l.push({type:"text",text:p[0],fuzzy:!0,source:"accessibility-tree"})}if(u||B){let p=u||B[1],v=d||(I?I[1]:y?y[1]:null);l.unshift({type:"role",role:p,name:v,source:d?"accessibility-tree":"selector"})}if(x&&l.unshift({type:"label",label:x,source:"accessibility-tree"}),A){let p=A[1],v=["link","button","textbox","menuitem","submenu","combobox","checkbox","radio","tab","treeitem","menu item"],E=null,C=p;for(let S of v)if(p.toLowerCase().endsWith(` ${S}`)){E=S.replace(" ",""),C=p.substring(0,p.length-S.length-1);break}if(E){l.push({type:"role",role:E,name:C});let S=C.replace(/\s*\([^)]+\)\s*$/,"");l.push({type:"text",text:S}),l.push({type:"text",text:C});let F=C.split(" ");F.length>1&&(l.push({type:"text",text:F[0],fuzzy:!0}),l.push({type:"text",text:F.slice(0,2).join(" "),fuzzy:!0}))}else{let S=p.replace(/\s*\([^)]+\)\s*$/,"");l.push({type:"text",text:S}),l.push({type:"text",text:p})}}let K=this.extractDOMStrategies(m,o,y?.[1]||A?.[1],a.pageId);l.push(...K);let $=this.extractStructuralContext(m);($.parent||$.sibling)&&l.forEach(p=>{["role","text","label","testid"].includes(p.type)&&($.parent&&(p.parent=$.parent),$.sibling&&(p.sibling=$.sibling))}),l.push({type:"css",value:m});let V=d||y?y[1]:A?A[1].replace(/\s*\([^)]+\)\s*$/,""):`Action ${r.length}`;r.push({method:f,name:V,action:f==="type"?"fill":f,value:w,strategies:l,timestamp:a.startTime,actualText:d,actualRole:u,actualAriaLabel:x})}}}catch{}return r}catch(t){throw new Error(`Failed to parse trace: ${t.message}`,{cause:t})}}static extractDOMStrategies(e,n,t,i){let r=[];if(!n||n.size===0||!t)return r;try{let s=n.get(i);if(!s)return r;let o=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),c=new RegExp(`data-testid=["']([^"']+)["'][^>]*>[^<]*${o}`,"i"),a=s.match(c);a&&r.push({type:"testid",value:a[1],priority:"high"});let f=new RegExp(`class=["']([^"']+)["'][^>]*>[^<]*${o}`,"gi"),m=s.matchAll(f);for(let d of m){let u=d[1].split(/\s+/).filter(x=>x&&!x.match(/^(css|jss|makeStyles|MuiBox|MuiStack)-\w+/)&&x.length>2);u.length>0&&(r.push({type:"class",value:u.join("."),priority:"medium"}),u.length===1&&r.push({type:"class",value:u[0],priority:"medium"}))}let w=new RegExp(`id=["']([^"']+)["'][^>]*>[^<]*${o}`,"i"),l=s.match(w);l&&!l[1].match(/^(root|app|\d+|[a-f0-9-]{20,})$/i)&&r.push({type:"id",value:l[1],priority:"high"})}catch(s){console.warn(`[TraceParser] DOM extraction failed: ${s.message}`)}return r}static extractStructuralContext(e){let n={parent:null,sibling:null},t=e.split(">>").map(s=>s.trim());if(t.length>1){let o=t[t.length-2].replace(/internal:text="[^"]+"\s*/gi,"").replace(/internal:role=\S+\s*/gi,"").replace(/internal:label="[^"]+"\s*/gi,"").trim();o&&(o.match(/^(form|section|nav|header|aside|main|article)\b/)||o.includes("[")||o.match(/[#.]\w/))&&(n.parent=o)}let r=t[t.length-1].match(/([^+~]+)\s*[+~]\s*(.+)/);return r&&(n.sibling=r[1].trim()),n}};import{existsSync as te}from"fs";import{join as Y}from"path";var L=class extends g{constructor(e={}){super(e),this.priority=190,this.traceData=null}getName(){return"TraceText"}getPriority(){return this.priority}async loadTrace(e){if(this.traceData)return;let n=Y(e,"traces"),t=Y(e,"trace.zip");if(te(t))try{this.traceData=await z.parseTraceZip(t),console.log(`[TraceTextEnricher] \u2705 Loaded trace with ${this.traceData.length} actions`)}catch(i){console.log(`[TraceTextEnricher] \u26A0\uFE0F Failed to parse trace: ${i.message}`)}}async enrich(e,n){let t=e.data?.params?.ref,i=e.id;if(t===void 0&&i===void 0||(!this.traceData&&n.sessionPath&&await this.loadTrace(n.sessionPath),!this.traceData))return null;let r=this.traceData[i];if(!r)return console.log(`[TraceTextEnricher] \u26A0\uFE0F No trace action for event ${i}`),null;let s=r.actualText||this._extractTextFromSelector(r.selector),o=r.actualRole,c=r.actualAriaLabel;return s||o||c?(console.log(`[TraceTextEnricher] \u2705 Event ${i}: text="${s}", role="${o}", label="${c}"`),{traceActualText:s,traceActualRole:o,traceActualAriaLabel:c,traceSelector:r.selector,traceStrategies:r.strategies}):null}_extractTextFromSelector(e){if(!e)return null;let n=e.match(/internal:label="([^"]+)"/);if(n)return n[1];let t=e.match(/internal:text="([^"]+)"/);if(t)return t[1];let i=e.match(/getByText\(['"]([^'"]+)['"]\)/);if(i)return i[1];let r=e.match(/name:\s*['"]([^'"]+)['"]/);return r?r[1]:null}};function X(h={}){let e=new T(h);return h.enableMCPRef!==!1&&e.register(new O(h)),h.enableTraceText!==!1&&e.register(new L(h)),h.enableAccessibility!==!1&&e.register(new P(h)),h.enablePageState!==!1&&e.register(new M(h)),h.enablePosition!==!1&&e.register(new k(h)),h.enableDOM!==!1&&e.register(new R(h)),e}function Z(h={}){let e=new T(h);return e.register(new P(h)),e.register(new M(h)),e}import{readFileSync as re,writeFileSync as q}from"fs";import{join as U}from"path";async function ne(h,e={}){let n=U(h,"events.json"),t=U(h,"trace.zip");try{let i=JSON.parse(re(n,"utf-8")),r=i.map(o=>({...o,_enrichmentNote:"Full enrichment requires live Playwright access. Use EnrichmentPipeline during test execution."})),s=`${n}.backup`;return q(s,JSON.stringify(i,null,2)),q(n,JSON.stringify(r,null,2)),{enrichedCount:r.length,skippedCount:0,errors:[]}}catch(i){return console.error("[EnrichmentIntegration] Failed to enrich events:",i.message),{enrichedCount:0,skippedCount:0,errors:[i.message]}}}var D=class{constructor(e={}){this.pipeline=e.minimal?Z(e):X(e),this.events=[],this.config=e}async recordEvent(e,n,t){let i={id:this.events.length,type:e,timestamp:new Date().toISOString(),data:n},r=await this.pipeline.enrich(i,{...t,event:i});return this.events.push(r),r}saveEvents(e){q(e,JSON.stringify(this.events,null,2)),console.log(`[LiveEnrichment] Saved ${this.events.length} enriched events to ${e}`),this.pipeline.logStatus()}getStats(){return this.pipeline.getStats()}},Ye={enrichRecordedEvents:ne,LiveEnrichmentRecorder:D};export{D as LiveEnrichmentRecorder,Ye as default,ne as enrichRecordedEvents};
3
+ Registered enrichers (${this.enrichers.length}):`);for(let e of this.enrichers){let n=e.enabled?"\u2713":"\u2717",t=this.stats.errors[e.getName()]||0,i=t>0?` (${t} errors)`:"";console.log(` ${n} ${e.getName()} (priority: ${e.getPriority()})${i}`)}console.log()}};var k=class extends g{getName(){return"PositionEnricher"}getPriority(){return 90}canEnrich(e){return!this.enabled||!e.element||!e.event?!1:["click","fill","type","selectOption","hover"].includes(e.event.type)}async enrich(e,n){try{let{page:t,element:i}=n,r=await i.boundingBox();if(!r)return null;let s=await t.evaluate(()=>({scrollX:window.scrollX,scrollY:window.scrollY,width:window.innerWidth,height:window.innerHeight})),o=r.y>=s.scrollY&&r.y+r.height<=s.scrollY+s.height&&r.x>=0&&r.x+r.width<=s.width;return{position:{boundingBox:r,viewport:s,inViewport:o,centerPoint:{x:Math.round(r.x+r.width/2),y:Math.round(r.y+r.height/2)}}}}catch(t){return this.handleError(t,e)}}};import J from"node:crypto";var P=class extends g{getName(){return"AccessibilityEnricher"}getPriority(){return 100}canEnrich(e){return!this.enabled||!e.element||!e.event?!1:["click","fill","type","selectOption","hover"].includes(e.event.type)}async enrich(e,n){try{let{page:t,element:i}=n,r=await t.accessibility.snapshot(),s=await this.findAxNode(i,r);if(!s)return null;let o=await this.getAxContext(s,r),c=this.hashAxSubtree(s),a=this.hashAxPath(o.path);return{accessibility:{role:s.role,name:s.name||"",level:o.level,parent:o.parent,siblings:o.siblings,axTreeHash:c,axPathHash:a}}}catch(t){return this.handleError(t,e)}}async findAxNode(e,n){let t=await e.evaluate(i=>({role:i.getAttribute("role")||i.tagName.toLowerCase(),name:i.getAttribute("aria-label")||i.textContent?.trim()||"",tagName:i.tagName.toLowerCase()}));return this.searchAxTree(n,t)}searchAxTree(e,n){if(!e)return null;if(e.role===n.role&&(e.name||"").includes(n.name.substring(0,20)))return e;if(e.children)for(let t of e.children){let i=this.searchAxTree(t,n);if(i)return i}return null}getAxContext(e,n){let t={level:0,parent:null,siblings:[],path:[]},i=this.findParent(e,n);return i&&(t.parent={role:i.role,name:i.name},t.siblings=(i.children||[]).filter(r=>r!==e).map(r=>({role:r.role,name:r.name})).slice(0,3)),t.level=this.calculateLevel(e,n),t.path=this.buildPath(e,n),t}findParent(e,n,t=n){if(!t||!t.children)return null;if(t.children.includes(e))return t;for(let i of t.children){let r=this.findParent(e,n,i);if(r)return r}return null}calculateLevel(e,n,t=n,i=0){if(t===e)return i;if(t.children)for(let r of t.children){let s=this.calculateLevel(e,n,r,i+1);if(s>=0)return s}return-1}buildPath(e,n,t=n,i=[]){if(t===e)return[...i,{role:t.role,name:t.name}];if(t.children)for(let r of t.children){let s=this.buildPath(e,n,r,[...i,{role:t.role,name:t.name}]);if(s)return s}return null}hashAxSubtree(e){let n=JSON.stringify({role:e.role,name:e.name,children:(e.children||[]).map(t=>({role:t.role,name:t.name}))});return J.createHash("md5").update(n).digest("hex").substring(0,12)}hashAxPath(e){let n=e.map(t=>`${t.role}:${t.name}`).join("/");return J.createHash("md5").update(n).digest("hex").substring(0,12)}};var M=class extends g{constructor(e={}){super(e),this.pendingRequests=new Set,this.setupNetworkTracking=!1}getName(){return"PageStateEnricher"}getPriority(){return 95}canEnrich(e){return this.enabled&&e.page}async setupTracking(e){this.setupNetworkTracking||(e.on("request",n=>{["document","xhr","fetch"].includes(n.resourceType())&&this.pendingRequests.add(n.url())}),e.on("requestfinished",n=>{this.pendingRequests.delete(n.url())}),e.on("requestfailed",n=>{this.pendingRequests.delete(n.url())}),this.setupNetworkTracking=!0)}async enrich(e,n){try{let{page:t}=n;await this.setupTracking(t);let i=await t.evaluate(()=>({readyState:document.readyState,domContentLoaded:document.readyState!=="loading",loadComplete:document.readyState==="complete",url:document.location.href})),r=await this.checkDOMStability(t);return{page:{networkIdle:this.pendingRequests.size===0,pendingRequests:this.pendingRequests.size,domStable:r,...i}}}catch(t){return this.handleError(t,e)}}async checkDOMStability(e,n=500){try{return await e.evaluate(i=>new Promise(r=>{let s,o=0,c=new MutationObserver(()=>{o++,clearTimeout(s),s=setTimeout(()=>{c.disconnect(),r(o===0)},i)});c.observe(document.body,{childList:!0,subtree:!0,attributes:!0}),s=setTimeout(()=>{c.disconnect(),r(!0)},i)}),n)}catch{return!1}}reset(){this.pendingRequests.clear(),this.setupNetworkTracking=!1}};var R=class extends g{getName(){return"DOMEnricher"}getPriority(){return 85}canEnrich(e){return!this.enabled||!e.element||!e.event?!1:["click","fill","type","selectOption","hover"].includes(e.event.type)}async enrich(e,n){try{let{element:t}=n,i=await t.evaluate(r=>{let s=l=>{let d=[],u=l;for(;u&&u!==document.body;){let x=u.tagName.toLowerCase(),b=u.parentElement;if(b){let y=Array.from(b.children).filter(N=>N.tagName===u.tagName);if(y.length>1){let N=y.indexOf(u)+1;x+=`:nth-child(${N})`}}d.unshift(x),u=u.parentElement}return`body > ${d.join(" > ")}`},o=l=>{let d=[],u=l;for(;u&&u!==document.body;){let x=1,b=u.previousSibling;for(;b;)b.nodeType===1&&b.tagName===u.tagName&&x++,b=b.previousSibling;let y=u.tagName.toLowerCase();d.unshift(`${y}[${x}]`),u=u.parentElement}return`/html/body/${d.join("/")}`},c={};for(let l of r.attributes)c[l.name]=l.value;let a=window.getComputedStyle(r),f={display:a.display,visibility:a.visibility,opacity:a.opacity,pointerEvents:a.pointerEvents},m=0,w=r.parentElement;for(;w;)m++,w=w.parentElement;return{path:s(r),xpath:o(r),depth:m,parent:r.parentElement?r.parentElement.tagName.toLowerCase():null,tagName:r.tagName.toLowerCase(),attributes:c,state:{visible:a.display!=="none"&&a.visibility!=="hidden",enabled:!r.disabled,focused:document.activeElement===r,...f}}});return{dom:{path:i.path,xpath:i.xpath,depth:i.depth,parent:i.parent,selector:this.buildSmartSelector(i)},attributes:i.attributes,state:i.state}}catch(t){return this.handleError(t,e)}}buildSmartSelector(e){let n=e.tagName;if(e.attributes.id)return`#${e.attributes.id}`;if(e.attributes["data-test-id"])return`[data-test-id="${e.attributes["data-test-id"]}"]`;if(e.attributes.class){let t=e.attributes.class.split(" ").filter(i=>i&&!i.match(/^(active|focus|hover|disabled)/));t.length>0&&(n+=`.${t.slice(0,2).join(".")}`)}return e.parent&&(n=`${e.parent} > ${n}`),n}};var O=class extends g{constructor(e={}){super(e),this.priority=200}getName(){return"MCPRef"}getPriority(){return this.priority}async enrich(e,n){let t=e.data?.params?.ref,i=e.data?.params?.element;if(!t&&!i)return null;let r=null,s=null,o=null;if(n?.element)try{let c=await n.element.evaluate(a=>({text:a.textContent?.trim()||"",innerText:a.innerText?.trim()||"",value:a.value||"",label:a.getAttribute("aria-label")||a.getAttribute("label")||"",role:a.getAttribute("role")||a.tagName.toLowerCase(),placeholder:a.getAttribute("placeholder")||"",title:a.getAttribute("title")||""}));r=c.text||c.innerText||c.value||c.placeholder,s=c.role,o=c.label||c.title,console.log(`[MCPRefEnricher] \u2705 Captured actual text: "${r}" (AI said: "${i}")`)}catch(c){console.log(`[MCPRefEnricher] \u26A0\uFE0F Could not extract actual text: ${c.message}`)}return{mcpRef:t,mcpElement:i,actualText:r,actualRole:s,actualLabel:o,recordedSelector:r||i}}};import{readFileSync as G,existsSync as H,readdirSync as W}from"node:fs";import{join as j}from"node:path";import{execSync as Q}from"node:child_process";import{tmpdir as ee}from"node:os";var z=class{static async parseTraceZip(e){let n;if(e.endsWith(".zip")&&H(e)){let t=j(ee(),`trace-${Date.now()}`);Q(`unzip -q "${e}" -d "${t}"`,{stdio:"pipe"});let r=W(t).find(s=>s.endsWith(".trace"));if(!r)throw new Error("No .trace file found in zip");n=j(t,r)}else if(H(e)){let i=W(e).find(r=>r.endsWith(".trace"));if(!i)throw new Error("No .trace file found");n=j(e,i)}else throw new Error(`Trace not found at ${e}`);try{let i=G(n,"utf-8").trim().split(`
4
+ `),r=[],s=new Map,o=new Map;for(let c of i)try{let a=JSON.parse(c);if(a.type==="snapshot"&&a.snapshot&&a.snapshot.accessibility){let f=new Map;for(let m of a.snapshot.accessibility)m.ref&&f.set(m.ref,m);s.set(a.snapshotName,f)}if(a.type==="frame-snapshot"&&a.snapshot){let f=Buffer.from(a.snapshot.html||"","base64").toString("utf-8");f&&f.length>100&&o.set(a.pageId||"default",f)}}catch{}for(let c of i)try{let a=JSON.parse(c);if(a.type==="before"&&a.params&&a.params.selector){let f=a.method;if(["click","fill","type","selectOption"].includes(f)){let m=a.params.selector,w=a.params.text||a.params.value||"",l=[],d=null,u=null,x=null,b=m.match(/aria-ref=([a-z0-9]+)/i);if(b&&a.snapshotName){let p=b[1],v=s.get(a.snapshotName);if(v&&v.has(p)){let E=v.get(p);d=E.name||null,u=E.role||null,x=E.label||null,console.log(`[TraceParser] \u2705 Found ACTUAL element data: text="${d}", role="${u}"`)}}let y=m.match(/internal:text="([^"]+)"/i),N=m.match(/internal:label="([^"]+)"/i),_=m.match(/internal:placeholder="([^"]+)"/i),B=m.match(/internal:role=([^ ]+)/i),A=m.match(/internal:describe="([^"]+)"/i),I=m.match(/name="([^"]+)"/i);if(y){l.push({type:"text",text:y[1]});let p=y[1].split(" ");p.length>1&&(l.push({type:"text",text:p[0],fuzzy:!0}),l.push({type:"text",text:p[p.length-1],fuzzy:!0}))}if(N&&l.push({type:"label",label:N[1]}),_&&l.push({type:"placeholder",placeholder:_[1]}),d){l.unshift({type:"text",text:d,source:"accessibility-tree"});let p=d.split(" ");p.length>1&&l.push({type:"text",text:p[0],fuzzy:!0,source:"accessibility-tree"})}if(u||B){let p=u||B[1],v=d||(I?I[1]:y?y[1]:null);l.unshift({type:"role",role:p,name:v,source:d?"accessibility-tree":"selector"})}if(x&&l.unshift({type:"label",label:x,source:"accessibility-tree"}),A){let p=A[1],v=["link","button","textbox","menuitem","submenu","combobox","checkbox","radio","tab","treeitem","menu item"],E=null,C=p;for(let S of v)if(p.toLowerCase().endsWith(` ${S}`)){E=S.replace(" ",""),C=p.substring(0,p.length-S.length-1);break}if(E){l.push({type:"role",role:E,name:C});let S=C.replace(/\s*\([^)]+\)\s*$/,"");l.push({type:"text",text:S}),l.push({type:"text",text:C});let F=C.split(" ");F.length>1&&(l.push({type:"text",text:F[0],fuzzy:!0}),l.push({type:"text",text:F.slice(0,2).join(" "),fuzzy:!0}))}else{let S=p.replace(/\s*\([^)]+\)\s*$/,"");l.push({type:"text",text:S}),l.push({type:"text",text:p})}}let K=this.extractDOMStrategies(m,o,y?.[1]||A?.[1],a.pageId);l.push(...K);let $=this.extractStructuralContext(m);($.parent||$.sibling)&&l.forEach(p=>{["role","text","label","testid"].includes(p.type)&&($.parent&&(p.parent=$.parent),$.sibling&&(p.sibling=$.sibling))}),l.push({type:"css",value:m});let V=d||y?y[1]:A?A[1].replace(/\s*\([^)]+\)\s*$/,""):`Action ${r.length}`;r.push({method:f,name:V,action:f==="type"?"fill":f,value:w,strategies:l,timestamp:a.startTime,actualText:d,actualRole:u,actualAriaLabel:x})}}}catch{}return r}catch(t){throw new Error(`Failed to parse trace: ${t.message}`,{cause:t})}}static extractDOMStrategies(e,n,t,i){let r=[];if(!n||n.size===0||!t)return r;try{let s=n.get(i);if(!s)return r;let o=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),c=new RegExp(`data-testid=["']([^"']+)["'][^>]*>[^<]*${o}`,"i"),a=s.match(c);a&&r.push({type:"testid",value:a[1],priority:"high"});let f=new RegExp(`class=["']([^"']+)["'][^>]*>[^<]*${o}`,"gi"),m=s.matchAll(f);for(let d of m){let u=d[1].split(/\s+/).filter(x=>x&&!x.match(/^(css|jss|makeStyles|MuiBox|MuiStack)-\w+/)&&x.length>2);u.length>0&&(r.push({type:"class",value:u.join("."),priority:"medium"}),u.length===1&&r.push({type:"class",value:u[0],priority:"medium"}))}let w=new RegExp(`id=["']([^"']+)["'][^>]*>[^<]*${o}`,"i"),l=s.match(w);l&&!l[1].match(/^(root|app|\d+|[a-f0-9-]{20,})$/i)&&r.push({type:"id",value:l[1],priority:"high"})}catch(s){console.warn(`[TraceParser] DOM extraction failed: ${s.message}`)}return r}static extractStructuralContext(e){let n={parent:null,sibling:null},t=e.split(">>").map(s=>s.trim());if(t.length>1){let o=t[t.length-2].replace(/internal:text="[^"]+"\s*/gi,"").replace(/internal:role=\S+\s*/gi,"").replace(/internal:label="[^"]+"\s*/gi,"").trim();o&&(o.match(/^(form|section|nav|header|aside|main|article)\b/)||o.includes("[")||o.match(/[#.]\w/))&&(n.parent=o)}let r=t[t.length-1].match(/([^+~]+)\s*[+~]\s*(.+)/);return r&&(n.sibling=r[1].trim()),n}};import{existsSync as te}from"node:fs";import{join as Y}from"node:path";var L=class extends g{constructor(e={}){super(e),this.priority=190,this.traceData=null}getName(){return"TraceText"}getPriority(){return this.priority}async loadTrace(e){if(this.traceData)return;let n=Y(e,"traces"),t=Y(e,"trace.zip");if(te(t))try{this.traceData=await z.parseTraceZip(t),console.log(`[TraceTextEnricher] \u2705 Loaded trace with ${this.traceData.length} actions`)}catch(i){console.log(`[TraceTextEnricher] \u26A0\uFE0F Failed to parse trace: ${i.message}`)}}async enrich(e,n){let t=e.data?.params?.ref,i=e.id;if(t===void 0&&i===void 0||(!this.traceData&&n.sessionPath&&await this.loadTrace(n.sessionPath),!this.traceData))return null;let r=this.traceData[i];if(!r)return console.log(`[TraceTextEnricher] \u26A0\uFE0F No trace action for event ${i}`),null;let s=r.actualText||this._extractTextFromSelector(r.selector),o=r.actualRole,c=r.actualAriaLabel;return s||o||c?(console.log(`[TraceTextEnricher] \u2705 Event ${i}: text="${s}", role="${o}", label="${c}"`),{traceActualText:s,traceActualRole:o,traceActualAriaLabel:c,traceSelector:r.selector,traceStrategies:r.strategies}):null}_extractTextFromSelector(e){if(!e)return null;let n=e.match(/internal:label="([^"]+)"/);if(n)return n[1];let t=e.match(/internal:text="([^"]+)"/);if(t)return t[1];let i=e.match(/getByText\(['"]([^'"]+)['"]\)/);if(i)return i[1];let r=e.match(/name:\s*['"]([^'"]+)['"]/);return r?r[1]:null}};function X(h={}){let e=new T(h);return h.enableMCPRef!==!1&&e.register(new O(h)),h.enableTraceText!==!1&&e.register(new L(h)),h.enableAccessibility!==!1&&e.register(new P(h)),h.enablePageState!==!1&&e.register(new M(h)),h.enablePosition!==!1&&e.register(new k(h)),h.enableDOM!==!1&&e.register(new R(h)),e}function Z(h={}){let e=new T(h);return e.register(new P(h)),e.register(new M(h)),e}import{readFileSync as re,writeFileSync as q}from"node:fs";import{join as U}from"node:path";async function ne(h,e={}){let n=U(h,"events.json"),t=U(h,"trace.zip");try{let i=JSON.parse(re(n,"utf-8")),r=i.map(o=>({...o,_enrichmentNote:"Full enrichment requires live Playwright access. Use EnrichmentPipeline during test execution."})),s=`${n}.backup`;return q(s,JSON.stringify(i,null,2)),q(n,JSON.stringify(r,null,2)),{enrichedCount:r.length,skippedCount:0,errors:[]}}catch(i){return console.error("[EnrichmentIntegration] Failed to enrich events:",i.message),{enrichedCount:0,skippedCount:0,errors:[i.message]}}}var D=class{constructor(e={}){this.pipeline=e.minimal?Z(e):X(e),this.events=[],this.config=e}async recordEvent(e,n,t){let i={id:this.events.length,type:e,timestamp:new Date().toISOString(),data:n},r=await this.pipeline.enrich(i,{...t,event:i});return this.events.push(r),r}saveEvents(e){q(e,JSON.stringify(this.events,null,2)),console.log(`[LiveEnrichment] Saved ${this.events.length} enriched events to ${e}`),this.pipeline.logStatus()}getStats(){return this.pipeline.getStats()}},Ye={enrichRecordedEvents:ne,LiveEnrichmentRecorder:D};export{D as LiveEnrichmentRecorder,Ye as default,ne as enrichRecordedEvents};
@@ -1,2 +1,2 @@
1
- var M=class{constructor(t={}){this.config=t,this.enabled=t.enabled!==!1,this.priority=t.priority||50}getName(){throw new Error("EventEnricher.getName() must be implemented")}canEnrich(t){return this.enabled}async enrich(t,c){throw new Error("EventEnricher.enrich() must be implemented")}handleError(t,c){return console.warn(`[${this.getName()}] Enrichment failed for event ${c.type}:`,t.message),null}};import{readFileSync as B,existsSync as k,readdirSync as D}from"fs";import{join as z}from"path";import{execSync as W}from"child_process";import{tmpdir as I}from"os";var E=class{static async parseTraceZip(t){let c;if(t.endsWith(".zip")&&k(t)){let a=z(I(),`trace-${Date.now()}`);W(`unzip -q "${t}" -d "${a}"`,{stdio:"pipe"});let e=D(a).find(o=>o.endsWith(".trace"));if(!e)throw new Error("No .trace file found in zip");c=z(a,e)}else if(k(t)){let i=D(t).find(e=>e.endsWith(".trace"));if(!i)throw new Error("No .trace file found");c=z(t,i)}else throw new Error(`Trace not found at ${t}`);try{let i=B(c,"utf-8").trim().split(`
2
- `),e=[],o=new Map,l=new Map;for(let m of i)try{let r=JSON.parse(m);if(r.type==="snapshot"&&r.snapshot&&r.snapshot.accessibility){let h=new Map;for(let p of r.snapshot.accessibility)p.ref&&h.set(p.ref,p);o.set(r.snapshotName,h)}if(r.type==="frame-snapshot"&&r.snapshot){let h=Buffer.from(r.snapshot.html||"","base64").toString("utf-8");h&&h.length>100&&l.set(r.pageId||"default",h)}}catch{}for(let m of i)try{let r=JSON.parse(m);if(r.type==="before"&&r.params&&r.params.selector){let h=r.method;if(["click","fill","type","selectOption"].includes(h)){let p=r.params.selector,S=r.params.text||r.params.value||"",s=[],u=null,f=null,d=null,R=p.match(/aria-ref=([a-z0-9]+)/i);if(R&&r.snapshotName){let n=R[1],y=o.get(r.snapshotName);if(y&&y.has(n)){let g=y.get(n);u=g.name||null,f=g.role||null,d=g.label||null,console.log(`[TraceParser] \u2705 Found ACTUAL element data: text="${u}", role="${f}"`)}}let x=p.match(/internal:text="([^"]+)"/i),A=p.match(/internal:label="([^"]+)"/i),F=p.match(/internal:placeholder="([^"]+)"/i),C=p.match(/internal:role=([^ ]+)/i),$=p.match(/internal:describe="([^"]+)"/i),L=p.match(/name="([^"]+)"/i);if(x){s.push({type:"text",text:x[1]});let n=x[1].split(" ");n.length>1&&(s.push({type:"text",text:n[0],fuzzy:!0}),s.push({type:"text",text:n[n.length-1],fuzzy:!0}))}if(A&&s.push({type:"label",label:A[1]}),F&&s.push({type:"placeholder",placeholder:F[1]}),u){s.unshift({type:"text",text:u,source:"accessibility-tree"});let n=u.split(" ");n.length>1&&s.push({type:"text",text:n[0],fuzzy:!0,source:"accessibility-tree"})}if(f||C){let n=f||C[1],y=u||(L?L[1]:x?x[1]:null);s.unshift({type:"role",role:n,name:y,source:u?"accessibility-tree":"selector"})}if(d&&s.unshift({type:"label",label:d,source:"accessibility-tree"}),$){let n=$[1],y=["link","button","textbox","menuitem","submenu","combobox","checkbox","radio","tab","treeitem","menu item"],g=null,T=n;for(let b of y)if(n.toLowerCase().endsWith(` ${b}`)){g=b.replace(" ",""),T=n.substring(0,n.length-b.length-1);break}if(g){s.push({type:"role",role:g,name:T});let b=T.replace(/\s*\([^)]+\)\s*$/,"");s.push({type:"text",text:b}),s.push({type:"text",text:T});let v=T.split(" ");v.length>1&&(s.push({type:"text",text:v[0],fuzzy:!0}),s.push({type:"text",text:v.slice(0,2).join(" "),fuzzy:!0}))}else{let b=n.replace(/\s*\([^)]+\)\s*$/,"");s.push({type:"text",text:b}),s.push({type:"text",text:n})}}let _=this.extractDOMStrategies(p,l,x?.[1]||$?.[1],r.pageId);s.push(..._);let w=this.extractStructuralContext(p);(w.parent||w.sibling)&&s.forEach(n=>{["role","text","label","testid"].includes(n.type)&&(w.parent&&(n.parent=w.parent),w.sibling&&(n.sibling=w.sibling))}),s.push({type:"css",value:p});let j=u||x?x[1]:$?$[1].replace(/\s*\([^)]+\)\s*$/,""):`Action ${e.length}`;e.push({method:h,name:j,action:h==="type"?"fill":h,value:S,strategies:s,timestamp:r.startTime,actualText:u,actualRole:f,actualAriaLabel:d})}}}catch{}return e}catch(a){throw new Error(`Failed to parse trace: ${a.message}`,{cause:a})}}static extractDOMStrategies(t,c,a,i){let e=[];if(!c||c.size===0||!a)return e;try{let o=c.get(i);if(!o)return e;let l=a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),m=new RegExp(`data-testid=["']([^"']+)["'][^>]*>[^<]*${l}`,"i"),r=o.match(m);r&&e.push({type:"testid",value:r[1],priority:"high"});let h=new RegExp(`class=["']([^"']+)["'][^>]*>[^<]*${l}`,"gi"),p=o.matchAll(h);for(let u of p){let f=u[1].split(/\s+/).filter(d=>d&&!d.match(/^(css|jss|makeStyles|MuiBox|MuiStack)-\w+/)&&d.length>2);f.length>0&&(e.push({type:"class",value:f.join("."),priority:"medium"}),f.length===1&&e.push({type:"class",value:f[0],priority:"medium"}))}let S=new RegExp(`id=["']([^"']+)["'][^>]*>[^<]*${l}`,"i"),s=o.match(S);s&&!s[1].match(/^(root|app|\d+|[a-f0-9-]{20,})$/i)&&e.push({type:"id",value:s[1],priority:"high"})}catch(o){console.warn(`[TraceParser] DOM extraction failed: ${o.message}`)}return e}static extractStructuralContext(t){let c={parent:null,sibling:null},a=t.split(">>").map(o=>o.trim());if(a.length>1){let l=a[a.length-2].replace(/internal:text="[^"]+"\s*/gi,"").replace(/internal:role=\S+\s*/gi,"").replace(/internal:label="[^"]+"\s*/gi,"").trim();l&&(l.match(/^(form|section|nav|header|aside|main|article)\b/)||l.includes("[")||l.match(/[#.]\w/))&&(c.parent=l)}let e=a[a.length-1].match(/([^+~]+)\s*[+~]\s*(.+)/);return e&&(c.sibling=e[1].trim()),c}};import{existsSync as Z}from"fs";import{join as O}from"path";var P=class extends M{constructor(t={}){super(t),this.priority=190,this.traceData=null}getName(){return"TraceText"}getPriority(){return this.priority}async loadTrace(t){if(this.traceData)return;let c=O(t,"traces"),a=O(t,"trace.zip");if(Z(a))try{this.traceData=await E.parseTraceZip(a),console.log(`[TraceTextEnricher] \u2705 Loaded trace with ${this.traceData.length} actions`)}catch(i){console.log(`[TraceTextEnricher] \u26A0\uFE0F Failed to parse trace: ${i.message}`)}}async enrich(t,c){let a=t.data?.params?.ref,i=t.id;if(a===void 0&&i===void 0||(!this.traceData&&c.sessionPath&&await this.loadTrace(c.sessionPath),!this.traceData))return null;let e=this.traceData[i];if(!e)return console.log(`[TraceTextEnricher] \u26A0\uFE0F No trace action for event ${i}`),null;let o=e.actualText||this._extractTextFromSelector(e.selector),l=e.actualRole,m=e.actualAriaLabel;return o||l||m?(console.log(`[TraceTextEnricher] \u2705 Event ${i}: text="${o}", role="${l}", label="${m}"`),{traceActualText:o,traceActualRole:l,traceActualAriaLabel:m,traceSelector:e.selector,traceStrategies:e.strategies}):null}_extractTextFromSelector(t){if(!t)return null;let c=t.match(/internal:label="([^"]+)"/);if(c)return c[1];let a=t.match(/internal:text="([^"]+)"/);if(a)return a[1];let i=t.match(/getByText\(['"]([^'"]+)['"]\)/);if(i)return i[1];let e=t.match(/name:\s*['"]([^'"]+)['"]/);return e?e[1]:null}};export{P as TraceTextEnricher};
1
+ var M=class{constructor(t={}){this.config=t,this.enabled=t.enabled!==!1,this.priority=t.priority||50}getName(){throw new Error("EventEnricher.getName() must be implemented")}canEnrich(t){return this.enabled}async enrich(t,c){throw new Error("EventEnricher.enrich() must be implemented")}handleError(t,c){return console.warn(`[${this.getName()}] Enrichment failed for event ${c.type}:`,t.message),null}};import{readFileSync as B,existsSync as k,readdirSync as D}from"node:fs";import{join as z}from"node:path";import{execSync as W}from"node:child_process";import{tmpdir as I}from"node:os";var E=class{static async parseTraceZip(t){let c;if(t.endsWith(".zip")&&k(t)){let a=z(I(),`trace-${Date.now()}`);W(`unzip -q "${t}" -d "${a}"`,{stdio:"pipe"});let e=D(a).find(o=>o.endsWith(".trace"));if(!e)throw new Error("No .trace file found in zip");c=z(a,e)}else if(k(t)){let i=D(t).find(e=>e.endsWith(".trace"));if(!i)throw new Error("No .trace file found");c=z(t,i)}else throw new Error(`Trace not found at ${t}`);try{let i=B(c,"utf-8").trim().split(`
2
+ `),e=[],o=new Map,l=new Map;for(let m of i)try{let r=JSON.parse(m);if(r.type==="snapshot"&&r.snapshot&&r.snapshot.accessibility){let h=new Map;for(let p of r.snapshot.accessibility)p.ref&&h.set(p.ref,p);o.set(r.snapshotName,h)}if(r.type==="frame-snapshot"&&r.snapshot){let h=Buffer.from(r.snapshot.html||"","base64").toString("utf-8");h&&h.length>100&&l.set(r.pageId||"default",h)}}catch{}for(let m of i)try{let r=JSON.parse(m);if(r.type==="before"&&r.params&&r.params.selector){let h=r.method;if(["click","fill","type","selectOption"].includes(h)){let p=r.params.selector,S=r.params.text||r.params.value||"",s=[],u=null,f=null,d=null,R=p.match(/aria-ref=([a-z0-9]+)/i);if(R&&r.snapshotName){let n=R[1],y=o.get(r.snapshotName);if(y&&y.has(n)){let g=y.get(n);u=g.name||null,f=g.role||null,d=g.label||null,console.log(`[TraceParser] \u2705 Found ACTUAL element data: text="${u}", role="${f}"`)}}let x=p.match(/internal:text="([^"]+)"/i),A=p.match(/internal:label="([^"]+)"/i),F=p.match(/internal:placeholder="([^"]+)"/i),C=p.match(/internal:role=([^ ]+)/i),$=p.match(/internal:describe="([^"]+)"/i),L=p.match(/name="([^"]+)"/i);if(x){s.push({type:"text",text:x[1]});let n=x[1].split(" ");n.length>1&&(s.push({type:"text",text:n[0],fuzzy:!0}),s.push({type:"text",text:n[n.length-1],fuzzy:!0}))}if(A&&s.push({type:"label",label:A[1]}),F&&s.push({type:"placeholder",placeholder:F[1]}),u){s.unshift({type:"text",text:u,source:"accessibility-tree"});let n=u.split(" ");n.length>1&&s.push({type:"text",text:n[0],fuzzy:!0,source:"accessibility-tree"})}if(f||C){let n=f||C[1],y=u||(L?L[1]:x?x[1]:null);s.unshift({type:"role",role:n,name:y,source:u?"accessibility-tree":"selector"})}if(d&&s.unshift({type:"label",label:d,source:"accessibility-tree"}),$){let n=$[1],y=["link","button","textbox","menuitem","submenu","combobox","checkbox","radio","tab","treeitem","menu item"],g=null,T=n;for(let b of y)if(n.toLowerCase().endsWith(` ${b}`)){g=b.replace(" ",""),T=n.substring(0,n.length-b.length-1);break}if(g){s.push({type:"role",role:g,name:T});let b=T.replace(/\s*\([^)]+\)\s*$/,"");s.push({type:"text",text:b}),s.push({type:"text",text:T});let v=T.split(" ");v.length>1&&(s.push({type:"text",text:v[0],fuzzy:!0}),s.push({type:"text",text:v.slice(0,2).join(" "),fuzzy:!0}))}else{let b=n.replace(/\s*\([^)]+\)\s*$/,"");s.push({type:"text",text:b}),s.push({type:"text",text:n})}}let _=this.extractDOMStrategies(p,l,x?.[1]||$?.[1],r.pageId);s.push(..._);let w=this.extractStructuralContext(p);(w.parent||w.sibling)&&s.forEach(n=>{["role","text","label","testid"].includes(n.type)&&(w.parent&&(n.parent=w.parent),w.sibling&&(n.sibling=w.sibling))}),s.push({type:"css",value:p});let j=u||x?x[1]:$?$[1].replace(/\s*\([^)]+\)\s*$/,""):`Action ${e.length}`;e.push({method:h,name:j,action:h==="type"?"fill":h,value:S,strategies:s,timestamp:r.startTime,actualText:u,actualRole:f,actualAriaLabel:d})}}}catch{}return e}catch(a){throw new Error(`Failed to parse trace: ${a.message}`,{cause:a})}}static extractDOMStrategies(t,c,a,i){let e=[];if(!c||c.size===0||!a)return e;try{let o=c.get(i);if(!o)return e;let l=a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),m=new RegExp(`data-testid=["']([^"']+)["'][^>]*>[^<]*${l}`,"i"),r=o.match(m);r&&e.push({type:"testid",value:r[1],priority:"high"});let h=new RegExp(`class=["']([^"']+)["'][^>]*>[^<]*${l}`,"gi"),p=o.matchAll(h);for(let u of p){let f=u[1].split(/\s+/).filter(d=>d&&!d.match(/^(css|jss|makeStyles|MuiBox|MuiStack)-\w+/)&&d.length>2);f.length>0&&(e.push({type:"class",value:f.join("."),priority:"medium"}),f.length===1&&e.push({type:"class",value:f[0],priority:"medium"}))}let S=new RegExp(`id=["']([^"']+)["'][^>]*>[^<]*${l}`,"i"),s=o.match(S);s&&!s[1].match(/^(root|app|\d+|[a-f0-9-]{20,})$/i)&&e.push({type:"id",value:s[1],priority:"high"})}catch(o){console.warn(`[TraceParser] DOM extraction failed: ${o.message}`)}return e}static extractStructuralContext(t){let c={parent:null,sibling:null},a=t.split(">>").map(o=>o.trim());if(a.length>1){let l=a[a.length-2].replace(/internal:text="[^"]+"\s*/gi,"").replace(/internal:role=\S+\s*/gi,"").replace(/internal:label="[^"]+"\s*/gi,"").trim();l&&(l.match(/^(form|section|nav|header|aside|main|article)\b/)||l.includes("[")||l.match(/[#.]\w/))&&(c.parent=l)}let e=a[a.length-1].match(/([^+~]+)\s*[+~]\s*(.+)/);return e&&(c.sibling=e[1].trim()),c}};import{existsSync as Z}from"node:fs";import{join as O}from"node:path";var P=class extends M{constructor(t={}){super(t),this.priority=190,this.traceData=null}getName(){return"TraceText"}getPriority(){return this.priority}async loadTrace(t){if(this.traceData)return;let c=O(t,"traces"),a=O(t,"trace.zip");if(Z(a))try{this.traceData=await E.parseTraceZip(a),console.log(`[TraceTextEnricher] \u2705 Loaded trace with ${this.traceData.length} actions`)}catch(i){console.log(`[TraceTextEnricher] \u26A0\uFE0F Failed to parse trace: ${i.message}`)}}async enrich(t,c){let a=t.data?.params?.ref,i=t.id;if(a===void 0&&i===void 0||(!this.traceData&&c.sessionPath&&await this.loadTrace(c.sessionPath),!this.traceData))return null;let e=this.traceData[i];if(!e)return console.log(`[TraceTextEnricher] \u26A0\uFE0F No trace action for event ${i}`),null;let o=e.actualText||this._extractTextFromSelector(e.selector),l=e.actualRole,m=e.actualAriaLabel;return o||l||m?(console.log(`[TraceTextEnricher] \u2705 Event ${i}: text="${o}", role="${l}", label="${m}"`),{traceActualText:o,traceActualRole:l,traceActualAriaLabel:m,traceSelector:e.selector,traceStrategies:e.strategies}):null}_extractTextFromSelector(t){if(!t)return null;let c=t.match(/internal:label="([^"]+)"/);if(c)return c[1];let a=t.match(/internal:text="([^"]+)"/);if(a)return a[1];let i=t.match(/getByText\(['"]([^'"]+)['"]\)/);if(i)return i[1];let e=t.match(/name:\s*['"]([^'"]+)['"]/);return e?e[1]:null}};export{P as TraceTextEnricher};