diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fd6e5572..dc19599f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,18 +2,19 @@ name: TeleDOM CI Pipeline on: push: - branches: [ main ] + branches: [ master, main, 'fix/**', 'feature/**' ] pull_request: - branches: [ main ] + branches: [ master, main ] + workflow_dispatch: jobs: build-and-test: - name: Build & Test (Node ${{ matrix.node-version }} on ${{ matrix.os }}) + name: Node ${{ matrix.node-version }} (${{ matrix.os }}) runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, windows-latest] - node-version: [18.x, 20.x, 22.x] + node-version: [20.x, 22.x] steps: - name: Checkout Repository @@ -32,6 +33,50 @@ jobs: - name: Run Unit Tests run: npm run test:unit + env: + NODE_OPTIONS: "--experimental-require-module" - name: Run Operational Test Suite run: npm run test:operational + env: + NODE_OPTIONS: "--experimental-require-module" + + python-sdk: + name: Python ${{ matrix.python-version }} (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest] + python-version: ["3.10", "3.11", "3.12"] + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Setup Node.js (for bridge server in operational tests) + uses: actions/setup-node@v4 + with: + node-version: 20.x + + - name: Install Node Dependencies & Build Server + run: | + npm install + npm run build + + - name: Setup Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install Python QA Tools + run: python -m pip install ruff mypy + + - name: Lint Python SDK (Ruff) + run: python -m ruff check sdk/python + + - name: Typecheck Python SDK (Mypy) + run: python -m mypy sdk/python + + - name: Run Python SDK Tests + run: python sdk/python/test_sdk.py + diff --git a/README.md b/README.md index 8401b771..f2afc491 100644 --- a/README.md +++ b/README.md @@ -1,138 +1,363 @@ -# ⚡ TeleDOM v4.1 +
+
+# TeleDOM v4.1
+
+**Temporal Browser Intelligence Engine + Agent-Owned Workflow Runtime**
+
+*350 Certified MCP Tools • Sub-Millisecond Time-Travel DOM • Manifest V3 Chrome Extension • Zero-Dependency Python SDK*
+
+[](package.json)
+[](LICENSE)
+[](https://www.typescriptlang.org/)
+[](./sdk/python/)
+[](https://developer.chrome.com/docs/extensions/mv3/)
+[](./docs/TOOLS_CATALOG_350_EN.md)
+[](#running-tests--quality-verification)
+[](#token-efficient-operating-profiles)
+
+
+
+# تلهدام نسخه ۴.۱ (TeleDOM v4.1)
+
+**موتور هوش زمانی مرورگر + محیط اجرای اتوماسیون با مالکیت عامل**
+
+*۳۵۰ ابزار اعتبارسنجیشده MCP • بازسازی زمانمحور DOM زیر میلیثانیه • افزونه کروم MV3 • پکیج پایتون بدون وابستگی*
+
+[](package.json)
+[](LICENSE)
+[](https://www.typescriptlang.org/)
+[](./sdk/python/)
+[](https://developer.chrome.com/docs/extensions/mv3/)
+[](./docs/TOOLS_CATALOG_350_FA.md)
+[](#اجرای-تستها-و-تضمین-کیفیت)
+[](#پروفایلهای-بهینه-مصرف-توکن)
+
+=q||w.top>=A),_=!O&&C!=="none"&&N!=="hidden"&&I>0&&M,P={disabled:i.disabled??e.hasAttribute("disabled"),readOnly:i.readOnly??e.hasAttribute("readonly"),checked:i.checked,selected:i.selected,focused:s.activeElement===e,isShadowHost:!!e.shadowRoot,hasShadowRoot:!!e.shadowRoot},H=[];let $=e.parentElement;for(;$&&$.tagName&&$.tagName.toLowerCase()!=="html";)H.push(this.computeBestSelector($)),$=$.parentElement;const F={count:e.children?e.children.length:0,tags:e.children?Array.from(e.children).slice(0,10).map(G=>G.tagName.toLowerCase()):[]};let W;if(t){const G=t.getId(e);W={logicalNodeId:G??null,creationSequence:null,lastMutationSequence:null,eventCount:0,isRecorded:G!=null}}return{tag:r,id:e.id||void 0,classes:o,role:h||void 0,ariaAttributes:Object.keys(d).length>0?d:void 0,text:v.slice(0,200),normalizedText:m.slice(0,200),value:g,type:b.type||void 0,selector:a,bestSelector:a,selectorCandidates:c,bounds:w,visibility:{isVisible:_,display:C,visibility:N,opacity:I,pointerEvents:R,isClipped:O,isInViewport:M,zIndex:x},computedStyle:E?{display:C,visibility:N,opacity:String(I),position:E.position,zIndex:String(x),pointerEvents:R,overflow:E.overflow,boxSizing:E.boxSizing,color:E.color,backgroundColor:E.backgroundColor,fontSize:E.fontSize}:{},attributes:u,state:P,context:{parentChain:H,parentSelector:H[0]||void 0,childrenSummary:F,containingBlock:(E==null?void 0:E.position)==="fixed"?"viewport":H[0]||void 0,iframe:null,shadowRoot:e.shadowRoot?"open":null},forensics:W}}static inspectVisualState(e){var b,T;const t=e.ownerDocument||document,s=t.defaultView||(typeof window<"u"?window:{}),n=e.getBoundingClientRect?e.getBoundingClientRect():{x:0,y:0,width:0,height:0,top:0,right:0,bottom:0,left:0},i=s.getComputedStyle?s.getComputedStyle(e):null,r=s.innerWidth||((b=t.documentElement)==null?void 0:b.clientWidth)||1920,o=s.innerHeight||((T=t.documentElement)==null?void 0:T.clientHeight)||1080,a=s.scrollX||s.pageXOffset||0,c=s.scrollY||s.pageYOffset||0,u=s.devicePixelRatio||1,d=(i==null?void 0:i.display)||"block",h=(i==null?void 0:i.visibility)||"visible",p=i&&parseFloat(i.opacity)||1,y=n.right>0&&n.bottom>0&&n.left=r||n.top>=o;let g=null;if(t.elementFromPoint&&y&&!v&&d!=="none"){const w=Math.max(0,Math.min(r-1,n.left+n.width/2)),E=Math.max(0,Math.min(o-1,n.top+n.height/2));try{const C=t.elementFromPoint(w,E);C&&C!==e&&!e.contains(C)&&!C.contains(e)&&(g=this.computeBestSelector(C))}catch{}}return{selector:this.computeBestSelector(e),bounds:{x:n.x??n.left??0,y:n.y??n.top??0,width:n.width??0,height:n.height??0,top:n.top??0,right:n.right??0,bottom:n.bottom??0,left:n.left??0},viewport:{scrollX:a,scrollY:c,width:r,height:o,devicePixelRatio:u},layout:{display:d,position:(i==null?void 0:i.position)||"static",zIndex:(i==null?void 0:i.zIndex)||"auto",opacity:p,visibility:h,overflow:(i==null?void 0:i.overflow)||"visible",boxSizing:(i==null?void 0:i.boxSizing)||"content-box",pointerEvents:(i==null?void 0:i.pointerEvents)||"auto"},occlusion:{isInViewport:y,isClipped:v||m,isZeroDimension:v,isTransparent:p===0,isDisplayNone:d==="none",isVisibilityHidden:h==="hidden",isOffscreen:m,occludedBy:g},computedStyleSummary:i?{display:d,position:i.position,zIndex:i.zIndex,opacity:String(p),visibility:h,pointerEvents:i.pointerEvents}:{}}}static generateSelectorCandidates(e){const t=e.ownerDocument||document,s=e.tagName?e.tagName.toLowerCase():"element",n=[];if(e.id&&/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(e.id)){const c=`#${e.id}`;try{t.querySelectorAll&&t.querySelectorAll(c).length===1&&n.push(c)}catch{n.push(c)}}const i=["data-testid","data-test","data-id","data-qa","data-cy","aria-label","name"];for(const c of i){const u=e.getAttribute(c);if(u&&/^[a-zA-Z0-9_-]+$/.test(u)){const d=`${s}[${c}="${u}"]`;try{t.querySelectorAll&&t.querySelectorAll(d).length===1&&n.push(d)}catch{n.push(d)}}}const r=this.extractClasses(e).filter(c=>/^[a-zA-Z0-9_-]+$/.test(c)&&!c.startsWith("ng-")&&!c.startsWith("_ng"));if(r.length>0){const c=`${s}.${r.slice(0,3).join(".")}`;try{t.querySelectorAll&&t.querySelectorAll(c).length===1&&n.push(c)}catch{n.push(c)}}if(e.parentElement&&e.parentElement.children){const c=Array.from(e.parentElement.children).filter(u=>u.tagName&&u.tagName.toLowerCase()===s);if(c.length>1){const u=c.indexOf(e)+1;if(u>0){const d=this.computeBestSelector(e.parentElement);n.push(`${d} > ${s}:nth-of-type(${u})`)}}}const o=r.length>0?`${s}.${r[0]}`:s;return n.push(o),{bestSelector:n[0]||s,candidates:n}}static computeBestSelector(e){return this.generateSelectorCandidates(e).bestSelector}static extractClasses(e){return e.classList&&typeof e.classList.forEach=="function"?Array.from(e.classList):typeof e.className=="string"?e.className.split(/\s+/).filter(Boolean):e.className&&typeof e.className.baseVal=="string"?e.className.baseVal.split(/\s+/).filter(Boolean):[]}static inferImplicitRole(e){switch(e.tagName?e.tagName.toLowerCase():""){case"a":return e.hasAttribute("href")?"link":void 0;case"button":return"button";case"input":{const s=e.type||"text";return s==="button"||s==="submit"||s==="reset"?"button":s==="checkbox"?"checkbox":s==="radio"?"radio":"textbox"}case"select":return"combobox";case"textarea":return"textbox";case"nav":return"navigation";case"header":return"banner";case"footer":return"contentinfo";case"main":return"main";case"article":return"article";case"section":return"region";default:return}}}f(L,"privacyEngine",new se);class De{constructor(e){f(this,"registry");f(this,"lastSelectedElementRef");f(this,"timingHook",null);f(this,"lastTrajectory",[]);this.registry=e}setLastSelectedElement(e){this.lastSelectedElementRef=e}setTimingHook(e){this.timingHook=e}getLastTrajectory(){return this.lastTrajectory}async timing(e){this.timingHook&&await this.timingHook(e)}resolveTarget(e,t=document){if(e.selectedElementRef&&this.lastSelectedElementRef&&t.contains(this.lastSelectedElementRef))return this.lastSelectedElementRef;if(typeof e.nodeId=="number"&&this.registry){const s=this.registry.getNode(e.nodeId);if(s&&s instanceof Element&&t.contains(s))return s}if(e.selector)try{const s=t.querySelectorAll(e.selector);if(s.length>1){for(let n=0;n {r+=T.length});try{d.observe(t.body||t.documentElement,{childList:!0,attributes:!0,characterData:!0,subtree:!0})}catch{}const h=T=>{o.push(T.message||"Runtime Error")};typeof window<"u"&&window.addEventListener("error",h);try{await this.dispatchAction(n,e)}finally{typeof window<"u"&&window.removeEventListener("error",h)}let p=!0;if((b=e.options)!=null&&b.waitForStabilization){const T=e.options.stabilizationTimeoutMs||300;await new Promise(w=>setTimeout(w,Math.min(2e3,T)))}d.disconnect();let y;t.contains(n)&&(y=L.inspectElement(n,this.registry));const v=Date.now()-s,m=a!=null&&a.__FORENSIC_CONSOLE_BUFFER__?a.__FORENSIC_CONSOLE_BUFFER__.slice(c).filter(T=>(T==null?void 0:T.level)==="error").length:0,g=a!=null&&a.__FORENSIC_NETWORK_BUFFER__?a.__FORENSIC_NETWORK_BUFFER__.slice(u).length:0;return{success:!0,action:e.action,target:y||i,beforeState:i,afterState:y,effects:{domMutations:r,consoleErrors:m,networkRequests:g,runtimeErrors:o},durationMs:v,stabilized:p}}async dispatchAction(e,t){var n,i,r,o,a,c;const s=e;switch(t.action){case"click":{this.scrollIntoViewIfNeeded(e),await this.timing("move"),await this.timing("click"),this.dispatchMouseEvent(e,"pointerdown"),this.dispatchMouseEvent(e,"mousedown"),typeof s.focus=="function"&&s.focus(),this.dispatchMouseEvent(e,"pointerup"),this.dispatchMouseEvent(e,"mouseup"),typeof s.click=="function"?s.click():this.dispatchMouseEvent(e,"click");break}case"double_click":{this.scrollIntoViewIfNeeded(e),await this.timing("click"),this.dispatchMouseEvent(e,"click"),await this.timing("click"),this.dispatchMouseEvent(e,"click"),this.dispatchMouseEvent(e,"dblclick");break}case"right_click":{this.scrollIntoViewIfNeeded(e),await this.timing("click"),this.dispatchMouseEvent(e,"pointerdown",{button:2}),this.dispatchMouseEvent(e,"mousedown",{button:2}),this.dispatchMouseEvent(e,"contextmenu",{button:2});break}case"hover":{await this.timing("move"),this.dispatchMouseEvent(e,"pointerenter"),this.dispatchMouseEvent(e,"mouseenter"),this.dispatchMouseEvent(e,"mouseover"),await this.timing("move"),this.dispatchMouseEvent(e,"mousemove");break}case"focus":{typeof s.focus=="function"&&s.focus(),e.dispatchEvent(new FocusEvent("focus",{bubbles:!0}));break}case"blur":{typeof s.blur=="function"&&s.blur(),e.dispatchEvent(new FocusEvent("blur",{bubbles:!0}));break}case"type":{const u=t.text||"",d=e,h=((n=e.ownerDocument)==null?void 0:n.defaultView)||(typeof window<"u"?window:null);typeof s.focus=="function"&&s.focus();for(const y of u){await this.timing("type");const v=g=>{try{const T=(h==null?void 0:h.KeyboardEvent)||(typeof KeyboardEvent<"u"?KeyboardEvent:null);if(T)return new T(g,{key:y,bubbles:!0})}catch{}const b=(h==null?void 0:h.CustomEvent)||(h==null?void 0:h.Event)||CustomEvent;return new b(g,{bubbles:!0,cancelable:!0})},m=(g,b)=>{try{const w=(h==null?void 0:h.InputEvent)||(typeof InputEvent<"u"?InputEvent:null);if(w)return new w(g,b)}catch{}const T=(h==null?void 0:h.CustomEvent)||(h==null?void 0:h.Event)||CustomEvent;return new T(g,{bubbles:!0,cancelable:!0})};e.dispatchEvent(v("keydown")),e.dispatchEvent(v("keypress")),"value"in d&&(d.value=(d.value||"")+y),e.dispatchEvent(m("input",{data:y,inputType:"insertText",bubbles:!0})),e.dispatchEvent(v("keyup"))}const p=(h==null?void 0:h.Event)||Event;e.dispatchEvent(new p("change",{bubbles:!0}));break}case"clear":{const u=e,d=((i=e.ownerDocument)==null?void 0:i.defaultView)||(typeof window<"u"?window:null);if("value"in u){u.value="";const h=(y,v)=>{try{const g=(d==null?void 0:d.InputEvent)||(typeof InputEvent<"u"?InputEvent:null);if(g)return new g(y,v)}catch{}const m=(d==null?void 0:d.CustomEvent)||(d==null?void 0:d.Event)||CustomEvent;return new m(y,{bubbles:!0,cancelable:!0})};e.dispatchEvent(h("input",{inputType:"deleteContentBackward",bubbles:!0}));const p=(d==null?void 0:d.Event)||Event;e.dispatchEvent(new p("change",{bubbles:!0}))}break}case"press_key":{const u=t.key||"Enter",d=((r=e.ownerDocument)==null?void 0:r.defaultView)||(typeof window<"u"?window:null),h=p=>{try{const v=(d==null?void 0:d.KeyboardEvent)||(typeof KeyboardEvent<"u"?KeyboardEvent:null);if(v)return new v(p,{key:u,bubbles:!0})}catch{}const y=(d==null?void 0:d.CustomEvent)||(d==null?void 0:d.Event)||CustomEvent;return new y(p,{bubbles:!0,cancelable:!0})};e.dispatchEvent(h("keydown")),e.dispatchEvent(h("keypress")),e.dispatchEvent(h("keyup"));break}case"select_option":{const u=e;((o=u.tagName)==null?void 0:o.toLowerCase())==="select"&&t.optionValue&&(u.value=t.optionValue,e.dispatchEvent(new Event("change",{bubbles:!0})));break}case"scroll_into_view":{this.scrollIntoViewIfNeeded(e,!0);break}case"scroll":{const u=((a=t.scrollDelta)==null?void 0:a.x)||0,d=((c=t.scrollDelta)==null?void 0:c.y)||0;typeof e.scrollBy=="function"&&e.scrollBy(u,d);break}default:throw new Error(`Unsupported interaction action: ${t.action}`)}}scrollIntoViewIfNeeded(e,t=!1){if(typeof e.scrollIntoView=="function")try{e.scrollIntoView({behavior:"auto",block:"center",inline:"center"})}catch{e.scrollIntoView(t)}}dispatchMouseEvent(e,t,s={}){const n=e.getBoundingClientRect?e.getBoundingClientRect():{left:0,top:0,width:0,height:0},i=n.left+n.width/2,r=n.top+n.height/2,o=new MouseEvent(t,{bubbles:s.bubbles!==void 0?s.bubbles:!0,cancelable:s.cancelable!==void 0?s.cancelable:!0,clientX:i,clientY:r,button:s.button||0,buttons:s.button===2?2:1});e.dispatchEvent(o)}}class ae{static matches(e,t){if(!e||e.nodeType!==U.ELEMENT_NODE)return!1;const s=t.trim();return s?s.includes(",")?s.split(",").some(n=>this.matchesSimple(e,n.trim())):this.matchesCompound(e,s):!1}static querySelector(e,t,s){const n=this.querySelectorAll(e,t,s,1);return n.length>0?n[0]:null}static querySelectorAll(e,t,s,n=1/0){const i=[],r=s[t];if(!r)return i;const o=[...r.children||[]],a=new Set;for(;o.length>0&&i.length =n))break;u.children&&u.children.length>0&&o.push(...u.children)}}return i}static getElementById(e,t){for(const s of Object.values(t))if(s.nodeType===U.ELEMENT_NODE&&!s.isDetached&&s.attributes&&s.attributes.id===e&&this.isNodeConnected(s,t))return s;return null}static isNodeConnected(e,t){if(e.isDetached)return!1;let s=e;const n=new Set;for(;s&&s.parentId;){if(n.has(s.id))return!1;n.add(s.id);const i=t[s.parentId];if(!i||i.isDetached)return!1;s=i}return!0}static computeSelector(e,t){var r,o;if(!e)return"";if(e.nodeType!==U.ELEMENT_NODE)return e.tagName||`#node-${e.id}`;if((r=e.attributes)!=null&&r.id)return`#${e.attributes.id}`;const s=e.tagName||"div",n=(((o=e.attributes)==null?void 0:o.class)||"").split(/\s+/).filter(a=>a&&!a.startsWith("ng-")).slice(0,2),i=n.length>0?"."+n.join("."):"";if(e.parentId&&t[e.parentId]){const c=(t[e.parentId].children||[]).map(u=>t[u]).filter(u=>u&&u.nodeType===U.ELEMENT_NODE&&u.tagName===s);if(c.length>1){const u=c.findIndex(d=>d.id===e.id)+1;return`${s}${i}:nth-of-type(${u})`}}return`${s}${i}`}static matchesCompound(e,t){return this.matchesSimple(e,t)}static matchesSimple(e,t){var i,r,o,a,c,u,d;const s=((i=e.tagName)==null?void 0:i.toLowerCase())||"";if(t==="*")return!0;if(t.startsWith("#")){const h=t.substring(1);return((r=e.attributes)==null?void 0:r.id)===h}if(t.startsWith(".")){const h=t.substring(1);return(((o=e.attributes)==null?void 0:o.class)||"").split(/\s+/).includes(h)}if(t.startsWith("[")&&t.endsWith("]")){const h=t.substring(1,t.length-1);if(h.includes("=")){const[p,y]=h.split("="),v=y.replace(/^["']|["']$/g,"");return((a=e.attributes)==null?void 0:a[p.trim()])===v}return!!((c=e.attributes)!=null&&c[h.trim()])}const n=t.match(/^([a-zA-Z0-9_-]+)(.*)$/);if(n){const h=n[1].toLowerCase(),p=n[2];if(h!==s&&h!=="*")return!1;if(!p)return!0;if(p.startsWith("#"))return((u=e.attributes)==null?void 0:u.id)===p.substring(1);if(p.startsWith("."))return(((d=e.attributes)==null?void 0:d.class)||"").split(/\s+/).includes(p.substring(1));if(p.startsWith("["))return this.matchesSimple(e,p)}return!1}}class $e{static traceElement(e,t,s){var x,q;const n=[...t].sort((A,S)=>A.sequence-S.sequence);let i=e.nodeId,r="unknown",o=e.selector||"",a={},c=0,u=0,d="init";if(!i&&e.selector&&s){const A=ae.querySelector(e.selector,s.rootId,s.nodes);A&&(i=A.id,r=A.tagName||"element",a={...A.attributes||{}},o=e.selector)}if(!i&&e.selector){for(const A of n)if(A.type==="DOM_MUTATION_ADD"){const S=A.payload;if(S.node&&ae.matches(S.node,e.selector)){i=S.node.id,r=S.node.tagName||"element",a={...S.node.attributes||{}},c=A.timestamp,u=A.sequence,d=A.id;break}}}if(!i)return null;const h=[];let p=!0,y=null,v=null,m,g=0;if(s&&s.nodes[i]){const A=s.nodes[i];r=A.tagName||r,a={...A.attributes||{}},o||(o=ae.computeSelector(A,s.nodes)),h.push({timestamp:s.timestamp,sequence:s.sequence,wallClockTime:Date.now(),stage:"CREATED",eventId:s.snapshotId,eventType:"DOM_SNAPSHOT",description:`Element <${r}> existed in initial baseline snapshot [ID: ${i}]`,details:{initialParentId:A.parentId,attributes:a},nodeSnapshot:A})}const b=new Map;if(s)for(const[A,S]of Object.entries(s.nodes))b.set(Number(A),S.parentId??null);const T=(A,S)=>{let M=b.get(S);const O=new Set;for(;M&&!O.has(M);){if(M===A)return!0;O.add(M),M=b.get(M)}return!1};for(const A of n){const S=A.timestamp,M=A.sequence,O=A.wallClockTime;if(A.type==="DOM_MUTATION_ADD"){const _=A.payload;(x=_.node)!=null&&x.id&&b.set(_.node.id,_.parentId??null),((q=_.node)==null?void 0:q.id)===i&&(p=!0,r=_.node.tagName||r,c=S,u=M,d=A.id,a={..._.node.attributes||{}},h.push({timestamp:S,sequence:M,wallClockTime:O,stage:"ATTACHED_TO_DOM",eventId:A.id,eventType:A.type,description:`Element <${r}> added to DOM under parent ID ${_.parentId}`,details:{parentId:_.parentId,index:_.index},nodeSnapshot:_.node}))}if(A.type==="DOM_MUTATION_REMOVE"){const _=A.payload;_.nodeId===i?(p=!1,y=S,v=M,m=A.id,h.push({timestamp:S,sequence:M,wallClockTime:O,stage:"REMOVED_FROM_DOM",eventId:A.id,eventType:A.type,description:`Element <${r}> explicitly removed from parent ID ${_.parentId}`,details:{parentId:_.parentId,removedIndex:_.index}})):T(_.nodeId,i)&&(p=!1,y=S,v=M,m=A.id,h.push({timestamp:S,sequence:M,wallClockTime:O,stage:"PARENT_SUBTREE_REPLACED",eventId:A.id,eventType:A.type,description:`Ancestor element [ID: ${_.nodeId}] was removed, causing target element [ID: ${i}] to detach from DOM`,details:{removedAncestorId:_.nodeId,parentId:_.parentId}}))}if(A.type==="DOM_MUTATION_MOVE"){const _=A.payload;_.nodeId&&b.set(_.nodeId,_.newParentId??null),_.nodeId===i&&(g++,h.push({timestamp:S,sequence:M,wallClockTime:O,stage:"REPARENTED",eventId:A.id,eventType:A.type,description:`Element reparented from parent ${_.oldParentId} to ${_.newParentId}`,details:{oldParentId:_.oldParentId,newParentId:_.newParentId}}))}if(A.type==="DOM_MUTATION_ATTR"){const _=A.payload;if(_.nodeId===i){g++;const P=_.attributeName.toLowerCase();let H="ATTRIBUTE_MODIFIED";P==="class"&&(H="CLASS_MODIFIED"),P==="style"&&(H="STYLE_MODIFIED"),h.push({timestamp:S,sequence:M,wallClockTime:O,stage:H,eventId:A.id,eventType:A.type,description:`Attribute '${_.attributeName}' changed from '${_.oldValue??""}' to '${_.newValue??""}'`,details:{attributeName:_.attributeName,oldValue:_.oldValue,newValue:_.newValue}})}}if(A.type==="DOM_MUTATION_TEXT"){const _=A.payload;_.nodeId===i&&(g++,h.push({timestamp:S,sequence:M,wallClockTime:O,stage:"TEXT_MODIFIED",eventId:A.id,eventType:A.type,description:`Text content changed: "${_.oldText}" → "${_.newText}"`,details:{oldText:_.oldText,newText:_.newText}}))}}const w=y??c,E=500,C=n.filter(A=>(A.category==="ERROR"||A.category==="CONSOLE")&&Math.abs(A.timestamp-w)<=E),N=n.filter(A=>A.category==="NETWORK"&&Math.abs(A.timestamp-w)<=E),I=n.length>0?n[n.length-1].timestamp:c,R=Math.max(0,(y??I)-c);return{targetNodeId:i,tagName:r,selectorHint:o,initialAttributes:a,createdAt:c,createdSequence:u,createdEventId:d,removedAt:y,removedSequence:v,removedEventId:m,isCurrentlyAlive:p,lifespanMs:Math.round(R*100)/100,mutationCount:g,entries:h,correlatedDiagnostics:C,correlatedNetwork:N}}}class qe{static analyze(e,t,s){var R,x,q,A;const n=typeof e=="number"?{nodeId:e}:{selector:e},i=$e.traceElement(n,t,s);if(!i)return{targetQuery:e,found:!1,disappearanceMechanism:"UNKNOWN",likelyRootCause:"Target element could not be found in recording baseline or event stream",confidenceScore:0,detailedExplanation:`No element matching "${e}" was ever created, recorded in the initial DOM snapshot, or observed in mutation events.`,evidentiaryTrail:[],precedingEvents:[],followingEvents:[],correlatedErrors:[],correlatedNetworkCalls:[],alternativeHypotheses:[{hypothesis:"Element was injected into an unmonitored isolated iframe or ShadowRoot closed mode",likelihood:40,evidenceFor:["Element query yielded zero matches in monitored document"],evidenceAgainst:["Iframes/ShadowRoots were accessible in this session"]},{hypothesis:"Selector typo or timing mismatch",likelihood:60,evidenceFor:["Target selector did not match any recorded tag or class"],evidenceAgainst:[]}]};const r=[...t].sort((S,M)=>S.sequence-M.sequence),o=[],a=[];let c="UNKNOWN",u="Unknown disappearance mechanism",d=50,h="",p=i.removedAt??void 0;const y=i.entries.find(S=>S.stage==="REMOVED_FROM_DOM"),v=i.entries.find(S=>S.stage==="PARENT_SUBTREE_REPLACED"),m=i.entries.find(S=>S.stage==="CLASS_MODIFIED"&&/\b(hidden|hide|d-none|invisible|collapsed)\b/i.test(String(S.details.newValue||""))),g=i.entries.find(S=>S.stage==="STYLE_MODIFIED"&&/display\s*:\s*none|visibility\s*:\s*hidden|opacity\s*:\s*0/i.test(String(S.details.newValue||"")));y?(c="DIRECT_NODE_REMOVAL",p=y.timestamp,u=`Element [ID: ${i.targetNodeId}] <${i.tagName}> was directly removed from its parent [ID: ${y.details.parentId}] via DOM removeChild/replaceChild`,d=95,o.push({timestamp:y.timestamp,sequence:y.sequence,eventId:y.eventId,eventType:y.eventType,evidenceType:"DIRECT",description:`Direct DOM removal mutation: element detached from parent ID ${y.details.parentId}`,confidenceContribution:50})):v?(c="PARENT_SUBTREE_REPLACED",p=v.timestamp,u=`Host framework (e.g. React/Vue re-render) destroyed and replaced Ancestor container [ID: ${v.details.removedAncestorId}], causing injected element to be unmounted`,d=92,o.push({timestamp:v.timestamp,sequence:v.sequence,eventId:v.eventId,eventType:v.eventType,evidenceType:"DIRECT",description:`Ancestor container [ID: ${v.details.removedAncestorId}] was removed, wiping out all child subtrees`,confidenceContribution:50})):g?(c="STYLE_DISPLAY_NONE",p=g.timestamp,u=`Element was visually hidden by an inline style modification: "${g.details.newValue}"`,d=88,o.push({timestamp:g.timestamp,sequence:g.sequence,eventId:g.eventId,eventType:g.eventType,evidenceType:"DIRECT",description:`Inline style changed to "${g.details.newValue}"`,confidenceContribution:45})):m?(c="CLASS_TRIGGERED_HIDDEN",p=m.timestamp,u=`Element was visually hidden because its CSS class list was modified to include "${m.details.newValue}"`,d=85,o.push({timestamp:m.timestamp,sequence:m.sequence,eventId:m.eventId,eventType:m.eventType,evidenceType:"DIRECT",description:`Class list changed from "${m.details.oldValue??""}" to "${m.details.newValue??""}"`,confidenceContribution:45})):i.isCurrentlyAlive&&(c="UNKNOWN",u=`Element [ID: ${i.targetNodeId}] is currently alive and attached to the DOM tree (no unmount mutation detected)`,d=70,h="The element exists in the current DOM state. If it is not visible on screen, it may be clipped by viewport boundaries, z-index stacking context, or 0x0 pixel dimensions.");const b=p??i.createdAt,T=500,w=r.filter(S=>S.timestamp>=b-T&&S.timestampS.timestamp>b&&S.timestamp<=b+T),C=w.filter(S=>S.category==="ERROR");if(C.length>0){const S=C[0],M=((R=S.payload)==null?void 0:R.message)||"Unknown runtime error";o.push({timestamp:S.timestamp,sequence:S.sequence,eventId:S.id,eventType:S.type,evidenceType:"PRECEDING",description:`Runtime error occurred ${(b-S.timestamp).toFixed(1)}ms before disappearance: "${M}"`,confidenceContribution:20,rawEvent:S}),u+=` (preceded by runtime error: "${M}")`}const N=w.filter(S=>S.type==="NETWORK_RESPONSE_COMPLETE"||S.type==="NETWORK_REQUEST_FAILED");if(N.length>0){const S=N[0],M=((x=S.payload)==null?void 0:x.url)||"network request";o.push({timestamp:S.timestamp,sequence:S.sequence,eventId:S.id,eventType:S.type,evidenceType:"PRECEDING",description:`Network response completed ${(b-S.timestamp).toFixed(1)}ms before disappearance: ${M}`,confidenceContribution:15,rawEvent:S})}const I=w.filter(S=>S.category==="NAVIGATION");if(I.length>0){const S=I[0];o.push({timestamp:S.timestamp,sequence:S.sequence,eventId:S.id,eventType:S.type,evidenceType:"PRECEDING",description:`Navigation event (${(q=S.payload)==null?void 0:q.navigationType}) occurred ${(b-S.timestamp).toFixed(1)}ms before disappearance`,confidenceContribution:25,rawEvent:S}),u+=` following SPA navigation to "${(A=S.payload)==null?void 0:A.url}"`}return h||(h=[`Element <${i.tagName}> (Logical ID: ${i.targetNodeId}, selector: "${i.selectorHint}") was created at ${i.createdAt.toFixed(1)}ms.`,`It remained alive in the DOM for ${i.lifespanMs.toFixed(1)}ms and experienced ${i.mutationCount} mutations.`,`At timestamp ${b.toFixed(1)}ms, it disappeared via [${c}].`,`Diagnosis: ${u}.`].join(" ")),c==="PARENT_SUBTREE_REPLACED"?(a.push({hypothesis:"Direct cleanup called by extension code",likelihood:25,evidenceFor:["Element was unmounted shortly after creation"],evidenceAgainst:["Ancestor container mutation was recorded from host page context"]}),a.push({hypothesis:"Host single-page app route change destroyed component tree",likelihood:35,evidenceFor:I.length>0?["Preceding navigation event recorded"]:[],evidenceAgainst:I.length===0?["No navigation events occurred in temporal window"]:[]})):c==="DIRECT_NODE_REMOVAL"&&a.push({hypothesis:"Third-party script or ad-blocker removed the injected node",likelihood:30,evidenceFor:["Direct node removal occurred without ancestor replacement"],evidenceAgainst:["No ad-blocker signatures or extension error logs observed"]}),{targetQuery:e,targetNodeId:i.targetNodeId,found:!0,tagName:i.tagName,selectorHint:i.selectorHint,createdAt:i.createdAt,firstVisibleAt:i.createdAt,lastKnownGoodStateAt:Math.max(0,b-1),disappearedAt:p,lifespanMs:i.lifespanMs,disappearanceMechanism:c,likelyRootCause:u,confidenceScore:Math.min(99,d),detailedExplanation:h,evidentiaryTrail:o,precedingEvents:w,followingEvents:E,correlatedErrors:C,correlatedNetworkCalls:N,alternativeHypotheses:a}}}class Pe{constructor(e){f(this,"activeObservation",null);f(this,"registry");f(this,"sequenceCounter");this.registry=e,this.sequenceCounter=new oe}isObserving(){return this.activeObservation!==null}startObservation(e,t=document){this.activeObservation&&this.stopObservation(t);const s=`obs_${Date.now()}_${Math.random().toString(36).slice(2,6)}`,n=Date.now(),i=L.inspectElement(e,this.registry),r=i.bestSelector,o=[],a=this.registry?this.registry.getOrCreateId(e,0):100;o.push({id:`evt_init_${s}`,sessionId:s,timestamp:0,sequence:1,wallClockTime:n,type:"DOM_MUTATION_ADD",category:"DOM",source:"BROWSER_RUNTIME",targetNodeId:a,targetSelector:r,payload:{node:{id:a,nodeType:1,tagName:i.tag,attributes:i.attributes,textContent:i.text,children:[],parentId:null},parentId:null,index:0}});const c=new MutationObserver(u=>{const d=Date.now()-n;for(const h of u)if(h.type==="childList"){for(let p=0;p 0&&(m=qe.analyze(n,a)),{observationId:t,targetSelector:n,targetNodeId:((g=r.forensics)==null?void 0:g.logicalNodeId)||void 0,startTime:i,endTime:u,durationMs:d,initialState:r,finalState:p,disappeared:y,disappearanceReason:v,mutations:a.filter(b=>b.category==="DOM"),diagnostics:a.filter(b=>b.category==="ERROR"||b.category==="CONSOLE"),networkEvents:a.filter(b=>b.category==="NETWORK"),screenshots:c,correlationReport:m}}}class Ue{constructor(e={}){f(this,"isExplicitModeActive",!1);f(this,"isGlobalShortcutActive",!1);f(this,"highlighterEl",null);f(this,"badgeEl",null);f(this,"lastSelectedElement",null);f(this,"options",{});f(this,"onMouseMoveBound");f(this,"onClickBound");f(this,"onKeyDownBound");f(this,"onGlobalClickBound");this.options=e,this.onMouseMoveBound=this.handleMouseMove.bind(this),this.onClickBound=this.handleClick.bind(this),this.onKeyDownBound=this.handleKeyDown.bind(this),this.onGlobalClickBound=this.handleGlobalCtrlShiftClick.bind(this),this.initGlobalShortcutListener()}initGlobalShortcutListener(){typeof window>"u"||this.isGlobalShortcutActive||(window.addEventListener("click",this.onGlobalClickBound,!0),this.isGlobalShortcutActive=!0)}startPicker(e){typeof document>"u"||(e&&(this.options={...this.options,...e}),!this.isExplicitModeActive&&(this.isExplicitModeActive=!0,this.ensureHighlighter(),document.body&&(document.body.style.cursor="crosshair"),window.addEventListener("mousemove",this.onMouseMoveBound,!0),window.addEventListener("click",this.onClickBound,!0),window.addEventListener("keydown",this.onKeyDownBound,!0)))}stopPicker(){this.isExplicitModeActive&&(this.isExplicitModeActive=!1,typeof document<"u"&&document.body&&(document.body.style.cursor="default"),this.removeHighlighter(),typeof window<"u"&&(window.removeEventListener("mousemove",this.onMouseMoveBound,!0),window.removeEventListener("click",this.onClickBound,!0),window.removeEventListener("keydown",this.onKeyDownBound,!0)))}getLastSelectedElement(){return this.lastSelectedElement}setSelectedElement(e){let t;return"tag"in e&&"bestSelector"in e&&typeof e.getAttribute!="function"?t=e:(t=L.inspectElement(e,this.options.nodeRegistry),this.flashSelection(e)),this.lastSelectedElement=t,this.options.onSelected&&this.options.onSelected(t),t}handleGlobalCtrlShiftClick(e){if(!e.ctrlKey||!e.shiftKey)return;const t=e.target;if(!t||this.isExtensionOwned(t))return;e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation();const s=this.setSelectedElement(t);this.notifyExtension(s)}handleMouseMove(e){if(!this.isExplicitModeActive)return;const t=e.target;if(!t||this.isExtensionOwned(t)){this.hideHighlighter();return}this.updateHighlighter(t)}handleClick(e){if(!this.isExplicitModeActive)return;const t=e.target;if(!t||this.isExtensionOwned(t))return;e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation();const s=this.setSelectedElement(t);this.notifyExtension(s),this.stopPicker()}handleKeyDown(e){e.key==="Escape"&&this.isExplicitModeActive&&(e.preventDefault(),this.stopPicker(),this.options.onCanceled&&this.options.onCanceled())}isExtensionOwned(e){return!!(e.id==="forensic-recorder-floating-host"||e.id==="forensic-inspect-highlighter"||e.closest("#forensic-recorder-floating-host")||e.closest("#forensic-inspect-highlighter")||e.hasAttribute("data-forensic-internal")||e.closest("[data-forensic-internal]"))}ensureHighlighter(){if(typeof document>"u"||this.highlighterEl)return;const e=this.options.highlightColor||"#0ea5e9",t=document.createElement("div");t.id="forensic-inspect-highlighter",t.setAttribute("data-forensic-internal","true"),t.style.position="fixed",t.style.pointerEvents="none",t.style.zIndex="2147483640",t.style.border=`2px solid ${e}`,t.style.background="rgba(14, 165, 233, 0.18)",t.style.borderRadius="3px",t.style.boxShadow=`0 0 12px ${e}88`,t.style.transition="all 0.05s ease-out",t.style.display="none";const s=document.createElement("div");s.setAttribute("data-forensic-internal","true"),s.style.position="absolute",s.style.bottom="100%",s.style.left="0",s.style.transform="translateY(-4px)",s.style.background="#0f172a",s.style.color="#38bdf8",s.style.fontSize="11px",s.style.fontFamily="monospace",s.style.fontWeight="bold",s.style.padding="2px 6px",s.style.borderRadius="3px",s.style.boxShadow="0 2px 6px rgba(0,0,0,0.5)",s.style.whiteSpace="nowrap",s.style.pointerEvents="none",t.appendChild(s),document.body.appendChild(t),this.highlighterEl=t,this.badgeEl=s}updateHighlighter(e){if(this.ensureHighlighter(),!this.highlighterEl||!this.badgeEl)return;const t=e.getBoundingClientRect();this.highlighterEl.style.display="block",this.highlighterEl.style.left=`${t.left}px`,this.highlighterEl.style.top=`${t.top}px`,this.highlighterEl.style.width=`${Math.max(1,t.width)}px`,this.highlighterEl.style.height=`${Math.max(1,t.height)}px`;const s=e.tagName.toLowerCase(),n=e.id?`#${e.id}`:"",i=e.className&&typeof e.className=="string"?"."+e.className.split(/\s+/)[0]:"",r=`${Math.round(t.width)}×${Math.round(t.height)}`;this.badgeEl.textContent=`<${s}${n}${i}> [${r}]`}hideHighlighter(){this.highlighterEl&&(this.highlighterEl.style.display="none")}removeHighlighter(){this.highlighterEl&&this.highlighterEl.parentElement&&this.highlighterEl.remove(),this.highlighterEl=null,this.badgeEl=null}flashSelection(e){if(typeof document>"u"||!e.getBoundingClientRect)return;const t=e.getBoundingClientRect(),s=document.createElement("div");s.setAttribute("data-forensic-internal","true"),s.style.position="fixed",s.style.left=`${t.left}px`,s.style.top=`${t.top}px`,s.style.width=`${Math.max(1,t.width)}px`,s.style.height=`${Math.max(1,t.height)}px`,s.style.border="2px solid #22c55e",s.style.background="rgba(34, 197, 94, 0.25)",s.style.zIndex="2147483645",s.style.pointerEvents="none",s.style.transition="opacity 0.6s ease-out",document.body.appendChild(s),setTimeout(()=>{s.style.opacity="0",setTimeout(()=>s.remove(),600)},400)}notifyExtension(e){var t;try{typeof chrome<"u"&&((t=chrome.runtime)!=null&&t.sendMessage)&&chrome.runtime.sendMessage({type:"ELEMENT_SELECTED",elementInfo:e,timestamp:Date.now()})}catch{}}destroy(){this.stopPicker(),typeof window<"u"&&window.removeEventListener("click",this.onGlobalClickBound,!0),this.isGlobalShortcutActive=!1}}class fe{static getCrcTable(){if(this.crcTable)return this.crcTable;const e=new Uint32Array(256);for(let t=0;t<256;t++){let s=t;for(let n=0;n<8;n++)s=s&1?3988292384^s>>>1:s>>>1;e[t]=s>>>0}return this.crcTable=e,e}static crc32(e,t=0,s=e.length){const n=this.getCrcTable();let i=4294967295;for(let r=t;r >>8^n[(i^e[r])&255];return(i^4294967295)>>>0}static adler32(e){let t=1,s=0;for(let n=0;n >>0}static createPNG(e){const t=Math.max(1,Math.min(1920,Math.floor(e.width))),s=Math.max(1,Math.min(1080,Math.floor(e.height))),n=e.backgroundColor||[15,23,42,255],i=e.headerColor||[56,189,248,255],r=e.borderColor||[99,102,241,255],o=1+t*4,a=new Uint8Array(o*s),c=Math.min(30,Math.floor(s*.2));for(let g=0;g =e.length,h=new Uint8Array(5+u);h[0]=d?1:0,h[1]=u&255,h[2]=u>>>8&255;const p=~u&65535;h[3]=p&255,h[4]=p>>>8&255,h.set(e.subarray(n,n+u),5),t.push(h),n+=u}const i=t.reduce((c,u)=>c+u.length,0)+2+4,r=new Uint8Array(i);let o=0;r[o++]=120,r[o++]=1;for(const c of t)r.set(c,o),o+=c.length;const a=this.adler32(e);return r[o++]=a>>>24&255,r[o++]=a>>>16&255,r[o++]=a>>>8&255,r[o++]=a&255,r}static writeChunk(e,t,s,n){const i=n.length,r=new DataView(e.buffer,e.byteOffset,e.byteLength);r.setUint32(t,i,!1),t+=4;const o=new Uint8Array(4+i);for(let c=0;c<4;c++){const u=s.charCodeAt(c);e[t+c]=u,o[c]=u}t+=4,i>0&&(e.set(n,t),o.set(n,4),t+=i);const a=this.crc32(o);return r.setUint32(t,a,!1),t+=4,t}}f(fe,"crcTable",null);const ne=500;class He{constructor(e,t){f(this,"history",[]);f(this,"undoStack",[]);f(this,"redoStack",[]);f(this,"counter",0);f(this,"transaction",null);this.doc=e,this.registry=t}mutate(e){var d;const t=`mut_${Date.now().toString(36)}_${++this.counter}`,s=Date.now();let n;try{n=this.resolveTarget(e.target)}catch(h){return this.failure(t,e,null,h.message,Date.now()-s)}const i=this.snapshotState(n);let r=null,o=null,a,c=!0;try{const h=this.applyOperation(t,e,n);h&&(this.transaction?this.transaction.undoRecords.push(h):(this.undoStack.push(h),this.redoStack=[]));const y=(n.isConnected!==void 0?n.isConnected:this.doc.contains(n))?n:this.doc.querySelector(i.selector)||n;r=this.snapshotState(y),o=this.quickDiff(i,r,n)}catch(h){c=!1,a=h.message,r=null}const u={mutationId:t,operation:e.operation,success:c,before:i,after:r,diff:o,affectedSelector:c?i.selector:null,durationMs:Date.now()-s,error:a,undoable:c&&(this.transaction?this.transaction.undoRecords.length>0:this.undoStack.length>0)};return this.transaction&&this.transaction.steps.push({stepId:`step_${this.transaction.steps.length+1}`,mutation:u}),this.pushHistory({mutationId:t,transactionId:(d=this.transaction)==null?void 0:d.id,timestamp:Date.now(),operation:e.operation,targetSelector:i.selector,success:c,summary:`${e.operation} on ${i.selector}${o?` (+${o.added}/-${o.removed}/~${o.changed})`:""}`,undoApplied:!1,redoApplied:!1}),u}beginTransaction(){if(this.transaction)throw new Error(`TRANSACTION_ALREADY_OPEN: ${this.transaction.id} — commit or rollback first.`);return this.transaction={id:`tx_${Date.now().toString(36)}_${++this.counter}`,steps:[],undoRecords:[]},this.transaction.id}commitTransaction(e){if(!this.transaction)throw new Error("NO_OPEN_TRANSACTION: begin a transaction before committing.");const t=this.transaction,s=Date.now();let n=!0,i;if(e)try{n=e({id:t.id,steps:t.steps})!==!1,n||(i="VERIFY_FAILED: caller verification rejected the transaction state.")}catch(o){n=!1,i=`VERIFY_ERROR: ${o.message}`}if(!n)return this.rollbackInternal(t,i||"VERIFY_FAILED",s);this.undoStack.push(...t.undoRecords),this.undoStack.length>ne&&this.undoStack.splice(0,this.undoStack.length-ne),this.redoStack=[];const r=this.summaryOf(t);return this.transaction=null,{transactionId:t.id,committed:!0,rolledBack:!1,steps:t.steps,durationMs:Date.now()-s,finalStateSummary:r}}rollbackTransaction(e){if(!this.transaction)throw new Error("NO_OPEN_TRANSACTION: begin a transaction before rolling back.");const t=this.transaction;return this.rollbackInternal(t,e||"ROLLBACK_REQUESTED",Date.now())}rollbackInternal(e,t,s){for(const i of[...e.undoRecords].reverse())try{this.applyUndo(i)}catch{}const n=this.summaryOf(e);return this.transaction=null,{transactionId:e.id,committed:!1,rolledBack:!0,steps:e.steps,error:t,durationMs:Date.now()-s,finalStateSummary:n}}undo(){const e=this.transaction?this.transaction.undoRecords:this.undoStack,t=e.pop();if(!t)return{success:!1,message:"Nothing to undo — the mutation history is empty."};try{this.applyUndo(t)}catch(s){return e.push(t),{success:!1,mutationId:t.mutationId,message:`UNDO_FAILED: ${s.message}`}}return this.redoStack.push(t),this.markHistory(t.mutationId,"undo"),{success:!0,mutationId:t.mutationId,message:`Undid ${t.operation} on ${t.targetSelector}.`}}redo(){const e=this.redoStack.pop();if(!e)return{success:!1,message:"Nothing to redo — no undone mutation is pending."};try{const t=this.resolveTarget({selector:e.targetSelector}),s={operation:e.operation,target:{selector:e.targetSelector}};return this.reapplyRecord(e,t,s)?((this.transaction?this.transaction.undoRecords:this.undoStack).push(e),this.markHistory(e.mutationId,"redo"),{success:!0,mutationId:e.mutationId,message:`Redid ${e.operation} on ${e.targetSelector}.`}):(this.redoStack.push(e),{success:!1,mutationId:e.mutationId,message:"REDO_FAILED: target state diverged — cannot safely reapply."})}catch(t){return this.redoStack.push(e),{success:!1,mutationId:e.mutationId,message:`REDO_FAILED: ${t.message}`}}}getHistory(e=100){return this.history.slice(-e)}getUndoDepth(){return this.transaction?this.transaction.undoRecords.length:this.undoStack.length}getRedoDepth(){return this.redoStack.length}getOpenTransactionId(){var e;return((e=this.transaction)==null?void 0:e.id)||null}preview(e){var t;try{const s=this.resolveTarget(e.target),n=[];let i=1;(e.operation==="set_inner_html"||e.operation==="set_outer_html")&&(n.push("HTML replacement can destroy descendant node identity — captured regions targeting children may become stale."),i=s.querySelectorAll("*").length+1),(e.operation==="remove_element"||e.operation==="unwrap_element")&&(n.push("Removal is destructive; the undo record preserves the full serialized subtree."),i=s.querySelectorAll("*").length+1),e.operation==="move_element"&&!e.parent&&n.push("No parent target supplied — move requires payload.parent."),e.operation==="wrap_element"&&!e.newElementHtml&&n.push("No wrapper HTML supplied — a neutralwrapper will be generated.");const r=Be(e,s);return{valid:n.filter(o=>o.includes("requires")||o.includes("No parent")).length===0,operation:e.operation,target:{selector:this.snapshotState(s).selector,tag:s.tagName.toLowerCase()},expectedChange:r,affectedNodes:i,warnings:n}}catch(s){return{valid:!1,operation:e.operation,target:{selector:String(((t=e.target)==null?void 0:t.selector)||""),tag:""},expectedChange:"—",affectedNodes:0,warnings:[],error:s.message}}}applyOperation(e,t,s){var r;const n=this.snapshotState(s).selector,i=t.operation;switch(i){case"set_attribute":{if(!t.attribute)throw new Error("ATTRIBUTE_REQUIRED: payload.attribute is missing.");const o=s.getAttribute(t.attribute);return s.setAttribute(t.attribute,t.value??""),this.undoFor(e,i,n,{kind:o===null?"remove-attribute":"restore-attribute",attribute:t.attribute,value:o})}case"remove_attribute":{if(!t.attribute)throw new Error("ATTRIBUTE_REQUIRED: payload.attribute is missing.");const o=s.getAttribute(t.attribute);if(o===null)throw new Error(`ATTRIBUTE_NOT_PRESENT: "${t.attribute}" is not set on ${n}.`);return s.removeAttribute(t.attribute),this.undoFor(e,i,n,{kind:"restore-attribute",attribute:t.attribute,value:o})}case"set_text":{const o=s.textContent||"";return s.textContent=t.text??"",this.undoFor(e,i,n,{kind:"restore-text",text:o})}case"replace_text":{if(!t.text||!t.replacement)throw new Error("TEXT_PATTERNS_REQUIRED: payload.text (search) and payload.replacement are required.");const o=s.textContent||"";return s.textContent=o.split(t.text).join(t.replacement),this.undoFor(e,i,n,{kind:"restore-text",text:o})}case"set_inner_html":{const o=s.innerHTML;return s.innerHTML=t.html??"",this.undoFor(e,i,n,{kind:"restore-outer-html",outerHtml:s.outerHTML.replace(t.html??"",o)||void 0,text:o,attribute:"__inner"})}case"set_outer_html":{const o=s.outerHTML,a=s.parentElement;if(!a)throw new Error("ORPHAN_ELEMENT: element has no parent — cannot replace outer HTML.");const c=this.doc.createComment(`mcpdom_undo_${e}`);s.replaceWith(c);const u=this.doc.createElement("template");u.innerHTML=t.html??"";const d=u.content.firstElementChild;return d?c.replaceWith(d):c.replaceWith(this.doc.createTextNode(t.html??"")),this.undoFor(e,i,n,{kind:"reinsert-node",outerHtml:o,parentSelector:this.snapshotState(a).selector,nextSiblingSelector:this.siblingSelector(d||s)})}case"add_class":{const o=Array.from(s.classList);for(const a of t.classes||[])s.classList.add(a);return this.undoFor(e,i,n,{kind:"restore-classes",classes:o})}case"remove_class":{const o=Array.from(s.classList);for(const a of t.classes||[])s.classList.remove(a);return this.undoFor(e,i,n,{kind:"restore-classes",classes:o})}case"replace_class":{const o=Array.from(s.classList);for(const a of t.classes||[])s.classList.remove(a);return t.value&&s.classList.add(t.value),this.undoFor(e,i,n,{kind:"restore-classes",classes:o})}case"set_style":{const o=this.doc.defaultView;if(!(o!=null&&o.getComputedStyle))throw new Error("STYLE_UNAVAILABLE: computed style API is unavailable in this context.");const a={};for(const c of Object.keys(t.style||{}))a[c]=o.getComputedStyle(s).getPropertyValue(c),s.style.setProperty(c,t.style[c]);return this.undoFor(e,i,n,{kind:"restore-style",style:a})}case"remove_style":{const o={};for(const a of t.classes||[])o[a]=s.style.getPropertyValue(a),s.style.removeProperty(a);return this.undoFor(e,i,n,{kind:"restore-style",style:o})}case"add_element":{const o=t.parent?this.resolveTarget(t.parent):s,a=this.doc.createElement("template");a.innerHTML=t.newElementHtml??"";const c=a.content.firstElementChild;if(!c)throw new Error("INVALID_HTML: payload.newElementHtml does not produce an element.");switch(t.position||"append"){case"before":s.before(c);break;case"after":s.after(c);break;case"prepend":o.prepend(c);break;default:o.appendChild(c)}return this.undoFor(e,i,n,{kind:"remove-node",attribute:this.snapshotState(c).selector})}case"remove_element":{const o=s.outerHTML,a=s.parentElement,c=s.nextElementSibling;return s.remove(),this.undoFor(e,i,n,{kind:"reinsert-node",outerHtml:o,parentSelector:a?this.snapshotState(a).selector:void 0,nextSiblingSelector:c?this.snapshotState(c).selector:null})}case"replace_element":{const o=s.outerHTML,a=s.parentElement,c=this.doc.createElement("template");c.innerHTML=t.newElementHtml??"";const u=c.content.firstElementChild;if(!u)throw new Error("INVALID_HTML: payload.newElementHtml does not produce an element.");const d=s.nextElementSibling;return s.replaceWith(u),this.undoFor(e,i,n,{kind:"reinsert-node",outerHtml:o,parentSelector:a?this.snapshotState(a).selector:void 0,nextSiblingSelector:d?this.snapshotState(d).selector:null})}case"move_element":{if(!t.parent)throw new Error("PARENT_REQUIRED: payload.parent is required for move_element.");const o=this.resolveTarget(t.parent),a=s.outerHTML,c=s.parentElement,u=s.nextElementSibling,d=t.position==="before"||t.position==="prepend"?o.firstElementChild:null;return o[t.position==="prepend"?"prepend":"appendChild"](s),this.undoFor(e,i,n,{kind:"restore-position",parentSelector:c?this.snapshotState(c).selector:void 0,nextSiblingSelector:u?this.snapshotState(u).selector:d?this.snapshotState(d).selector:null,outerHtml:a})}case"wrap_element":{const o=this.doc.createElement("template");o.innerHTML=t.newElementHtml||'';const a=o.content.firstElementChild;if(!a)throw new Error("INVALID_HTML: wrapper template produced no element.");const c=s.parentElement,u=s.nextElementSibling;return s.replaceWith(a),a.appendChild(s),this.undoFor(e,i,n,{kind:"restore-position",parentSelector:c?this.snapshotState(c).selector:void 0,nextSiblingSelector:u?this.snapshotState(u).selector:null})}case"unwrap_element":{const o=s.outerHTML,a=s.parentElement;if(!a)throw new Error("ORPHAN_ELEMENT: cannot unwrap a root-level element.");const c=s.nextElementSibling,u=Array.from(s.children);for(const d of u)a.insertBefore(d,s);return s.remove(),this.undoFor(e,i,n,{kind:"reinsert-node",outerHtml:o,parentSelector:this.snapshotState(a).selector,nextSiblingSelector:c?this.snapshotState(c).selector:null})}case"clone_subtree":{const o=t.parent?this.resolveTarget(t.parent):s.parentElement||s,a=s.cloneNode(!0);if(t.copyAttributes!==!1)for(const c of Array.from(a.attributes))c.name==="id"&&a.removeAttribute("id");return(r=o.appendChild)==null||r.call(o,a),this.undoFor(e,i,n,{kind:"remove-node",attribute:this.snapshotState(a).selector})}default:throw new Error(`UNKNOWN_OPERATION: ${i} is not a supported DOM mutation.`)}}applyUndo(e){const t=e.inverse;switch(t.kind){case"restore-outer-html":{const s=this.resolveTarget({selector:e.targetSelector});if(t.outerHtml!==void 0){const n=this.doc.createElement("template");n.innerHTML=t.outerHtml;const i=n.content.firstElementChild;i&&s.replaceWith(i)}else t.attribute==="__inner"&&(s.innerHTML=t.text||"");break}case"reinsert-node":{const s=t.parentSelector?this.resolveTarget({selector:t.parentSelector}):this.doc.body,n=this.doc.createElement("template");n.innerHTML=t.outerHtml||"";const i=n.content.firstElementChild;if(!i)throw new Error("UNDO_CORRUPT: serialized subtree could not be restored.");const r=t.nextSiblingSelector?this.safeResolve(t.nextSiblingSelector):null;s.insertBefore(i,r);break}case"remove-node":{const s=this.safeResolve(t.attribute||e.targetSelector);s&&s.remove();break}case"restore-attribute":{this.resolveTarget({selector:e.targetSelector}).setAttribute(t.attribute,t.value??"");break}case"remove-attribute":{this.resolveTarget({selector:e.targetSelector}).removeAttribute(t.attribute);break}case"restore-text":{const s=this.resolveTarget({selector:e.targetSelector});s.textContent=t.text||"";break}case"restore-classes":{const s=this.resolveTarget({selector:e.targetSelector});s.removeAttribute("class");for(const n of t.classes||[])s.classList.add(n);break}case"restore-style":{const s=this.resolveTarget({selector:e.targetSelector});s.style.removeProperty("all");for(const[n,i]of Object.entries(t.style||{}))s.style.setProperty(n,i);break}case"restore-position":{const s=this.doc.createElement("template");s.innerHTML=t.outerHtml||"";const n=s.content.firstElementChild;if(!n)throw new Error("UNDO_CORRUPT: serialized subtree could not be restored.");const i=this.safeResolve(e.targetSelector);i&&i.remove();const r=t.parentSelector?this.safeResolve(t.parentSelector):this.doc.body,o=t.nextSiblingSelector?this.safeResolve(t.nextSiblingSelector):null;(r||this.doc.body).insertBefore(n,o);break}}}reapplyRecord(e,t,s){var i;const n=e.inverse;switch(e.operation){case"set_attribute":return(n.kind==="restore-attribute"||n.kind==="remove-attribute")&&s.value!==void 0?(t.setAttribute(s.attribute||n.attribute||"",s.value),!0):!1;case"add_class":{for(const r of s.classes||[])t.classList.add(r);return(((i=s.classes)==null?void 0:i.length)||0)>0}case"remove_class":{for(const r of s.classes||n.classes||[])t.classList.remove(r);return!0}case"set_text":return s.text!==void 0?(t.textContent=s.text,!0):!1;case"set_inner_html":return s.html!==void 0?(t.innerHTML=s.html,!0):!1;default:return!1}}resolveTarget(e){if(!e)throw new Error("TARGET_REQUIRED: mutation requires a target.");if(typeof e=="string"&&(e={selector:e}),e.selector){try{const t=this.doc.querySelectorAll(e.selector);if(t.length===1)return t[0];if(t.length>1)return Array.from(t).find(n=>{try{return L.inspectElement(n).visibility.isVisible}catch{return!1}})||t[0]}catch(t){throw new Error(`TARGET_INVALID: ${t.message}`)}throw new Error(`TARGET_NOT_FOUND: selector "${e.selector}" matches no element.`)}if(e.xpath){try{const s=this.doc.evaluate(e.xpath,this.doc,null,9,null).singleNodeValue;if(s)return s}catch(t){throw new Error(`TARGET_INVALID_XPATH: ${t.message}`)}throw new Error("TARGET_NOT_FOUND: xpath matches no element.")}if(typeof e.nodeId=="number"&&this.registry){const t=this.registry.getNode(e.nodeId);if(t&&t.nodeType===1&&this.doc.contains(t))return t;throw new Error("TARGET_STALE: logical node id no longer resolves to an attached element.")}throw new Error("TARGET_INVALID: target has neither selector, xpath nor nodeId.")}safeResolve(e){try{return this.doc.querySelector(e)}catch{return null}}snapshotState(e){const t=L.inspectElement(e,this.registry),s=e.outerHTML.length>2e4?e.outerHTML.slice(0,2e4)+"…[truncated]":e.outerHTML;return{selector:t.bestSelector,outerHtml:s,attributes:this.attrsOf(e)}}attrsOf(e){const t={};for(const s of Array.from(e.attributes))t[s.name]=s.value.length>300?s.value.slice(0,300)+"…":s.value;return t}quickDiff(e,t,s){if(!t)return null;let n=0,i=0,r=0;const o=new Set(Object.keys(e.attributes)),a=new Set(Object.keys(t.attributes||{}));for(const u of o)a.has(u)||i++;for(const u of a)o.has(u)?e.attributes[u]!==t.attributes[u]&&r++:n++;e.outerHtml!==t.outerHtml&&n+i+r===0&&r++;const c=s.querySelectorAll?s.querySelectorAll("*").length:0;return{added:n,removed:i,changed:r,summary:`attributes +${n}/-${i}/~${r}; subtree nodes: ${c}`}}undoFor(e,t,s,n){return{mutationId:e,operation:t,targetSelector:s,inverse:n}}siblingSelector(e){try{return this.snapshotState(e).selector}catch{return null}}pushHistory(e){this.history.push(e),this.history.length>ne&&this.history.splice(0,this.history.length-ne)}markHistory(e,t){for(let s=this.history.length-1;s>=0;s--)if(this.history[s].mutationId===e){t==="undo"?this.history[s].undoApplied=!0:this.history[s].redoApplied=!0;return}}summaryOf(e){var n;const t=((n=this.doc.documentElement)==null?void 0:n.outerHTML.length)||0,s=e.steps.filter(i=>i.mutation.success).length;return{domLength:t,diffSummary:`${s}/${e.steps.length} mutations applied`}}failure(e,t,s,n,i){var r;return{mutationId:e,operation:t.operation,success:!1,before:s||{selector:String(((r=t.target)==null?void 0:r.selector)||"?"),outerHtml:"",attributes:{}},after:null,diff:null,affectedSelector:null,durationMs:i,error:n,undoable:!1}}}function Be(l,e){switch(l.operation){case"set_attribute":return`attribute "${l.attribute}" will be set to "${(l.value??"").slice(0,40)}"`;case"remove_attribute":return`attribute "${l.attribute}" will be removed`;case"set_text":return`text content will be replaced (${(l.text||"").length} chars)`;case"replace_text":return`every occurrence of "${l.text}" will become "${l.replacement}"`;case"set_inner_html":return`inner HTML will be replaced (${(l.html||"").length} chars)`;case"set_outer_html":return"element (and subtree) will be replaced with provided HTML";case"add_class":return`classes ${(l.classes||[]).join(", ")} will be added`;case"remove_class":return`classes ${(l.classes||[]).join(", ")} will be removed`;case"replace_class":return`classes ${(l.classes||[]).join(", ")} will be replaced with "${l.value}"`;case"set_style":return`inline styles ${Object.keys(l.style||{}).join(", ")} will be set`;case"remove_style":return`inline styles ${(l.classes||[]).join(", ")} will be removed`;case"add_element":return`a new element will be inserted ${l.position||"append"} the target`;case"remove_element":return"the element and its subtree will be removed";case"replace_element":return"the element will be replaced with new HTML";case"move_element":return"the element will be moved into the specified parent";case"wrap_element":return"the element will be wrapped in a new container";case"unwrap_element":return"children will be lifted out and the wrapper removed";case"clone_subtree":return"a deep clone of the subtree will be appended";default:return"unknown operation"}}class Fe{constructor(){f(this,"executionCounter",0)}async execute(e,t,s={}){const n=Math.min(Math.max(s.timeoutMs??5e3,100),3e4),i=`js_${Date.now().toString(36)}_${++this.executionCounter}`,r=e.defaultView;if(!r)return this.result(i,"BLOCKED_BY_CONTEXT",0,t,[],{name:"NoWindow",message:"The document has no associated window — execution context unavailable."});const o=e.documentElement?e.documentElement.outerHTML.length:0,a=[],c=this.hookConsole(r,a);let u="EXECUTED_SUCCESSFULLY",d,h,p=o,y=!1;const v=Date.now();try{const b=this.buildRunner(r,t),T=new Promise((w,E)=>{var N;const C=setTimeout(()=>{y=!0,E(new Error(`Script timed out after ${n}ms`))},n);(N=C==null?void 0:C.unref)==null||N.call(C)});d=await Promise.race([b,T])}catch(b){y?u="TIMED_OUT":u="EXECUTED_WITH_ERROR",h={name:(b==null?void 0:b.name)||"Error",message:(b==null?void 0:b.message)||String(b),stack:b!=null&&b.stack?String(b.stack).slice(0,2e3):void 0}}const m=Date.now()-v;p=e.documentElement?e.documentElement.outerHTML.length:0,c();const g=this.serialize(d);return u==="EXECUTED_SUCCESSFULLY"&&g.serializationFailed&&(u="SERIALIZATION_FAILED",h={name:"SerializationError",message:g.message||"Result could not be serialized."}),{status:u,executionId:i,durationMs:m,result:u==="EXECUTED_SUCCESSFULLY"?g.text:void 0,error:h,consoleOutput:a.slice(0,100),domChanged:o!==p,domLengthBefore:o,domLengthAfter:p,world:s.world||"ISOLATED",timeoutMs:n,codePreview:t.length>300?t.slice(0,300)+"…":t}}buildRunner(e,t){const s=`(async function() { +`))}catch{}const c={id:this.sequenceCounter.generateEventId("con",i),sessionId:this.sessionId,timestamp:s,sequence:i,wallClockTime:n,type:`RUNTIME_CONSOLE_${e.toUpperCase()}`,category:e==="error"?"ERROR":"CONSOLE",source:"PAGE",payload:{level:e,args:r,formattedMessage:o,stackTrace:a}};this.callback(c)}instrumentGlobalErrors(){if(typeof window>"u")return;const e=t=>{var o,a;const s=this.sequenceCounter.getRelativeTimestamp(),n=this.sequenceCounter.getWallClock(),i=this.sequenceCounter.nextSequence(),r={id:this.sequenceCounter.generateEventId("err",i),sessionId:this.sessionId,timestamp:s,sequence:i,wallClockTime:n,type:"RUNTIME_ERROR",category:"ERROR",source:"PAGE",payload:{message:t.message||"Unknown runtime error",filename:t.filename,lineno:t.lineno,colno:t.colno,stack:((o=t.error)==null?void 0:o.stack)||void 0,name:((a=t.error)==null?void 0:a.name)||"Error"}};this.callback(r)};window.addEventListener("error",e),this.cleanups.push(()=>window.removeEventListener("error",e))}instrumentUnhandledRejections(){if(typeof window>"u")return;const e=t=>{const s=this.sequenceCounter.getRelativeTimestamp(),n=this.sequenceCounter.getWallClock(),i=this.sequenceCounter.nextSequence();let r="Unhandled Promise Rejection",o;if(t.reason instanceof Error)r=t.reason.message,o=t.reason.stack;else if(typeof t.reason=="string")r=t.reason;else if(t.reason)try{r=JSON.stringify(t.reason)}catch{r=String(t.reason)}const a={id:this.sequenceCounter.generateEventId("rej",i),sessionId:this.sessionId,timestamp:s,sequence:i,wallClockTime:n,type:"RUNTIME_UNHANDLED_REJECTION",category:"ERROR",source:"PAGE",payload:{message:r,stack:o,isUnhandledRejection:!0}};this.callback(a)};window.addEventListener("unhandledrejection",e),this.cleanups.push(()=>window.removeEventListener("unhandledrejection",e))}}class Re{constructor(e,t,s,n=""){b(this,"privacy");b(this,"sequenceCounter");b(this,"callback");b(this,"sessionId");b(this,"isInstrumented",!1);b(this,"originalFetch",null);b(this,"originalXHROpen",null);b(this,"originalXHRSend",null);b(this,"cleanups",[]);this.privacy=e,this.sequenceCounter=t,this.callback=s,this.sessionId=n}setSessionId(e){this.sessionId=e}start(){this.isInstrumented||typeof window>"u"||(this.isInstrumented=!0,this.cleanups=[],this.instrumentFetch(),this.instrumentXHR())}stop(){this.cleanups.forEach(e=>{try{e()}catch{}}),this.cleanups=[],this.isInstrumented=!1}instrumentFetch(){if(typeof window.fetch!="function")return;this.originalFetch=window.fetch;const e=this;window.fetch=async function(...t){const s=e.sequenceCounter.generateEventId("req_f"),n=t[0],i=t[1];let r="";typeof n=="string"?r=n:n instanceof URL?r=n.toString():n&&typeof n=="object"&&"url"in n&&(r=n.url);const o=((i==null?void 0:i.method)||(typeof n=="object"&&"method"in n?n.method:"GET")).toUpperCase(),a=e.privacy.sanitizeUrl(r),c=e.sequenceCounter.getRelativeTimestamp(),u=e.sequenceCounter.getWallClock(),h=e.sequenceCounter.nextSequence(),g={id:s,sessionId:e.sessionId,timestamp:c,sequence:h,wallClockTime:u,type:"NETWORK_REQUEST_START",category:"NETWORK",source:"PAGE",payload:{requestId:s,url:a,method:o,resourceType:"fetch",hasBody:!!(i!=null&&i.body)}};e.callback(g);try{const p=await e.originalFetch.apply(this,t),y=e.sequenceCounter.getRelativeTimestamp(),v=e.sequenceCounter.getWallClock(),m=e.sequenceCounter.nextSequence(),d=Math.max(0,Math.round((y-c)*100)/100),f={id:e.sequenceCounter.generateEventId("res_f",m),sessionId:e.sessionId,timestamp:y,sequence:m,wallClockTime:v,type:"NETWORK_RESPONSE_COMPLETE",category:"NETWORK",source:"PAGE",causality:{triggeredBy:s,precededBy:s},payload:{requestId:s,url:a,method:o,status:p.status,statusText:p.statusText,durationMs:d}};return e.callback(f),p}catch(p){const y=e.sequenceCounter.getRelativeTimestamp(),v=e.sequenceCounter.getWallClock(),m=e.sequenceCounter.nextSequence(),d=Math.max(0,Math.round((y-c)*100)/100),f={id:e.sequenceCounter.generateEventId("res_err",m),sessionId:e.sessionId,timestamp:y,sequence:m,wallClockTime:v,type:"NETWORK_REQUEST_FAILED",category:"NETWORK",source:"PAGE",causality:{triggeredBy:s,precededBy:s},payload:{requestId:s,url:a,method:o,status:0,statusText:"Failed",durationMs:d,error:(p==null?void 0:p.message)||"Network request failed"}};throw e.callback(f),p}},this.cleanups.push(()=>{this.originalFetch&&(window.fetch=this.originalFetch)})}instrumentXHR(){if(typeof XMLHttpRequest>"u")return;this.originalXHROpen=XMLHttpRequest.prototype.open,this.originalXHRSend=XMLHttpRequest.prototype.send;const e=this;XMLHttpRequest.prototype.open=function(t,s,...n){return this._forensicRequestId=e.sequenceCounter.generateEventId("req_x"),this._forensicMethod=(t||"GET").toUpperCase(),this._forensicUrl=typeof s=="string"?s:s.toString(),e.originalXHROpen.apply(this,[t,s,...n])},XMLHttpRequest.prototype.send=function(t){const s=this._forensicRequestId||e.sequenceCounter.generateEventId("req_x"),n=this._forensicMethod||"GET",i=e.privacy.sanitizeUrl(this._forensicUrl||""),r=e.sequenceCounter.getRelativeTimestamp(),o=e.sequenceCounter.getWallClock(),a=e.sequenceCounter.nextSequence();this._forensicStartTime=r;const c={id:s,sessionId:e.sessionId,timestamp:r,sequence:a,wallClockTime:o,type:"NETWORK_REQUEST_START",category:"NETWORK",source:"PAGE",payload:{requestId:s,url:i,method:n,resourceType:"xhr",hasBody:!!t}};e.callback(c);const u=()=>{const h=e.sequenceCounter.getRelativeTimestamp(),g=e.sequenceCounter.getWallClock(),p=e.sequenceCounter.nextSequence(),y=Math.max(0,Math.round((h-(this._forensicStartTime||r))*100)/100),v={id:e.sequenceCounter.generateEventId("res_x",p),sessionId:e.sessionId,timestamp:h,sequence:p,wallClockTime:g,type:this.status>=200&&this.status<400?"NETWORK_RESPONSE_COMPLETE":"NETWORK_REQUEST_FAILED",category:"NETWORK",source:"PAGE",causality:{triggeredBy:s,precededBy:s},payload:{requestId:s,url:i,method:n,status:this.status,statusText:this.statusText,durationMs:y,error:this.status===0?"XHR Network Error or Aborted":void 0}};e.callback(v)};return this.addEventListener("load",u),this.addEventListener("error",u),this.addEventListener("abort",u),e.originalXHRSend.apply(this,[t])},this.cleanups.push(()=>{this.originalXHROpen&&(XMLHttpRequest.prototype.open=this.originalXHROpen),this.originalXHRSend&&(XMLHttpRequest.prototype.send=this.originalXHRSend)})}}class Oe{constructor(e={}){b(this,"sequenceCounter");b(this,"registry");b(this,"privacy");b(this,"snapshotEngine");b(this,"mutationObserver");b(this,"eventCollector");b(this,"diagnostics");b(this,"networkMonitor");b(this,"metadata");b(this,"isRecording",!1);b(this,"isPaused",!1);b(this,"eventListeners",new Set);b(this,"checkpointListeners",new Set);b(this,"lastCheckpointSequence",0);b(this,"lastCheckpointTimestamp",0);b(this,"checkpointTimer",null);b(this,"checkpointIntervalEvents",200);b(this,"checkpointIntervalMs",3e4);this.sequenceCounter=new ne,this.registry=new H,this.privacy=new J(e.privacy),this.snapshotEngine=new he(this.registry,this.privacy,this.sequenceCounter);const t=n=>this.handleEvent(n);this.mutationObserver=new Ne(this.registry,this.privacy,this.sequenceCounter,this.snapshotEngine,t),this.eventCollector=new ke(this.registry,this.privacy,this.sequenceCounter,t),this.diagnostics=new Me(this.privacy,this.sequenceCounter,t),this.networkMonitor=new Re(this.privacy,this.sequenceCounter,t),e.checkpointIntervalEvents&&(this.checkpointIntervalEvents=e.checkpointIntervalEvents),e.checkpointIntervalMs&&(this.checkpointIntervalMs=e.checkpointIntervalMs);const s=e.sessionId||`session_${Date.now()}_${Math.random().toString(36).substring(2,7)}`;this.metadata=this.createInitialMetadata(s,e.sessionName)}getSessionId(){return this.metadata.id}getMetadata(){return{...this.metadata,durationMs:this.sequenceCounter.getRelativeTimestamp(),endTime:this.metadata.endTime||Date.now()}}getRegistry(){return this.registry}onEvent(e){return this.eventListeners.add(e),()=>this.eventListeners.delete(e)}onCheckpoint(e){return this.checkpointListeners.add(e),()=>this.checkpointListeners.delete(e)}start(e=typeof document<"u"?document:{}){if(this.isRecording)throw new Error(`Recorder session ${this.metadata.id} is already active`);this.sequenceCounter.reset(),this.registry.reset(),this.isRecording=!0,this.isPaused=!1,this.metadata.status="recording",this.metadata.startTime=Date.now(),this.mutationObserver.setSessionId(this.metadata.id),this.eventCollector.setSessionId(this.metadata.id),this.diagnostics.setSessionId(this.metadata.id),this.networkMonitor.setSessionId(this.metadata.id);const t=this.snapshotEngine.captureSnapshot(e,this.metadata.id);this.metadata.stats.nodeCount=t.totalNodeCount;const s={id:this.sequenceCounter.generateEventId("snap_init",t.sequence),sessionId:this.metadata.id,timestamp:t.timestamp,sequence:t.sequence,wallClockTime:Date.now(),type:"DOM_SNAPSHOT",category:"DOM",source:"PAGE",payload:{snapshot:t}};return this.createCheckpoint(t,"INITIAL"),this.mutationObserver.start(e),this.eventCollector.start(),this.diagnostics.start(),this.networkMonitor.start(),this.handleEvent(s),this.checkpointIntervalMs>0&&typeof setInterval<"u"&&(this.checkpointTimer=setInterval(()=>{this.isRecording&&!this.isPaused&&this.captureCheckpoint("PERIODIC",e)},this.checkpointIntervalMs)),t}stop(){return this.isRecording?(this.mutationObserver.takeRecords(),this.mutationObserver.stop(),this.eventCollector.stop(),this.diagnostics.stop(),this.networkMonitor.stop(),this.checkpointTimer&&(clearInterval(this.checkpointTimer),this.checkpointTimer=null),this.isRecording=!1,this.metadata.status="stopped",this.metadata.endTime=Date.now(),this.metadata.durationMs=this.sequenceCounter.getRelativeTimestamp(),this.getMetadata()):this.getMetadata()}pause(){!this.isRecording||this.isPaused||(this.isPaused=!0,this.metadata.status="paused")}resume(){!this.isRecording||!this.isPaused||(this.isPaused=!1,this.metadata.status="recording")}captureCheckpoint(e="MANUAL",t=document){if(!this.isRecording)return null;const s=this.snapshotEngine.captureSnapshot(t,this.metadata.id);return this.createCheckpoint(s,e)}recordCustomEvent(e,t,s,n){const i=this.sequenceCounter.getRelativeTimestamp(),r=this.sequenceCounter.getWallClock(),o=this.sequenceCounter.nextSequence(),a={id:this.sequenceCounter.generateEventId("ext",o),sessionId:this.metadata.id,timestamp:i,sequence:o,wallClockTime:r,type:e,category:"EXTENSION",source:"CONTENT_SCRIPT",targetNodeId:s,targetSelector:n,payload:t};return this.handleEvent(a),a}recordScreenshot(e,t="MANUAL"){const s=this.sequenceCounter.getRelativeTimestamp(),n=this.sequenceCounter.getWallClock(),i=this.sequenceCounter.nextSequence(),r={id:this.sequenceCounter.generateEventId("scr",i),sessionId:this.metadata.id,timestamp:s,sequence:i,wallClockTime:n,type:"SCREENSHOT_CHECKPOINT",category:"SCREENSHOT",source:"BROWSER_RUNTIME",payload:{screenshotId:`shot_${i}`,dataUrl:e,viewport:{width:typeof window<"u"?window.innerWidth:1920,height:typeof window<"u"?window.innerHeight:1080,scrollX:typeof window<"u"?window.scrollX:0,scrollY:typeof window<"u"?window.scrollY:0,devicePixelRatio:typeof window<"u"?window.devicePixelRatio:1},triggerReason:t}};return this.handleEvent(r),r}addAnnotation(e,t,s="AGENT",n){const i=this.sequenceCounter.getRelativeTimestamp(),r=this.sequenceCounter.nextSequence(),o={id:`ann_${r}_${Math.random().toString(36).substring(2,6)}`,sessionId:this.metadata.id,timestamp:i,sequence:r,nodeId:n,author:s,label:e,comment:t,createdAt:Date.now()},a={id:o.id,sessionId:this.metadata.id,timestamp:i,sequence:r,wallClockTime:Date.now(),type:"ANNOTATION",category:"ANNOTATION",source:s==="USER"?"USER_INTERACTION":"BROWSER_RUNTIME",targetNodeId:n,payload:{annotation:o}};return this.handleEvent(a),o}createCheckpoint(e,t){const s=this.sequenceCounter.getSequence()-this.lastCheckpointSequence;this.lastCheckpointSequence=this.sequenceCounter.getSequence(),this.lastCheckpointTimestamp=e.timestamp,this.metadata.stats.checkpointCount+=1;const n={checkpointId:`chk_${e.sequence}_${Date.now()}`,sessionId:this.metadata.id,timestamp:e.timestamp,sequence:e.sequence,wallClockTime:Date.now(),snapshot:e,eventIndex:this.metadata.stats.eventCount,eventsSinceLastCheckpoint:s,trigger:t},i={id:n.checkpointId,sessionId:this.metadata.id,timestamp:e.timestamp,sequence:e.sequence,wallClockTime:n.wallClockTime,type:"CHECKPOINT",category:"CHECKPOINT",source:"BROWSER_RUNTIME",payload:{checkpointId:n.checkpointId,snapshot:e,eventsSinceLastCheckpoint:s,totalEventsSoFar:this.metadata.stats.eventCount}};return this.checkpointListeners.forEach(r=>{try{r(n)}catch(o){console.error("[ForensicRecorder] Checkpoint listener error:",o)}}),this.handleEvent(i),n}handleEvent(e){this.isPaused&&e.type!=="CHECKPOINT"&&e.type!=="ANNOTATION"||(this.metadata.stats.eventCount+=1,e.category==="DOM"&&(this.metadata.stats.mutationCount+=1),e.category==="ERROR"&&(this.metadata.stats.errorCount+=1),e.category==="CONSOLE"&&(this.metadata.stats.consoleCount+=1),e.category==="NETWORK"&&(this.metadata.stats.networkCount+=1),e.category==="SCREENSHOT"&&(this.metadata.stats.screenshotCount+=1),this.isRecording&&e.type!=="CHECKPOINT"&&e.type!=="DOM_SNAPSHOT"&&this.sequenceCounter.getSequence()-this.lastCheckpointSequence>=this.checkpointIntervalEvents&&typeof document<"u"&&this.captureCheckpoint("PERIODIC"),this.eventListeners.forEach(t=>{try{t(e)}catch(s){console.error("[ForensicRecorder] Event listener error:",s)}}))}createInitialMetadata(e,t){const s={domRecording:typeof MutationObserver<"u"?"HEALTHY":"UNAVAILABLE",userEvents:typeof window<"u"?"HEALTHY":"UNAVAILABLE",console:typeof console<"u"?"HEALTHY":"UNAVAILABLE",network:typeof window<"u"&&typeof window.fetch<"u"?"HEALTHY":"PARTIAL",screenshots:"HEALTHY",shadowDom:typeof Element<"u"&&"attachShadow"in Element.prototype?"HEALTHY":"RESTRICTED",iframes:"PARTIAL"},n={eventCount:0,mutationCount:0,errorCount:0,consoleCount:0,networkCount:0,checkpointCount:0,screenshotCount:0,nodeCount:0};return{id:e,name:t||`Recording ${new Date().toLocaleTimeString()}`,url:typeof window<"u"?window.location.href:"about:blank",origin:typeof window<"u"?window.location.origin:"",title:typeof document<"u"?document.title:"Forensic Session",userAgent:typeof navigator<"u"?navigator.userAgent:"Node.js/ForensicAgent",schemaVersion:"2.0.0",recorderVersion:"2.0.0",extensionVersion:"2.0.0",startTime:Date.now(),status:"recording",health:s,stats:n}}}class k{static inspectPage(e=document){var n,i,r,o,a,c,u,h,g,p,y,v,m,d;const t=e.defaultView||(typeof window<"u"?window:{}),s=e.activeElement;return{url:((n=t.location)==null?void 0:n.href)||((i=e.location)==null?void 0:i.href)||"",title:e.title||"",origin:((r=t.location)==null?void 0:r.origin)||"",viewport:{width:t.innerWidth||((o=e.documentElement)==null?void 0:o.clientWidth)||1920,height:t.innerHeight||((a=e.documentElement)==null?void 0:a.clientHeight)||1080,scrollX:t.scrollX||t.pageXOffset||((c=e.documentElement)==null?void 0:c.scrollLeft)||0,scrollY:t.scrollY||t.pageYOffset||((u=e.documentElement)==null?void 0:u.scrollTop)||0,devicePixelRatio:t.devicePixelRatio||1},documentDimensions:{width:Math.max(((h=e.body)==null?void 0:h.scrollWidth)||0,((g=e.documentElement)==null?void 0:g.scrollWidth)||0),height:Math.max(((p=e.body)==null?void 0:p.scrollHeight)||0,((y=e.documentElement)==null?void 0:y.scrollHeight)||0)},activeElement:s?{tag:((v=s.tagName)==null?void 0:v.toLowerCase())||"",selector:this.computeBestSelector(s),text:(m=s.textContent)==null?void 0:m.slice(0,100).trim()}:void 0,focusedElement:typeof e.hasFocus=="function"&&e.hasFocus()&&s?{tag:((d=s.tagName)==null?void 0:d.toLowerCase())||"",selector:this.computeBestSelector(s)}:void 0,visibilityState:e.visibilityState||"visible",readyState:e.readyState||"complete",framesCount:e.querySelectorAll?e.querySelectorAll("iframe, frame").length:0}}static inspectElement(e,t){var xe,_e;const s=e.ownerDocument||document,n=s.defaultView||(typeof window<"u"?window:{}),i=e,r=e.tagName?e.tagName.toLowerCase():"element",o=this.extractClasses(e),{bestSelector:a,candidates:c}=this.generateSelectorCandidates(e),u={},h={};if(e.attributes)for(let V=0;V- `}attachEvents(){if(!this.shadowRoot)return;const e=this.shadowRoot.querySelector("#drag-header");e&&e.addEventListener("mousedown",c=>{this.isDragging=!0,this.dragStartX=c.clientX-this.posX,this.dragStartY=c.clientY-this.posY;const u=h=>{!this.isDragging||!this.hostElement||(this.posX=Math.max(10,Math.min(window.innerWidth-80,h.clientX-this.dragStartX)),this.posY=Math.max(10,Math.min(window.innerHeight-50,h.clientY-this.dragStartY)),this.hostElement.style.left=`${this.posX}px`,this.hostElement.style.top=`${this.posY}px`)},d=()=>{this.isDragging=!1,window.removeEventListener("mousemove",u),window.removeEventListener("mouseup",d),this.savePosition()};window.addEventListener("mousemove",u),window.addEventListener("mouseup",d)});const t=this.shadowRoot.querySelector("#btn-toggle-min");t==null||t.addEventListener("click",()=>{this.isMinimized=!this.isMinimized,this.savePosition(),this.render(),this.attachEvents()});const s=this.shadowRoot.querySelector("#btn-close");s==null||s.addEventListener("click",()=>{this.unmount()});const n=this.shadowRoot.querySelector("#btn-record");n==null||n.addEventListener("click",()=>{this.isRecording?this.callbacks.onStopRecord():this.callbacks.onStartRecord()});const i=this.shadowRoot.querySelector("#btn-checkpoint");i==null||i.addEventListener("click",()=>{if(this.callbacks.onCaptureCheckpoint(),i){const c=i.textContent;i.textContent="✔ Saved!",setTimeout(()=>i.textContent=c,1e3)}});const r=this.shadowRoot.querySelector("#btn-inspect");r==null||r.addEventListener("click",()=>{this.callbacks.onInspectElement()});const o=this.shadowRoot.querySelector("#btn-annotate");o==null||o.addEventListener("click",()=>{const c=prompt("Enter observation, bug note, or hypothesis at this exact moment:");c&&c.trim()&&this.callbacks.onAddAnnotation(c.trim())});const a=this.shadowRoot.querySelector("#btn-dashboard");a==null||a.addEventListener("click",()=>{this.callbacks.onOpenDashboard()})}}(function(){var w;let l=null;const e=new Lt;let t=[],s=null,n=null,i=!1;const r=500,o=[],a=[];window.addEventListener("message",E=>{var C;if(((C=E.data)==null?void 0:C._forensicOrigin)==="PAGE_MAIN"){const{type:N,payload:I}=E.data;if(N==="CONSOLE_ENTRY")o.push(I),o.length>r&&o.shift();else if(N==="NETWORK_ENTRY"){const R=a.findIndex(x=>x.requestId===I.requestId);R>=0?a[R]={...a[R],...I}:(a.push(I),a.length>r&&a.shift())}}});function c(){var E;try{if(typeof chrome<"u"&&((E=chrome.runtime)!=null&&E.getURL)){const C=document.createElement("script");C.src=chrome.runtime.getURL("dist/extension/page-script.js"),C.onload=()=>C.remove(),(document.head||document.documentElement).appendChild(C)}}catch{}}function u(){var C;if(t.length===0||!l)return;const E=[...t];t=[];try{typeof chrome<"u"&&((C=chrome.runtime)!=null&&C.sendMessage)&&chrome.runtime.sendMessage({type:"FORENSIC_EVENTS_CHUNK",sessionId:l.getSessionId(),events:E})}catch{}}function d(E,C,N){var R;if(l)return l.getMetadata();l=new Le({sessionId:C,sessionName:E||`Recording on ${document.title||window.location.hostname}`}),l.onEvent(x=>{t.push(x),n&&n.incrementEventCount(),t.length>=25&&u()}),l.onCheckpoint(x=>{var q;try{typeof chrome<"u"&&((q=chrome.runtime)!=null&&q.sendMessage)&&chrome.runtime.sendMessage({type:"FORENSIC_CHECKPOINT",sessionId:x.sessionId,checkpoint:x})}catch{}});const I=l.start(document);try{typeof chrome<"u"&&((R=chrome.runtime)!=null&&R.sendMessage)&&chrome.runtime.sendMessage({type:"FORENSIC_SESSION_START",metadata:l.getMetadata(),initialSnapshot:I})}catch{}return s||(s=setInterval(u,1e3)),n&&n.updateState(!0,!1,N||Date.now(),0),l.getMetadata()}function h(){var N;if(!l)return null;u(),s&&(clearInterval(s),s=null);const E=l.stop();try{typeof chrome<"u"&&((N=chrome.runtime)!=null&&N.sendMessage)&&chrome.runtime.sendMessage({type:"FORENSIC_SESSION_STOP",sessionId:E.id,metadata:E})}catch{}const C={...E};return l=null,n&&n.updateState(!1,!1,0,0),C}function p(){if(i){i=!1,document.body.style.cursor="default";return}i=!0,document.body.style.cursor="crosshair";const E=document.createElement("div");E.id="forensic-inspect-highlighter",E.style.position="fixed",E.style.pointerEvents="none",E.style.zIndex="2147483640",E.style.border="2px dashed #38bdf8",E.style.background="rgba(56, 189, 248, 0.15)",E.style.transition="all 0.05s ease",document.body.appendChild(E);const C=I=>{if(!i)return;const R=I.target;if(!R||R.id==="forensic-recorder-floating-host"||R.closest("#forensic-recorder-floating-host")){E.style.display="none";return}const x=R.getBoundingClientRect();E.style.display="block",E.style.left=`${x.left}px`,E.style.top=`${x.top}px`,E.style.width=`${x.width}px`,E.style.height=`${x.height}px`},N=I=>{if(!i)return;const R=I.target;if(!R.closest("#forensic-recorder-floating-host")&&(I.preventDefault(),I.stopPropagation(),i=!1,document.body.style.cursor="default",E.remove(),window.removeEventListener("mousemove",C,!0),window.removeEventListener("click",N,!0),l)){const x=R.id?`#${R.id}`:R.className?`.${R.className.split(" ")[0]}`:R.tagName.toLowerCase();l.addAnnotation("Inspect Element",`Inspected element <${R.tagName.toLowerCase()}> with selector '${x}'`,"USER"),alert(`🎯 Inspected element <${R.tagName.toLowerCase()}> recorded! Checkpoint saved.`)}};window.addEventListener("mousemove",C,!0),window.addEventListener("click",N,!0)}function y(){return n||(n=new Ht({onStartRecord:()=>{d()},onStopRecord:()=>{h()},onTogglePause:()=>{l&&(l.getMetadata().status==="recording"?l.pause():l.resume())},onCaptureCheckpoint:()=>{l&&l.captureCheckpoint("MANUAL",document)},onAddAnnotation:E=>{l&&l.addAnnotation("User Note",E,"USER")},onInspectElement:()=>{p()},onOpenDashboard:()=>{const E=l?l.getSessionId():void 0;chrome.runtime.sendMessage({type:"OPEN_DASHBOARD_TAB",sessionId:E})}})),n}function v(){var E;try{typeof chrome<"u"&&((E=chrome.runtime)!=null&&E.sendMessage)&&chrome.runtime.sendMessage({type:"GET_TAB_RECORDING_STATE"},C=>{chrome.runtime.lastError||!C||C.isRecording&&C.recording&&(y().mount(),d(C.recording.sessionName,C.recording.sessionId,C.recording.startTime))})}catch{}}typeof chrome<"u"&&((w=chrome.runtime)!=null&&w.onMessage)&&chrome.runtime.onMessage.addListener((E,C,N)=>{if(E.type==="HIDE_FORENSIC_OVERLAYS")return n&&n.hide(),document.querySelectorAll('#forensic-recorder-floating-host, #forensic-inspect-highlighter, [id^="forensic-"]').forEach(R=>{const x=R;x.style.setProperty("display","none","important"),x.style.setProperty("visibility","hidden","important"),x.style.setProperty("opacity","0","important")}),N({success:!0}),!0;if(E.type==="RESTORE_FORENSIC_OVERLAYS")return n&&n.show(),document.querySelectorAll('#forensic-recorder-floating-host, #forensic-inspect-highlighter, [id^="forensic-"]').forEach(R=>{const x=R;x.style.removeProperty("display"),x.style.removeProperty("visibility"),x.style.removeProperty("opacity")}),N({success:!0}),!0;if(E.type==="BROWSER_COMMAND_REQUEST"){if(["LIST_TABS","FOCUS_TAB","RELOAD_TAB","LIST_EXTENSIONS","RELOAD_EXTENSION","CLOSE_TAB","OPEN_TAB","RESIZE_VIEWPORT","RESET_VIEWPORT"].includes(E.command))return!1;if(E.command==="GET_TAB_CONSOLE_LOGS"){const{level:I,searchQuery:R,limit:x=100,clearAfterRead:q}=E.payload||{};let A=[...o];if(I&&I!=="all"&&(A=A.filter(S=>S.level===I)),R){const S=String(R).toLowerCase();A=A.filter(M=>{var O,_;return((O=M.text)==null?void 0:O.toLowerCase().includes(S))||((_=M.source)==null?void 0:_.toLowerCase().includes(S))})}return x>0&&(A=A.slice(-x)),q&&(o.length=0),N({id:E.id,command:E.command,success:!0,data:{url:window.location.href,title:document.title,totalCaptured:o.length,returnedCount:A.length,logs:A}}),!0}if(E.command==="GET_TAB_NETWORK_REQUESTS"){const{method:I,searchQuery:R,status:x,onlyErrors:q,limit:A=100,clearAfterRead:S}=E.payload||{};let M=[...a];if(I&&(M=M.filter(O=>{var _;return((_=O.method)==null?void 0:_.toUpperCase())===String(I).toUpperCase()})),x&&(M=M.filter(O=>O.status===Number(x))),q&&(M=M.filter(O=>O.error||O.status&&O.status>=400)),R){const O=String(R).toLowerCase();M=M.filter(_=>{var P;return(P=_.url)==null?void 0:P.toLowerCase().includes(O)})}return A>0&&(M=M.slice(-A)),S&&(a.length=0),N({id:E.id,command:E.command,success:!0,data:{url:window.location.href,title:document.title,totalCaptured:a.length,returnedCount:M.length,requests:M}}),!0}return e.handleCommand(E,document).then(I=>{N(I)}),!0}else if(E.type==="START_RECORDING"){const I=d(E.sessionName);y().mount(),N({success:!0,metadata:I})}else if(E.type==="STOP_RECORDING"){const I=h();N({success:!0,metadata:I})}else if(E.type==="TOGGLE_FLOATING_OVERLAY"){const I=y();document.getElementById("forensic-recorder-floating-host")?(I.unmount(),N({isOpen:!1})):(I.mount(),I.updateState((l==null?void 0:l.getMetadata().status)==="recording",!1,(l==null?void 0:l.getMetadata().startTime)||0,0),N({isOpen:!0}))}else if(E.type==="GET_RECORDER_STATUS")N({isRecording:(l==null?void 0:l.getMetadata().status)==="recording",metadata:(l==null?void 0:l.getMetadata())||null});else if(E.type==="CAPTURE_CHECKPOINT")if(l){const I=l.captureCheckpoint("MANUAL",document);N({success:!0,checkpoint:I})}else N({success:!1,error:"Not currently recording"});return!0});let m=null,g=null;function b(){if(!(typeof WebSocket>"u"))try{const E=new WebSocket("ws://127.0.0.1:3847");E.onopen=()=>{m=E,console.log("[Forensic ContentScript] Connected directly to MCP Bridge on ws://127.0.0.1:3847"),g&&(clearInterval(g),g=null),E.send(JSON.stringify({type:"REGISTER_CLIENT",clientType:"CONTENT_SCRIPT",url:window.location.href,title:document.title}))},E.onclose=()=>{m=null,T()},E.onerror=()=>{m=null,T()},E.onmessage=async C=>{var N;try{const I=JSON.parse(C.data.toString());if(I.type==="BROWSER_COMMAND_REQUEST"){const{id:R,command:x,payload:q}=I;if(["LIST_TABS","OPEN_TAB","LIST_EXTENSIONS","RELOAD_EXTENSION","CLOSE_TAB","FOCUS_TAB","RELOAD_TAB","RESIZE_VIEWPORT","RESET_VIEWPORT"].includes(x)){if(typeof chrome<"u"&&((N=chrome.runtime)!=null&&N.sendMessage)){chrome.runtime.sendMessage(I,S=>{if(chrome.runtime.lastError){if(x==="CLOSE_TAB"){E.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:R,command:x,success:!0,data:{closed:!0,url:window.location.href,title:document.title}})),setTimeout(()=>window.close(),100);return}if(x==="RELOAD_TAB"){E.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:R,command:x,success:!0,data:{reloaded:!0,url:window.location.href,title:document.title}})),setTimeout(()=>window.location.reload(),100);return}E.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:R,command:x,success:!1,error:{code:"FORWARD_ERROR",message:chrome.runtime.lastError.message}}))}else E.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",...S||{id:R,command:x,success:!0}}))});return}if(x==="CLOSE_TAB"){E.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:R,command:x,success:!0,data:{closed:!0,url:window.location.href,title:document.title}})),setTimeout(()=>window.close(),100);return}if(x==="RELOAD_TAB"){E.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:R,command:x,success:!0,data:{reloaded:!0,url:window.location.href,title:document.title}})),setTimeout(()=>window.location.reload(),100);return}}if(x==="GET_TAB_CONSOLE_LOGS"){const{level:S,searchQuery:M,limit:O=100,clearAfterRead:_}=q||{};let P=[...o];if(S&&S!=="all"&&(P=P.filter(H=>H.level===S)),M){const H=String(M).toLowerCase();P=P.filter($=>{var F,W;return((F=$.text)==null?void 0:F.toLowerCase().includes(H))||((W=$.source)==null?void 0:W.toLowerCase().includes(H))})}O>0&&(P=P.slice(-O)),_&&(o.length=0),E.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:R,command:x,success:!0,data:{url:window.location.href,title:document.title,totalCaptured:o.length,returnedCount:P.length,logs:P}}));return}if(x==="GET_TAB_NETWORK_REQUESTS"){const{method:S,searchQuery:M,status:O,onlyErrors:_,limit:P=100,clearAfterRead:H}=q||{};let $=[...a];if(S&&($=$.filter(F=>{var W;return((W=F.method)==null?void 0:W.toUpperCase())===String(S).toUpperCase()})),O&&($=$.filter(F=>F.status===Number(O))),_&&($=$.filter(F=>F.error||F.status&&F.status>=400)),M){const F=String(M).toLowerCase();$=$.filter(W=>{var te;return(te=W.url)==null?void 0:te.toLowerCase().includes(F)})}P>0&&($=$.slice(-P)),H&&(a.length=0),E.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:R,command:x,success:!0,data:{url:window.location.href,title:document.title,totalCaptured:a.length,returnedCount:$.length,requests:$}}));return}const A=await e.handleCommand(I,document);E.send(JSON.stringify(A))}}catch(I){console.error("[Forensic ContentScript] Bridge message error:",I)}}}catch{m=null,T()}}function T(){g||(g=setInterval(()=>{(!m||m.readyState!==WebSocket.OPEN)&&b()},4e3))}c(),b(),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",v):v()})()})(); + `}attachEvents(){if(!this.shadowRoot)return;const e=this.shadowRoot.querySelector("#drag-header");e&&e.addEventListener("mousedown",c=>{this.isDragging=!0,this.dragStartX=c.clientX-this.posX,this.dragStartY=c.clientY-this.posY;const u=g=>{!this.isDragging||!this.hostElement||(this.posX=Math.max(10,Math.min(window.innerWidth-80,g.clientX-this.dragStartX)),this.posY=Math.max(10,Math.min(window.innerHeight-50,g.clientY-this.dragStartY)),this.hostElement.style.left=`${this.posX}px`,this.hostElement.style.top=`${this.posY}px`)},h=()=>{this.isDragging=!1,window.removeEventListener("mousemove",u),window.removeEventListener("mouseup",h),this.savePosition()};window.addEventListener("mousemove",u),window.addEventListener("mouseup",h)});const t=this.shadowRoot.querySelector("#btn-toggle-min");t==null||t.addEventListener("click",()=>{this.isMinimized=!this.isMinimized,this.savePosition(),this.render(),this.attachEvents()});const s=this.shadowRoot.querySelector("#btn-close");s==null||s.addEventListener("click",()=>{this.unmount()});const n=this.shadowRoot.querySelector("#btn-record");n==null||n.addEventListener("click",()=>{this.isRecording?this.callbacks.onStopRecord():this.callbacks.onStartRecord()});const i=this.shadowRoot.querySelector("#btn-checkpoint");i==null||i.addEventListener("click",()=>{if(this.callbacks.onCaptureCheckpoint(),i){const c=i.textContent;i.textContent="✔ Saved!",setTimeout(()=>i.textContent=c,1e3)}});const r=this.shadowRoot.querySelector("#btn-inspect");r==null||r.addEventListener("click",()=>{this.callbacks.onInspectElement()});const o=this.shadowRoot.querySelector("#btn-annotate");o==null||o.addEventListener("click",()=>{const c=prompt("Enter observation, bug note, or hypothesis at this exact moment:");c&&c.trim()&&this.callbacks.onAddAnnotation(c.trim())});const a=this.shadowRoot.querySelector("#btn-dashboard");a==null||a.addEventListener("click",()=>{this.callbacks.onOpenDashboard()})}}(function(){var m;let l=null;const e=new Ot;let t=[],s=null,n=null,i=!1;const r=500,o=[],a=[];window.addEventListener("message",d=>{var f;if(((f=d.data)==null?void 0:f._forensicOrigin)==="PAGE_MAIN"){const{type:w,payload:E}=d.data;if(w==="CONSOLE_ENTRY")o.push(E),o.length>r&&o.shift();else if(w==="NETWORK_ENTRY"){const S=a.findIndex(T=>T.requestId===E.requestId);S>=0?a[S]={...a[S],...E}:(a.push(E),a.length>r&&a.shift())}}});function c(){var d;try{if(typeof chrome<"u"&&((d=chrome.runtime)!=null&&d.getURL)){const f=document.createElement("script");f.src=chrome.runtime.getURL("dist/extension/page-script.js"),f.onload=()=>f.remove(),(document.head||document.documentElement).appendChild(f)}}catch{}}function u(){var f;if(t.length===0||!l)return;const d=[...t];t=[];try{typeof chrome<"u"&&((f=chrome.runtime)!=null&&f.sendMessage)&&chrome.runtime.sendMessage({type:"FORENSIC_EVENTS_CHUNK",sessionId:l.getSessionId(),events:d})}catch{}}function h(d,f,w){var S;if(l)return l.getMetadata();l=new Oe({sessionId:f,sessionName:d||`Recording on ${document.title||window.location.hostname}`}),l.onEvent(T=>{t.push(T),n&&n.incrementEventCount(),t.length>=25&&u()}),l.onCheckpoint(T=>{var x;try{typeof chrome<"u"&&((x=chrome.runtime)!=null&&x.sendMessage)&&chrome.runtime.sendMessage({type:"FORENSIC_CHECKPOINT",sessionId:T.sessionId,checkpoint:T})}catch{}});const E=l.start(document);try{typeof chrome<"u"&&((S=chrome.runtime)!=null&&S.sendMessage)&&chrome.runtime.sendMessage({type:"FORENSIC_SESSION_START",metadata:l.getMetadata(),initialSnapshot:E})}catch{}return s||(s=setInterval(u,1e3)),n&&n.updateState(!0,!1,w||Date.now(),0),l.getMetadata()}function g(){var w;if(!l)return null;u(),s&&(clearInterval(s),s=null);const d=l.stop();try{typeof chrome<"u"&&((w=chrome.runtime)!=null&&w.sendMessage)&&chrome.runtime.sendMessage({type:"FORENSIC_SESSION_STOP",sessionId:d.id,metadata:d})}catch{}const f={...d};return l=null,n&&n.updateState(!1,!1,0,0),f}function p(){if(i){i=!1,document.body.style.cursor="default";return}i=!0,document.body.style.cursor="crosshair";const d=document.createElement("div");d.id="forensic-inspect-highlighter",d.style.position="fixed",d.style.pointerEvents="none",d.style.zIndex="2147483640",d.style.border="2px dashed #38bdf8",d.style.background="rgba(56, 189, 248, 0.15)",d.style.transition="all 0.05s ease",document.body.appendChild(d);const f=E=>{if(!i)return;const S=E.target;if(!S||S.id==="forensic-recorder-floating-host"||S.closest("#forensic-recorder-floating-host")){d.style.display="none";return}const T=S.getBoundingClientRect();d.style.display="block",d.style.left=`${T.left}px`,d.style.top=`${T.top}px`,d.style.width=`${T.width}px`,d.style.height=`${T.height}px`},w=E=>{if(!i)return;const S=E.target;if(!S.closest("#forensic-recorder-floating-host")&&(E.preventDefault(),E.stopPropagation(),i=!1,document.body.style.cursor="default",d.remove(),window.removeEventListener("mousemove",f,!0),window.removeEventListener("click",w,!0),l)){const T=S.id?`#${S.id}`:S.className?`.${S.className.split(" ")[0]}`:S.tagName.toLowerCase();l.addAnnotation("Inspect Element",`Inspected element <${S.tagName.toLowerCase()}> with selector '${T}'`,"USER"),alert(`🎯 Inspected element <${S.tagName.toLowerCase()}> recorded! Checkpoint saved.`)}};window.addEventListener("mousemove",f,!0),window.addEventListener("click",w,!0)}function y(){return n||(n=new Ut({onStartRecord:()=>{h()},onStopRecord:()=>{g()},onTogglePause:()=>{l&&(l.getMetadata().status==="recording"?l.pause():l.resume())},onCaptureCheckpoint:()=>{l&&l.captureCheckpoint("MANUAL",document)},onAddAnnotation:d=>{l&&l.addAnnotation("User Note",d,"USER")},onInspectElement:()=>{p()},onOpenDashboard:()=>{const d=l?l.getSessionId():void 0;chrome.runtime.sendMessage({type:"OPEN_DASHBOARD_TAB",sessionId:d})}})),n}function v(){var d;try{typeof chrome<"u"&&((d=chrome.runtime)!=null&&d.sendMessage)&&chrome.runtime.sendMessage({type:"GET_TAB_RECORDING_STATE"},f=>{chrome.runtime.lastError||!f||f.isRecording&&f.recording&&(y().mount(),h(f.recording.sessionName,f.recording.sessionId,f.recording.startTime))})}catch{}}typeof chrome<"u"&&((m=chrome.runtime)!=null&&m.onMessage)&&chrome.runtime.onMessage.addListener((d,f,w)=>{if(d.type==="HIDE_FORENSIC_OVERLAYS")return n&&n.hide(),document.querySelectorAll('#forensic-recorder-floating-host, #forensic-inspect-highlighter, [id^="forensic-"]').forEach(S=>{const T=S;T.style.setProperty("display","none","important"),T.style.setProperty("visibility","hidden","important"),T.style.setProperty("opacity","0","important")}),w({success:!0}),!0;if(d.type==="RESTORE_FORENSIC_OVERLAYS")return n&&n.show(),document.querySelectorAll('#forensic-recorder-floating-host, #forensic-inspect-highlighter, [id^="forensic-"]').forEach(S=>{const T=S;T.style.removeProperty("display"),T.style.removeProperty("visibility"),T.style.removeProperty("opacity")}),w({success:!0}),!0;if(d.type==="BROWSER_COMMAND_REQUEST"){if(["LIST_TABS","FOCUS_TAB","RELOAD_TAB","LIST_EXTENSIONS","RELOAD_EXTENSION","CLOSE_TAB","OPEN_TAB","RESIZE_VIEWPORT","RESET_VIEWPORT"].includes(d.command))return!1;if(d.command==="GET_TAB_CONSOLE_LOGS"){const{level:E,searchQuery:S,limit:T=100,clearAfterRead:x}=d.payload||{};let N=[...o];if(E&&E!=="all"&&(N=N.filter(D=>D.level===E)),S){const D=String(S).toLowerCase();N=N.filter(M=>{var L,I;return((L=M.text)==null?void 0:L.toLowerCase().includes(D))||((I=M.source)==null?void 0:I.toLowerCase().includes(D))})}return T>0&&(N=N.slice(-T)),x&&(o.length=0),w({id:d.id,command:d.command,success:!0,data:{url:window.location.href,title:document.title,totalCaptured:o.length,returnedCount:N.length,logs:N}}),!0}if(d.command==="GET_TAB_NETWORK_REQUESTS"){const{method:E,searchQuery:S,status:T,onlyErrors:x,limit:N=100,clearAfterRead:D}=d.payload||{};let M=[...a];if(E&&(M=M.filter(L=>{var I;return((I=L.method)==null?void 0:I.toUpperCase())===String(E).toUpperCase()})),T&&(M=M.filter(L=>L.status===Number(T))),x&&(M=M.filter(L=>L.error||L.status&&L.status>=400)),S){const L=String(S).toLowerCase();M=M.filter(I=>{var C;return(C=I.url)==null?void 0:C.toLowerCase().includes(L)})}return N>0&&(M=M.slice(-N)),D&&(a.length=0),w({id:d.id,command:d.command,success:!0,data:{url:window.location.href,title:document.title,totalCaptured:a.length,returnedCount:M.length,requests:M}}),!0}return e.handleCommand(d,document).then(E=>{w(E)}),!0}else if(d.type==="START_RECORDING"){const E=h(d.sessionName);y().mount(),w({success:!0,metadata:E})}else if(d.type==="STOP_RECORDING"){const E=g();w({success:!0,metadata:E})}else if(d.type==="TOGGLE_FLOATING_OVERLAY"){const E=y();document.getElementById("forensic-recorder-floating-host")?(E.unmount(),w({isOpen:!1})):(E.mount(),E.updateState((l==null?void 0:l.getMetadata().status)==="recording",!1,(l==null?void 0:l.getMetadata().startTime)||0,0),w({isOpen:!0}))}else if(d.type==="GET_RECORDER_STATUS")w({isRecording:(l==null?void 0:l.getMetadata().status)==="recording",metadata:(l==null?void 0:l.getMetadata())||null});else if(d.type==="CAPTURE_CHECKPOINT")if(l){const E=l.captureCheckpoint("MANUAL",document);w({success:!0,checkpoint:E})}else w({success:!1,error:"Not currently recording"});return!0}),c(),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",v):v()})()})(); diff --git a/chrome-extension/dist/extension/service-worker.js b/chrome-extension/dist/extension/service-worker.js index 8a07840c..3df46b93 100644 --- a/chrome-extension/dist/extension/service-worker.js +++ b/chrome-extension/dist/extension/service-worker.js @@ -1 +1 @@ -var v=Object.defineProperty;var P=(E,l,d)=>l in E?v(E,l,{enumerable:!0,configurable:!0,writable:!0,value:d}):E[l]=d;var b=(E,l,d)=>P(E,typeof l!="symbol"?l+"":l,d);(function(){"use strict";var T,_,p,R;class E{constructor(s="ForensicRecorderDB"){b(this,"dbName");b(this,"dbVersion",1);b(this,"db",null);this.dbName=s}async openDB(){if(this.db)return this.db;if(typeof indexedDB>"u")throw new Error("IndexedDB is not available in current runtime environment");return new Promise((s,e)=>{const r=indexedDB.open(this.dbName,this.dbVersion);r.onupgradeneeded=c=>{const t=c.target.result;if(t.objectStoreNames.contains("sessions")||t.createObjectStore("sessions",{keyPath:"id"}),!t.objectStoreNames.contains("events")){const n=t.createObjectStore("events",{keyPath:"id"});n.createIndex("sessionId","sessionId",{unique:!1}),n.createIndex("sequence","sequence",{unique:!1})}t.objectStoreNames.contains("checkpoints")||t.createObjectStore("checkpoints",{keyPath:"checkpointId"}).createIndex("sessionId","sessionId",{unique:!1}),t.objectStoreNames.contains("snapshots")||t.createObjectStore("snapshots",{keyPath:"sessionId"}),t.objectStoreNames.contains("annotations")||t.createObjectStore("annotations",{keyPath:"id"}).createIndex("sessionId","sessionId",{unique:!1})},r.onsuccess=()=>{this.db=r.result,s(this.db)},r.onerror=()=>e(r.error)})}async saveSession(s){const e=await this.openDB();return new Promise((r,c)=>{const t=e.transaction("sessions","readwrite");t.objectStore("sessions").put(s),t.oncomplete=()=>r(),t.onerror=()=>c(t.error)})}async getSession(s){const e=await this.openDB();return new Promise((r,c)=>{const o=e.transaction("sessions","readonly").objectStore("sessions").get(s);o.onsuccess=()=>r(o.result||null),o.onerror=()=>c(o.error)})}async listSessions(){const s=await this.openDB();return new Promise((e,r)=>{const n=s.transaction("sessions","readonly").objectStore("sessions").getAll();n.onsuccess=()=>{const o=n.result||[];o.sort((a,u)=>u.startTime-a.startTime),e(o)},n.onerror=()=>r(n.error)})}async deleteSession(s){const e=await this.openDB();return new Promise((r,c)=>{const t=e.transaction(["sessions","events","checkpoints","snapshots","annotations"],"readwrite");t.objectStore("sessions").delete(s),t.objectStore("snapshots").delete(s);const a=t.objectStore("events").index("sessionId").openCursor(IDBKeyRange.only(s));a.onsuccess=()=>{const u=a.result;u&&(u.delete(),u.continue())},t.oncomplete=()=>r(!0),t.onerror=()=>c(t.error)})}async appendEvents(s,e){if(e.length===0)return;const r=await this.openDB();return new Promise((c,t)=>{const n=r.transaction("events","readwrite"),o=n.objectStore("events");for(const a of e)o.put(a);n.oncomplete=()=>c(),n.onerror=()=>t(n.error)})}async getEvents(s,e){const r=await this.openDB();return new Promise((c,t)=>{const u=r.transaction("events","readonly").objectStore("events").index("sessionId").getAll(IDBKeyRange.only(s));u.onsuccess=()=>{let m=u.result||[];m.sort((h,f)=>h.sequence-f.sequence),e&&(m=m.filter(h=>!(e.category&&h.category!==e.category||e.type&&h.type!==e.type||typeof e.fromTimestamp=="number"&&h.timestamp0||E.height>0||E.right>0||E.bottom>0,R=!C||E.right>0&&E.bottom>0&&E.left =L||E.top>=I),A=!P&&T!=="none"&&x!=="hidden"&&N>0&&R,se={disabled:i.disabled??e.hasAttribute("disabled"),readOnly:i.readOnly??e.hasAttribute("readonly"),checked:i.checked,selected:i.selected,focused:s.activeElement===e,isShadowHost:!!e.shadowRoot,hasShadowRoot:!!e.shadowRoot},z=[];let G=e.parentElement;for(;G&&G.tagName&&G.tagName.toLowerCase()!=="html";)z.push(this.computeBestSelector(G)),G=G.parentElement;const Ht={count:e.children?e.children.length:0,tags:e.children?Array.from(e.children).slice(0,10).map(V=>V.tagName.toLowerCase()):[]};let Ae;if(t){const V=t.getId(e);Ae={logicalNodeId:V??null,creationSequence:null,lastMutationSequence:null,eventCount:0,isRecorded:V!=null}}return{tag:r,id:e.id||void 0,classes:o,role:g||void 0,ariaAttributes:Object.keys(h).length>0?h:void 0,text:v.slice(0,200),normalizedText:m.slice(0,200),value:d,type:f.type||void 0,selector:a,bestSelector:a,selectorCandidates:c,bounds:E,visibility:{isVisible:A,display:T,visibility:x,opacity:N,pointerEvents:D,isClipped:P,isInViewport:R,zIndex:M},computedStyle:S?{display:T,visibility:x,opacity:String(N),position:S.position,zIndex:String(M),pointerEvents:D,overflow:S.overflow,boxSizing:S.boxSizing,color:S.color,backgroundColor:S.backgroundColor,fontSize:S.fontSize}:{},attributes:u,state:se,context:{parentChain:z,parentSelector:z[0]||void 0,childrenSummary:Ht,containingBlock:(S==null?void 0:S.position)==="fixed"?"viewport":z[0]||void 0,iframe:null,shadowRoot:e.shadowRoot?"open":null},forensics:Ae}}static inspectVisualState(e){var f,w;const t=e.ownerDocument||document,s=t.defaultView||(typeof window<"u"?window:{}),n=e.getBoundingClientRect?e.getBoundingClientRect():{x:0,y:0,width:0,height:0,top:0,right:0,bottom:0,left:0},i=s.getComputedStyle?s.getComputedStyle(e):null,r=s.innerWidth||((f=t.documentElement)==null?void 0:f.clientWidth)||1920,o=s.innerHeight||((w=t.documentElement)==null?void 0:w.clientHeight)||1080,a=s.scrollX||s.pageXOffset||0,c=s.scrollY||s.pageYOffset||0,u=s.devicePixelRatio||1,h=(i==null?void 0:i.display)||"block",g=(i==null?void 0:i.visibility)||"visible",p=i&&parseFloat(i.opacity)||1,y=n.right>0&&n.bottom>0&&n.left =r||n.top>=o;let d=null;if(t.elementFromPoint&&y&&!v&&h!=="none"){const E=Math.max(0,Math.min(r-1,n.left+n.width/2)),S=Math.max(0,Math.min(o-1,n.top+n.height/2));try{const T=t.elementFromPoint(E,S);T&&T!==e&&!e.contains(T)&&!T.contains(e)&&(d=this.computeBestSelector(T))}catch{}}return{selector:this.computeBestSelector(e),bounds:{x:n.x??n.left??0,y:n.y??n.top??0,width:n.width??0,height:n.height??0,top:n.top??0,right:n.right??0,bottom:n.bottom??0,left:n.left??0},viewport:{scrollX:a,scrollY:c,width:r,height:o,devicePixelRatio:u},layout:{display:h,position:(i==null?void 0:i.position)||"static",zIndex:(i==null?void 0:i.zIndex)||"auto",opacity:p,visibility:g,overflow:(i==null?void 0:i.overflow)||"visible",boxSizing:(i==null?void 0:i.boxSizing)||"content-box",pointerEvents:(i==null?void 0:i.pointerEvents)||"auto"},occlusion:{isInViewport:y,isClipped:v||m,isZeroDimension:v,isTransparent:p===0,isDisplayNone:h==="none",isVisibilityHidden:g==="hidden",isOffscreen:m,occludedBy:d},computedStyleSummary:i?{display:h,position:i.position,zIndex:i.zIndex,opacity:String(p),visibility:g,pointerEvents:i.pointerEvents}:{}}}static generateSelectorCandidates(e){const t=e.ownerDocument||document,s=e.tagName?e.tagName.toLowerCase():"element",n=[];if(e.id&&/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(e.id)){const c=`#${e.id}`;try{t.querySelectorAll&&t.querySelectorAll(c).length===1&&n.push(c)}catch{n.push(c)}}const i=["data-testid","data-test","data-id","data-qa","data-cy","aria-label","name"];for(const c of i){const u=e.getAttribute(c);if(u&&/^[a-zA-Z0-9_-]+$/.test(u)){const h=`${s}[${c}="${u}"]`;try{t.querySelectorAll&&t.querySelectorAll(h).length===1&&n.push(h)}catch{n.push(h)}}}const r=this.extractClasses(e).filter(c=>/^[a-zA-Z0-9_-]+$/.test(c)&&!c.startsWith("ng-")&&!c.startsWith("_ng"));if(r.length>0){const c=`${s}.${r.slice(0,3).join(".")}`;try{t.querySelectorAll&&t.querySelectorAll(c).length===1&&n.push(c)}catch{n.push(c)}}if(e.parentElement&&e.parentElement.children){const c=Array.from(e.parentElement.children).filter(u=>u.tagName&&u.tagName.toLowerCase()===s);if(c.length>1){const u=c.indexOf(e)+1;if(u>0){const h=this.computeBestSelector(e.parentElement);n.push(`${h} > ${s}:nth-of-type(${u})`)}}}const o=r.length>0?`${s}.${r[0]}`:s;return n.push(o),{bestSelector:n[0]||s,candidates:n}}static computeBestSelector(e){return this.generateSelectorCandidates(e).bestSelector}static extractClasses(e){return e.classList&&typeof e.classList.forEach=="function"?Array.from(e.classList):typeof e.className=="string"?e.className.split(/\s+/).filter(Boolean):e.className&&typeof e.className.baseVal=="string"?e.className.baseVal.split(/\s+/).filter(Boolean):[]}static inferImplicitRole(e){switch(e.tagName?e.tagName.toLowerCase():""){case"a":return e.hasAttribute("href")?"link":void 0;case"button":return"button";case"input":{const s=e.type||"text";return s==="button"||s==="submit"||s==="reset"?"button":s==="checkbox"?"checkbox":s==="radio"?"radio":"textbox"}case"select":return"combobox";case"textarea":return"textbox";case"nav":return"navigation";case"header":return"banner";case"footer":return"contentinfo";case"main":return"main";case"article":return"article";case"section":return"region";default:return}}}b(k,"privacyEngine",new J);class Le{constructor(e){b(this,"registry");b(this,"lastSelectedElementRef");b(this,"timingHook",null);b(this,"lastTrajectory",[]);this.registry=e}setLastSelectedElement(e){this.lastSelectedElementRef=e}setTimingHook(e){this.timingHook=e}getLastTrajectory(){return this.lastTrajectory}async timing(e){this.timingHook&&await this.timingHook(e)}resolveTarget(e,t=document){if(e.selectedElementRef&&this.lastSelectedElementRef&&t.contains(this.lastSelectedElementRef))return this.lastSelectedElementRef;if(typeof e.nodeId=="number"&&this.registry){const s=this.registry.getNode(e.nodeId);if(s&&s instanceof Element&&t.contains(s))return s}if(e.selector)try{const s=t.querySelectorAll(e.selector);if(s.length>1){for(let n=0;n {r+=w.length});try{h.observe(t.body||t.documentElement,{childList:!0,attributes:!0,characterData:!0,subtree:!0})}catch{}const g=w=>{o.push(w.message||"Runtime Error")};typeof window<"u"&&window.addEventListener("error",g);try{await this.dispatchAction(n,e)}finally{typeof window<"u"&&window.removeEventListener("error",g)}let p=!0;if((f=e.options)!=null&&f.waitForStabilization){const w=e.options.stabilizationTimeoutMs||300;await new Promise(E=>setTimeout(E,Math.min(2e3,w)))}h.disconnect();let y;t.contains(n)&&(y=k.inspectElement(n,this.registry));const v=Date.now()-s,m=a!=null&&a.__FORENSIC_CONSOLE_BUFFER__?a.__FORENSIC_CONSOLE_BUFFER__.slice(c).filter(w=>(w==null?void 0:w.level)==="error").length:0,d=a!=null&&a.__FORENSIC_NETWORK_BUFFER__?a.__FORENSIC_NETWORK_BUFFER__.slice(u).length:0;return{success:!0,action:e.action,target:y||i,beforeState:i,afterState:y,effects:{domMutations:r,consoleErrors:m,networkRequests:d,runtimeErrors:o},durationMs:v,stabilized:p}}async dispatchAction(e,t){var n,i,r,o,a,c;const s=e;switch(t.action){case"click":{this.scrollIntoViewIfNeeded(e),await this.timing("move"),await this.timing("click"),this.dispatchMouseEvent(e,"pointerdown"),this.dispatchMouseEvent(e,"mousedown"),typeof s.focus=="function"&&s.focus(),this.dispatchMouseEvent(e,"pointerup"),this.dispatchMouseEvent(e,"mouseup"),typeof s.click=="function"?s.click():this.dispatchMouseEvent(e,"click");break}case"double_click":{this.scrollIntoViewIfNeeded(e),await this.timing("click"),this.dispatchMouseEvent(e,"click"),await this.timing("click"),this.dispatchMouseEvent(e,"click"),this.dispatchMouseEvent(e,"dblclick");break}case"right_click":{this.scrollIntoViewIfNeeded(e),await this.timing("click"),this.dispatchMouseEvent(e,"pointerdown",{button:2}),this.dispatchMouseEvent(e,"mousedown",{button:2}),this.dispatchMouseEvent(e,"contextmenu",{button:2});break}case"hover":{await this.timing("move"),this.dispatchMouseEvent(e,"pointerenter"),this.dispatchMouseEvent(e,"mouseenter"),this.dispatchMouseEvent(e,"mouseover"),await this.timing("move"),this.dispatchMouseEvent(e,"mousemove");break}case"focus":{typeof s.focus=="function"&&s.focus(),e.dispatchEvent(new FocusEvent("focus",{bubbles:!0}));break}case"blur":{typeof s.blur=="function"&&s.blur(),e.dispatchEvent(new FocusEvent("blur",{bubbles:!0}));break}case"type":{const u=t.text||"",h=e,g=((n=e.ownerDocument)==null?void 0:n.defaultView)||(typeof window<"u"?window:null);typeof s.focus=="function"&&s.focus();for(const y of u){await this.timing("type");const v=d=>{try{const w=(g==null?void 0:g.KeyboardEvent)||(typeof KeyboardEvent<"u"?KeyboardEvent:null);if(w)return new w(d,{key:y,bubbles:!0})}catch{}const f=(g==null?void 0:g.CustomEvent)||(g==null?void 0:g.Event)||CustomEvent;return new f(d,{bubbles:!0,cancelable:!0})},m=(d,f)=>{try{const E=(g==null?void 0:g.InputEvent)||(typeof InputEvent<"u"?InputEvent:null);if(E)return new E(d,f)}catch{}const w=(g==null?void 0:g.CustomEvent)||(g==null?void 0:g.Event)||CustomEvent;return new w(d,{bubbles:!0,cancelable:!0})};e.dispatchEvent(v("keydown")),e.dispatchEvent(v("keypress")),"value"in h&&(h.value=(h.value||"")+y),e.dispatchEvent(m("input",{data:y,inputType:"insertText",bubbles:!0})),e.dispatchEvent(v("keyup"))}const p=(g==null?void 0:g.Event)||Event;e.dispatchEvent(new p("change",{bubbles:!0}));break}case"clear":{const u=e,h=((i=e.ownerDocument)==null?void 0:i.defaultView)||(typeof window<"u"?window:null);if("value"in u){u.value="";const g=(y,v)=>{try{const d=(h==null?void 0:h.InputEvent)||(typeof InputEvent<"u"?InputEvent:null);if(d)return new d(y,v)}catch{}const m=(h==null?void 0:h.CustomEvent)||(h==null?void 0:h.Event)||CustomEvent;return new m(y,{bubbles:!0,cancelable:!0})};e.dispatchEvent(g("input",{inputType:"deleteContentBackward",bubbles:!0}));const p=(h==null?void 0:h.Event)||Event;e.dispatchEvent(new p("change",{bubbles:!0}))}break}case"press_key":{const u=t.key||"Enter",h=((r=e.ownerDocument)==null?void 0:r.defaultView)||(typeof window<"u"?window:null),g=p=>{try{const v=(h==null?void 0:h.KeyboardEvent)||(typeof KeyboardEvent<"u"?KeyboardEvent:null);if(v)return new v(p,{key:u,bubbles:!0})}catch{}const y=(h==null?void 0:h.CustomEvent)||(h==null?void 0:h.Event)||CustomEvent;return new y(p,{bubbles:!0,cancelable:!0})};e.dispatchEvent(g("keydown")),e.dispatchEvent(g("keypress")),e.dispatchEvent(g("keyup"));break}case"select_option":{const u=e;((o=u.tagName)==null?void 0:o.toLowerCase())==="select"&&t.optionValue&&(u.value=t.optionValue,e.dispatchEvent(new Event("change",{bubbles:!0})));break}case"scroll_into_view":{this.scrollIntoViewIfNeeded(e,!0);break}case"scroll":{const u=((a=t.scrollDelta)==null?void 0:a.x)||0,h=((c=t.scrollDelta)==null?void 0:c.y)||0;typeof e.scrollBy=="function"&&e.scrollBy(u,h);break}default:throw new Error(`Unsupported interaction action: ${t.action}`)}}scrollIntoViewIfNeeded(e,t=!1){if(typeof e.scrollIntoView=="function")try{e.scrollIntoView({behavior:"auto",block:"center",inline:"center"})}catch{e.scrollIntoView(t)}}dispatchMouseEvent(e,t,s={}){const n=e.getBoundingClientRect?e.getBoundingClientRect():{left:0,top:0,width:0,height:0},i=n.left+n.width/2,r=n.top+n.height/2,o=new MouseEvent(t,{bubbles:s.bubbles!==void 0?s.bubbles:!0,cancelable:s.cancelable!==void 0?s.cancelable:!0,clientX:i,clientY:r,button:s.button||0,buttons:s.button===2?2:1});e.dispatchEvent(o)}}class ie{static matches(e,t){if(!e||e.nodeType!==$.ELEMENT_NODE)return!1;const s=t.trim();return s?s.includes(",")?s.split(",").some(n=>this.matchesSimple(e,n.trim())):this.matchesCompound(e,s):!1}static querySelector(e,t,s){const n=this.querySelectorAll(e,t,s,1);return n.length>0?n[0]:null}static querySelectorAll(e,t,s,n=1/0){const i=[],r=s[t];if(!r)return i;const o=[...r.children||[]],a=new Set;for(;o.length>0&&i.length =n))break;u.children&&u.children.length>0&&o.push(...u.children)}}return i}static getElementById(e,t){for(const s of Object.values(t))if(s.nodeType===$.ELEMENT_NODE&&!s.isDetached&&s.attributes&&s.attributes.id===e&&this.isNodeConnected(s,t))return s;return null}static isNodeConnected(e,t){if(e.isDetached)return!1;let s=e;const n=new Set;for(;s&&s.parentId;){if(n.has(s.id))return!1;n.add(s.id);const i=t[s.parentId];if(!i||i.isDetached)return!1;s=i}return!0}static computeSelector(e,t){var r,o;if(!e)return"";if(e.nodeType!==$.ELEMENT_NODE)return e.tagName||`#node-${e.id}`;if((r=e.attributes)!=null&&r.id)return`#${e.attributes.id}`;const s=e.tagName||"div",n=(((o=e.attributes)==null?void 0:o.class)||"").split(/\s+/).filter(a=>a&&!a.startsWith("ng-")).slice(0,2),i=n.length>0?"."+n.join("."):"";if(e.parentId&&t[e.parentId]){const c=(t[e.parentId].children||[]).map(u=>t[u]).filter(u=>u&&u.nodeType===$.ELEMENT_NODE&&u.tagName===s);if(c.length>1){const u=c.findIndex(h=>h.id===e.id)+1;return`${s}${i}:nth-of-type(${u})`}}return`${s}${i}`}static matchesCompound(e,t){return this.matchesSimple(e,t)}static matchesSimple(e,t){var i,r,o,a,c,u,h;const s=((i=e.tagName)==null?void 0:i.toLowerCase())||"";if(t==="*")return!0;if(t.startsWith("#")){const g=t.substring(1);return((r=e.attributes)==null?void 0:r.id)===g}if(t.startsWith(".")){const g=t.substring(1);return(((o=e.attributes)==null?void 0:o.class)||"").split(/\s+/).includes(g)}if(t.startsWith("[")&&t.endsWith("]")){const g=t.substring(1,t.length-1);if(g.includes("=")){const[p,y]=g.split("="),v=y.replace(/^["']|["']$/g,"");return((a=e.attributes)==null?void 0:a[p.trim()])===v}return!!((c=e.attributes)!=null&&c[g.trim()])}const n=t.match(/^([a-zA-Z0-9_-]+)(.*)$/);if(n){const g=n[1].toLowerCase(),p=n[2];if(g!==s&&g!=="*")return!1;if(!p)return!0;if(p.startsWith("#"))return((u=e.attributes)==null?void 0:u.id)===p.substring(1);if(p.startsWith("."))return(((h=e.attributes)==null?void 0:h.class)||"").split(/\s+/).includes(p.substring(1));if(p.startsWith("["))return this.matchesSimple(e,p)}return!1}}class De{static traceElement(e,t,s){var M,L;const n=[...t].sort((I,C)=>I.sequence-C.sequence);let i=e.nodeId,r="unknown",o=e.selector||"",a={},c=0,u=0,h="init";if(!i&&e.selector&&s){const I=ie.querySelector(e.selector,s.rootId,s.nodes);I&&(i=I.id,r=I.tagName||"element",a={...I.attributes||{}},o=e.selector)}if(!i&&e.selector){for(const I of n)if(I.type==="DOM_MUTATION_ADD"){const C=I.payload;if(C.node&&ie.matches(C.node,e.selector)){i=C.node.id,r=C.node.tagName||"element",a={...C.node.attributes||{}},c=I.timestamp,u=I.sequence,h=I.id;break}}}if(!i)return null;const g=[];let p=!0,y=null,v=null,m,d=0;if(s&&s.nodes[i]){const I=s.nodes[i];r=I.tagName||r,a={...I.attributes||{}},o||(o=ie.computeSelector(I,s.nodes)),g.push({timestamp:s.timestamp,sequence:s.sequence,wallClockTime:Date.now(),stage:"CREATED",eventId:s.snapshotId,eventType:"DOM_SNAPSHOT",description:`Element <${r}> existed in initial baseline snapshot [ID: ${i}]`,details:{initialParentId:I.parentId,attributes:a},nodeSnapshot:I})}const f=new Map;if(s)for(const[I,C]of Object.entries(s.nodes))f.set(Number(I),C.parentId??null);const w=(I,C)=>{let R=f.get(C);const P=new Set;for(;R&&!P.has(R);){if(R===I)return!0;P.add(R),R=f.get(R)}return!1};for(const I of n){const C=I.timestamp,R=I.sequence,P=I.wallClockTime;if(I.type==="DOM_MUTATION_ADD"){const A=I.payload;(M=A.node)!=null&&M.id&&f.set(A.node.id,A.parentId??null),((L=A.node)==null?void 0:L.id)===i&&(p=!0,r=A.node.tagName||r,c=C,u=R,h=I.id,a={...A.node.attributes||{}},g.push({timestamp:C,sequence:R,wallClockTime:P,stage:"ATTACHED_TO_DOM",eventId:I.id,eventType:I.type,description:`Element <${r}> added to DOM under parent ID ${A.parentId}`,details:{parentId:A.parentId,index:A.index},nodeSnapshot:A.node}))}if(I.type==="DOM_MUTATION_REMOVE"){const A=I.payload;A.nodeId===i?(p=!1,y=C,v=R,m=I.id,g.push({timestamp:C,sequence:R,wallClockTime:P,stage:"REMOVED_FROM_DOM",eventId:I.id,eventType:I.type,description:`Element <${r}> explicitly removed from parent ID ${A.parentId}`,details:{parentId:A.parentId,removedIndex:A.index}})):w(A.nodeId,i)&&(p=!1,y=C,v=R,m=I.id,g.push({timestamp:C,sequence:R,wallClockTime:P,stage:"PARENT_SUBTREE_REPLACED",eventId:I.id,eventType:I.type,description:`Ancestor element [ID: ${A.nodeId}] was removed, causing target element [ID: ${i}] to detach from DOM`,details:{removedAncestorId:A.nodeId,parentId:A.parentId}}))}if(I.type==="DOM_MUTATION_MOVE"){const A=I.payload;A.nodeId&&f.set(A.nodeId,A.newParentId??null),A.nodeId===i&&(d++,g.push({timestamp:C,sequence:R,wallClockTime:P,stage:"REPARENTED",eventId:I.id,eventType:I.type,description:`Element reparented from parent ${A.oldParentId} to ${A.newParentId}`,details:{oldParentId:A.oldParentId,newParentId:A.newParentId}}))}if(I.type==="DOM_MUTATION_ATTR"){const A=I.payload;if(A.nodeId===i){d++;const se=A.attributeName.toLowerCase();let z="ATTRIBUTE_MODIFIED";se==="class"&&(z="CLASS_MODIFIED"),se==="style"&&(z="STYLE_MODIFIED"),g.push({timestamp:C,sequence:R,wallClockTime:P,stage:z,eventId:I.id,eventType:I.type,description:`Attribute '${A.attributeName}' changed from '${A.oldValue??""}' to '${A.newValue??""}'`,details:{attributeName:A.attributeName,oldValue:A.oldValue,newValue:A.newValue}})}}if(I.type==="DOM_MUTATION_TEXT"){const A=I.payload;A.nodeId===i&&(d++,g.push({timestamp:C,sequence:R,wallClockTime:P,stage:"TEXT_MODIFIED",eventId:I.id,eventType:I.type,description:`Text content changed: "${A.oldText}" → "${A.newText}"`,details:{oldText:A.oldText,newText:A.newText}}))}}const E=y??c,S=500,T=n.filter(I=>(I.category==="ERROR"||I.category==="CONSOLE")&&Math.abs(I.timestamp-E)<=S),x=n.filter(I=>I.category==="NETWORK"&&Math.abs(I.timestamp-E)<=S),N=n.length>0?n[n.length-1].timestamp:c,D=Math.max(0,(y??N)-c);return{targetNodeId:i,tagName:r,selectorHint:o,initialAttributes:a,createdAt:c,createdSequence:u,createdEventId:h,removedAt:y,removedSequence:v,removedEventId:m,isCurrentlyAlive:p,lifespanMs:Math.round(D*100)/100,mutationCount:d,entries:g,correlatedDiagnostics:T,correlatedNetwork:x}}}class $e{static analyze(e,t,s){var D,M,L,I;const n=typeof e=="number"?{nodeId:e}:{selector:e},i=De.traceElement(n,t,s);if(!i)return{targetQuery:e,found:!1,disappearanceMechanism:"UNKNOWN",likelyRootCause:"Target element could not be found in recording baseline or event stream",confidenceScore:0,detailedExplanation:`No element matching "${e}" was ever created, recorded in the initial DOM snapshot, or observed in mutation events.`,evidentiaryTrail:[],precedingEvents:[],followingEvents:[],correlatedErrors:[],correlatedNetworkCalls:[],alternativeHypotheses:[{hypothesis:"Element was injected into an unmonitored isolated iframe or ShadowRoot closed mode",likelihood:40,evidenceFor:["Element query yielded zero matches in monitored document"],evidenceAgainst:["Iframes/ShadowRoots were accessible in this session"]},{hypothesis:"Selector typo or timing mismatch",likelihood:60,evidenceFor:["Target selector did not match any recorded tag or class"],evidenceAgainst:[]}]};const r=[...t].sort((C,R)=>C.sequence-R.sequence),o=[],a=[];let c="UNKNOWN",u="Unknown disappearance mechanism",h=50,g="",p=i.removedAt??void 0;const y=i.entries.find(C=>C.stage==="REMOVED_FROM_DOM"),v=i.entries.find(C=>C.stage==="PARENT_SUBTREE_REPLACED"),m=i.entries.find(C=>C.stage==="CLASS_MODIFIED"&&/\b(hidden|hide|d-none|invisible|collapsed)\b/i.test(String(C.details.newValue||""))),d=i.entries.find(C=>C.stage==="STYLE_MODIFIED"&&/display\s*:\s*none|visibility\s*:\s*hidden|opacity\s*:\s*0/i.test(String(C.details.newValue||"")));y?(c="DIRECT_NODE_REMOVAL",p=y.timestamp,u=`Element [ID: ${i.targetNodeId}] <${i.tagName}> was directly removed from its parent [ID: ${y.details.parentId}] via DOM removeChild/replaceChild`,h=95,o.push({timestamp:y.timestamp,sequence:y.sequence,eventId:y.eventId,eventType:y.eventType,evidenceType:"DIRECT",description:`Direct DOM removal mutation: element detached from parent ID ${y.details.parentId}`,confidenceContribution:50})):v?(c="PARENT_SUBTREE_REPLACED",p=v.timestamp,u=`Host framework (e.g. React/Vue re-render) destroyed and replaced Ancestor container [ID: ${v.details.removedAncestorId}], causing injected element to be unmounted`,h=92,o.push({timestamp:v.timestamp,sequence:v.sequence,eventId:v.eventId,eventType:v.eventType,evidenceType:"DIRECT",description:`Ancestor container [ID: ${v.details.removedAncestorId}] was removed, wiping out all child subtrees`,confidenceContribution:50})):d?(c="STYLE_DISPLAY_NONE",p=d.timestamp,u=`Element was visually hidden by an inline style modification: "${d.details.newValue}"`,h=88,o.push({timestamp:d.timestamp,sequence:d.sequence,eventId:d.eventId,eventType:d.eventType,evidenceType:"DIRECT",description:`Inline style changed to "${d.details.newValue}"`,confidenceContribution:45})):m?(c="CLASS_TRIGGERED_HIDDEN",p=m.timestamp,u=`Element was visually hidden because its CSS class list was modified to include "${m.details.newValue}"`,h=85,o.push({timestamp:m.timestamp,sequence:m.sequence,eventId:m.eventId,eventType:m.eventType,evidenceType:"DIRECT",description:`Class list changed from "${m.details.oldValue??""}" to "${m.details.newValue??""}"`,confidenceContribution:45})):i.isCurrentlyAlive&&(c="UNKNOWN",u=`Element [ID: ${i.targetNodeId}] is currently alive and attached to the DOM tree (no unmount mutation detected)`,h=70,g="The element exists in the current DOM state. If it is not visible on screen, it may be clipped by viewport boundaries, z-index stacking context, or 0x0 pixel dimensions.");const f=p??i.createdAt,w=500,E=r.filter(C=>C.timestamp>=f-w&&C.timestamp C.timestamp>f&&C.timestamp<=f+w),T=E.filter(C=>C.category==="ERROR");if(T.length>0){const C=T[0],R=((D=C.payload)==null?void 0:D.message)||"Unknown runtime error";o.push({timestamp:C.timestamp,sequence:C.sequence,eventId:C.id,eventType:C.type,evidenceType:"PRECEDING",description:`Runtime error occurred ${(f-C.timestamp).toFixed(1)}ms before disappearance: "${R}"`,confidenceContribution:20,rawEvent:C}),u+=` (preceded by runtime error: "${R}")`}const x=E.filter(C=>C.type==="NETWORK_RESPONSE_COMPLETE"||C.type==="NETWORK_REQUEST_FAILED");if(x.length>0){const C=x[0],R=((M=C.payload)==null?void 0:M.url)||"network request";o.push({timestamp:C.timestamp,sequence:C.sequence,eventId:C.id,eventType:C.type,evidenceType:"PRECEDING",description:`Network response completed ${(f-C.timestamp).toFixed(1)}ms before disappearance: ${R}`,confidenceContribution:15,rawEvent:C})}const N=E.filter(C=>C.category==="NAVIGATION");if(N.length>0){const C=N[0];o.push({timestamp:C.timestamp,sequence:C.sequence,eventId:C.id,eventType:C.type,evidenceType:"PRECEDING",description:`Navigation event (${(L=C.payload)==null?void 0:L.navigationType}) occurred ${(f-C.timestamp).toFixed(1)}ms before disappearance`,confidenceContribution:25,rawEvent:C}),u+=` following SPA navigation to "${(I=C.payload)==null?void 0:I.url}"`}return g||(g=[`Element <${i.tagName}> (Logical ID: ${i.targetNodeId}, selector: "${i.selectorHint}") was created at ${i.createdAt.toFixed(1)}ms.`,`It remained alive in the DOM for ${i.lifespanMs.toFixed(1)}ms and experienced ${i.mutationCount} mutations.`,`At timestamp ${f.toFixed(1)}ms, it disappeared via [${c}].`,`Diagnosis: ${u}.`].join(" ")),c==="PARENT_SUBTREE_REPLACED"?(a.push({hypothesis:"Direct cleanup called by extension code",likelihood:25,evidenceFor:["Element was unmounted shortly after creation"],evidenceAgainst:["Ancestor container mutation was recorded from host page context"]}),a.push({hypothesis:"Host single-page app route change destroyed component tree",likelihood:35,evidenceFor:N.length>0?["Preceding navigation event recorded"]:[],evidenceAgainst:N.length===0?["No navigation events occurred in temporal window"]:[]})):c==="DIRECT_NODE_REMOVAL"&&a.push({hypothesis:"Third-party script or ad-blocker removed the injected node",likelihood:30,evidenceFor:["Direct node removal occurred without ancestor replacement"],evidenceAgainst:["No ad-blocker signatures or extension error logs observed"]}),{targetQuery:e,targetNodeId:i.targetNodeId,found:!0,tagName:i.tagName,selectorHint:i.selectorHint,createdAt:i.createdAt,firstVisibleAt:i.createdAt,lastKnownGoodStateAt:Math.max(0,f-1),disappearedAt:p,lifespanMs:i.lifespanMs,disappearanceMechanism:c,likelyRootCause:u,confidenceScore:Math.min(99,h),detailedExplanation:g,evidentiaryTrail:o,precedingEvents:E,followingEvents:S,correlatedErrors:T,correlatedNetworkCalls:x,alternativeHypotheses:a}}}class qe{constructor(e){b(this,"activeObservation",null);b(this,"registry");b(this,"sequenceCounter");this.registry=e,this.sequenceCounter=new ne}isObserving(){return this.activeObservation!==null}startObservation(e,t=document){this.activeObservation&&this.stopObservation(t);const s=`obs_${Date.now()}_${Math.random().toString(36).slice(2,6)}`,n=Date.now(),i=k.inspectElement(e,this.registry),r=i.bestSelector,o=[],a=this.registry?this.registry.getOrCreateId(e,0):100;o.push({id:`evt_init_${s}`,sessionId:s,timestamp:0,sequence:1,wallClockTime:n,type:"DOM_MUTATION_ADD",category:"DOM",source:"BROWSER_RUNTIME",targetNodeId:a,targetSelector:r,payload:{node:{id:a,nodeType:1,tagName:i.tag,attributes:i.attributes,textContent:i.text,children:[],parentId:null},parentId:null,index:0}});const c=new MutationObserver(u=>{const h=Date.now()-n;for(const g of u)if(g.type==="childList"){for(let p=0;p 0&&(m=$e.analyze(n,a)),{observationId:t,targetSelector:n,targetNodeId:((d=r.forensics)==null?void 0:d.logicalNodeId)||void 0,startTime:i,endTime:u,durationMs:h,initialState:r,finalState:p,disappeared:y,disappearanceReason:v,mutations:a.filter(f=>f.category==="DOM"),diagnostics:a.filter(f=>f.category==="ERROR"||f.category==="CONSOLE"),networkEvents:a.filter(f=>f.category==="NETWORK"),screenshots:c,correlationReport:m}}}class Pe{constructor(e={}){b(this,"isExplicitModeActive",!1);b(this,"isGlobalShortcutActive",!1);b(this,"highlighterEl",null);b(this,"badgeEl",null);b(this,"lastSelectedElement",null);b(this,"options",{});b(this,"onMouseMoveBound");b(this,"onClickBound");b(this,"onKeyDownBound");b(this,"onGlobalClickBound");this.options=e,this.onMouseMoveBound=this.handleMouseMove.bind(this),this.onClickBound=this.handleClick.bind(this),this.onKeyDownBound=this.handleKeyDown.bind(this),this.onGlobalClickBound=this.handleGlobalCtrlShiftClick.bind(this),this.initGlobalShortcutListener()}initGlobalShortcutListener(){typeof window>"u"||this.isGlobalShortcutActive||(window.addEventListener("click",this.onGlobalClickBound,!0),this.isGlobalShortcutActive=!0)}startPicker(e){typeof document>"u"||(e&&(this.options={...this.options,...e}),!this.isExplicitModeActive&&(this.isExplicitModeActive=!0,this.ensureHighlighter(),document.body&&(document.body.style.cursor="crosshair"),window.addEventListener("mousemove",this.onMouseMoveBound,!0),window.addEventListener("click",this.onClickBound,!0),window.addEventListener("keydown",this.onKeyDownBound,!0)))}stopPicker(){this.isExplicitModeActive&&(this.isExplicitModeActive=!1,typeof document<"u"&&document.body&&(document.body.style.cursor="default"),this.removeHighlighter(),typeof window<"u"&&(window.removeEventListener("mousemove",this.onMouseMoveBound,!0),window.removeEventListener("click",this.onClickBound,!0),window.removeEventListener("keydown",this.onKeyDownBound,!0)))}getLastSelectedElement(){return this.lastSelectedElement}setSelectedElement(e){let t;return"tag"in e&&"bestSelector"in e&&typeof e.getAttribute!="function"?t=e:(t=k.inspectElement(e,this.options.nodeRegistry),this.flashSelection(e)),this.lastSelectedElement=t,this.options.onSelected&&this.options.onSelected(t),t}handleGlobalCtrlShiftClick(e){if(!e.ctrlKey||!e.shiftKey)return;const t=e.target;if(!t||this.isExtensionOwned(t))return;e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation();const s=this.setSelectedElement(t);this.notifyExtension(s)}handleMouseMove(e){if(!this.isExplicitModeActive)return;const t=e.target;if(!t||this.isExtensionOwned(t)){this.hideHighlighter();return}this.updateHighlighter(t)}handleClick(e){if(!this.isExplicitModeActive)return;const t=e.target;if(!t||this.isExtensionOwned(t))return;e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation();const s=this.setSelectedElement(t);this.notifyExtension(s),this.stopPicker()}handleKeyDown(e){e.key==="Escape"&&this.isExplicitModeActive&&(e.preventDefault(),this.stopPicker(),this.options.onCanceled&&this.options.onCanceled())}isExtensionOwned(e){return!!(e.id==="forensic-recorder-floating-host"||e.id==="forensic-inspect-highlighter"||e.closest("#forensic-recorder-floating-host")||e.closest("#forensic-inspect-highlighter")||e.hasAttribute("data-forensic-internal")||e.closest("[data-forensic-internal]"))}ensureHighlighter(){if(typeof document>"u"||this.highlighterEl)return;const e=this.options.highlightColor||"#0ea5e9",t=document.createElement("div");t.id="forensic-inspect-highlighter",t.setAttribute("data-forensic-internal","true"),t.style.position="fixed",t.style.pointerEvents="none",t.style.zIndex="2147483640",t.style.border=`2px solid ${e}`,t.style.background="rgba(14, 165, 233, 0.18)",t.style.borderRadius="3px",t.style.boxShadow=`0 0 12px ${e}88`,t.style.transition="all 0.05s ease-out",t.style.display="none";const s=document.createElement("div");s.setAttribute("data-forensic-internal","true"),s.style.position="absolute",s.style.bottom="100%",s.style.left="0",s.style.transform="translateY(-4px)",s.style.background="#0f172a",s.style.color="#38bdf8",s.style.fontSize="11px",s.style.fontFamily="monospace",s.style.fontWeight="bold",s.style.padding="2px 6px",s.style.borderRadius="3px",s.style.boxShadow="0 2px 6px rgba(0,0,0,0.5)",s.style.whiteSpace="nowrap",s.style.pointerEvents="none",t.appendChild(s),document.body.appendChild(t),this.highlighterEl=t,this.badgeEl=s}updateHighlighter(e){if(this.ensureHighlighter(),!this.highlighterEl||!this.badgeEl)return;const t=e.getBoundingClientRect();this.highlighterEl.style.display="block",this.highlighterEl.style.left=`${t.left}px`,this.highlighterEl.style.top=`${t.top}px`,this.highlighterEl.style.width=`${Math.max(1,t.width)}px`,this.highlighterEl.style.height=`${Math.max(1,t.height)}px`;const s=e.tagName.toLowerCase(),n=e.id?`#${e.id}`:"",i=e.className&&typeof e.className=="string"?"."+e.className.split(/\s+/)[0]:"",r=`${Math.round(t.width)}×${Math.round(t.height)}`;this.badgeEl.textContent=`<${s}${n}${i}> [${r}]`}hideHighlighter(){this.highlighterEl&&(this.highlighterEl.style.display="none")}removeHighlighter(){this.highlighterEl&&this.highlighterEl.parentElement&&this.highlighterEl.remove(),this.highlighterEl=null,this.badgeEl=null}flashSelection(e){if(typeof document>"u"||!e.getBoundingClientRect)return;const t=e.getBoundingClientRect(),s=document.createElement("div");s.setAttribute("data-forensic-internal","true"),s.style.position="fixed",s.style.left=`${t.left}px`,s.style.top=`${t.top}px`,s.style.width=`${Math.max(1,t.width)}px`,s.style.height=`${Math.max(1,t.height)}px`,s.style.border="2px solid #22c55e",s.style.background="rgba(34, 197, 94, 0.25)",s.style.zIndex="2147483645",s.style.pointerEvents="none",s.style.transition="opacity 0.6s ease-out",document.body.appendChild(s),setTimeout(()=>{s.style.opacity="0",setTimeout(()=>s.remove(),600)},400)}notifyExtension(e){var t;try{typeof chrome<"u"&&((t=chrome.runtime)!=null&&t.sendMessage)&&chrome.runtime.sendMessage({type:"ELEMENT_SELECTED",elementInfo:e,timestamp:Date.now()})}catch{}}destroy(){this.stopPicker(),typeof window<"u"&&window.removeEventListener("click",this.onGlobalClickBound,!0),this.isGlobalShortcutActive=!1}}class ge{static getCrcTable(){if(this.crcTable)return this.crcTable;const e=new Uint32Array(256);for(let t=0;t<256;t++){let s=t;for(let n=0;n<8;n++)s=s&1?3988292384^s>>>1:s>>>1;e[t]=s>>>0}return this.crcTable=e,e}static crc32(e,t=0,s=e.length){const n=this.getCrcTable();let i=4294967295;for(let r=t;r >>8^n[(i^e[r])&255];return(i^4294967295)>>>0}static adler32(e){let t=1,s=0;for(let n=0;n >>0}static createPNG(e){const t=Math.max(1,Math.min(1920,Math.floor(e.width))),s=Math.max(1,Math.min(1080,Math.floor(e.height))),n=e.backgroundColor||[15,23,42,255],i=e.headerColor||[56,189,248,255],r=e.borderColor||[99,102,241,255],o=1+t*4,a=new Uint8Array(o*s),c=Math.min(30,Math.floor(s*.2));for(let d=0;d =e.length,g=new Uint8Array(5+u);g[0]=h?1:0,g[1]=u&255,g[2]=u>>>8&255;const p=~u&65535;g[3]=p&255,g[4]=p>>>8&255,g.set(e.subarray(n,n+u),5),t.push(g),n+=u}const i=t.reduce((c,u)=>c+u.length,0)+2+4,r=new Uint8Array(i);let o=0;r[o++]=120,r[o++]=1;for(const c of t)r.set(c,o),o+=c.length;const a=this.adler32(e);return r[o++]=a>>>24&255,r[o++]=a>>>16&255,r[o++]=a>>>8&255,r[o++]=a&255,r}static writeChunk(e,t,s,n){const i=n.length,r=new DataView(e.buffer,e.byteOffset,e.byteLength);r.setUint32(t,i,!1),t+=4;const o=new Uint8Array(4+i);for(let c=0;c<4;c++){const u=s.charCodeAt(c);e[t+c]=u,o[c]=u}t+=4,i>0&&(e.set(n,t),o.set(n,4),t+=i);const a=this.crc32(o);return r.setUint32(t,a,!1),t+=4,t}}b(ge,"crcTable",null);const Q=500;class Ue{constructor(e,t){b(this,"history",[]);b(this,"undoStack",[]);b(this,"redoStack",[]);b(this,"counter",0);b(this,"transaction",null);this.doc=e,this.registry=t}mutate(e){var h;const t=`mut_${Date.now().toString(36)}_${++this.counter}`,s=Date.now();let n;try{n=this.resolveTarget(e.target)}catch(g){return this.failure(t,e,null,g.message,Date.now()-s)}const i=this.snapshotState(n);let r=null,o=null,a,c=!0;try{const g=this.applyOperation(t,e,n);g&&(this.transaction?this.transaction.undoRecords.push(g):(this.undoStack.push(g),this.redoStack=[]));const y=(n.isConnected!==void 0?n.isConnected:this.doc.contains(n))?n:this.doc.querySelector(i.selector)||n;r=this.snapshotState(y),o=this.quickDiff(i,r,n)}catch(g){c=!1,a=g.message,r=null}const u={mutationId:t,operation:e.operation,success:c,before:i,after:r,diff:o,affectedSelector:c?i.selector:null,durationMs:Date.now()-s,error:a,undoable:c&&(this.transaction?this.transaction.undoRecords.length>0:this.undoStack.length>0)};return this.transaction&&this.transaction.steps.push({stepId:`step_${this.transaction.steps.length+1}`,mutation:u}),this.pushHistory({mutationId:t,transactionId:(h=this.transaction)==null?void 0:h.id,timestamp:Date.now(),operation:e.operation,targetSelector:i.selector,success:c,summary:`${e.operation} on ${i.selector}${o?` (+${o.added}/-${o.removed}/~${o.changed})`:""}`,undoApplied:!1,redoApplied:!1}),u}beginTransaction(){if(this.transaction)throw new Error(`TRANSACTION_ALREADY_OPEN: ${this.transaction.id} — commit or rollback first.`);return this.transaction={id:`tx_${Date.now().toString(36)}_${++this.counter}`,steps:[],undoRecords:[]},this.transaction.id}commitTransaction(e){if(!this.transaction)throw new Error("NO_OPEN_TRANSACTION: begin a transaction before committing.");const t=this.transaction,s=Date.now();let n=!0,i;if(e)try{n=e({id:t.id,steps:t.steps})!==!1,n||(i="VERIFY_FAILED: caller verification rejected the transaction state.")}catch(o){n=!1,i=`VERIFY_ERROR: ${o.message}`}if(!n)return this.rollbackInternal(t,i||"VERIFY_FAILED",s);this.undoStack.push(...t.undoRecords),this.undoStack.length>Q&&this.undoStack.splice(0,this.undoStack.length-Q),this.redoStack=[];const r=this.summaryOf(t);return this.transaction=null,{transactionId:t.id,committed:!0,rolledBack:!1,steps:t.steps,durationMs:Date.now()-s,finalStateSummary:r}}rollbackTransaction(e){if(!this.transaction)throw new Error("NO_OPEN_TRANSACTION: begin a transaction before rolling back.");const t=this.transaction;return this.rollbackInternal(t,e||"ROLLBACK_REQUESTED",Date.now())}rollbackInternal(e,t,s){for(const i of[...e.undoRecords].reverse())try{this.applyUndo(i)}catch{}const n=this.summaryOf(e);return this.transaction=null,{transactionId:e.id,committed:!1,rolledBack:!0,steps:e.steps,error:t,durationMs:Date.now()-s,finalStateSummary:n}}undo(){const e=this.transaction?this.transaction.undoRecords:this.undoStack,t=e.pop();if(!t)return{success:!1,message:"Nothing to undo — the mutation history is empty."};try{this.applyUndo(t)}catch(s){return e.push(t),{success:!1,mutationId:t.mutationId,message:`UNDO_FAILED: ${s.message}`}}return this.redoStack.push(t),this.markHistory(t.mutationId,"undo"),{success:!0,mutationId:t.mutationId,message:`Undid ${t.operation} on ${t.targetSelector}.`}}redo(){const e=this.redoStack.pop();if(!e)return{success:!1,message:"Nothing to redo — no undone mutation is pending."};try{const t=this.resolveTarget({selector:e.targetSelector}),s={operation:e.operation,target:{selector:e.targetSelector}};return this.reapplyRecord(e,t,s)?((this.transaction?this.transaction.undoRecords:this.undoStack).push(e),this.markHistory(e.mutationId,"redo"),{success:!0,mutationId:e.mutationId,message:`Redid ${e.operation} on ${e.targetSelector}.`}):(this.redoStack.push(e),{success:!1,mutationId:e.mutationId,message:"REDO_FAILED: target state diverged — cannot safely reapply."})}catch(t){return this.redoStack.push(e),{success:!1,mutationId:e.mutationId,message:`REDO_FAILED: ${t.message}`}}}getHistory(e=100){return this.history.slice(-e)}getUndoDepth(){return this.transaction?this.transaction.undoRecords.length:this.undoStack.length}getRedoDepth(){return this.redoStack.length}getOpenTransactionId(){var e;return((e=this.transaction)==null?void 0:e.id)||null}preview(e){var t;try{const s=this.resolveTarget(e.target),n=[];let i=1;(e.operation==="set_inner_html"||e.operation==="set_outer_html")&&(n.push("HTML replacement can destroy descendant node identity — captured regions targeting children may become stale."),i=s.querySelectorAll("*").length+1),(e.operation==="remove_element"||e.operation==="unwrap_element")&&(n.push("Removal is destructive; the undo record preserves the full serialized subtree."),i=s.querySelectorAll("*").length+1),e.operation==="move_element"&&!e.parent&&n.push("No parent target supplied — move requires payload.parent."),e.operation==="wrap_element"&&!e.newElementHtml&&n.push("No wrapper HTML supplied — a neutralwrapper will be generated.");const r=He(e,s);return{valid:n.filter(o=>o.includes("requires")||o.includes("No parent")).length===0,operation:e.operation,target:{selector:this.snapshotState(s).selector,tag:s.tagName.toLowerCase()},expectedChange:r,affectedNodes:i,warnings:n}}catch(s){return{valid:!1,operation:e.operation,target:{selector:String(((t=e.target)==null?void 0:t.selector)||""),tag:""},expectedChange:"—",affectedNodes:0,warnings:[],error:s.message}}}applyOperation(e,t,s){var r;const n=this.snapshotState(s).selector,i=t.operation;switch(i){case"set_attribute":{if(!t.attribute)throw new Error("ATTRIBUTE_REQUIRED: payload.attribute is missing.");const o=s.getAttribute(t.attribute);return s.setAttribute(t.attribute,t.value??""),this.undoFor(e,i,n,{kind:o===null?"remove-attribute":"restore-attribute",attribute:t.attribute,value:o})}case"remove_attribute":{if(!t.attribute)throw new Error("ATTRIBUTE_REQUIRED: payload.attribute is missing.");const o=s.getAttribute(t.attribute);if(o===null)throw new Error(`ATTRIBUTE_NOT_PRESENT: "${t.attribute}" is not set on ${n}.`);return s.removeAttribute(t.attribute),this.undoFor(e,i,n,{kind:"restore-attribute",attribute:t.attribute,value:o})}case"set_text":{const o=s.textContent||"";return s.textContent=t.text??"",this.undoFor(e,i,n,{kind:"restore-text",text:o})}case"replace_text":{if(!t.text||!t.replacement)throw new Error("TEXT_PATTERNS_REQUIRED: payload.text (search) and payload.replacement are required.");const o=s.textContent||"";return s.textContent=o.split(t.text).join(t.replacement),this.undoFor(e,i,n,{kind:"restore-text",text:o})}case"set_inner_html":{const o=s.innerHTML;return s.innerHTML=t.html??"",this.undoFor(e,i,n,{kind:"restore-outer-html",outerHtml:s.outerHTML.replace(t.html??"",o)||void 0,text:o,attribute:"__inner"})}case"set_outer_html":{const o=s.outerHTML,a=s.parentElement;if(!a)throw new Error("ORPHAN_ELEMENT: element has no parent — cannot replace outer HTML.");const c=this.doc.createComment(`mcpdom_undo_${e}`);s.replaceWith(c);const u=this.doc.createElement("template");u.innerHTML=t.html??"";const h=u.content.firstElementChild;return h?c.replaceWith(h):c.replaceWith(this.doc.createTextNode(t.html??"")),this.undoFor(e,i,n,{kind:"reinsert-node",outerHtml:o,parentSelector:this.snapshotState(a).selector,nextSiblingSelector:this.siblingSelector(h||s)})}case"add_class":{const o=Array.from(s.classList);for(const a of t.classes||[])s.classList.add(a);return this.undoFor(e,i,n,{kind:"restore-classes",classes:o})}case"remove_class":{const o=Array.from(s.classList);for(const a of t.classes||[])s.classList.remove(a);return this.undoFor(e,i,n,{kind:"restore-classes",classes:o})}case"replace_class":{const o=Array.from(s.classList);for(const a of t.classes||[])s.classList.remove(a);return t.value&&s.classList.add(t.value),this.undoFor(e,i,n,{kind:"restore-classes",classes:o})}case"set_style":{const o=this.doc.defaultView;if(!(o!=null&&o.getComputedStyle))throw new Error("STYLE_UNAVAILABLE: computed style API is unavailable in this context.");const a={};for(const c of Object.keys(t.style||{}))a[c]=o.getComputedStyle(s).getPropertyValue(c),s.style.setProperty(c,t.style[c]);return this.undoFor(e,i,n,{kind:"restore-style",style:a})}case"remove_style":{const o={};for(const a of t.classes||[])o[a]=s.style.getPropertyValue(a),s.style.removeProperty(a);return this.undoFor(e,i,n,{kind:"restore-style",style:o})}case"add_element":{const o=t.parent?this.resolveTarget(t.parent):s,a=this.doc.createElement("template");a.innerHTML=t.newElementHtml??"";const c=a.content.firstElementChild;if(!c)throw new Error("INVALID_HTML: payload.newElementHtml does not produce an element.");switch(t.position||"append"){case"before":s.before(c);break;case"after":s.after(c);break;case"prepend":o.prepend(c);break;default:o.appendChild(c)}return this.undoFor(e,i,n,{kind:"remove-node",attribute:this.snapshotState(c).selector})}case"remove_element":{const o=s.outerHTML,a=s.parentElement,c=s.nextElementSibling;return s.remove(),this.undoFor(e,i,n,{kind:"reinsert-node",outerHtml:o,parentSelector:a?this.snapshotState(a).selector:void 0,nextSiblingSelector:c?this.snapshotState(c).selector:null})}case"replace_element":{const o=s.outerHTML,a=s.parentElement,c=this.doc.createElement("template");c.innerHTML=t.newElementHtml??"";const u=c.content.firstElementChild;if(!u)throw new Error("INVALID_HTML: payload.newElementHtml does not produce an element.");const h=s.nextElementSibling;return s.replaceWith(u),this.undoFor(e,i,n,{kind:"reinsert-node",outerHtml:o,parentSelector:a?this.snapshotState(a).selector:void 0,nextSiblingSelector:h?this.snapshotState(h).selector:null})}case"move_element":{if(!t.parent)throw new Error("PARENT_REQUIRED: payload.parent is required for move_element.");const o=this.resolveTarget(t.parent),a=s.outerHTML,c=s.parentElement,u=s.nextElementSibling,h=t.position==="before"||t.position==="prepend"?o.firstElementChild:null;return o[t.position==="prepend"?"prepend":"appendChild"](s),this.undoFor(e,i,n,{kind:"restore-position",parentSelector:c?this.snapshotState(c).selector:void 0,nextSiblingSelector:u?this.snapshotState(u).selector:h?this.snapshotState(h).selector:null,outerHtml:a})}case"wrap_element":{const o=this.doc.createElement("template");o.innerHTML=t.newElementHtml||'';const a=o.content.firstElementChild;if(!a)throw new Error("INVALID_HTML: wrapper template produced no element.");const c=s.parentElement,u=s.nextElementSibling;return s.replaceWith(a),a.appendChild(s),this.undoFor(e,i,n,{kind:"restore-position",parentSelector:c?this.snapshotState(c).selector:void 0,nextSiblingSelector:u?this.snapshotState(u).selector:null})}case"unwrap_element":{const o=s.outerHTML,a=s.parentElement;if(!a)throw new Error("ORPHAN_ELEMENT: cannot unwrap a root-level element.");const c=s.nextElementSibling,u=Array.from(s.children);for(const h of u)a.insertBefore(h,s);return s.remove(),this.undoFor(e,i,n,{kind:"reinsert-node",outerHtml:o,parentSelector:this.snapshotState(a).selector,nextSiblingSelector:c?this.snapshotState(c).selector:null})}case"clone_subtree":{const o=t.parent?this.resolveTarget(t.parent):s.parentElement||s,a=s.cloneNode(!0);if(t.copyAttributes!==!1)for(const c of Array.from(a.attributes))c.name==="id"&&a.removeAttribute("id");return(r=o.appendChild)==null||r.call(o,a),this.undoFor(e,i,n,{kind:"remove-node",attribute:this.snapshotState(a).selector})}default:throw new Error(`UNKNOWN_OPERATION: ${i} is not a supported DOM mutation.`)}}applyUndo(e){const t=e.inverse;switch(t.kind){case"restore-outer-html":{const s=this.resolveTarget({selector:e.targetSelector});if(t.outerHtml!==void 0){const n=this.doc.createElement("template");n.innerHTML=t.outerHtml;const i=n.content.firstElementChild;i&&s.replaceWith(i)}else t.attribute==="__inner"&&(s.innerHTML=t.text||"");break}case"reinsert-node":{const s=t.parentSelector?this.resolveTarget({selector:t.parentSelector}):this.doc.body,n=this.doc.createElement("template");n.innerHTML=t.outerHtml||"";const i=n.content.firstElementChild;if(!i)throw new Error("UNDO_CORRUPT: serialized subtree could not be restored.");const r=t.nextSiblingSelector?this.safeResolve(t.nextSiblingSelector):null;s.insertBefore(i,r);break}case"remove-node":{const s=this.safeResolve(t.attribute||e.targetSelector);s&&s.remove();break}case"restore-attribute":{this.resolveTarget({selector:e.targetSelector}).setAttribute(t.attribute,t.value??"");break}case"remove-attribute":{this.resolveTarget({selector:e.targetSelector}).removeAttribute(t.attribute);break}case"restore-text":{const s=this.resolveTarget({selector:e.targetSelector});s.textContent=t.text||"";break}case"restore-classes":{const s=this.resolveTarget({selector:e.targetSelector});s.removeAttribute("class");for(const n of t.classes||[])s.classList.add(n);break}case"restore-style":{const s=this.resolveTarget({selector:e.targetSelector});s.style.removeProperty("all");for(const[n,i]of Object.entries(t.style||{}))s.style.setProperty(n,i);break}case"restore-position":{const s=this.doc.createElement("template");s.innerHTML=t.outerHtml||"";const n=s.content.firstElementChild;if(!n)throw new Error("UNDO_CORRUPT: serialized subtree could not be restored.");const i=this.safeResolve(e.targetSelector);i&&i.remove();const r=t.parentSelector?this.safeResolve(t.parentSelector):this.doc.body,o=t.nextSiblingSelector?this.safeResolve(t.nextSiblingSelector):null;(r||this.doc.body).insertBefore(n,o);break}}}reapplyRecord(e,t,s){var i;const n=e.inverse;switch(e.operation){case"set_attribute":return(n.kind==="restore-attribute"||n.kind==="remove-attribute")&&s.value!==void 0?(t.setAttribute(s.attribute||n.attribute||"",s.value),!0):!1;case"add_class":{for(const r of s.classes||[])t.classList.add(r);return(((i=s.classes)==null?void 0:i.length)||0)>0}case"remove_class":{for(const r of s.classes||n.classes||[])t.classList.remove(r);return!0}case"set_text":return s.text!==void 0?(t.textContent=s.text,!0):!1;case"set_inner_html":return s.html!==void 0?(t.innerHTML=s.html,!0):!1;default:return!1}}resolveTarget(e){if(!e)throw new Error("TARGET_REQUIRED: mutation requires a target.");if(typeof e=="string"&&(e={selector:e}),e.selector){try{const t=this.doc.querySelectorAll(e.selector);if(t.length===1)return t[0];if(t.length>1)return Array.from(t).find(n=>{try{return k.inspectElement(n).visibility.isVisible}catch{return!1}})||t[0]}catch(t){throw new Error(`TARGET_INVALID: ${t.message}`)}throw new Error(`TARGET_NOT_FOUND: selector "${e.selector}" matches no element.`)}if(e.xpath){try{const s=this.doc.evaluate(e.xpath,this.doc,null,9,null).singleNodeValue;if(s)return s}catch(t){throw new Error(`TARGET_INVALID_XPATH: ${t.message}`)}throw new Error("TARGET_NOT_FOUND: xpath matches no element.")}if(typeof e.nodeId=="number"&&this.registry){const t=this.registry.getNode(e.nodeId);if(t&&t.nodeType===1&&this.doc.contains(t))return t;throw new Error("TARGET_STALE: logical node id no longer resolves to an attached element.")}throw new Error("TARGET_INVALID: target has neither selector, xpath nor nodeId.")}safeResolve(e){try{return this.doc.querySelector(e)}catch{return null}}snapshotState(e){const t=k.inspectElement(e,this.registry),s=e.outerHTML.length>2e4?e.outerHTML.slice(0,2e4)+"…[truncated]":e.outerHTML;return{selector:t.bestSelector,outerHtml:s,attributes:this.attrsOf(e)}}attrsOf(e){const t={};for(const s of Array.from(e.attributes))t[s.name]=s.value.length>300?s.value.slice(0,300)+"…":s.value;return t}quickDiff(e,t,s){if(!t)return null;let n=0,i=0,r=0;const o=new Set(Object.keys(e.attributes)),a=new Set(Object.keys(t.attributes||{}));for(const u of o)a.has(u)||i++;for(const u of a)o.has(u)?e.attributes[u]!==t.attributes[u]&&r++:n++;e.outerHtml!==t.outerHtml&&n+i+r===0&&r++;const c=s.querySelectorAll?s.querySelectorAll("*").length:0;return{added:n,removed:i,changed:r,summary:`attributes +${n}/-${i}/~${r}; subtree nodes: ${c}`}}undoFor(e,t,s,n){return{mutationId:e,operation:t,targetSelector:s,inverse:n}}siblingSelector(e){try{return this.snapshotState(e).selector}catch{return null}}pushHistory(e){this.history.push(e),this.history.length>Q&&this.history.splice(0,this.history.length-Q)}markHistory(e,t){for(let s=this.history.length-1;s>=0;s--)if(this.history[s].mutationId===e){t==="undo"?this.history[s].undoApplied=!0:this.history[s].redoApplied=!0;return}}summaryOf(e){var n;const t=((n=this.doc.documentElement)==null?void 0:n.outerHTML.length)||0,s=e.steps.filter(i=>i.mutation.success).length;return{domLength:t,diffSummary:`${s}/${e.steps.length} mutations applied`}}failure(e,t,s,n,i){var r;return{mutationId:e,operation:t.operation,success:!1,before:s||{selector:String(((r=t.target)==null?void 0:r.selector)||"?"),outerHtml:"",attributes:{}},after:null,diff:null,affectedSelector:null,durationMs:i,error:n,undoable:!1}}}function He(l,e){switch(l.operation){case"set_attribute":return`attribute "${l.attribute}" will be set to "${(l.value??"").slice(0,40)}"`;case"remove_attribute":return`attribute "${l.attribute}" will be removed`;case"set_text":return`text content will be replaced (${(l.text||"").length} chars)`;case"replace_text":return`every occurrence of "${l.text}" will become "${l.replacement}"`;case"set_inner_html":return`inner HTML will be replaced (${(l.html||"").length} chars)`;case"set_outer_html":return"element (and subtree) will be replaced with provided HTML";case"add_class":return`classes ${(l.classes||[]).join(", ")} will be added`;case"remove_class":return`classes ${(l.classes||[]).join(", ")} will be removed`;case"replace_class":return`classes ${(l.classes||[]).join(", ")} will be replaced with "${l.value}"`;case"set_style":return`inline styles ${Object.keys(l.style||{}).join(", ")} will be set`;case"remove_style":return`inline styles ${(l.classes||[]).join(", ")} will be removed`;case"add_element":return`a new element will be inserted ${l.position||"append"} the target`;case"remove_element":return"the element and its subtree will be removed";case"replace_element":return"the element will be replaced with new HTML";case"move_element":return"the element will be moved into the specified parent";case"wrap_element":return"the element will be wrapped in a new container";case"unwrap_element":return"children will be lifted out and the wrapper removed";case"clone_subtree":return"a deep clone of the subtree will be appended";default:return"unknown operation"}}class Fe{constructor(){b(this,"executionCounter",0)}async execute(e,t,s={}){const n=Math.min(Math.max(s.timeoutMs??5e3,100),3e4),i=`js_${Date.now().toString(36)}_${++this.executionCounter}`,r=e.defaultView;if(!r)return this.result(i,"BLOCKED_BY_CONTEXT",0,t,[],{name:"NoWindow",message:"The document has no associated window — execution context unavailable."});const o=e.documentElement?e.documentElement.outerHTML.length:0,a=[],c=this.hookConsole(r,a);let u="EXECUTED_SUCCESSFULLY",h,g,p=o,y=!1;const v=Date.now();try{const f=this.buildRunner(r,t),w=new Promise((E,S)=>{var x;const T=setTimeout(()=>{y=!0,S(new Error(`Script timed out after ${n}ms`))},n);(x=T==null?void 0:T.unref)==null||x.call(T)});h=await Promise.race([f,w])}catch(f){y?u="TIMED_OUT":u="EXECUTED_WITH_ERROR",g={name:(f==null?void 0:f.name)||"Error",message:(f==null?void 0:f.message)||String(f),stack:f!=null&&f.stack?String(f.stack).slice(0,2e3):void 0}}const m=Date.now()-v;p=e.documentElement?e.documentElement.outerHTML.length:0,c();const d=this.serialize(h);return u==="EXECUTED_SUCCESSFULLY"&&d.serializationFailed&&(u="SERIALIZATION_FAILED",g={name:"SerializationError",message:d.message||"Result could not be serialized."}),{status:u,executionId:i,durationMs:m,result:u==="EXECUTED_SUCCESSFULLY"?d.text:void 0,error:g,consoleOutput:a.slice(0,100),domChanged:o!==p,domLengthBefore:o,domLengthAfter:p,world:s.world||"ISOLATED",timeoutMs:n,codePreview:t.length>300?t.slice(0,300)+"…":t}}buildRunner(e,t){const s=`(async function() { ${t} -})()`,n=e;if(typeof n.eval!="function")return Promise.reject(new Error("BLOCKED_BY_CONTEXT: window.eval is unavailable in this context."));try{const i=n.eval(s);return i&&typeof i.then=="function"?i:Promise.resolve(i)}catch(i){return Promise.reject(i)}}hookConsole(e,t){var o;const s=["log","warn","error","info","debug"],n={},i=e,r=100;for(const a of s){const c=(o=i.console)==null?void 0:o[a];if(typeof c=="function"){n[a]=c;try{i.console[a]=(...u)=>{t.length{for(const a of s)if(n[a])try{i.console[a]=n[a]}catch{}}}serialize(e){if(e===void 0)return{text:"undefined"};if(e===null)return{text:"null"};try{if(typeof e=="string")return{text:e.slice(0,5e3)};const t=JSON.stringify(e,be,1);return t===void 0?{serializationFailed:!0,message:"JSON.stringify returned undefined (circular or non-serializable structure)."}:{text:t.length>5e4?t.slice(0,5e4)+"…[truncated]":t}}catch(t){return{serializationFailed:!0,message:(t==null?void 0:t.message)||"Serialization failed."}}}result(e,t,s,n,i,r){return{status:t,executionId:e,durationMs:s,error:r,consoleOutput:i,domChanged:!1,domLengthBefore:0,domLengthAfter:0,world:"ISOLATED",timeoutMs:5e3,codePreview:n.length>300?n.slice(0,300)+"…":n}}}function be(l,e){var t;if(e&&typeof e=="object"&&e.nodeType===1){const s=e;return{__element:!0,tag:s.tagName.toLowerCase(),id:s.getAttribute("id")||void 0,selector:s.tagName.toLowerCase()+(s.getAttribute("id")?`#${s.getAttribute("id")}`:""),text:(s.textContent||"").trim().slice(0,60)}}return typeof e=="function"?{__function:!0,name:e.name||"anonymous"}:e&&e.nodeType===9?{__document:!0,url:(t=e.location)==null?void 0:t.href}:e}function Ve(l){try{if(typeof l=="string")return l;if(l instanceof Error)return`${l.name}: ${l.message}`;const e=JSON.stringify(l,be);return e===void 0?String(l):e}catch{return String(l)}}const ye={"desktop-full-hd":{width:1920,height:1080,category:"desktop"},"desktop-hd":{width:1366,height:768,category:"desktop"},"desktop-laptop":{width:1440,height:900,category:"desktop"},"desktop-xga":{width:1280,height:1024,category:"desktop"},"desktop-1024":{width:1024,height:768,category:"desktop"},"tablet-ipad":{width:768,height:1024,category:"tablet"},"tablet-ipad-pro":{width:1024,height:1366,category:"tablet"},"tablet-portrait":{width:768,height:1024,category:"tablet"},"tablet-landscape":{width:1024,height:768,category:"tablet"},"mobile-iphone-se":{width:375,height:667,category:"mobile"},"mobile-iphone-12":{width:390,height:844,category:"mobile"},"mobile-iphone-14-pro-max":{width:430,height:932,category:"mobile"},"mobile-pixel-7":{width:412,height:915,category:"mobile"},"mobile-galaxy-s8":{width:360,height:740,category:"mobile"},"mobile-small":{width:320,height:568,category:"mobile"},"test-a4":{width:800,height:600,category:"test"},"test-square":{width:512,height:512,category:"test"}},Ee={"iphone-13":{width:390,height:844,devicePixelRatio:3,userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1",touch:!0,category:"mobile"},"ipad-air":{width:820,height:1180,devicePixelRatio:2,userAgent:"Mozilla/5.0 (iPad; CPU OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1",touch:!0,category:"tablet"},"pixel-7":{width:412,height:915,devicePixelRatio:2.625,userAgent:"Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",touch:!0,category:"mobile"},"galaxy-s23":{width:384,height:800,devicePixelRatio:3,userAgent:"Mozilla/5.0 (Linux; Android 14; SM-S911B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",touch:!0,category:"mobile"},"macbook-pro-16":{width:1728,height:1080,devicePixelRatio:2,userAgent:"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",touch:!1,category:"desktop"},"windows-desktop":{width:1920,height:1080,devicePixelRatio:1,userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",touch:!1,category:"desktop"}};class ze{constructor(e){f(this,"original",null);f(this,"modified",!1);f(this,"activePreset",null);f(this,"activeDevice",null);this.doc=e}state(){const e=this.doc.defaultView;return{width:(e==null?void 0:e.innerWidth)||0,height:(e==null?void 0:e.innerHeight)||0,devicePixelRatio:(e==null?void 0:e.devicePixelRatio)||1,scrollX:(e==null?void 0:e.scrollX)||0,scrollY:(e==null?void 0:e.scrollY)||0,original:this.original,isModified:this.modified}}resize(e,t,s){const n=this.doc.defaultView,i={width:(n==null?void 0:n.innerWidth)||0,height:(n==null?void 0:n.innerHeight)||0},r=this.pageDigest();this.original||(this.original={...i});const o=this.applySize(e,t);this.modified=!0,this.activePreset=s||this.activePreset;const a=this.pageDigest();return{success:!0,applied:{width:o.width,height:o.height},previous:i,original:{...this.original},preset:s||void 0,beforeState:r,afterState:a,reversible:!0,mode:this.isSimulation()?"simulation":"browser-window"}}applyPreset(e){const t=ye[e];if(!t)throw new Error(`UNKNOWN_PRESET: "${e}". Available: ${Object.keys(ye).join(", ")}`);return this.resize(t.width,t.height,e)}emulateDevice(e){const t=Ee[e];if(!t)throw new Error(`UNKNOWN_DEVICE: "${e}". Available: ${Object.keys(Ee).join(", ")}`);const s=this.resize(t.width,t.height,`device:${e}`);this.activeDevice=e;const n=this.doc.defaultView;return n&&this.isSimulation()&&n.devicePixelRatio!==void 0&&(n.devicePixelRatio=t.devicePixelRatio),{device:e,resize:s,profile:{width:t.width,height:t.height,devicePixelRatio:t.devicePixelRatio,touch:t.touch,category:t.category},userAgentNote:this.isSimulation()?"User-Agent override requires the Chrome DevTools Protocol (real browser session); in this context the viewport, dpr and touch metadata are applied and the UA is reported but not enforced.":"User-Agent and touch behaviors are applied by the browser emulation layer.",userAgentApplied:!this.isSimulation()}}reset(){var s,n;const e={width:((s=this.doc.defaultView)==null?void 0:s.innerWidth)||0,height:((n=this.doc.defaultView)==null?void 0:n.innerHeight)||0},t=this.original?{...this.original}:{...e};return this.original&&this.applySize(this.original.width,this.original.height),this.modified=!1,this.activePreset=null,this.activeDevice=null,{success:!0,applied:{width:t.width,height:t.height},previous:e,original:{...t},reversible:!0,mode:this.isSimulation()?"simulation":"browser-window"}}runResponsiveTest(e,t={restore:!0}){var c,u,d,h;const s=t.restore!==!1,n=this.original?{...this.original}:{width:((c=this.doc.defaultView)==null?void 0:c.innerWidth)||0,height:((u=this.doc.defaultView)==null?void 0:u.innerHeight)||0};this.original||(this.original={...n});const i=e.map(p=>{this.applySize(p.width,p.height),this.modified=!0;const y=this.pageDigest();return{label:p.label,width:p.width,height:p.height,domLength:y.domLength,interactiveCount:y.interactiveCount,horizontalOverflow:this.hasHorizontalOverflow(),screenshotId:void 0}}),r=i.slice(1).map((p,y)=>({from:i[y].label,to:p.label,domLengthDelta:p.domLength-i[y].domLength,interactiveDelta:p.interactiveCount-i[y].interactiveCount}));let o={width:((d=i[i.length-1])==null?void 0:d.width)||0,height:((h=i[i.length-1])==null?void 0:h.height)||0},a=!1;return s&&(this.applySize(n.width,n.height),this.modified=!1,o={...n},a=!0),{success:!0,originalViewport:n,steps:i,restored:a,finalViewport:o,comparisons:r}}getActivePreset(){return this.activePreset}getActiveDevice(){return this.activeDevice}applySize(e,t){const s=Math.max(200,Math.min(7680,Math.round(e))),n=Math.max(200,Math.min(4320,Math.round(t))),i=this.doc.defaultView;return i&&(typeof i.innerWidth=="number"&&(i.innerWidth=s),typeof i.innerHeight=="number"&&(i.innerHeight=n),typeof i.outerWidth=="number"&&(i.outerWidth=s),typeof i.outerHeight=="number"&&(i.outerHeight=n)),{width:s,height:n}}pageDigest(){var t,s,n,i;const e=this.doc.querySelectorAll('a[href], button, input, select, textarea, [role="button"], [onclick]').length;return{url:((s=(t=this.doc.defaultView)==null?void 0:t.location)==null?void 0:s.href)||((n=this.doc.location)==null?void 0:n.href)||"",domLength:((i=this.doc.documentElement)==null?void 0:i.outerHTML.length)||0,interactiveCount:e}}hasHorizontalOverflow(){const e=this.doc.documentElement,t=this.doc.body,s=this.doc.defaultView;return!s||!e?!1:Math.max(e.scrollWidth||0,(t==null?void 0:t.scrollWidth)||0)>(s.innerWidth||e.clientWidth||0)+1}isSimulation(){return typeof globalThis.__FORENSIC_SIMULATION__<"u"}}const We=[/^css-/,/^jsx-/,/^sc-[A-Za-z]/,/^emotion/,/^chakra-/,/^mantine-/i,/^_ng[a-z]/,/^ng-/i,/^v-/,/^(?=.*\d)[a-z0-9]{6,12}$/i,/^data-v-/],Xe=["id","name","data-testid","data-test","data-id","data-qa","data-cy","data-component","data-role","aria-label","aria-labelledby","aria-describedby","role","type","href","for","title","alt","rel","placeholder"];function ve(l){let e=2166136261;for(let t=0;t >>0).toString(16).padStart(8,"0")}function ie(l){return We.some(e=>e.test(l))}function Ge(l){return Xe.includes(l)}function ce(l){const e=l.trim();return e?!!((e.match(/\d/g)||[]).length/e.length>.5||/^\d+[.,:\-/ ]+\d+/.test(e)||/\b\d{10,}\b/.test(e)):!1}function Ke(l,e=80){return Array.from(l.childNodes).filter(s=>s.nodeType===3).map(s=>(s.textContent||"").trim()).join(" ").replace(/\s+/g," ").slice(0,e)}function Ye(l,e){const t=[];let s=l;for(;s&&t.length !ie(b)),r=Ke(e),o=e.getBoundingClientRect(),a={width:Math.round(o.width),height:Math.round(o.height)},c=Ye(e,4),u=c.join(">"),h=Array.from(e.children||[]).slice(0,8).map(b=>b.tagName.toLowerCase()).join("|"),p=e.getAttribute("role")||(t!=null&&t.getComputedStyle,void 0)||je(e),y=ve(JSON.stringify({t:e.tagName.toLowerCase(),a:s,c:i.slice(0,4),r:p||null,anc:u,desc:h,txt:ce(r)?null:r.slice(0,40),d:a})),v=[];let m="low";return!s.id&&!s["data-testid"]&&!s.name&&(m="medium",v.push("no stable identity attribute")),n.length>0&&i.length===0&&(m=v.length?"high":"medium",v.push("all classes are framework-generated")),ce(r)&&(v.push("text appears dynamic"),m==="low"&&(m="medium")),e.tagName.toLowerCase().includes("-")&&(v.push("custom element (web component)"),m==="low"&&(m="medium")),{fingerprintId:`fp_${y}`,hash:y,tagHierarchy:c,stableAttributes:s,meaningfulText:r,classes:i,role:p||void 0,dimensions:a,ancestorPattern:u,descendantPattern:h,volatilityRisk:m,volatilityReasons:v}}compare(e,t){const s=[],n=e.tagHierarchy[0]===t.tagHierarchy[0]?1:0;s.push({name:"tag",score:n,weight:.15});const i=we(e.ancestorPattern.split(">"),t.ancestorPattern.split(">"));s.push({name:"ancestorPattern",score:i,weight:.2});const r=Je(e.stableAttributes,t.stableAttributes);s.push({name:"stableAttributes",score:r,weight:.25});const o=we(e.classes,t.classes);s.push({name:"classes",score:o,weight:.1});const a=(e.role||"")===(t.role||"")&&e.role?1:0;s.push({name:"role",score:a,weight:.1});const c=e.meaningfulText===t.meaningfulText&&e.meaningfulText?1:0;s.push({name:"text",score:c,weight:.1});const u=Ze(e.dimensions,t.dimensions);s.push({name:"dimensions",score:u,weight:.1});const d=s.reduce((h,p)=>h+p.score*p.weight,0);return{score:Math.round(d*1e3)/1e3,components:s}}}function je(l){switch(l.tagName.toLowerCase()){case"a":return l.getAttribute("href")?"link":void 0;case"button":return"button";case"nav":return"navigation";case"header":return"banner";case"footer":return"contentinfo";case"main":return"main";case"aside":return"complementary";case"article":return"article";case"form":return"form";case"input":{const t=l.getAttribute("type")||"text";return t==="checkbox"?"checkbox":t==="radio"?"radio":t==="button"||t==="submit"?"button":"textbox"}case"select":return"combobox";case"textarea":return"textbox";case"img":return"img";case"table":return"table";case"ul":case"ol":return"list";case"li":return"listitem";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return"heading";default:return}}function we(l,e){if(!l.length&&!e.length)return 1;if(!l.length||!e.length)return 0;const t=new Set(e);return l.filter(n=>t.has(n)).length/Math.max(l.length,e.length)}function Je(l,e){const t=Object.keys(l),s=Object.keys(e);if(!t.length&&!s.length)return .5;if(!t.length||!s.length)return 0;let n=0,i=0;for(const r of t)r in e&&(i++,l[r]===e[r]&&n++);return i===0?0:n/Math.max(t.length,s.length)}function Ze(l,e){if(l.width===0&&l.height===0&&e.width===0&&e.height===0)return .5;const t=Se(l.width,e.width),s=Se(l.height,e.height);return(t+s)/2}function Se(l,e){if(l===e)return 1;if(l===0||e===0)return 0;const t=Math.min(l,e)/Math.max(l,e);return t>.9?1:t>.7?.5:0}const Qe=["data-testid","data-test","data-id","data-qa","data-cy","data-component","data-role","aria-label","name","id"],Te=/^[a-zA-Z][a-zA-Z0-9_-]*$/,et=/^[a-zA-Z0-9_ .:-]+$/;class Z{constructor(e){f(this,"doc");this.doc=e}generateCandidates(e){const t=[],s=e.tagName.toLowerCase(),n=e.getAttribute("id");if(n&&Te.test(n)){const u=`#${Ce(n)}`;t.push(this.evaluate(e,u,"id",1,["unique stable id"]))}for(const u of Qe){if(u==="id")continue;const d=e.getAttribute(u);if(d&&et.test(d)&&d.length<100){const h=`${s}[${u}="${Q(d)}"]`;t.push(this.evaluate(e,h,"semantic-attribute",.92,[`semantic attribute ${u}`]))}}const i=Array.from(e.classList||[]).filter(u=>!ie(u));if(i.length){const u=`${s}.${i.slice(0,3).map(Ce).join(".")}`;t.push(this.evaluate(e,u,"class",.72,i.length?["stable class names"]:[]))}const r=this.buildStructuralPath(e);r&&t.push(this.evaluate(e,r,"structural-path",.55,["position-based structural path"]));const o=B(e);if(o&&o.length>=2&&o.length<=60&&!ce(o)){const u=`${s}:nth-of-type(1)`,d=this.buildTextXPath(e,o);d&&(t.push({selector:u,strategy:"text-derived-xpath",confidence:.6,unique:this.isXPathUnique(d),reasons:[`matches text "${o.slice(0,30)}"`]}),t[t.length-1].xpath=d)}const a=this.buildAttributeFingerprintSelector(e);a&&t.push(this.evaluate(e,a,"attribute-fingerprint",.68,["combination of stable attributes"]));const c=new Map;for(const u of t){const d=u.strategy==="text-derived-xpath"?`xpath:${u.xpath}`:u.selector,h=c.get(d);(!h||u.confidence>h.confidence)&&c.set(d,u)}return Array.from(c.values()).sort((u,d)=>d.confidence-u.confidence)}bestSelector(e){const t=this.generateCandidates(e),s=t.find(n=>n.unique&&n.confidence>=.7)||t[0];return{selector:(s==null?void 0:s.selector)||e.tagName.toLowerCase(),strategy:(s==null?void 0:s.strategy)||"tag",confidence:(s==null?void 0:s.confidence)||.3}}buildXPath(e){const t=[];let s=e;for(;s&&s!==this.doc.documentElement;){const n=s.getAttribute("id");if(n&&Te.test(n)){t.unshift(`*[@id="${Q(n)}"]`);break}const i=s.parentElement;if(!i){t.unshift(s.tagName.toLowerCase());break}const o=Array.from(i.children).filter(a=>a.tagName===s.tagName).indexOf(s)+1;t.unshift(`${s.tagName.toLowerCase()}[${o}]`),s=i}return s===this.doc.documentElement&&(!t.length||!t[0].includes("@id"))&&t.unshift("html"),"//"+t.join("/")}buildTextXPath(e,t){try{const s=e.tagName.toLowerCase(),n=tt(t);return`//${s}[normalize-space(text())=${n}]`}catch{return null}}buildStructuralPath(e,t=4){const s=[];let n=e;for(;n&&s.length c.tagName===n.tagName);if(a.length>1){const c=a.indexOf(n)+1;s.unshift(`${o}:nth-of-type(${c})`)}else s.unshift(o);if(n=r,n===this.doc.body){s.unshift("body");break}if(n===this.doc.documentElement)break}const i=s.join(" > ");return i.includes("body")?i:"body > "+i}buildAttributeFingerprintSelector(e){const t=e.tagName.toLowerCase(),s=[],n=e.getAttribute("type");n&&s.push(`type="${Q(n)}"`);const i=e.getAttribute("href");i&&i.length<80&&!i.startsWith("javascript:")&&s.push(`href^="${Q(i.slice(0,40))}"`);const r=e.getAttribute("placeholder");return r&&r.length<60&&s.push(`placeholder="${Q(r)}"`),s.length>=2?`${t}[${s.join("][")}]`:null}evaluate(e,t,s,n,i){let r=!1,o=0;try{const c=this.doc.querySelectorAll(t);o=c.length,r=c.length===1&&c[0]===e}catch{return{selector:t,strategy:s,confidence:0,unique:!1,reasons:["invalid selector syntax"]}}let a=n;return o===0?(a=0,i.push("selector matched nothing (invalid candidate)")):o===1&&r?i.push("matches exactly this element"):(a=a*.4,i.push(`matches ${o} elements — ambiguous`)),{selector:t,strategy:s,confidence:Math.round(a*100)/100,unique:r,reasons:i}}isXPathUnique(e){try{return this.doc.evaluate(`count(${e})`,this.doc,null,4,null).numberValue===1}catch{return!1}}}function B(l){return Array.from(l.childNodes).filter(e=>e.nodeType===3).map(e=>(e.textContent||"").trim()).join(" ").replace(/\s+/g," ")}function Ce(l){return l.replace(/([^a-zA-Z0-9_\u00A0-\uFFFF-])/g,"\\$1")}function Q(l){return l.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function tt(l){return l.includes("'")?l.includes('"')?`concat(${l.split("'").map(e=>`'${e}'`).join(`, "'", `)})`:`"${l}"`:`'${l}'`}class st{constructor(e,t){f(this,"fingerprintEngine",new re);f(this,"counter",0);this.doc=e,this.registry=t}buildTarget(e,t="selector"){var d;const s=new Z(this.doc),n=s.generateCandidates(e),i=s.bestSelector(e),r=this.fingerprintEngine.fingerprint(e),o=L.inspectElement(e,this.registry),a=e.getBoundingClientRect();let c=i.confidence*.6;return r.volatilityRisk==="low"?c+=.3:r.volatilityRisk==="medium"&&(c+=.15),n.find(h=>h.unique&&h.confidence>=.9)&&(c+=.1),c=Math.max(.05,Math.min(1,c)),this.counter++,{targetId:`tgt_${Date.now().toString(36)}_${this.counter}`,tag:e.tagName.toLowerCase(),role:o.role||r.role,selector:i.selector,selectorCandidates:n,xpath:s.buildXPath(e),domPath:(((d=o.context)==null?void 0:d.parentChain)||[]).concat(i.selector).join(" > "),textFingerprint:r.meaningfulText,attributeFingerprint:JSON.stringify(r.stableAttributes),structuralFingerprint:r.hash,attributes:o.attributes||{},confidence:Math.round(c*100)/100,bounds:{x:Math.round(a.x),y:Math.round(a.y),width:Math.round(a.width),height:Math.round(a.height)},resolvedFrom:t}}resolveAndBuild(e){let t=null,s="unknown";typeof e=="string"&&(e={selector:e});const n=e;if(n.selectedElementRef&&(s="selectedElementRef"),!t&&n.selector)try{const i=this.doc.querySelectorAll(n.selector);if(i.length===0)return{error:`TARGET_NOT_FOUND: selector "${n.selector}" matches no element`};i.length>1?(t=nt(i,this.doc)||i[0],s+="+disambiguated"):(t=i[0],s="selector")}catch(i){return{error:`TARGET_INVALID: ${i.message}`}}if(!t&&n.xpath)try{t=this.doc.evaluate(n.xpath,this.doc,null,9,null).singleNodeValue,s="xpath"}catch(i){return{error:`TARGET_INVALID_XPATH: ${i.message}`}}if(!t&&typeof n.nodeId=="number"&&this.registry){const i=this.registry.getNode(n.nodeId);i&&i.nodeType===1&&this.doc.contains(i)&&(t=i,s="nodeId")}return!t&&n.coordinates&&(t=this.doc.elementFromPoint(n.coordinates.x,n.coordinates.y),s="coordinates"),t?{element:t,target:this.buildTarget(t,s)}:{error:"TARGET_NOT_FOUND: no usable resolution strategy succeeded"}}}function nt(l,e){for(const t of Array.from(l)){const s=t;try{if(L.inspectElement(s).visibility.isVisible)return s}catch{}}return null}class it{constructor(e){f(this,"fingerprintEngine",new re);this.doc=e}recover(e,t){var p;const s=[],n=[];let i=null;try{i=this.doc.querySelectorAll(e)}catch(y){s.push(`selector syntax error: ${y.message}`)}if(i&&i.length>0){s.push("selector still matches — no recovery needed");const y=i[0];return{recovered:!0,confidence:1,strategy:"original-selector",resolvedSelector:e,matchedElementInfo:Ie(y),alternatives:[],diagnostics:s,recommendation:"Original selector works; the earlier failure was transient (likely a navigation or render race)."}}s.push("selector no longer matches any element");const o=this.collectCandidates(t,s).map(y=>({element:y,score:this.scoreMatch(y,t)})).filter(y=>y.score.score>.35).sort((y,v)=>v.score.score-y.score.score);for(const y of o.slice(0,5)){const v=new Z(this.doc).bestSelector(y.element);n.push({selector:v.selector,confidence:Math.round(y.score.score*100)/100,strategy:"recovery-match"})}if(!o.length)return{recovered:!1,confidence:0,strategy:"none",alternatives:n,diagnostics:s,recommendation:"No sufficiently similar element exists. The region may have been removed, or the page structure changed fundamentally. Re-inspect the page and capture a new target."};const a=o[0],c=o.length>1?a.score.score-o[1].score.score:1;s.push(`best candidate score: ${a.score.score.toFixed(3)} (margin ${c.toFixed(3)})`);for(const y of a.score.components)y.score>0&&s.push(` - ${y.name}: ${(y.score*100).toFixed(0)}%`);if(a.score.score<.62||o.length>1&&c<.15)return{recovered:!1,confidence:Math.round(a.score.score*100)/100,strategy:"recovery-refused",resolvedSelector:(p=n[0])==null?void 0:p.selector,alternatives:n,diagnostics:s,recommendation:"Recovery refused: best match is not confident enough or too close to a competing element. Inspect alternatives manually before acting — refusing to avoid acting on a wrong element."};const h=new Z(this.doc).bestSelector(a.element).selector;return{recovered:!0,confidence:Math.round(a.score.score*100)/100,strategy:"fingerprint-recovery",resolvedSelector:h,matchedElementInfo:Ie(a.element),alternatives:n,diagnostics:s,recommendation:`Recovered target with ${(a.score.score*100).toFixed(0)}% confidence. Verify the resolved selector before destructive actions.`}}collectCandidates(e,t){var r,o;const s=new Set,n=this.doc.querySelectorAll(e.tag);let i=0;for(const a of Array.from(n))if(s.add(a),++i>=400)break;if((r=e.classes)!=null&&r.length){const a=e.classes.filter(c=>!ie(c));for(const c of a.slice(0,2))try{for(const u of Array.from(this.doc.querySelectorAll(`.${c}`)).slice(0,100))s.add(u)}catch{}}if((o=e.stableAttributes)!=null&&o.name)try{for(const a of Array.from(this.doc.querySelectorAll(`[name="${e.stableAttributes.name}"]`)))s.add(a)}catch{}if(e.parentSelector)try{for(const a of Array.from(this.doc.querySelectorAll(`${e.parentSelector} > ${e.tag}`)).slice(0,100))s.add(a)}catch{}return t.push(`collected ${s.size} candidate elements for scoring`),Array.from(s)}scoreMatch(e,t){const s=[],n=e.tagName.toLowerCase()===t.tag.toLowerCase()?1:0;s.push({name:"tag",score:n,weight:.15});const i=(t.text||"").trim().slice(0,40),r=B(e).slice(0,40),o=(e.textContent||"").trim().slice(0,40);let a=0;if(i){const g=r?r===i?1:le(i,r):0,b=o?o===i?1:le(i,o):0;a=Math.max(g,b)}s.push({name:"text",score:a,weight:.3});const c=new Set((t.classes||[]).filter(g=>!ie(g))),u=Array.from(e.classList||[]),d=c.size?u.filter(g=>c.has(g)).length/c.size:.5;s.push({name:"classes",score:d,weight:.2});const h=t.stableAttributes||{},p=Object.keys(h);let y=.5;if(p.length){let g=0;for(const b of p)e.getAttribute(b)===h[b]&&g++;y=g/p.length}s.push({name:"attributes",score:y,weight:.2});const v=t.childCount!==void 0?e.children.length===t.childCount?1:le(String(t.childCount),String(e.children.length)):.5;if(s.push({name:"childCount",score:v,weight:.05}),t.fingerprintHash){const g={fingerprintId:"snapshot",hash:t.fingerprintHash,tagHierarchy:[t.tag],stableAttributes:h,meaningfulText:i,classes:t.classes||[],dimensions:{width:0,height:0},ancestorPattern:"",descendantPattern:"",volatilityRisk:"medium",volatilityReasons:[]},b=this.fingerprintEngine.fingerprint(e),T=this.fingerprintEngine.compare(g,b);s.push({name:"fingerprint",score:T.score,weight:.1})}const m=s.reduce((g,b)=>g+b.score*b.weight,0);return{score:Math.max(0,Math.min(1,m)),components:s}}diagnose(e){const t=[];let s=!0,n=0,i,r=[];try{n=this.doc.querySelectorAll(e).length}catch(o){s=!1,i=o.message,t.push("Selector is syntactically invalid CSS.")}if(s&&n===0){t.push("Selector parses but matches nothing — element may be removed, re-rendered, or inside a shadow root."),r=this.relaxSelector(e);for(const o of r)try{if(this.doc.querySelectorAll(o).length>0){t.push(`Relaxed form "${o}" matches — the over-specific part of the selector is stale.`);break}}catch{}}return s&&n>1&&t.push(`Selector matches ${n} elements — it is ambiguous; use a more specific form or index.`),{selector:e,valid:s,matches:n,parseError:i,closestWorkingSelectors:r.filter(o=>{try{return this.doc.querySelectorAll(o).length>0}catch{return!1}}),diagnosis:t}}relaxSelector(e){const t=[],s=e.split(/[ >]+/).filter(Boolean);s.length>1&&(t.push(s.slice(0,-1).join(" ")),t.push(s[s.length-1]));const n=e.replace(/:nth-of-type\(\d+\)/g,"").replace(/\.[^. >#:[]+/g,(i,r,o)=>o[r-1]==="\\"?i:"");return n!==e&&n.trim()&&t.push(n.trim()),t}}function le(l,e){if(!l||!e)return 0;const t=Ae(l),s=Ae(e);if(t===s)return 1;if(t.includes(s)||s.includes(t))return .7;const n=new Set(t.split(/\s+/)),i=new Set(s.split(/\s+/));return Array.from(n).filter(o=>i.has(o)).length/Math.max(n.size,i.size)}function Ae(l){return l.toLowerCase().replace(/[^a-z0-9 ]/g," ").replace(/\s+/g," ").trim()}function Ie(l){return{tag:l.tagName.toLowerCase(),id:l.getAttribute("id")||void 0,text:B(l).slice(0,60),classes:Array.from(l.classList||[])}}class ue{constructor(e){f(this,"state");this.state=e>>>0,this.state===0&&(this.state=2654435769)}next(){this.state=this.state+1831565813>>>0;let e=this.state;return e=Math.imul(e^e>>>15,e|1),e^=e+Math.imul(e^e>>>7,e|61),((e^e>>>14)>>>0)/4294967296}range(e,t){return e+this.next()*(t-e)}int(e,t){return Math.floor(this.range(e,t+1))}chance(e){return this.next() setTimeout(t,e))}chance(){return this.rng.next()<.5}}const ot=[{ruleId:"red_key_password",kind:"key-pattern",pattern:"password|passwd|pwd",description:"Keys containing password/passwd/pwd",enabled:!0,userAdded:!1},{ruleId:"red_key_token",kind:"key-pattern",pattern:"token|jwt|bearer|auth|session.?id|secret|api.?key|client.?secret",description:"Keys containing token/jwt/auth/session-id/secret/api-key",enabled:!0,userAdded:!1},{ruleId:"red_key_credential",kind:"key-pattern",pattern:"credential|login|user.?pass|otp|2fa|mfa|verification",description:"Keys containing credential/login/otp/2fa/verification",enabled:!0,userAdded:!1},{ruleId:"red_key_payment",kind:"key-pattern",pattern:"card|payment|billing|iban|cvv|cvc|pan",description:"Keys containing card/payment/billing/iban/cvv",enabled:!0,userAdded:!1},{ruleId:"red_key_personal",kind:"key-pattern",pattern:"ssn|social.?security|national.?id|passport|tax.?id",description:"Keys containing personal identifier patterns",enabled:!0,userAdded:!1},{ruleId:"red_val_jwt",kind:"value-pattern",pattern:"eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+",description:"JWT-shaped tokens",enabled:!0,userAdded:!1},{ruleId:"red_val_bearer",kind:"value-pattern",pattern:"bearer\\s+[A-Za-z0-9._-]+",description:"Bearer tokens",enabled:!0,userAdded:!1},{ruleId:"red_val_long_hex",kind:"value-pattern",pattern:"\\b[a-f0-9]{32,}\\b",description:"32+ char hex strings (session/API ids)",enabled:!0,userAdded:!1},{ruleId:"red_val_sk",kind:"value-pattern",pattern:"\\b(sk|pk|rk)_[A-Za-z0-9_]{20,}\\b",description:"Stripe-style secret keys (sk_live_…)",enabled:!0,userAdded:!1},{ruleId:"red_attr_input_password",kind:"attribute-name",pattern:"value",description:"value attributes on password inputs handled by PrivacyEngine maskValue",enabled:!0,userAdded:!1},{ruleId:"red_attr_secret",kind:"attribute-name",pattern:"data-secret|data-token|data-api-key|secret|access.?token",description:"Secret-carrying attributes",enabled:!0,userAdded:!1}],at=[{exclusionId:"excl_mcpdom_overlay",selector:"[data-mcpdom-internal], [data-forensic-internal], #forensic-recorder-floating-host, #forensic-inspect-highlighter",reason:"MCPDOM-injected UI must never contaminate captured DOM (§68 clean capture)",userAdded:!1},{exclusionId:"excl_mcpdom_ids",selector:'[id^="forensic-"], [id^="mcpdom-"]',reason:"MCPDOM-namespaced nodes",userAdded:!1}],de="[REDACTED]";class he{constructor(e){f(this,"config");f(this,"base",new se);f(this,"compiledKeyPatterns",[]);f(this,"compiledValuePatterns",[]);f(this,"compiledAttrPatterns",[]);this.config={rules:[...ot],exclusions:[...at],stubMode:!0,...e},this.recompile()}recompile(){this.compiledKeyPatterns=[],this.compiledValuePatterns=[],this.compiledAttrPatterns=[];for(const e of this.config.rules){if(!e.enabled)continue;const t="i";try{switch(e.kind){case"key-pattern":this.compiledKeyPatterns.push(new RegExp(e.pattern,t));break;case"value-pattern":this.compiledValuePatterns.push(new RegExp(e.pattern,"i"));break;case"attribute-name":this.compiledAttrPatterns.push(new RegExp(`^(${e.pattern})$`,"i"));break}}catch{}}}getRules(){return[...this.config.rules]}setRuleEnabled(e,t){const s=this.config.rules.find(n=>n.ruleId===e);return s?(s.enabled=t,this.recompile(),!0):!1}addRule(e){const t=`red_custom_${this.config.rules.length+1}_${Date.now().toString(36)}`,s={...e,ruleId:t,userAdded:!0};return this.config.rules.push(s),this.recompile(),s}removeRule(e){const t=this.config.rules.findIndex(s=>s.ruleId===e);return t<0||!this.config.rules[t].userAdded?!1:(this.config.rules.splice(t,1),this.recompile(),!0)}getExclusions(){return[...this.config.exclusions]}addExclusion(e,t){const n={exclusionId:`excl_custom_${this.config.exclusions.length+1}_${Date.now().toString(36)}`,selector:e,reason:t,userAdded:!0};return this.config.exclusions.push(n),n}removeExclusion(e){const t=this.config.exclusions.findIndex(s=>s.exclusionId===e);return t<0||!this.config.exclusions[t].userAdded?!1:(this.config.exclusions.splice(t,1),!0)}isSensitiveKey(e){return this.compiledKeyPatterns.some(t=>t.test(e))}redactValue(e){let t=e;for(const s of this.compiledValuePatterns)s.test(t)&&(t=t.replace(new RegExp(s.source,"gi"),de));return t}redactByKeyValue(e,t){return this.isSensitiveKey(e)?this.config.stubMode?de:t:this.redactValue(t)}isSensitiveAttribute(e){return this.compiledAttrPatterns.some(t=>t.test(e))}redactAttributes(e){const t={};for(const[s,n]of Object.entries(e))this.isSensitiveAttribute(s)?t[s]=de:t[s]=this.redactValue(n);return t}cleanSubtree(e){const t=e.cloneNode(!0);for(const s of this.config.exclusions){let n=null;try{n=t.querySelectorAll(s.selector)}catch{continue}for(const i of Array.from(n))i.remove();try{if(t.matches(s.selector))return this.doclessEmptyStub(t)}catch{}}return t}isExcluded(e){for(const t of this.config.exclusions)try{if(e.matches(t.selector)||e.closest(t.selector))return!0}catch{}return!1}doclessEmptyStub(e){return e.innerHTML="",e.setAttribute("data-mcpdom-excluded","true"),e}toJSON(){return{rules:this.getRules(),exclusions:this.getExclusions(),stubMode:this.config.stubMode}}static fromJSON(e){return new he({rules:Array.isArray(e==null?void 0:e.rules)?e.rules:void 0,exclusions:Array.isArray(e==null?void 0:e.exclusions)?e.exclusions:void 0,stubMode:typeof(e==null?void 0:e.stubMode)=="boolean"?e.stubMode:void 0})}}const ge='a[href], button, input, select, textarea, [role="button"], [role="link"], [role="tab"], [onclick], [tabindex]';function X(l,e){return{items:l.slice(0,e),truncated:l.length>e}}function k(l,e,t,s,n,i){return{analyzer:l,summary:e,count:t,items:s,warnings:n,truncated:i}}function D(l){try{return L.inspectElement(l).bestSelector}catch{return l.tagName.toLowerCase()}}const ct=l=>{const e=Array.from(l.querySelectorAll("form")),t=e.map(n=>{const i=Array.from(n.querySelectorAll("input, select, textarea")).map(r=>({tag:r.tagName.toLowerCase(),type:r.getAttribute("type")||(r.tagName.toLowerCase()==="textarea"?"textarea":r.tagName.toLowerCase()==="select"?"select":"text"),name:r.getAttribute("name")||void 0,id:r.getAttribute("id")||void 0,required:r.hasAttribute("required"),pattern:r.getAttribute("pattern")||void 0,maxLength:r.getAttribute("maxlength")||void 0,placeholder:r.getAttribute("placeholder")||void 0,ariaLabel:r.getAttribute("aria-label")||void 0,autocomplete:r.getAttribute("autocomplete")||void 0,hasLabel:!!(r.getAttribute("id")&&l.querySelector(`label[for="${r.getAttribute("id")}"]`))||!!r.closest("label"),defaultValue:r.value!==void 0&&(r.getAttribute("type")||"text")!=="password"?String(r.value).slice(0,40):void 0}));return{selector:D(n),action:n.getAttribute("action")||void 0,method:(n.getAttribute("method")||"GET").toUpperCase(),id:n.getAttribute("id")||void 0,fieldCount:i.length,submitButton:n.querySelector('button[type="submit"], input[type="submit"]')?D(n.querySelector('button[type="submit"], input[type="submit"]')):void 0,validationAttributes:i.filter(r=>r.required||r.pattern).length,fields:i}}),s=X(t,50);return k("analyze_forms",`${e.length} form(s) with ${t.reduce((n,i)=>n+i.fieldCount,0)} total fields`,e.length,s.items,[],s.truncated)},lt=l=>{const e=Array.from(l.querySelectorAll("a[href]")),t=e.map(n=>({href:n.getAttribute("href")||"",text:B(n).slice(0,60),selector:D(n),rel:n.getAttribute("rel")||void 0,target:n.getAttribute("target")||void 0,download:n.hasAttribute("download"),external:/^https?:\/\//i.test(n.getAttribute("href")||"")&&!ut(n.getAttribute("href")||"",l),anchorOnly:(n.getAttribute("href")||"").startsWith("#")})),s=X(t,200);return k("extract_links",`${e.length} link(s): ${t.filter(n=>n.external).length} external, ${t.filter(n=>n.anchorOnly).length} anchors`,e.length,s.items,[],s.truncated)};function ut(l,e){var t,s,n,i;try{return new URL(l,((s=(t=e.defaultView)==null?void 0:t.location)==null?void 0:s.href)||"http://localhost").origin===(((i=(n=e.defaultView)==null?void 0:n.location)==null?void 0:i.origin)||"")}catch{return!1}}const dt=l=>{const e=Array.from(l.querySelectorAll("img")),t=Array.from(l.querySelectorAll("video")),s=Array.from(l.querySelectorAll("audio")),n=Array.from(l.querySelectorAll("canvas")),i=[],r=[...e.map(c=>({kind:"img",selector:D(c),src:(c.getAttribute("src")||"").slice(0,150),alt:c.getAttribute("alt"),width:c.getAttribute("width")||void 0,height:c.getAttribute("height")||void 0,naturalWidth:c.naturalWidth||void 0,naturalHeight:c.naturalHeight||void 0,lazy:c.getAttribute("loading")==="lazy",missingAlt:!c.hasAttribute("alt")})),...t.map(c=>{var u;return{kind:"video",selector:D(c),src:(c.getAttribute("src")||((u=c.querySelector("source"))==null?void 0:u.getAttribute("src"))||"").slice(0,150),controls:c.hasAttribute("controls"),autoplay:c.hasAttribute("autoplay"),muted:c.hasAttribute("muted"),poster:c.getAttribute("poster")||void 0}}),...s.map(c=>{var u;return{kind:"audio",selector:D(c),src:(c.getAttribute("src")||((u=c.querySelector("source"))==null?void 0:u.getAttribute("src"))||"").slice(0,150),controls:c.hasAttribute("controls")}}),...n.map(c=>({kind:"canvas",selector:D(c),width:c.width,height:c.height}))],o=r.filter(c=>c.missingAlt).length;o&&i.push(`${o} image(s) missing alt text (accessibility risk).`);const a=X(r,200);return k("analyze_media",`${e.length} images, ${t.length} videos, ${s.length} audios, ${n.length} canvases`,r.length,a.items,i,a.truncated)},ht=l=>{const e=l.defaultView,t=[],s={};if(e!=null&&e.getComputedStyle){const i=e.getComputedStyle(l.documentElement);for(let r=0;r ({name:i,value:r}));return k("get_css_variables",`${n.length} CSS custom properties found`,n.length,n,t,!1)},gt=l=>{const e=l.defaultView,t=[],s=new Map;if(e!=null&&e.getComputedStyle)for(const i of Array.from(l.querySelectorAll("body, body *")).slice(0,800)){const r=e.getComputedStyle(i),o=r.fontFamily||"",a=r.fontSize||"",c=`${o.split(",")[0].replace(/["']/g,"").trim()} @ ${a}`;s.set(c,(s.get(c)||0)+1)}else t.push("getComputedStyle unavailable — font usage analysis requires rendered styles.");const n=Array.from(s.entries()).map(([i,r])=>({font:i,usage:r})).sort((i,r)=>r.usage-i.usage);return k("analyze_fonts",`${n.length} distinct font/size combinations`,n.length,n,t,!1)},pt=l=>{const e=l.defaultView,t=[],s=new Map;if(e!=null&&e.getComputedStyle)for(const i of Array.from(l.querySelectorAll("body, body *")).slice(0,800)){const r=e.getComputedStyle(i);for(const o of["color","background-color","border-top-color"]){const a=r.getPropertyValue(o);a&&a!=="rgba(0, 0, 0, 0)"&&s.set(a,(s.get(a)||0)+1)}}else{for(const i of Array.from(l.querySelectorAll("[style]")).slice(0,300)){const r=i.getAttribute("style")||"",o=/(color)\s*:\s*([^;]+)/gi;let a;for(;a=o.exec(r);)s.set(a[2].trim(),(s.get(a[2].trim())||0)+1)}t.push("getComputedStyle unavailable — palette from inline styles only.")}const n=Array.from(s.entries()).map(([i,r])=>({color:i,usage:r})).sort((i,r)=>r.usage-i.usage).slice(0,40);return k("extract_color_palette",`${s.size} distinct colors in use`,s.size,n,t,!1)},mt=l=>{const e=l.defaultView,t=[],s=[];if(!(e!=null&&e.getComputedStyle))return t.push("getComputedStyle unavailable — z-index analysis requires rendered styles."),k("detect_zindex_conflicts","unavailable",0,[],t,!1);const n=[];for(const i of Array.from(l.querySelectorAll("body *")).slice(0,1e3)){const r=e.getComputedStyle(i),o=r.zIndex;o&&o!=="auto"&&parseInt(o,10)>0&&n.push({selector:D(i),z:parseInt(o,10),position:r.position,stacking:r.position==="fixed"||r.position==="sticky"||r.opacity!=="1"||r.transform!=="none"?"creates-stacking-context":"plain"})}for(let i=0;i 1e5&&s.push({zIndex:n[i].z,elements:[n[i].selector],note:"extremely high z-index — competes with platform overlays (MCPDOM uses 2147483640+)."})}return k("detect_zindex_conflicts",`${n.length} z-indexed elements, ${s.length} potential conflict(s)`,s.length,X(s,40).items,t,s.length>40)},ft=l=>{const e=l.defaultView,t=[],s=l.documentElement,n=l.body,i=Math.max((s==null?void 0:s.scrollWidth)||0,(n==null?void 0:n.scrollWidth)||0),r=(e==null?void 0:e.innerWidth)||(s==null?void 0:s.clientWidth)||0,o=i>r+1;if(o&&(t.push({issue:"horizontal-overflow",detail:`document scrollWidth ${i} exceeds viewport ${r}`}),e!=null&&e.getComputedStyle))for(const c of Array.from(l.querySelectorAll("body *")).slice(0,600)){const u=c.getBoundingClientRect();if(u.right>r+2&&u.width>100&&(t.push({issue:"element-exceeds-viewport",selector:D(c),right:Math.round(u.right),width:Math.round(u.width)}),t.length>15))break}let a=0;for(const c of Array.from(l.querySelectorAll(ge)).slice(0,500)){const u=c.getBoundingClientRect();(u.width===0||u.height===0)&&a++}return a&&t.push({issue:"zero-size-interactive-elements",count:a}),k("detect_layout_issues",o?`HORIZONTAL OVERFLOW: page is ${i-r}px wider than viewport`:"No horizontal overflow detected",t.length,t,[],!1)},bt=l=>{const e=Array.from(l.querySelectorAll(ge)),t=new Map,s=e.slice(0,300).map(n=>{const i=pe(n),r=i.role||n.tagName.toLowerCase();return t.set(r,(t.get(r)||0)+1),{selector:i.bestSelector,tag:i.tag,role:i.role,text:i.text.slice(0,40),visible:i.visibility.isVisible,disabled:n.disabled||n.hasAttribute("disabled"),inViewport:i.visibility.isInViewport}});return k("census_interactive_elements",`${e.length} interactive elements: ${Array.from(t.entries()).map(([n,i])=>`${n}×${i}`).join(", ")||"none"}`,e.length,s,[],e.length>300)};function pe(l){try{return L.inspectElement(l)}catch{return{tag:l.tagName.toLowerCase(),role:void 0,text:"",bestSelector:l.tagName.toLowerCase(),bounds:{x:0,y:0,width:0,height:0,top:0,right:0,bottom:0,left:0},visibility:{isVisible:!1,isInViewport:!1}}}}const yt=l=>{const e=["header","nav","main","aside","footer","article","section","figure","figcaption","mark","time","address","details","summary","dialog"],t=[];for(const i of e){const r=Array.from(l.querySelectorAll(i));if(r.length)for(const o of r.slice(0,20))t.push({tag:i,selector:D(o),role:o.getAttribute("role")||Et(i),text:B(o).slice(0,50),childCount:o.children.length})}const s=t.filter(i=>["banner","navigation","main","complementary","contentinfo"].includes(i.role)),n=[];return t.find(i=>i.tag==="main")||n.push("No element — page lacks a primary landmark."),l.querySelectorAll("header").length>1&&n.push("Multiple elements outside sections — ambiguous banner landmark."),k("detect_semantic_elements",`${t.length} semantic elements, ${s.length} landmarks`,t.length,X(t,100).items,n,t.length>100)};function Et(l){return{header:"banner",nav:"navigation",main:"main",aside:"complementary",footer:"contentinfo",article:"article",section:"region",form:"form"}[l]}const _e={analyze_forms:ct,extract_links:lt,analyze_media:dt,get_css_variables:ht,analyze_fonts:gt,extract_color_palette:pt,detect_zindex_conflicts:mt,detect_layout_issues:ft,census_interactive_elements:bt,detect_semantic_elements:yt,scan_accessibility_issues:l=>{var i;const e=[];for(const r of Array.from(l.querySelectorAll("img")).slice(0,200))r.hasAttribute("alt")||e.push({rule:"img-alt",severity:"error",selector:D(r),message:"Image is missing the alt attribute."});for(const r of Array.from(l.querySelectorAll("input:not([type=hidden]):not([type=submit]):not([type=button])")).slice(0,200)){const o=r.getAttribute("id");o&&l.querySelector(`label[for="${o}"]`)||r.closest("label")||r.getAttribute("aria-label")||r.getAttribute("aria-labelledby")||e.push({rule:"input-label",severity:"error",selector:D(r),message:"Form input has no associated label, aria-label or aria-labelledby."})}for(const r of Array.from(l.querySelectorAll('button, a[href], [role="button"]')).slice(0,300)){const o=B(r).trim(),a=r.getAttribute("aria-label");!o&&!a&&e.push({rule:"accessible-name",severity:"error",selector:D(r),message:"Interactive element has no accessible name (no text, no aria-label).",hint:r.querySelector("img[alt]")?"Contains an image — consider alt text or aria-label.":void 0})}const t=Array.from(l.querySelectorAll("h1, h2, h3, h4, h5, h6")).slice(0,100);let s=0;for(const r of t){const o=parseInt(r.tagName[1],10);s&&o>s+1&&e.push({rule:"heading-order",severity:"warning",selector:D(r),message:`Heading level jumps from h${s} to h${o}.`}),s=o}(i=l.documentElement)!=null&&i.getAttribute("lang")||e.push({rule:"html-lang",severity:"warning",selector:"html",message:"The element has no lang attribute."});const n=e.filter(r=>r.severity==="error").length;return k("scan_accessibility_issues",`${e.length} issue(s): ${n} errors, ${e.length-n} warnings`,e.length,X(e,100).items,[],e.length>100)},detect_dead_click_targets:l=>{const e=l.defaultView,t=[];for(const s of Array.from(l.querySelectorAll(ge)).slice(0,500)){const n=s.getBoundingClientRect(),i=e!=null&&e.getComputedStyle?e.getComputedStyle(s):null,r=n.width===0||n.height===0,o=i?i.pointerEvents==="none":!1,a=i?i.display==="none"||i.visibility==="hidden":!1,c=s.getAttribute("aria-hidden")==="true";(r||o||a||c)&&t.push({selector:D(s),tag:s.tagName.toLowerCase(),text:B(s).slice(0,30),reasons:[r&&"zero-size",o&&"pointer-events:none",a&&`hidden (${i?i.display:"?"}/${i?i.visibility:"?"})`,c&&"aria-hidden"].filter(Boolean)})}return k("detect_dead_click_targets",`${t.length} unreachable interactive element(s)`,t.length,X(t,80).items,[],t.length>80)},inventory_animations:l=>{const e=l.defaultView,t=[],s=[];if(!(e!=null&&e.getComputedStyle))return t.push("getComputedStyle unavailable — animation inventory requires rendered styles."),k("inventory_animations","unavailable",0,[],t,!1);for(const i of Array.from(l.querySelectorAll("body *")).slice(0,800)){const r=e.getComputedStyle(i),o=r.animationName!=="none"?`${r.animationName} ${r.animationDuration}`:null,a=r.transitionProperty!=="none"&&r.transitionProperty!=="all"?`${r.transitionProperty} ${r.transitionDuration}`:r.transitionProperty==="all"?`all ${r.transitionDuration}`:null;(o||a)&&s.push({selector:D(i),animation:o,transition:a,transitionTiming:r.transitionTimingFunction||void 0})}const n=s.filter(i=>i.animation&&i.animation.includes("infinite"));return n.length>5&&t.push(`${n.length} infinitely looping animations — may indicate decorative spinners or a stuck loading state.`),k("inventory_animations",`${s.length} animated/transitioning elements`,s.length,X(s,80).items,t,s.length>80)},map_frame_tree:l=>{const e=[],t=(n,i,r)=>{const o=Array.from(n.querySelectorAll("iframe, frame"));for(const a of o){const c=a.getAttribute("src")||"(no src)";let u=!1,d=null;try{const h=a.contentDocument;h&&(u=!0,d=h.querySelectorAll("*").length,r<3&&t(h,`${i} > ${a.tagName.toLowerCase()}[${c.slice(0,50)}]`,r+1))}catch{u=!1}e.push({path:`${i} > ${a.tagName.toLowerCase()}`,selector:D(a),src:c.slice(0,120),title:a.getAttribute("title")||void 0,name:a.getAttribute("name")||void 0,sandbox:a.getAttribute("sandbox")||void 0,accessible:u,childCount:d,limitation:u?void 0:"Same-origin policy blocks contentDocument access (cross-origin frame)."})}};t(l,"document",0);const s=e.filter(n=>!n.accessible).length;return k("map_frame_tree",`${e.length} frame(s), ${s} inaccessible (cross-origin)`,e.length,e,[],!1)},inventory_shadow_roots:l=>{const e=[],t=(s,n,i)=>{const r=(s instanceof ShadowRoot,Array.from(s.querySelectorAll("*")));for(const o of r)if(o.shadowRoot){const a=o.shadowRoot,c=`${n} > ${o.tagName.toLowerCase()}::shadowRoot(${a.mode})`;e.push({path:c.slice(0,200),hostSelector:D(o),hostTag:o.tagName.toLowerCase(),mode:a.mode,childCount:a.querySelectorAll("*").length,styles:a.querySelectorAll("style").length}),i<4&&t(a,c,i+1)}};return t(l.documentElement,"document",0),k("inventory_shadow_roots",`${e.length} open shadow root(s) found`,e.length,e,[],!1)},inspect_page_storage:l=>{const e=l.defaultView,t=new he,s=[],n=[];if(!(e!=null&&e.localStorage)||!(e!=null&&e.sessionStorage))return k("inspect_page_storage","Web Storage API unavailable in this context",0,[],["localStorage/sessionStorage are not accessible here (JSDOM limitation or sandboxed iframe)."],!1);try{for(let r=0;r r+(o.size||0),0);return k("inspect_page_storage",`${n.length} storage entries (~${i} bytes), sensitive keys redacted`,n.length,X(n,100).items,s,n.length>100)},get_performance_metrics:l=>{var i,r,o,a;const e=l.defaultView,t=[],s=e==null?void 0:e.performance;if(!(s!=null&&s.timing)&&!(s!=null&&s.getEntriesByType))return k("get_performance_metrics","Performance API unavailable",0,[],["window.performance is not exposed in this context."],!1);const n=[];try{const c=(r=(i=s.getEntriesByType)==null?void 0:i.call(s,"navigation"))==null?void 0:r[0];if(c)n.push({metric:"navigation-timing",domContentLoaded:Math.round(c.domContentLoadedEventEnd),loadComplete:Math.round(c.loadEventEnd),domInteractive:Math.round(c.domInteractive),type:c.type,redirectCount:c.redirectCount,sizeTransfer:c.transferSize});else if(s.timing){const h=s.timing;n.push({metric:"navigation-timing-legacy",domContentLoaded:h.domContentLoadedEventEnd-h.navigationStart,loadComplete:h.loadEventEnd-h.navigationStart,domInteractive:h.domInteractive-h.navigationStart})}const u=((o=s.getEntriesByType)==null?void 0:o.call(s,"paint"))||[];for(const h of u)n.push({metric:h.name,startTime:Math.round(h.startTime)});const d=((a=s.getEntriesByType)==null?void 0:a.call(s,"resource"))||[];if(d.length){const h=d.reduce((y,v)=>y+v.duration,0),p=[...d].sort((y,v)=>v.duration-y.duration).slice(0,5).map(y=>({url:String(y.name).slice(0,100),duration:Math.round(y.duration)}));n.push({metric:"resource-summary",count:d.length,totalDuration:Math.round(h),slowest:p})}s.memory&&n.push({metric:"memory",usedJSHeapMB:Math.round(s.memory.usedJSHeapSize/1048576*10)/10,totalJSHeapMB:Math.round(s.memory.totalJSHeapSize/1048576*10)/10})}catch(c){t.push(`performance read failed: ${c.message}`)}return k("get_performance_metrics",`${n.length} metric group(s)`,n.length,n,t,!1)},extract_seo_metadata:l=>{var r,o,a;const e=c=>{var u;return((u=l.querySelector(`meta[name="${c}"]`))==null?void 0:u.getAttribute("content"))||void 0},t=c=>{var u;return((u=l.querySelector(`meta[property="${c}"]`))==null?void 0:u.getAttribute("content"))||void 0},s=[{field:"title",value:l.title||void 0},{field:"description",value:e("description")},{field:"canonical",value:(r=l.querySelector('link[rel="canonical"]'))==null?void 0:r.getAttribute("href")},{field:"robots",value:e("robots")},{field:"viewport",value:e("viewport")},{field:"charset",value:(o=l.querySelector("meta[charset]"))==null?void 0:o.getAttribute("charset")},{field:"og:title",value:t("og:title")},{field:"og:description",value:t("og:description")},{field:"og:image",value:t("og:image")},{field:"og:url",value:t("og:url")},{field:"twitter:card",value:e("twitter:card")},{field:"language",value:(a=l.documentElement)==null?void 0:a.getAttribute("lang")}],n=l.querySelectorAll("h1").length,i=[];return n===0&&i.push("No h1 — page lacks a primary heading."),n>1&&i.push(`Multiple h1 elements (${n}).`),e("description")||i.push("No meta description."),s.push({field:"h1Count",value:n}),k("extract_seo_metadata",`SEO metadata extracted; ${i.length} warning(s)`,s.length,s,i,!1)},extract_structured_data:l=>{var t;const e=[];for(const s of Array.from(l.querySelectorAll('script[type="application/ld+json"]')))try{const n=JSON.parse(s.textContent||"{}");e.push({format:"JSON-LD",type:n["@type"]||(Array.isArray(n)?"array":"unknown"),data:n})}catch(n){e.push({format:"JSON-LD",type:"invalid-json",error:n.message})}for(const s of Array.from(l.querySelectorAll("[itemscope]")).slice(0,30)){const n=s.getAttribute("itemtype")||"unknown",i={};for(const r of Array.from(s.querySelectorAll("[itemprop]"))){const o=r.getAttribute("itemprop")||"",a=r.getAttribute("content")||r.getAttribute("href")||((t=r.textContent)==null?void 0:t.trim())||"";i[o]=a.slice(0,100)}e.push({format:"microdata",type:n.split("/").pop()||n,data:i})}return k("extract_structured_data",`${e.length} structured data block(s)`,e.length,e,[],!1)},extract_tables:l=>{const e=Array.from(l.querySelectorAll("table")),t=e.slice(0,30).map(s=>{var a,c,u;const n=Array.from(s.querySelectorAll("thead th, tr:first-child th")).map(d=>{var h;return((h=d.textContent)==null?void 0:h.trim())||""}),i=Array.from(s.querySelectorAll("tbody tr, tr")).filter(d=>!d.querySelector("th")).slice(0,50),r=i.map(d=>Array.from(d.querySelectorAll("td")).map(h=>(h.textContent||"").trim().slice(0,60))),o=(c=(a=s.querySelector("caption"))==null?void 0:a.textContent)==null?void 0:c.trim();return{selector:D(s),caption:o,columnCount:n.length||((u=r[0])==null?void 0:u.length)||0,rowCount:i.length,headers:n,rows:r}});return k("extract_tables",`${e.length} table(s)`,e.length,t,[],e.length>30)},extract_lists:l=>{const e=Array.from(l.querySelectorAll("ul, ol")),t=e.slice(0,60).map(s=>{const n=Array.from(s.querySelectorAll(":scope > li")).slice(0,40);return{selector:D(s),kind:s.tagName.toLowerCase(),ordered:s.tagName.toLowerCase()==="ol",itemCount:n.length,items:n.map(i=>B(i).slice(0,60)),nested:s.querySelectorAll("ul, ol").length}});return k("extract_lists",`${e.length} list(s)`,e.length,t,[],e.length>60)},analyze_page_content:l=>{const e=l.body,t=(e==null?void 0:e.innerText)||(e==null?void 0:e.textContent)||"",s=t.trim()?t.trim().split(/\s+/).length:0,n=Array.from(l.querySelectorAll("h1, h2, h3, h4, h5, h6")).map(c=>({level:parseInt(c.tagName[1],10),text:B(c).slice(0,80)})),i=l.querySelectorAll("p").length,r=i?Math.round(s/i):0,o=Math.round(s/220*10)/10,a=[{metric:"wordCount",value:s},{metric:"paragraphCount",value:i},{metric:"avgParagraphWords",value:r},{metric:"estimatedReadingMinutes",value:o},{metric:"headingCount",value:n.length},{metric:"imageCount",value:l.querySelectorAll("img").length},{metric:"linkDensity",value:Math.round(l.querySelectorAll("a[href]").length/Math.max(1,s)*1e3)/1e3},{metric:"headings",value:n.slice(0,50)}];return k("analyze_page_content",`${s} words, ${i} paragraphs, ~${o} min read`,a.length,a,[],!1)},search_dom:(l,e)=>{const t=String((e==null?void 0:e.query)||"").trim();if(!t)return k("search_dom","No query supplied",0,[],["Provide a text query; optionally tag/attr filters."],!1);const s=t.toLowerCase(),n=[],i=Math.min((e==null?void 0:e.limit)||50,200),r=Array.from(l.querySelectorAll("*"));for(const o of r){if(n.length>=i)break;if(e!=null&&e.tag&&o.tagName.toLowerCase()!==String(e.tag).toLowerCase())continue;const a=B(o),c=Array.from(o.attributes);let u=0,d="";o.tagName.toLowerCase().includes(s)&&(u+=.2,d="tag match"),a.toLowerCase().includes(s)&&a.length<200&&(u+=.6,d="text match");for(const h of c)if(h.name.toLowerCase().includes(s)||h.value.length<100&&h.value.toLowerCase().includes(s)){u+=.4,d=`attribute ${h.name} match`;break}if(e!=null&&e.attr){const h=String(e.attr).toLowerCase(),p=e.attrValue?String(e.attrValue).toLowerCase():null;if(c.find(v=>v.name.toLowerCase()===h&&(!p||v.value.toLowerCase().includes(p))))u+=.5;else continue}if(u>0){const h=pe(o);n.push({selector:h.bestSelector,tag:h.tag,role:h.role,text:h.text.slice(0,60),score:Math.round(u*100)/100,reason:d,visible:h.visibility.isVisible,bounds:{x:Math.round(h.bounds.x),y:Math.round(h.bounds.y),w:Math.round(h.bounds.width),h:Math.round(h.bounds.height)}})}}return n.sort((o,a)=>a.score-o.score),k("search_dom",`${n.length} element(s) match "${t}"`,n.length,n,[],n.length>=i)},inventory_ctas:l=>{var t;const e=[];for(const s of Array.from(l.querySelectorAll('button, a[class*="btn"], a[class*="button"], input[type="submit"], [role="button"]')).slice(0,100)){const n=pe(s);e.push({selector:n.bestSelector,tag:n.tag,text:n.text.slice(0,50),styleHint:(t=s.getAttribute("class"))==null?void 0:t.slice(0,60),primary:/primary|cta|submit|main/i.test(s.getAttribute("class")||"")||s.type==="submit",visible:n.visibility.isVisible})}return k("inventory_ctas",`${e.length} call-to-action element(s)`,e.length,e,[],!1)},detect_focus_traps:l=>{const e=[];for(const s of Array.from(l.querySelectorAll('[role="dialog"], [aria-modal="true"], dialog[open], .modal, [class*="modal"]')).slice(0,30)){const n=s.querySelectorAll('a[href], button, input, select, textarea, [tabindex]:not([tabindex="-1"])');e.push({selector:D(s),kind:s.getAttribute("role")||s.tagName.toLowerCase(),ariaModal:s.getAttribute("aria-modal"),focusableCount:n.length,firstFocusable:n[0]?D(n[0]):void 0,note:n.length===0?"Modal container has NO focusable elements — keyboard users are trapped.":void 0})}const t=l.querySelectorAll("[tabindex]>0");for(const s of Array.from(t).slice(0,20))e.push({selector:D(s),kind:"positive-tabindex",note:`tabindex=${s.tabIndex} breaks natural tab order.`});return k("detect_focus_traps",`${e.length} focus-management issue(s)/container(s)`,e.length,e,[],!1)},infer_responsive_breakpoints:l=>{const e=l.defaultView,t=[],s=new Set;for(const o of Array.from(l.querySelectorAll("style"))){const a=o.textContent||"",c=/@media[^{]*?\(\s*(?:min|max)-width\s*:\s*(\d+)(?:\.\d+)?px/g;let u;for(;u=c.exec(a);)s.add(parseInt(u[1],10))}for(const o of Array.from(l.querySelectorAll('link[rel="stylesheet"]')).slice(0,10)){const a=o.getAttribute("href")||"";if(/^\d+px$/.test(a)||a.includes("width=")){const c=a.match(/width=(\d+)/);c&&s.add(parseInt(c[1],10))}}for(const o of Array.from(l.querySelectorAll("img[srcset], source[srcset]")).slice(0,50)){const a=o.getAttribute("srcset")||"";for(const c of a.matchAll(/(\d+)w/g))s.add(parseInt(c[1],10))}e!=null&&e.matchMedia||t.push("matchMedia unavailable — live breakpoint probing skipped.");const n=Array.from(s).sort((o,a)=>o-a),i=n.map(o=>({breakpoint:o,note:o<=768?"mobile-class":o<=1024?"tablet-class":"desktop-class"})),r=e==null?void 0:e.innerWidth;if(r){const o=n.filter(a=>a<=r);i.unshift({breakpoint:`current viewport: ${r}px`,note:o.length?`below breakpoints: ${o.join(", ")}`:"no declared breakpoint below current width"})}return k("infer_responsive_breakpoints",`${n.length} breakpoint(s) inferred from CSS/srcset`,i.length,i,t,!1)},get_selection_state:l=>{var i;const e=l.defaultView,t=(i=e==null?void 0:e.getSelection)==null?void 0:i.call(e),s=l.activeElement,n=[{hasSelection:!!(t!=null&&t.toString()),selectedText:(t==null?void 0:t.toString().slice(0,200))||"",selectionRanges:(t==null?void 0:t.rangeCount)||0,activeElement:s?{tag:s.tagName.toLowerCase(),selector:D(s),editable:s.isContentEditable||["INPUT","TEXTAREA"].includes(s.tagName)}:null}];return k("get_selection_state",t!=null&&t.toString()?`Selection: "${t.toString().slice(0,40)}…"`:"No text selection",1,n,[],!1)}};function vt(l,e,t){const s=_e[l];return s?s(e,t):{analyzer:l,summary:`Unknown analyzer "${l}". Available: ${Object.keys(_e).join(", ")}`,count:0,items:[],warnings:[],truncated:!1}}const wt=2e3;class St{constructor(e=wt){f(this,"events",[]);f(this,"cap");f(this,"counter",0);this.cap=Math.max(10,e)}record(e,t,s={}){this.counter++;const n={eventId:`evt_${Date.now().toString(36)}_${this.counter}`,timestamp:Date.now(),kind:e,operationId:s.operationId,sessionId:s.sessionId,detail:t,data:s.data};return this.events.push(n),this.events.length>this.cap&&this.events.splice(0,this.events.length-this.cap),n}query(e){let t=this.events;e.kind&&(t=t.filter(n=>n.kind===e.kind)),e.operationId&&(t=t.filter(n=>n.operationId===e.operationId)),e.sinceTimestamp&&(t=t.filter(n=>n.timestamp>=e.sinceTimestamp));const s=e.limit&&e.limit>0?e.limit:200;return t.slice(-s)}size(){return this.events.length}toJSON(){return[...this.events]}}class Tt{constructor(){f(this,"counter",0);f(this,"operations",new Map)}begin(e){this.counter++;const t=`op_${Date.now().toString(36)}_${this.counter}`;return this.operations.set(t,{operationId:t,tool:e,startedAt:Date.now(),status:"RUNNING",timelineEventIds:[]}),t}end(e,t,s){const n=this.operations.get(e);n&&(n.endedAt=Date.now(),n.status=t,n.relatedError=s)}attachEvent(e,t){const s=this.operations.get(e);s&&s.timelineEventIds.push(t)}trace(e){const t=this.operations.get(e);return t?{...t,durationMs:t.endedAt?t.endedAt-t.startedAt:void 0}:null}recent(e=100){return Array.from(this.operations.values()).slice(-e).map(t=>({...t,durationMs:t.endedAt?t.endedAt-t.startedAt:void 0}))}}const xe=100;class Ct{constructor(e){f(this,"sessionId");f(this,"timeline",new St);f(this,"operations",new Tt);f(this,"tabs",new Map);f(this,"activeTabId",null);f(this,"startedAt",Date.now());f(this,"snapshots",[]);f(this,"commandHistory",[]);f(this,"annotationCount",0);f(this,"projectId");f(this,"tabCounter",0);f(this,"commandCounter",0);this.sessionId=e||`sess_${Date.now().toString(36)}`}registerTab(e,t,s){const n=e!==void 0?Array.from(this.tabs.values()).find(o=>o.browserTabId===e):void 0;if(n)return n.lastSeenAt=Date.now(),n.status="OPEN",n.url=t||n.url,n.title=s||n.title,n;this.tabCounter++;const i=`stab_${this.tabCounter}_${Date.now().toString(36)}`,r={sessionTabId:i,browserTabId:e,url:t,title:s,createdAt:Date.now(),lastSeenAt:Date.now(),status:"OPEN"};return this.tabs.set(i,r),this.timeline.record("TAB_OPENED",`tab ${i} registered (${t||"no url"})`,{sessionId:this.sessionId}),r}closeTab(e){const t=this.tabs.get(e);return t?(t.status="CLOSED",t.lastSeenAt=Date.now(),this.timeline.record("TAB_CLOSED",`tab ${e} closed`,{sessionId:this.sessionId}),!0):!1}switchTab(e){const t=this.tabs.get(e);return!t||t.status==="CLOSED"?!1:(this.activeTabId=e,this.timeline.record("TAB_SWITCHED",`active tab → ${e}`,{sessionId:this.sessionId}),!0)}getTabs(){return Array.from(this.tabs.values())}getActiveTab(){if(this.activeTabId){const e=this.tabs.get(this.activeTabId);if(e&&e.status==="OPEN")return e}return Array.from(this.tabs.values()).find(e=>e.status==="OPEN")||null}markAllStale(){let e=0;for(const t of this.tabs.values())t.status==="OPEN"&&(t.status="STALE",e++);return e}captureSnapshot(e,t,s){var a,c,u;const n=e.defaultView,i=((a=e.documentElement)==null?void 0:a.outerHTML)||"",r=e.querySelectorAll('a[href], button, input, select, textarea, [role="button"]').length,o={snapshotId:`snap_${Date.now().toString(36)}_${this.snapshots.length+1}`,timestamp:Date.now(),url:((c=n==null?void 0:n.location)==null?void 0:c.href)||((u=e.location)==null?void 0:u.href)||"",title:e.title||"",viewport:{width:(n==null?void 0:n.innerWidth)||0,height:(n==null?void 0:n.innerHeight)||0,scrollX:(n==null?void 0:n.scrollX)||0,scrollY:(n==null?void 0:n.scrollY)||0,devicePixelRatio:(n==null?void 0:n.devicePixelRatio)||1},domLength:i.length,domHash:ve(i),interactiveCount:r,selectedRegions:[],extensionEnabled:t,pendingMutations:s,annotationCount:this.annotationCount};return this.snapshots.push(o),this.snapshots.length>xe&&this.snapshots.splice(0,this.snapshots.length-xe),this.timeline.record("SNAPSHOT_CREATED",`snapshot ${o.snapshotId} (dom ${o.domLength}b)`,{sessionId:this.sessionId}),o}getSnapshot(e){return e?this.snapshots.find(t=>t.snapshotId===e)||null:this.snapshots[this.snapshots.length-1]||null}listSnapshots(){return this.snapshots.map(e=>({snapshotId:e.snapshotId,timestamp:e.timestamp,url:e.url,title:e.title,domLength:e.domLength,domHash:e.domHash}))}compareSnapshots(e,t){const s=["url","title","domLength","domHash","interactiveCount","extensionEnabled","annotationCount"],n=[];for(const r of s)e[r]!==t[r]&&n.push({field:r,before:e[r],after:t[r]});(e.viewport.width!==t.viewport.width||e.viewport.height!==t.viewport.height)&&n.push({field:"viewport",before:`${e.viewport.width}x${e.viewport.height}`,after:`${t.viewport.width}x${t.viewport.height}`});const i=t.domLength-e.domLength;return{identical:n.length===0,changes:n,domDelta:{beforeLength:e.domLength,afterLength:t.domLength,delta:i},summary:n.length===0?"States are identical.":`${n.length} field(s) changed; DOM size ${i>=0?"+":""}${i} bytes.`}}recordCommand(e,t,s,n,i){this.commandCounter++;const r=`cmd_${this.commandCounter}_${Date.now().toString(36)}`;return this.commandHistory.push({commandId:r,tool:e,args:t,outcome:s,timestamp:Date.now(),durationMs:n,error:i}),this.timeline.record("COMMAND_EXECUTED",`${e} → ${s}${i?` (${i})`:""}`,{sessionId:this.sessionId,data:{commandId:r}}),r}getCommandHistory(e=100){return this.commandHistory.slice(-e)}noteAnnotations(e){this.annotationCount=e}bindProject(e){this.projectId=e}getProjectId(){return this.projectId}summary(e,t,s,n){var i,r,o;return{sessionId:this.sessionId,startedAt:this.startedAt,url:((r=(i=e.defaultView)==null?void 0:i.location)==null?void 0:r.href)||((o=e.location)==null?void 0:o.href)||"",title:e.title||"",tabs:this.getTabs(),activeTabId:this.activeTabId,viewport:{width:t.width,height:t.height,isModified:t.isModified},extensionEnabled:s,snapshotCount:this.snapshots.length,commandCount:this.commandHistory.length,annotationCount:this.annotationCount,mutationHistoryCount:n.length,timelineEventCount:this.timeline.size(),projectId:this.projectId}}}const At=l=>{var e,t;try{const s=l.getBoundingClientRect();if(s.width===0&&s.height===0)return null;const n=((t=(e=l.ownerDocument)==null?void 0:e.defaultView)==null?void 0:t.innerWidth)||1920;return s.y n*1.5?"bottom":s.x n*.8?"right":"center"}catch{return null}},It={navigation:"navigation",banner:"header",contentinfo:"footer",complementary:"sidebar",main:"main",form:"form",search:"search",region:"section",dialog:"modal",alertdialog:"modal",table:"table",list:"list",combobox:"dropdown",button:"button",link:"link",textbox:"input",checkbox:"checkbox",radio:"radio",img:"image",article:"article"},_t={nav:"navigation",header:"header",footer:"footer",aside:"sidebar",main:"main",section:"section",article:"article",form:"form",table:"table",ul:"list",ol:"list",figure:"figure",dialog:"modal",button:"button",input:"input",select:"dropdown",textarea:"textarea",canvas:"canvas",video:"video",img:"image",h1:"heading",h2:"heading",h3:"heading"};function ee(l){return l.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"").replace(/_{2,}/g,"_").slice(0,48).replace(/_$/,"")}class xt{generate(e){return this.generateFromMeta({tagName:e.tagName.toLowerCase(),role:e.getAttribute("role")||void 0,text:B(e).trim(),ariaLabel:e.getAttribute("aria-label")||void 0,stableClass:Array.from(e.classList||[]).find(t=>/^[a-z][a-z0-9-]{2,}$/i.test(t)&&!Nt.has(t)),position:At(e),nearbyHeading:this.nearbyHeading(e)})}generateFromMeta(e){const t=[],s=[],n=e.role||Rt(e.tagName);if(n){const r=It[n]||n;s.push(r),t.push(`role=${n}`)}else{const r=_t[e.tagName]||e.tagName;s.push(r),t.push(`tag=${e.tagName}`)}if(e.ariaLabel&&(s.unshift(ee(e.ariaLabel)),t.push(`aria-label="${e.ariaLabel.slice(0,30)}"`)),e.text&&e.text.length<=40){const r=ee(e.text.split(/\s+/).slice(0,3).join(" "));r&&r.length>=2&&(s.push(r),t.push(`text="${e.text.slice(0,30)}"`))}if(e.nearbyHeading){const r=ee(e.nearbyHeading.split(/\s+/).slice(0,3).join(" "));r&&!s.includes(r)&&(s.push(r),t.push(`nearby-heading="${e.nearbyHeading.slice(0,30)}"`))}e.stableClass&&s.length<3&&(s.push(ee(e.stableClass)),t.push(`class=${e.stableClass}`)),e.tagName==="input"&&(s.some(r=>r.includes("input"))||(s.push("input"),t.push("tag=input"))),s.join("_").length<12&&e.position&&(s.push(e.position),t.push(`position=${e.position}`));let i=ee(s.join("_"))||"unnamed_region";return/^\d/.test(i)&&(i=`el_${i}`),{name:i,evidence:t}}nearbyHeading(e){let t=e.parentElement;for(let n=0;t&&n<4;n++){const i=t.querySelector('h1, h2, h3, h4, [role="heading"]');if(i)return B(i).trim().slice(0,40)||null;t=t.parentElement}let s=e.previousElementSibling;for(let n=0;s&&n<4;n++){if(/^H[1-4]$/.test(s.tagName)){const i=B(s).trim();if(i)return i.slice(0,40)}s=s.previousElementSibling}return null}}const Nt=new Set(["active","open","visible","hidden","selected","disabled","container","wrapper","root","item","col","row","flex","box","main","div","span","block"]);function Rt(l){switch(l){case"nav":return"navigation";case"header":return"banner";case"footer":return"contentinfo";case"aside":return"complementary";case"main":return"main";case"form":return"form";case"table":return"table";case"button":return"button";case"a":return"link";case"input":return"textbox";case"select":return"combobox";case"textarea":return"textbox";case"img":return"img";default:return null}}const Mt=["display","position","flex-direction","grid-template-columns","width","height","background-color","color","font-size","border-radius","overflow"];class kt{constructor(){f(this,"naming",new xt)}capture(e){const t=e.ownerDocument,s=new Z(t),n=new re,i=s.generateCandidates(e),r=s.bestSelector(e),o=n.fingerprint(e);let a=e,c=0,u="self";for(let g=0;g<3;g++){const b=a.parentElement;if(!b||b===t.body||b===t.documentElement)break;if(this.isMeaningfulContainer(b)){a=b,c=g+1,u="meaningful-ancestor";break}a=b,c=g+1}if(a===e){const g=e.parentElement;g&&g!==t.body&&e.querySelectorAll("*").length<4&&(a=g,c=1,u="direct-parent-fallback")}const d=this.boundedHtml(e,6e4),h=this.boundedHtml(a,12e4);L.inspectElement(e);const p=e.getBoundingClientRect(),y=t.defaultView,v={};if(y!=null&&y.getComputedStyle){const g=y.getComputedStyle(e);for(const b of Mt){const T=g.getPropertyValue(b);T&&T!=="none"&&T!=="auto"&&(v[b]=T)}}const m=e.parentElement;return{regionHtml:d,contextHtml:h,boundary:{strategy:u,ancestorLevels:c,note:c===0?"Region captured standalone (no meaningful ancestor within 3 levels).":`Context includes ${c} ancestor level(s) up to a meaningful container.`},selectorCandidates:i,bestSelector:r.selector,xpath:s.buildXPath(e),fingerprintHash:o.hash,dimensions:{width:Math.round(p.width),height:Math.round(p.height)},position:{x:Math.round(p.x),y:Math.round(p.y)},relevantStyles:v,parentInfo:m?{tag:m.tagName.toLowerCase(),selector:Ot(m),text:B(m).slice(0,60)}:void 0,childrenCount:e.children.length,childTags:Array.from(e.children).slice(0,12).map(g=>g.tagName.toLowerCase()),nameHint:this.naming.generate(e),fingerprintVolatility:o.volatilityRisk,volatilityReasons:o.volatilityReasons}}isMeaningfulContainer(e){const t=e.tagName.toLowerCase();if(["section","article","aside","main","nav","header","footer","form"].includes(t)||e.hasAttribute("id")||e.hasAttribute("data-testid")||e.getAttribute("role")||e.children.length>1&&e.querySelector(":scope > *:nth-child(3)"))return!0;const s=e.getAttribute("style")||"";return!!(s.includes("grid")||s.includes("flex"))}boundedHtml(e,t){const s=e.outerHTML;return s.length<=t?s:s.slice(0,t)+` -`}}function Ot(l){try{return new Z(l.ownerDocument).bestSelector(l).selector}catch{return l.tagName.toLowerCase()}}class Lt{constructor(e){f(this,"nodeRegistry");f(this,"snapshotEngine");f(this,"picker");f(this,"interactionEngine");f(this,"observer");f(this,"mutationEngines",new WeakMap);f(this,"viewportControllers",new WeakMap);f(this,"targetingEngines",new WeakMap);f(this,"jsEngine",new Fe);f(this,"fingerprintEngine",new re);f(this,"humanInteraction",new rt);f(this,"session",new Ct);f(this,"simulationTabs",[]);f(this,"simulationTabCounter",0);f(this,"simulationExtensions",[{id:"teledom@teledom",name:"TeleDOM Browser Intelligence Platform",version:"4.1.0",description:"The TeleDOM platform extension itself",enabled:!0,installType:"development",isApp:!1}]);f(this,"regionCapture",new kt);this.nodeRegistry=e||new z;const t=new se,s=new oe;this.snapshotEngine=new me(this.nodeRegistry,t,s),this.picker=new Ue({nodeRegistry:this.nodeRegistry}),this.interactionEngine=new De(this.nodeRegistry),this.observer=new Pe(this.nodeRegistry),this.picker.initGlobalShortcutListener(),this.interactionEngine.setTimingHook(async n=>{const i=this.humanInteraction.delay(n);i>0&&await new Promise(r=>setTimeout(r,i))})}getMutationEngine(e){let t=this.mutationEngines.get(e);return t||(t=new He(e,this.nodeRegistry),this.mutationEngines.set(e,t)),t}getViewportController(e){let t=this.viewportControllers.get(e);return t||(t=new ze(e),this.viewportControllers.set(e,t)),t}getTargetingEngine(e){let t=this.targetingEngines.get(e);return t||(t=new st(e,this.nodeRegistry),this.targetingEngines.set(e,t)),t}isSimulation(){return typeof globalThis.__FORENSIC_SIMULATION__<"u"}getPicker(){return this.picker}getInteractionEngine(){return this.interactionEngine}getObserver(){return this.observer}getNodeRegistry(){return this.nodeRegistry}async handleCommand(e,t=typeof document<"u"?document:{}){var o,a,c,u,d,h,p,y,v;const s=Date.now(),{id:n,command:i,payload:r}=e;try{switch(i){case"LIVE_PAGE_INSPECT":{const m=L.inspectPage(t);return this.success(n,i,m,s)}case"LIVE_ELEMENT_INSPECT":{const m=this.resolveTarget(r,t),g=L.inspectElement(m,this.nodeRegistry);return this.success(n,i,g,s)}case"GET_SELECTED_ELEMENT":{const m=this.picker.getLastSelectedElement();return this.success(n,i,m,s)}case"ELEMENT_PICKER_START":return this.picker.startPicker(),this.success(n,i,{pickerActive:!0},s);case"ELEMENT_PICKER_STOP":return this.picker.stopPicker(),this.success(n,i,{pickerActive:!1},s);case"LIVE_ELEMENT_INTERACT":{const m=r,g=await this.interactionEngine.interact(m,t);return this.success(n,i,g,s)}case"ELEMENT_OBSERVATION_START":{const m=this.resolveTarget(r,t),g=this.observer.startObservation(m,t);return this.success(n,i,g,s)}case"ELEMENT_OBSERVATION_STOP":{const m=this.observer.stopObservation(t);return this.success(n,i,m,s)}case"LIVE_DOM_SNAPSHOT":{if(((r==null?void 0:r.format)||"html")==="html"){const b=((o=t.documentElement)==null?void 0:o.outerHTML)||"";return this.success(n,i,{html:b},s)}const g=this.snapshotEngine.captureSnapshot(t,"live_session");return this.success(n,i,g,s)}case"LIVE_DOM_SUBTREE":{const m=this.resolveTarget(r,t),g=m.outerHTML||"",b=L.inspectElement(m,this.nodeRegistry);return this.success(n,i,{html:g,element:b},s)}case"GET_ELEMENT_VISUAL_STATE":{const m=this.resolveTarget(r,t),g=L.inspectVisualState(m);return this.success(n,i,g,s)}case"LIVE_PAGE_SCREENSHOT":case"LIVE_ELEMENT_SCREENSHOT":{const m=await this.handleScreenshotCapture(i,r,t);return this.success(n,i,m,s)}case"GET_TAB_CONSOLE_LOGS":{const{level:m,searchQuery:g,limit:b=100,clearAfterRead:T}=r||{};let w=typeof window<"u"&&window.__FORENSIC_CONSOLE_BUFFER__||[];if(m&&m!=="all"&&(w=w.filter(E=>E.level===m)),g){const E=String(g).toLowerCase();w=w.filter(C=>{var N,I;return((N=C.text)==null?void 0:N.toLowerCase().includes(E))||((I=C.source)==null?void 0:I.toLowerCase().includes(E))})}return b>0&&(w=w.slice(-b)),T&&typeof window<"u"&&window.__FORENSIC_CONSOLE_BUFFER__&&(window.__FORENSIC_CONSOLE_BUFFER__.length=0),this.success(n,i,{url:typeof window<"u"?window.location.href:"",title:t.title||"",totalCaptured:typeof window<"u"&&((a=window.__FORENSIC_CONSOLE_BUFFER__)==null?void 0:a.length)||w.length,returnedCount:w.length,logs:w},s)}case"GET_TAB_NETWORK_REQUESTS":{const{method:m,searchQuery:g,status:b,onlyErrors:T,limit:w=100,clearAfterRead:E}=r||{};let C=typeof window<"u"&&window.__FORENSIC_NETWORK_BUFFER__||[];if(m&&(C=C.filter(N=>{var I;return((I=N.method)==null?void 0:I.toUpperCase())===String(m).toUpperCase()})),b&&(C=C.filter(N=>N.status===Number(b))),T&&(C=C.filter(N=>N.error||N.status&&N.status>=400)),g){const N=String(g).toLowerCase();C=C.filter(I=>{var R;return(R=I.url)==null?void 0:R.toLowerCase().includes(N)})}return w>0&&(C=C.slice(-w)),E&&typeof window<"u"&&window.__FORENSIC_NETWORK_BUFFER__&&(window.__FORENSIC_NETWORK_BUFFER__.length=0),this.success(n,i,{url:typeof window<"u"?window.location.href:"",title:t.title||"",totalCaptured:typeof window<"u"&&((c=window.__FORENSIC_NETWORK_BUFFER__)==null?void 0:c.length)||C.length,returnedCount:C.length,requests:C},s)}case"CLOSE_TAB":{if(typeof globalThis.chrome<"u"&&((u=globalThis.chrome.runtime)!=null&&u.sendMessage)){const m=await new Promise(g=>{globalThis.chrome.runtime.sendMessage({type:"BROWSER_COMMAND_REQUEST",id:n,command:i,payload:r},b=>g(b))});if(m)return m}return this.isSimulation()?this.simulationCloseTab(r,t,n,i,s):typeof window<"u"?(setTimeout(()=>window.close(),100),this.success(n,i,{closed:!0,url:window.location.href,title:t.title},s)):this.success(n,i,{closed:!0},s)}case"RELOAD_TAB":{if(typeof globalThis.chrome<"u"&&((d=globalThis.chrome.runtime)!=null&&d.sendMessage)){const m=await new Promise(g=>{globalThis.chrome.runtime.sendMessage({type:"BROWSER_COMMAND_REQUEST",id:n,command:i,payload:r},b=>g(b))});if(m)return m}if(this.isSimulation()){const m=(r==null?void 0:r.mode)||"soft";return this.session.timeline.record("NAVIGATED",`tab reloaded (${m} mode)`),this.success(n,i,{reloaded:!0,mode:m,simulated:!0,url:((p=(h=t.defaultView)==null?void 0:h.location)==null?void 0:p.href)||"",title:t.title,note:"Node simulation context: DOM fixture retained; no real navigation occurs."},s)}return typeof window<"u"?(setTimeout(()=>window.location.reload(),100),this.success(n,i,{reloaded:!0,url:window.location.href,title:t.title},s)):this.success(n,i,{reloaded:!0},s)}case"OPEN_TAB":case"LIST_TABS":case"FOCUS_TAB":case"LIST_EXTENSIONS":case"RELOAD_EXTENSION":case"SET_EXTENSION_ENABLED":case"TOGGLE_EXTENSION":{if(this.isSimulation())return this.handleSimulationBackgroundCommand(n,i,r,t,s);if(typeof globalThis.chrome<"u"&&((y=globalThis.chrome.runtime)!=null&&y.sendMessage)){const m=await new Promise(g=>{globalThis.chrome.runtime.sendMessage({type:"BROWSER_COMMAND_REQUEST",id:n,command:i,payload:r},b=>g(b))});if(m)return m}return this.error(n,i,"BACKGROUND_EXECUTION_FAILED",`Command ${i} requires Chrome extension runtime`,s)}case"RESIZE_VIEWPORT":{const m=this.getViewportController(t);let g;if(r!=null&&r.preset)g=m.applyPreset(r.preset);else{const b=Number(r==null?void 0:r.width)||1280,T=Number(r==null?void 0:r.height)||800;g=m.resize(b,T)}return this.session.timeline.record("RESIZED",`viewport → ${g.applied.width}x${g.applied.height}`),this.success(n,i,g,s)}case"RESET_VIEWPORT":{const g=this.getViewportController(t).reset();return this.session.timeline.record("RESIZED",`viewport restored to ${g.applied.width}x${g.applied.height}`),this.success(n,i,g,s)}case"GET_VIEWPORT_STATE":{const m=this.getViewportController(t);return this.success(n,i,m.state(),s)}case"RUN_RESPONSIVE_TEST":{const m=this.getViewportController(t),g=(r==null?void 0:r.sizes)||Ut(),b=m.runResponsiveTest(g,{restore:(r==null?void 0:r.restore)!==!1});return this.success(n,i,b,s)}case"EMULATE_DEVICE":{const g=this.getViewportController(t).emulateDevice((r==null?void 0:r.device)||"pixel-7");return this.success(n,i,g,s)}case"EXECUTE_JS":case"EXECUTE_JS_AND_CAPTURE_CHANGES":{const m=String((r==null?void 0:r.code)||"");if(!m.trim())return this.error(n,i,"SCRIPT_EMPTY","payload.code is required.",s);const g=await this.jsEngine.execute(t,m,{timeoutMs:r==null?void 0:r.timeoutMs,world:(r==null?void 0:r.world)==="MAIN"?"MAIN":"ISOLATED"});return this.session.timeline.record("SCRIPT_EXECUTED",`${g.status} (${g.durationMs}ms)`),this.success(n,i,g,s)}case"DOM_MUTATE":{const g=this.getMutationEngine(t).mutate(r);return this.session.timeline.record("DOM_MUTATED",`${g.operation} on ${g.before.selector} → ${g.success?"OK":g.error}`),this.success(n,i,g,s)}case"DOM_MUTATE_TRANSACTION":{const m=this.getMutationEngine(t),g=(r==null?void 0:r.mode)||"begin";try{if(g==="begin"){const b=m.beginTransaction();return this.success(n,i,{transactionId:b,mode:g,open:!0},s)}if(g==="commit"){const b=m.commitTransaction();return this.session.timeline.record("DOM_MUTATED",`transaction ${b.transactionId} committed (${b.steps.length} steps)`),this.success(n,i,{...b,mode:g},s)}if(g==="rollback"){const b=m.rollbackTransaction(r==null?void 0:r.reason);return this.session.timeline.record("MUTATION_UNDONE",`transaction ${b.transactionId} rolled back`),this.success(n,i,{...b,mode:g},s)}return this.error(n,i,"INVALID_MODE",`mode must be begin|commit|rollback, got "${g}"`,s)}catch(b){return this.error(n,i,"DOM_MUTATION_FAILED",b.message,s)}}case"UNDO_DOM_MUTATION":{const g=this.getMutationEngine(t).undo();return g.success&&this.session.timeline.record("MUTATION_UNDONE",g.message),this.success(n,i,g,s)}case"REDO_DOM_MUTATION":{const g=this.getMutationEngine(t).redo();return g.success&&this.session.timeline.record("MUTATION_REDONE",g.message),this.success(n,i,g,s)}case"GET_MUTATION_HISTORY":{const m=this.getMutationEngine(t);return this.success(n,i,{entries:m.getHistory((r==null?void 0:r.limit)||100),undoDepth:m.getUndoDepth(),redoDepth:m.getRedoDepth(),openTransactionId:m.getOpenTransactionId()},s)}case"PREVIEW_DOM_MUTATION":{const g=this.getMutationEngine(t).preview(r);return this.success(n,i,g,s)}case"GENERATE_ELEMENT_TARGET":{const g=this.getTargetingEngine(t).resolveAndBuild((r==null?void 0:r.target)||(r==null?void 0:r.selector)||"");return"error"in g?this.error(n,i,"TARGET_NOT_FOUND",g.error,s):this.success(n,i,g.target,s)}case"RECOVER_SELECTOR":{const m=new it(t),g=(r==null?void 0:r.snapshot)||{},b=m.recover((r==null?void 0:r.selector)||"",g);return this.success(n,i,b,s)}case"GET_ELEMENT_ANCESTRY":{const m=this.resolveTarget(r,t);return this.success(n,i,Dt(m,t),s)}case"GET_ELEMENT_FINGERPRINT":{const m=this.resolveTarget(r,t),g=this.fingerprintEngine.fingerprint(m);return this.success(n,i,g,s)}case"GET_ELEMENT_RELATIONSHIPS":{const m=this.resolveTarget(r,t);return this.success(n,i,$t(m,t),s)}case"GET_ELEMENT_ACCESSIBILITY":{const m=this.resolveTarget(r,t);return this.success(n,i,qt(m),s)}case"GET_COMPUTED_STYLE":{const m=this.resolveTarget(r,t),g=t.defaultView;if(!(g!=null&&g.getComputedStyle))return this.error(n,i,"STYLE_UNAVAILABLE","getComputedStyle is unavailable in this context.",s);const b=g.getComputedStyle(m),T=Array.isArray(r==null?void 0:r.properties)&&r.properties.length?r.properties:["display","position","color","background-color","font-size","font-family","width","height","margin","padding","border","z-index","opacity","visibility","overflow","flex-direction","grid-template-columns"],w={};for(const E of T)w[E]=b.getPropertyValue(E);return this.success(n,i,{selector:L.inspectElement(m,this.nodeRegistry).bestSelector,styles:w},s)}case"ANALYZE_DOM":{const m=String((r==null?void 0:r.analyzer)||"");if(!m)return this.error(n,i,"ANALYZER_REQUIRED",'payload.analyzer is required (e.g. "analyze_forms").',s);const g=vt(m,t,r);return g.count===0&&g.warnings.length===0&&g.items.length===0&&g.summary.startsWith("Unknown analyzer")?this.error(n,i,"UNKNOWN_ANALYZER",g.summary,s):this.success(n,i,g,s)}case"DRAG_ELEMENT":{const m=this.resolveTarget(r==null?void 0:r.source,t),g=r!=null&&r.target?this.resolveTarget(r==null?void 0:r.target,t):null,b=await this.performDrag(m,g,r==null?void 0:r.offsets,t);return this.success(n,i,b,s)}case"SET_INPUT_CHECKED":{const g=this.resolveTarget(r,t);if(g.type!=="checkbox"&&g.type!=="radio")return this.error(n,i,"INPUT_TYPE_UNSUPPORTED",`Target input type "${g.type}" is not checkbox/radio.`,s);const b=g.checked;g.checked=(r==null?void 0:r.checked)!==!1;const T=[];for(const w of["input","change"])try{g.dispatchEvent(new t.defaultView.Event(w,{bubbles:!0})),T.push(w)}catch{}if(g.type==="radio"&&g.name)for(const w of Array.from(t.querySelectorAll(`input[type=radio][name="${g.name}"]`)))w!==g&&(w.checked=!1);return this.success(n,i,{success:!0,selector:L.inspectElement(g,this.nodeRegistry).bestSelector,inputType:g.type,checkedBefore:b,checkedAfter:g.checked,eventsFired:T},s)}case"PRESS_KEYBOARD_SHORTCUT":{const m=Array.isArray(r==null?void 0:r.keys)?r.keys:String((r==null?void 0:r.keys)||"Enter").split("+"),g=r!=null&&r.target?this.resolveTarget(r==null?void 0:r.target,t):t.activeElement||t.body;typeof g.focus=="function"&&g.focus();const b=[],T=t.defaultView;for(const w of m)for(const E of["keydown","keyup"])try{g.dispatchEvent(new((T==null?void 0:T.KeyboardEvent)||KeyboardEvent)(E,{key:w.trim(),bubbles:!0,cancelable:!0,ctrlKey:m.some(C=>/^(ctrl|control|cmd|meta)$/i.test(C))&&w!==m.find(C=>/^(ctrl|control|cmd|meta)$/i.test(C)),shiftKey:m.some(C=>/^shift$/i.test(C))&&w!=="Shift",altKey:m.some(C=>/^alt$/i.test(C))&&w!=="Alt"})),b.push(`${E}:${w}`)}catch{}return this.success(n,i,{success:!0,keys:m,targetSelector:L.inspectElement(g,this.nodeRegistry).bestSelector,eventsFired:b},s)}case"SCROLL_PAGE":{const m=t.defaultView;if(!m)return this.error(n,i,"NO_WINDOW","No window available for scrolling.",s);const g={x:m.scrollX||0,y:m.scrollY||0};let b;if(r!=null&&r.target||r!=null&&r.selector){const w=this.resolveTarget((r==null?void 0:r.target)||(r==null?void 0:r.selector),t);(v=w.scrollIntoView)==null||v.call(w,{behavior:(r==null?void 0:r.behavior)||"auto",block:"center"}),b=L.inspectElement(w,this.nodeRegistry).bestSelector}else m.scrollBy(Number(r==null?void 0:r.x)||0,Number(r==null?void 0:r.y)||0);const T={x:m.scrollX||0,y:m.scrollY||0};return this.success(n,i,{success:!0,scrollBefore:g,scrollAfter:T,requested:{x:Number(r==null?void 0:r.x)||0,y:Number(r==null?void 0:r.y)||0},targetSelector:b},s)}case"WAIT_FOR_CONDITION":return await this.waitForCondition(t,r||{},s,n,i);case"GET_PAGE_STATE":case"CAPTURE_PAGE_STATE":{const m=this.session.captureSnapshot(t,!0,this.getMutationEngine(t).getUndoDepth());return this.success(n,i,m,s)}case"CAPTURE_REGION":{const m=this.resolveTarget((r==null?void 0:r.target)||(r==null?void 0:r.selector),t),g=this.regionCapture.capture(m);return this.success(n,i,g,s)}case"GET_SIMULATION_TAB_STATE":return this.isSimulation()?this.success(n,i,{simulated:!0,tabs:this.simulationTabs,sessionSummary:this.session.getTabs()},s):this.error(n,i,"NOT_SIMULATION","Simulation tab state is only available in the Node simulation context.",s);default:return this.error(n,i,"UNKNOWN_COMMAND",`Unsupported command '${i}'`,s)}}catch(m){return this.error(n,i,"COMMAND_EXECUTION_FAILED",m.message,s,m.details)}}resolveTarget(e,t){if(!e)throw new Error("Target specifier must be provided");return typeof e=="string"?this.interactionEngine.resolveTarget({selector:e},t):typeof e=="number"?this.interactionEngine.resolveTarget({nodeId:e},t):this.interactionEngine.resolveTarget(e,t)}async performDrag(e,t,s,n){const i=n.defaultView,r=[],o=(p,y,v={})=>{try{const m=(i==null?void 0:i.MouseEvent)||(typeof MouseEvent<"u"?MouseEvent:null);m&&(p.dispatchEvent(new m(y,{bubbles:!0,cancelable:!0,...v})),r.push(y))}catch{}},a=e.getBoundingClientRect(),c=a.x+a.width/2,u=a.y+a.height/2;let d=c+((s==null?void 0:s.x)||0),h=u+((s==null?void 0:s.y)||0);if(t){const p=t.getBoundingClientRect();d=p.x+p.width/2,h=p.y+p.height/2}return o(e,"pointerdown",{button:1,clientX:c,clientY:u}),o(e,"mousedown",{button:1,clientX:c,clientY:u}),o(e,"dragstart",{clientX:c,clientY:u}),t&&(o(t,"dragenter",{clientX:d,clientY:h}),o(t,"dragover",{clientX:d,clientY:h}),o(t,"drop",{clientX:d,clientY:h})),o(e,"dragend",{clientX:d,clientY:h}),o(e,"pointerup",{button:1,clientX:d,clientY:h}),o(e,"mouseup",{button:1,clientX:d,clientY:h}),{success:r.length>0,sourceSelector:L.inspectElement(e,this.nodeRegistry).bestSelector,targetSelector:t?L.inspectElement(t,this.nodeRegistry).bestSelector:"(offset drop)",eventsFired:r,finalPosition:{x:Math.round(d),y:Math.round(h)},html5DndUsed:r.includes("dragstart")}}async waitForCondition(e,t,s,n,i){var p,y;const r=t.kind||"dom_stable",o=Math.min(Math.max(Number(t.timeoutMs)||5e3,100),3e4),a=Math.min(Math.max(Number(t.pollIntervalMs)||100,20),1e3),c=Date.now(),u=()=>{var v,m,g,b,T;switch(r){case"dom_stable":return{satisfied:!0,detail:`dom length ${((v=e.documentElement)==null?void 0:v.outerHTML.length)||0}`};case"selector_present":{const w=t.selector?e.querySelectorAll(t.selector).length:0;return{satisfied:w>0,detail:`"${t.selector}" matches ${w} element(s)`}}case"selector_visible":{if(!t.selector)return{satisfied:!1,detail:"no selector supplied"};const w=e.querySelector(t.selector);if(!w)return{satisfied:!1,detail:`"${t.selector}" not present`};try{const E=L.inspectElement(w).visibility.isVisible;return{satisfied:E,detail:`visibility=${E}`}}catch{return{satisfied:!1,detail:"inspection failed"}}}case"selector_absent":{const w=t.selector?e.querySelectorAll(t.selector).length:0;return{satisfied:w===0,detail:`"${t.selector}" matches ${w} element(s)`}}case"text_present":{const w=((m=e.body)==null?void 0:m.innerText)||((g=e.body)==null?void 0:g.textContent)||"",E=t.text?w.includes(String(t.text)):!1;return{satisfied:E,detail:`text "${String(t.text).slice(0,30)}" ${E?"found":"not found"}`}}case"url_contains":{const w=((T=(b=e.defaultView)==null?void 0:b.location)==null?void 0:T.href)||"";return{satisfied:t.text?w.includes(String(t.text)):!1,detail:w}}case"element_count":{const w=t.selector?e.querySelectorAll(t.selector).length:0,E=Number(t.count)||0;return{satisfied:w===E,detail:`${w}/${E} elements`}}case"readiness_state":return{satisfied:e.readyState===(t.state||"complete"),detail:`readyState=${e.readyState}`};default:return{satisfied:!1,detail:`unknown condition kind "${r}"`}}};if(r==="dom_stable"){let v=((p=e.documentElement)==null?void 0:p.outerHTML.length)||0,m=!1,g=0;for(;Date.now()-c setTimeout(w,a));const T=((y=e.documentElement)==null?void 0:y.outerHTML.length)||0;if(g++,T===v){m=!0;break}v=T}const b=Date.now()-c;return m&&this.session.timeline.record("WAIT_SATISFIED",`dom_stable after ${b}ms (${g} polls)`),this.success(n,i,{satisfied:m,condition:r,waitedMs:b,timeoutMs:o,detail:`dom length ${v}, ${g} polls`},s)}let d=u();for(;!d.satisfied&&Date.now()-c setTimeout(v,a)),d=u();const h=Date.now()-c;return d.satisfied&&this.session.timeline.record("WAIT_SATISFIED",`${r} after ${h}ms`),this.success(n,i,{satisfied:d.satisfied,condition:r,waitedMs:h,timeoutMs:o,detail:d.detail},s)}simulationCloseTab(e,t,s,n,i){const r=Number(e==null?void 0:e.tabId),o=Number.isFinite(r)?this.simulationTabs.findIndex(c=>c.browserTabId===r):this.simulationTabs.findIndex(c=>c.active);if(o<0)return this.error(s,n,"TAB_NOT_FOUND",`No simulated tab matches tabId=${r}`,i);const a=this.simulationTabs.splice(o,1)[0];return this.session.closeTab(a.sessionTabId),a.active&&this.simulationTabs.length&&(this.simulationTabs[0].active=!0,this.session.switchTab(this.simulationTabs[0].sessionTabId)),this.success(s,n,{closed:!0,closedTab:{id:a.browserTabId,url:a.url,title:a.title},simulated:!0,remaining:this.simulationTabs.length},i)}handleSimulationBackgroundCommand(e,t,s,n,i){const r=()=>{var o,a;if(!this.simulationTabs.length){this.simulationTabCounter++;const c={sessionTabId:`stab_${this.simulationTabCounter}`,browserTabId:this.simulationTabCounter,url:((a=(o=n.defaultView)==null?void 0:o.location)==null?void 0:a.href)||"about:blank",title:n.title||"Simulated Tab",active:!0,createdAt:Date.now()};this.simulationTabs.push(c),this.session.registerTab(c.browserTabId,c.url,c.title),this.session.switchTab(c.sessionTabId)}};switch(t){case"LIST_TABS":return r(),this.success(e,t,{simulated:!0,environment:"node-simulation",tabs:this.simulationTabs.map((o,a)=>({id:o.browserTabId,index:a,windowId:1,title:o.title,url:o.url,active:o.active,status:"complete",pinned:!1,audited:!1})),note:"Deterministic simulated tab state — a real browser tab list requires the Chrome extension connection."},i);case"OPEN_TAB":{const o=String((s==null?void 0:s.url)||"about:blank");this.simulationTabCounter++;const a={sessionTabId:`stab_${this.simulationTabCounter}`,browserTabId:this.simulationTabCounter,url:o,title:(s==null?void 0:s.title)||`Simulated Tab ${this.simulationTabCounter}`,active:!0,createdAt:Date.now()};this.simulationTabs.forEach(u=>u.active=!1),this.simulationTabs.push(a);const c=this.session.registerTab(a.browserTabId,o,a.title);return this.session.switchTab(c.sessionTabId),this.session.timeline.record("TAB_OPENED",`simulation tab ${a.browserTabId} → ${o}`),this.success(e,t,{opened:!0,tabId:a.browserTabId,url:o,simulated:!0,totalTabs:this.simulationTabs.length},i)}case"FOCUS_TAB":{r();const o=Number(s==null?void 0:s.tabId),a=this.simulationTabs.find(c=>c.browserTabId===o)||this.simulationTabs[0];return a?(this.simulationTabs.forEach(c=>c.active=!1),a.active=!0,this.session.switchTab(a.sessionTabId),this.session.timeline.record("TAB_SWITCHED",`simulation tab ${a.browserTabId} focused`),this.success(e,t,{focused:!0,tabId:a.browserTabId,url:a.url,simulated:!0},i)):this.error(e,t,"TAB_NOT_FOUND",`No simulated tab with tabId=${o}`,i)}case"LIST_EXTENSIONS":return this.success(e,t,{simulated:!0,extensions:this.simulationExtensions.map(o=>({...o,permissions:["activeTab","scripting","storage","tabs","management"]})),note:"Deterministic simulated extension state."},i);case"SET_EXTENSION_ENABLED":{const o=String((s==null?void 0:s.extensionId)||""),a=this.simulationExtensions.find(c=>c.id===o||c.name.toLowerCase().includes(o.toLowerCase()));return a?(a.enabled=!!(s!=null&&s.enabled),this.session.timeline.record("EXTENSION_STATE_CHANGED",`${a.id} → ${a.enabled?"enabled":"disabled"}`),this.success(e,t,{extensionId:a.id,enabled:a.enabled,simulated:!0},i)):this.error(e,t,"EXTENSION_NOT_FOUND",`No simulated extension matches "${o}". Known: ${this.simulationExtensions.map(c=>c.id).join(", ")}`,i)}case"TOGGLE_EXTENSION":{const o=String((s==null?void 0:s.extensionId)||""),a=this.simulationExtensions.find(c=>c.id===o||c.name.toLowerCase().includes(o.toLowerCase()));return a?(a.enabled=!a.enabled,this.session.timeline.record("EXTENSION_STATE_CHANGED",`${a.id} → ${a.enabled?"enabled":"disabled"}`),this.success(e,t,{extensionId:a.id,enabled:a.enabled,simulated:!0},i)):this.error(e,t,"EXTENSION_NOT_FOUND",`No simulated extension matches "${o}".`,i)}case"RELOAD_EXTENSION":{const o=String((s==null?void 0:s.extensionId)||this.simulationExtensions[0].id),a=this.simulationExtensions.find(c=>c.id===o||c.name.toLowerCase().includes(o.toLowerCase()));return a?this.success(e,t,{reloaded:!0,extensionId:a.id,simulated:!0,note:"Simulated reload: extension state preserved."},i):this.error(e,t,"EXTENSION_NOT_FOUND",`No simulated extension matches "${o}".`,i)}default:return this.error(e,t,"UNKNOWN_COMMAND",`Unhandled simulation command '${t}'`,i)}}async handleScreenshotCapture(e,t,s){var y,v,m,g,b;const n=s.defaultView||(typeof window<"u"?window:{}),i=Date.now(),r=`scr_${i}_${Math.random().toString(36).slice(2,6)}`,o=n.devicePixelRatio||1,a={width:n.innerWidth||((y=s.documentElement)==null?void 0:y.clientWidth)||1920,height:n.innerHeight||((v=s.documentElement)==null?void 0:v.clientHeight)||1080,scrollX:n.scrollX||n.pageXOffset||0,scrollY:n.scrollY||n.pageYOffset||0,devicePixelRatio:o};let c,u,d,h={width:a.width,height:a.height};if(e==="LIVE_ELEMENT_SCREENSHOT"){const T=this.resolveTarget(t,s),w=L.inspectElement(T,this.nodeRegistry);c=w.bestSelector,u=((m=w.forensics)==null?void 0:m.logicalNodeId)||void 0,d={x:w.bounds.x,y:w.bounds.y,width:w.bounds.width,height:w.bounds.height},h={width:Math.max(1,Math.round(w.bounds.width*o)),height:Math.max(1,Math.round(w.bounds.height*o))}}let p=(t==null?void 0:t.dataUrl)||"";if(e==="LIVE_ELEMENT_SCREENSHOT"&&p&&d&&typeof Image<"u")try{const T=await new Promise(w=>{const E=new Image;E.onload=()=>{try{const C=s.createElement("canvas"),N=Math.max(0,Math.floor(d.x*o)),I=Math.max(0,Math.floor(d.y*o)),R=Math.max(1,Math.floor(d.width*o)),x=Math.max(1,Math.floor(d.height*o));C.width=R,C.height=x;const q=C.getContext("2d");if(q){q.drawImage(E,N,I,R,x,0,0,R,x),w(C.toDataURL("image/png"));return}}catch{}w(p)},E.onerror=()=>w(p),E.src=p});T&&(p=T)}catch{}if(!p){const T=e==="LIVE_ELEMENT_SCREENSHOT"?Math.max(120,h.width||320):Math.max(800,a.width||1280),w=e==="LIVE_ELEMENT_SCREENSHOT"?Math.max(60,h.height||180):Math.max(600,a.height||800);p=fe.createDataUrl({width:T,height:w,backgroundColor:e==="LIVE_ELEMENT_SCREENSHOT"?[30,41,59,255]:[15,23,42,255],headerColor:[56,189,248,255],borderColor:[99,102,241,255],label:c||(e==="LIVE_ELEMENT_SCREENSHOT"?"Element Screenshot":"Page Screenshot")})}return{screenshotId:r,timestamp:i,url:((g=n.location)==null?void 0:g.href)||((b=s.location)==null?void 0:b.href)||"",viewport:a,targetSelector:c,targetNodeId:u,targetBounds:d,dataUrl:p,imageFormat:"png",dimensions:h,captureType:e==="LIVE_ELEMENT_SCREENSHOT"?"ELEMENT":"FULL_PAGE"}}success(e,t,s,n){return{id:e,command:t,success:!0,data:s,timestamp:Date.now(),durationMs:Date.now()-n}}error(e,t,s,n,i,r){return{id:e,command:t,success:!1,error:{code:s,message:n,details:r},timestamp:Date.now(),durationMs:Date.now()-i}}}function Dt(l,e){const t=[];let s=l.parentElement,n=1;for(;s&&n<=10;){const d=s.parentElement,h=d?Array.from(d.children).filter(p=>p.tagName===s.tagName):[];t.push({tag:s.tagName.toLowerCase(),selector:V(s),role:s.getAttribute("role")||void 0,text:K(s).slice(0,40),childIndex:h.length?h.indexOf(s)+1:1,siblingCount:d?Array.from(d.children).length:0,distance:n}),s=s.parentElement,n++}const i=l.parentElement,r=[];if(i){const d=Array.from(i.children),h=d.indexOf(l);for(let p=h-1;p>=0&&p>=h-5;p--)r.push({tag:d[p].tagName.toLowerCase(),selector:V(d[p]),role:d[p].getAttribute("role")||void 0,text:K(d[p]).slice(0,30),position:"before",distance:h-p});for(let p=h+1;p {o=Math.max(o,h);for(const p of Array.from(d.children))a.push(p.tagName.toLowerCase()),p.matches('a[href], button, input, select, textarea, [role="button"], [onclick]')&&c.push(V(p)),h<6&&u(p,h+1)};return u(l,1),{selector:V(l),ancestors:t,siblings:r,descendants:{count:l.querySelectorAll("*").length,maxDepth:o,tags:Array.from(new Set(a)).slice(0,30),interactive:c.slice(0,30)}}}function $t(l,e){const t=[{id:"self",selector:V(l),tag:l.tagName.toLowerCase(),role:l.getAttribute("role")||void 0,label:K(l).slice(0,30)||l.tagName.toLowerCase(),relationship:"self",depth:0}],s=[];let n=l.parentElement,i=1;for(;n&&i<=4;){const o=`ancestor_${i}`;t.push({id:o,selector:V(n),tag:n.tagName.toLowerCase(),role:n.getAttribute("role")||void 0,label:K(n).slice(0,30)||n.tagName.toLowerCase(),relationship:"parent",depth:i}),s.push({from:o,to:i===1?"self":`ancestor_${i-1}`,relation:"parent-of"}),n=n.parentElement,i++}for(const o of Array.from(l.children).slice(0,12)){const a=`child_${t.length}`;t.push({id:a,selector:V(o),tag:o.tagName.toLowerCase(),role:o.getAttribute("role")||void 0,label:K(o).slice(0,30)||o.tagName.toLowerCase(),relationship:"child",depth:1}),s.push({from:"self",to:a,relation:"contains"})}const r=l.parentElement;if(r)for(const o of Array.from(r.children).slice(0,12)){if(o===l)continue;const a=`sibling_${t.length}`;t.push({id:a,selector:V(o),tag:o.tagName.toLowerCase(),role:o.getAttribute("role")||void 0,label:K(o).slice(0,30)||o.tagName.toLowerCase(),relationship:"sibling",depth:1}),s.push({from:"self",to:a,relation:"sibling-of"})}return{rootSelector:V(l),nodes:t,edges:s}}function qt(l){const e={};for(const v of Array.from(l.attributes))v.name.startsWith("aria-")&&(e[v.name]=v.value);const t=K(l).trim(),s=l.getAttribute("aria-label"),n=l.getAttribute("aria-labelledby");let i;n&&(i=n.split(/\s+/).map(m=>{var g,b,T;return(T=(b=(g=l.ownerDocument)==null?void 0:g.getElementById(m))==null?void 0:b.textContent)==null?void 0:T.trim()}).filter(Boolean).join(" ").slice(0,60)||void 0);const r=l.getAttribute("title"),o=l.tagName.toLowerCase(),a=[];let c="";s?(c=s,a.push("aria-label")):i?(c=i,a.push("aria-labelledby")):t?(c=t.slice(0,60),a.push("text content")):r&&(c=r,a.push("title"));const u=[];(l.disabled||l.hasAttribute("disabled"))&&u.push("disabled"),l.checked&&u.push("checked");const d=l;d.tagName==="SELECT"&&typeof d.selectedOptions<"u"&&d.selectedOptions.length>0&&u.push("selected"),l.getAttribute("aria-expanded")&&u.push(`expanded=${l.getAttribute("aria-expanded")}`),l.getAttribute("aria-pressed")&&u.push(`pressed=${l.getAttribute("aria-pressed")}`),l.getAttribute("aria-hidden")==="true"&&u.push("hidden"),l.hasAttribute("required")&&u.push("required"),l.readOnly&&u.push("readonly");const h=["a[href]","button","input","select","textarea","[tabindex]"].some(v=>{try{return l.matches(v)}catch{return!1}}),p=[];!c&&h&&p.push("Focusable element has no accessible name."),o==="img"&&!l.hasAttribute("alt")&&p.push("Image has no alt attribute.");const y=/^h([1-6])$/.exec(o);return y&&!t&&p.push(`Heading h${y[1]} is empty.`),{selector:V(l),role:l.getAttribute("role")||void 0,implicitRole:Pt(l),name:c,nameSources:a,description:l.getAttribute("aria-describedby")||void 0,value:l.value!==void 0&&(l.getAttribute("type")||"text")!=="password"?String(l.value).slice(0,40):void 0,states:u,level:y?parseInt(y[1],10):void 0,focusable:h,tabIndex:l.tabIndex,ariaAttributes:e,issues:p}}function Pt(l){switch(l.tagName.toLowerCase()){case"a":return l.getAttribute("href")?"link":void 0;case"button":return"button";case"nav":return"navigation";case"header":return"banner";case"footer":return"contentinfo";case"main":return"main";case"aside":return"complementary";case"article":return"article";case"form":return"form";case"input":{const t=l.getAttribute("type")||"text";return{checkbox:"checkbox",radio:"radio",button:"button",submit:"button",reset:"button",range:"slider",search:"searchbox",email:"textbox",text:"textbox",password:"textbox",tel:"textbox",url:"textbox",number:"spinbutton"}[t]||"textbox"}case"select":return l.hasAttribute("multiple")?"listbox":"combobox";case"textarea":return"textbox";case"img":return"img";case"table":return"table";case"ul":case"ol":return"list";case"li":return"listitem";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return"heading";case"dialog":return"dialog";default:return}}function V(l){const e=l.getAttribute("id");if(e&&/^[a-zA-Z][\w-]*$/.test(e))return`#${e}`;const t=l.getAttribute("data-testid");if(t)return`${l.tagName.toLowerCase()}[data-testid="${t}"]`;const s=l.tagName.toLowerCase(),n=Array.from(l.classList||[]).slice(0,2);return n.length?`${s}.${n.join(".")}`:s}function K(l){return Array.from(l.childNodes).filter(e=>e.nodeType===3).map(e=>(e.textContent||"").trim()).join(" ").replace(/\s+/g," ")}function Ut(){return[{label:"desktop-1440x900",width:1440,height:900},{label:"laptop-1024x768",width:1024,height:768},{label:"tablet-768x1024",width:768,height:1024},{label:"mobile-375x667",width:375,height:667}]}class Ht{constructor(e){f(this,"hostElement",null);f(this,"shadowRoot",null);f(this,"callbacks");f(this,"isRecording",!1);f(this,"isPaused",!1);f(this,"isMinimized",!1);f(this,"startTime",0);f(this,"eventCount",0);f(this,"timerInterval",null);f(this,"isDragging",!1);f(this,"dragStartX",0);f(this,"dragStartY",0);f(this,"posX",window.innerWidth-340);f(this,"posY",40);this.callbacks=e,this.loadPosition()}mount(){this.hostElement&&document.body.contains(this.hostElement)||(this.hostElement=document.createElement("div"),this.hostElement.id="forensic-recorder-floating-host",this.hostElement.style.all="initial",this.hostElement.style.position="fixed",this.hostElement.style.zIndex="2147483647",this.hostElement.style.left=`${this.posX}px`,this.hostElement.style.top=`${this.posY}px`,this.shadowRoot=this.hostElement.attachShadow({mode:"open"}),this.render(),this.attachEvents(),(document.body||document.documentElement).appendChild(this.hostElement))}unmount(){this.timerInterval&&(clearInterval(this.timerInterval),this.timerInterval=null),this.hostElement&&this.hostElement.parentNode&&this.hostElement.parentNode.removeChild(this.hostElement),this.hostElement=null,this.shadowRoot=null}hide(){this.hostElement&&(this.hostElement.style.setProperty("display","none","important"),this.hostElement.style.setProperty("visibility","hidden","important"),this.hostElement.style.setProperty("opacity","0","important"))}show(){this.hostElement&&(this.hostElement.style.removeProperty("display"),this.hostElement.style.removeProperty("visibility"),this.hostElement.style.removeProperty("opacity"))}updateState(e,t=!1,s=0,n=0){this.isRecording=e,this.isPaused=t,this.startTime=s||(e?Date.now():0),this.eventCount=n,this.shadowRoot&&(this.render(),this.attachEvents()),this.isRecording&&!this.isPaused?this.startTimer():this.stopTimer()}incrementEventCount(){var t;this.eventCount++;const e=(t=this.shadowRoot)==null?void 0:t.querySelector("#evt-badge");e&&(e.textContent=`${this.eventCount} evts`)}startTimer(){this.stopTimer(),this.timerInterval=setInterval(()=>{var t;const e=(t=this.shadowRoot)==null?void 0:t.querySelector("#timer-display");if(e&&this.startTime){const s=(Date.now()-this.startTime)/1e3,n=Math.floor(s/60).toString().padStart(2,"0"),i=(s%60).toFixed(1).padStart(4,"0");e.textContent=`${n}:${i}`}},200)}stopTimer(){this.timerInterval&&(clearInterval(this.timerInterval),this.timerInterval=null)}savePosition(){try{sessionStorage.setItem("forensic_overlay_pos",JSON.stringify({x:this.posX,y:this.posY,min:this.isMinimized}))}catch{}}loadPosition(){try{const e=sessionStorage.getItem("forensic_overlay_pos");if(e){const t=JSON.parse(e);this.posX=Math.max(10,Math.min(window.innerWidth-300,t.x||this.posX)),this.posY=Math.max(10,Math.min(window.innerHeight-150,t.y||this.posY)),this.isMinimized=!!t.min}}catch{}}render(){if(!this.shadowRoot)return;const e=` +})()`,n=e;if(typeof n.eval!="function")return Promise.reject(new Error("BLOCKED_BY_CONTEXT: window.eval is unavailable in this context."));try{const i=n.eval(s);return i&&typeof i.then=="function"?i:Promise.resolve(i)}catch(i){return Promise.reject(i)}}hookConsole(e,t){var o;const s=["log","warn","error","info","debug"],n={},i=e,r=100;for(const a of s){const c=(o=i.console)==null?void 0:o[a];if(typeof c=="function"){n[a]=c;try{i.console[a]=(...u)=>{t.length {for(const a of s)if(n[a])try{i.console[a]=n[a]}catch{}}}serialize(e){if(e===void 0)return{text:"undefined"};if(e===null)return{text:"null"};try{if(typeof e=="string")return{text:e.slice(0,5e3)};const t=JSON.stringify(e,pe,1);return t===void 0?{serializationFailed:!0,message:"JSON.stringify returned undefined (circular or non-serializable structure)."}:{text:t.length>5e4?t.slice(0,5e4)+"…[truncated]":t}}catch(t){return{serializationFailed:!0,message:(t==null?void 0:t.message)||"Serialization failed."}}}result(e,t,s,n,i,r){return{status:t,executionId:e,durationMs:s,error:r,consoleOutput:i,domChanged:!1,domLengthBefore:0,domLengthAfter:0,world:"ISOLATED",timeoutMs:5e3,codePreview:n.length>300?n.slice(0,300)+"…":n}}}function pe(l,e){var t;if(e&&typeof e=="object"&&e.nodeType===1){const s=e;return{__element:!0,tag:s.tagName.toLowerCase(),id:s.getAttribute("id")||void 0,selector:s.tagName.toLowerCase()+(s.getAttribute("id")?`#${s.getAttribute("id")}`:""),text:(s.textContent||"").trim().slice(0,60)}}return typeof e=="function"?{__function:!0,name:e.name||"anonymous"}:e&&e.nodeType===9?{__document:!0,url:(t=e.location)==null?void 0:t.href}:e}function Ve(l){try{if(typeof l=="string")return l;if(l instanceof Error)return`${l.name}: ${l.message}`;const e=JSON.stringify(l,pe);return e===void 0?String(l):e}catch{return String(l)}}const me={"desktop-full-hd":{width:1920,height:1080,category:"desktop"},"desktop-hd":{width:1366,height:768,category:"desktop"},"desktop-laptop":{width:1440,height:900,category:"desktop"},"desktop-xga":{width:1280,height:1024,category:"desktop"},"desktop-1024":{width:1024,height:768,category:"desktop"},"tablet-ipad":{width:768,height:1024,category:"tablet"},"tablet-ipad-pro":{width:1024,height:1366,category:"tablet"},"tablet-portrait":{width:768,height:1024,category:"tablet"},"tablet-landscape":{width:1024,height:768,category:"tablet"},"mobile-iphone-se":{width:375,height:667,category:"mobile"},"mobile-iphone-12":{width:390,height:844,category:"mobile"},"mobile-iphone-14-pro-max":{width:430,height:932,category:"mobile"},"mobile-pixel-7":{width:412,height:915,category:"mobile"},"mobile-galaxy-s8":{width:360,height:740,category:"mobile"},"mobile-small":{width:320,height:568,category:"mobile"},"test-a4":{width:800,height:600,category:"test"},"test-square":{width:512,height:512,category:"test"}},fe={"iphone-13":{width:390,height:844,devicePixelRatio:3,userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1",touch:!0,category:"mobile"},"ipad-air":{width:820,height:1180,devicePixelRatio:2,userAgent:"Mozilla/5.0 (iPad; CPU OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1",touch:!0,category:"tablet"},"pixel-7":{width:412,height:915,devicePixelRatio:2.625,userAgent:"Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",touch:!0,category:"mobile"},"galaxy-s23":{width:384,height:800,devicePixelRatio:3,userAgent:"Mozilla/5.0 (Linux; Android 14; SM-S911B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",touch:!0,category:"mobile"},"macbook-pro-16":{width:1728,height:1080,devicePixelRatio:2,userAgent:"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",touch:!1,category:"desktop"},"windows-desktop":{width:1920,height:1080,devicePixelRatio:1,userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",touch:!1,category:"desktop"}};class Be{constructor(e){b(this,"original",null);b(this,"modified",!1);b(this,"activePreset",null);b(this,"activeDevice",null);this.doc=e}state(){const e=this.doc.defaultView;return{width:(e==null?void 0:e.innerWidth)||0,height:(e==null?void 0:e.innerHeight)||0,devicePixelRatio:(e==null?void 0:e.devicePixelRatio)||1,scrollX:(e==null?void 0:e.scrollX)||0,scrollY:(e==null?void 0:e.scrollY)||0,original:this.original,isModified:this.modified}}resize(e,t,s){const n=this.doc.defaultView,i={width:(n==null?void 0:n.innerWidth)||0,height:(n==null?void 0:n.innerHeight)||0},r=this.pageDigest();this.original||(this.original={...i});const o=this.applySize(e,t);this.modified=!0,this.activePreset=s||this.activePreset;const a=this.pageDigest();return{success:!0,applied:{width:o.width,height:o.height},previous:i,original:{...this.original},preset:s||void 0,beforeState:r,afterState:a,reversible:!0,mode:this.isSimulation()?"simulation":"browser-window"}}applyPreset(e){const t=me[e];if(!t)throw new Error(`UNKNOWN_PRESET: "${e}". Available: ${Object.keys(me).join(", ")}`);return this.resize(t.width,t.height,e)}emulateDevice(e){const t=fe[e];if(!t)throw new Error(`UNKNOWN_DEVICE: "${e}". Available: ${Object.keys(fe).join(", ")}`);const s=this.resize(t.width,t.height,`device:${e}`);this.activeDevice=e;const n=this.doc.defaultView;return n&&this.isSimulation()&&n.devicePixelRatio!==void 0&&(n.devicePixelRatio=t.devicePixelRatio),{device:e,resize:s,profile:{width:t.width,height:t.height,devicePixelRatio:t.devicePixelRatio,touch:t.touch,category:t.category},userAgentNote:this.isSimulation()?"User-Agent override requires the Chrome DevTools Protocol (real browser session); in this context the viewport, dpr and touch metadata are applied and the UA is reported but not enforced.":"User-Agent and touch behaviors are applied by the browser emulation layer.",userAgentApplied:!this.isSimulation()}}reset(){var s,n;const e={width:((s=this.doc.defaultView)==null?void 0:s.innerWidth)||0,height:((n=this.doc.defaultView)==null?void 0:n.innerHeight)||0},t=this.original?{...this.original}:{...e};return this.original&&this.applySize(this.original.width,this.original.height),this.modified=!1,this.activePreset=null,this.activeDevice=null,{success:!0,applied:{width:t.width,height:t.height},previous:e,original:{...t},reversible:!0,mode:this.isSimulation()?"simulation":"browser-window"}}runResponsiveTest(e,t={restore:!0}){var c,u,h,g;const s=t.restore!==!1,n=this.original?{...this.original}:{width:((c=this.doc.defaultView)==null?void 0:c.innerWidth)||0,height:((u=this.doc.defaultView)==null?void 0:u.innerHeight)||0};this.original||(this.original={...n});const i=e.map(p=>{this.applySize(p.width,p.height),this.modified=!0;const y=this.pageDigest();return{label:p.label,width:p.width,height:p.height,domLength:y.domLength,interactiveCount:y.interactiveCount,horizontalOverflow:this.hasHorizontalOverflow(),screenshotId:void 0}}),r=i.slice(1).map((p,y)=>({from:i[y].label,to:p.label,domLengthDelta:p.domLength-i[y].domLength,interactiveDelta:p.interactiveCount-i[y].interactiveCount}));let o={width:((h=i[i.length-1])==null?void 0:h.width)||0,height:((g=i[i.length-1])==null?void 0:g.height)||0},a=!1;return s&&(this.applySize(n.width,n.height),this.modified=!1,o={...n},a=!0),{success:!0,originalViewport:n,steps:i,restored:a,finalViewport:o,comparisons:r}}getActivePreset(){return this.activePreset}getActiveDevice(){return this.activeDevice}applySize(e,t){const s=Math.max(200,Math.min(7680,Math.round(e))),n=Math.max(200,Math.min(4320,Math.round(t))),i=this.doc.defaultView;return i&&(typeof i.innerWidth=="number"&&(i.innerWidth=s),typeof i.innerHeight=="number"&&(i.innerHeight=n),typeof i.outerWidth=="number"&&(i.outerWidth=s),typeof i.outerHeight=="number"&&(i.outerHeight=n)),{width:s,height:n}}pageDigest(){var t,s,n,i;const e=this.doc.querySelectorAll('a[href], button, input, select, textarea, [role="button"], [onclick]').length;return{url:((s=(t=this.doc.defaultView)==null?void 0:t.location)==null?void 0:s.href)||((n=this.doc.location)==null?void 0:n.href)||"",domLength:((i=this.doc.documentElement)==null?void 0:i.outerHTML.length)||0,interactiveCount:e}}hasHorizontalOverflow(){const e=this.doc.documentElement,t=this.doc.body,s=this.doc.defaultView;return!s||!e?!1:Math.max(e.scrollWidth||0,(t==null?void 0:t.scrollWidth)||0)>(s.innerWidth||e.clientWidth||0)+1}isSimulation(){return typeof globalThis.__FORENSIC_SIMULATION__<"u"}}const ze=[/^css-/,/^jsx-/,/^sc-[A-Za-z]/,/^emotion/,/^chakra-/,/^mantine-/i,/^_ng[a-z]/,/^ng-/i,/^v-/,/^(?=.*\d)[a-z0-9]{6,12}$/i,/^data-v-/],We=["id","name","data-testid","data-test","data-id","data-qa","data-cy","data-component","data-role","aria-label","aria-labelledby","aria-describedby","role","type","href","for","title","alt","rel","placeholder"];function be(l){let e=2166136261;for(let t=0;t >>0).toString(16).padStart(8,"0")}function ee(l){return ze.some(e=>e.test(l))}function Xe(l){return We.includes(l)}function re(l){const e=l.trim();return e?!!((e.match(/\d/g)||[]).length/e.length>.5||/^\d+[.,:\-/ ]+\d+/.test(e)||/\b\d{10,}\b/.test(e)):!1}function Ge(l,e=80){return Array.from(l.childNodes).filter(s=>s.nodeType===3).map(s=>(s.textContent||"").trim()).join(" ").replace(/\s+/g," ").slice(0,e)}function Ke(l,e){const t=[];let s=l;for(;s&&t.length !ee(f)),r=Ge(e),o=e.getBoundingClientRect(),a={width:Math.round(o.width),height:Math.round(o.height)},c=Ke(e,4),u=c.join(">"),g=Array.from(e.children||[]).slice(0,8).map(f=>f.tagName.toLowerCase()).join("|"),p=e.getAttribute("role")||(t!=null&&t.getComputedStyle,void 0)||Ye(e),y=be(JSON.stringify({t:e.tagName.toLowerCase(),a:s,c:i.slice(0,4),r:p||null,anc:u,desc:g,txt:re(r)?null:r.slice(0,40),d:a})),v=[];let m="low";return!s.id&&!s["data-testid"]&&!s.name&&(m="medium",v.push("no stable identity attribute")),n.length>0&&i.length===0&&(m=v.length?"high":"medium",v.push("all classes are framework-generated")),re(r)&&(v.push("text appears dynamic"),m==="low"&&(m="medium")),e.tagName.toLowerCase().includes("-")&&(v.push("custom element (web component)"),m==="low"&&(m="medium")),{fingerprintId:`fp_${y}`,hash:y,tagHierarchy:c,stableAttributes:s,meaningfulText:r,classes:i,role:p||void 0,dimensions:a,ancestorPattern:u,descendantPattern:g,volatilityRisk:m,volatilityReasons:v}}compare(e,t){const s=[],n=e.tagHierarchy[0]===t.tagHierarchy[0]?1:0;s.push({name:"tag",score:n,weight:.15});const i=ye(e.ancestorPattern.split(">"),t.ancestorPattern.split(">"));s.push({name:"ancestorPattern",score:i,weight:.2});const r=je(e.stableAttributes,t.stableAttributes);s.push({name:"stableAttributes",score:r,weight:.25});const o=ye(e.classes,t.classes);s.push({name:"classes",score:o,weight:.1});const a=(e.role||"")===(t.role||"")&&e.role?1:0;s.push({name:"role",score:a,weight:.1});const c=e.meaningfulText===t.meaningfulText&&e.meaningfulText?1:0;s.push({name:"text",score:c,weight:.1});const u=Ze(e.dimensions,t.dimensions);s.push({name:"dimensions",score:u,weight:.1});const h=s.reduce((g,p)=>g+p.score*p.weight,0);return{score:Math.round(h*1e3)/1e3,components:s}}}function Ye(l){switch(l.tagName.toLowerCase()){case"a":return l.getAttribute("href")?"link":void 0;case"button":return"button";case"nav":return"navigation";case"header":return"banner";case"footer":return"contentinfo";case"main":return"main";case"aside":return"complementary";case"article":return"article";case"form":return"form";case"input":{const t=l.getAttribute("type")||"text";return t==="checkbox"?"checkbox":t==="radio"?"radio":t==="button"||t==="submit"?"button":"textbox"}case"select":return"combobox";case"textarea":return"textbox";case"img":return"img";case"table":return"table";case"ul":case"ol":return"list";case"li":return"listitem";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return"heading";default:return}}function ye(l,e){if(!l.length&&!e.length)return 1;if(!l.length||!e.length)return 0;const t=new Set(e);return l.filter(n=>t.has(n)).length/Math.max(l.length,e.length)}function je(l,e){const t=Object.keys(l),s=Object.keys(e);if(!t.length&&!s.length)return .5;if(!t.length||!s.length)return 0;let n=0,i=0;for(const r of t)r in e&&(i++,l[r]===e[r]&&n++);return i===0?0:n/Math.max(t.length,s.length)}function Ze(l,e){if(l.width===0&&l.height===0&&e.width===0&&e.height===0)return .5;const t=Ee(l.width,e.width),s=Ee(l.height,e.height);return(t+s)/2}function Ee(l,e){if(l===e)return 1;if(l===0||e===0)return 0;const t=Math.min(l,e)/Math.max(l,e);return t>.9?1:t>.7?.5:0}const Je=["data-testid","data-test","data-id","data-qa","data-cy","data-component","data-role","aria-label","name","id"],ve=/^[a-zA-Z][a-zA-Z0-9_-]*$/,Qe=/^[a-zA-Z0-9_ .:-]+$/;class Y{constructor(e){b(this,"doc");this.doc=e}generateCandidates(e){const t=[],s=e.tagName.toLowerCase(),n=e.getAttribute("id");if(n&&ve.test(n)){const u=`#${we(n)}`;t.push(this.evaluate(e,u,"id",1,["unique stable id"]))}for(const u of Je){if(u==="id")continue;const h=e.getAttribute(u);if(h&&Qe.test(h)&&h.length<100){const g=`${s}[${u}="${j(h)}"]`;t.push(this.evaluate(e,g,"semantic-attribute",.92,[`semantic attribute ${u}`]))}}const i=Array.from(e.classList||[]).filter(u=>!ee(u));if(i.length){const u=`${s}.${i.slice(0,3).map(we).join(".")}`;t.push(this.evaluate(e,u,"class",.72,i.length?["stable class names"]:[]))}const r=this.buildStructuralPath(e);r&&t.push(this.evaluate(e,r,"structural-path",.55,["position-based structural path"]));const o=q(e);if(o&&o.length>=2&&o.length<=60&&!re(o)){const u=`${s}:nth-of-type(1)`,h=this.buildTextXPath(e,o);h&&(t.push({selector:u,strategy:"text-derived-xpath",confidence:.6,unique:this.isXPathUnique(h),reasons:[`matches text "${o.slice(0,30)}"`]}),t[t.length-1].xpath=h)}const a=this.buildAttributeFingerprintSelector(e);a&&t.push(this.evaluate(e,a,"attribute-fingerprint",.68,["combination of stable attributes"]));const c=new Map;for(const u of t){const h=u.strategy==="text-derived-xpath"?`xpath:${u.xpath}`:u.selector,g=c.get(h);(!g||u.confidence>g.confidence)&&c.set(h,u)}return Array.from(c.values()).sort((u,h)=>h.confidence-u.confidence)}bestSelector(e){const t=this.generateCandidates(e),s=t.find(n=>n.unique&&n.confidence>=.7)||t[0];return{selector:(s==null?void 0:s.selector)||e.tagName.toLowerCase(),strategy:(s==null?void 0:s.strategy)||"tag",confidence:(s==null?void 0:s.confidence)||.3}}buildXPath(e){const t=[];let s=e;for(;s&&s!==this.doc.documentElement;){const n=s.getAttribute("id");if(n&&ve.test(n)){t.unshift(`*[@id="${j(n)}"]`);break}const i=s.parentElement;if(!i){t.unshift(s.tagName.toLowerCase());break}const o=Array.from(i.children).filter(a=>a.tagName===s.tagName).indexOf(s)+1;t.unshift(`${s.tagName.toLowerCase()}[${o}]`),s=i}return s===this.doc.documentElement&&(!t.length||!t[0].includes("@id"))&&t.unshift("html"),"//"+t.join("/")}buildTextXPath(e,t){try{const s=e.tagName.toLowerCase(),n=et(t);return`//${s}[normalize-space(text())=${n}]`}catch{return null}}buildStructuralPath(e,t=4){const s=[];let n=e;for(;n&&s.length c.tagName===n.tagName);if(a.length>1){const c=a.indexOf(n)+1;s.unshift(`${o}:nth-of-type(${c})`)}else s.unshift(o);if(n=r,n===this.doc.body){s.unshift("body");break}if(n===this.doc.documentElement)break}const i=s.join(" > ");return i.includes("body")?i:"body > "+i}buildAttributeFingerprintSelector(e){const t=e.tagName.toLowerCase(),s=[],n=e.getAttribute("type");n&&s.push(`type="${j(n)}"`);const i=e.getAttribute("href");i&&i.length<80&&!i.startsWith("javascript:")&&s.push(`href^="${j(i.slice(0,40))}"`);const r=e.getAttribute("placeholder");return r&&r.length<60&&s.push(`placeholder="${j(r)}"`),s.length>=2?`${t}[${s.join("][")}]`:null}evaluate(e,t,s,n,i){let r=!1,o=0;try{const c=this.doc.querySelectorAll(t);o=c.length,r=c.length===1&&c[0]===e}catch{return{selector:t,strategy:s,confidence:0,unique:!1,reasons:["invalid selector syntax"]}}let a=n;return o===0?(a=0,i.push("selector matched nothing (invalid candidate)")):o===1&&r?i.push("matches exactly this element"):(a=a*.4,i.push(`matches ${o} elements — ambiguous`)),{selector:t,strategy:s,confidence:Math.round(a*100)/100,unique:r,reasons:i}}isXPathUnique(e){try{return this.doc.evaluate(`count(${e})`,this.doc,null,4,null).numberValue===1}catch{return!1}}}function q(l){return Array.from(l.childNodes).filter(e=>e.nodeType===3).map(e=>(e.textContent||"").trim()).join(" ").replace(/\s+/g," ")}function we(l){return l.replace(/([^a-zA-Z0-9_\u00A0-\uFFFF-])/g,"\\$1")}function j(l){return l.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function et(l){return l.includes("'")?l.includes('"')?`concat(${l.split("'").map(e=>`'${e}'`).join(`, "'", `)})`:`"${l}"`:`'${l}'`}class tt{constructor(e,t){b(this,"fingerprintEngine",new te);b(this,"counter",0);this.doc=e,this.registry=t}buildTarget(e,t="selector"){var h;const s=new Y(this.doc),n=s.generateCandidates(e),i=s.bestSelector(e),r=this.fingerprintEngine.fingerprint(e),o=k.inspectElement(e,this.registry),a=e.getBoundingClientRect();let c=i.confidence*.6;return r.volatilityRisk==="low"?c+=.3:r.volatilityRisk==="medium"&&(c+=.15),n.find(g=>g.unique&&g.confidence>=.9)&&(c+=.1),c=Math.max(.05,Math.min(1,c)),this.counter++,{targetId:`tgt_${Date.now().toString(36)}_${this.counter}`,tag:e.tagName.toLowerCase(),role:o.role||r.role,selector:i.selector,selectorCandidates:n,xpath:s.buildXPath(e),domPath:(((h=o.context)==null?void 0:h.parentChain)||[]).concat(i.selector).join(" > "),textFingerprint:r.meaningfulText,attributeFingerprint:JSON.stringify(r.stableAttributes),structuralFingerprint:r.hash,attributes:o.attributes||{},confidence:Math.round(c*100)/100,bounds:{x:Math.round(a.x),y:Math.round(a.y),width:Math.round(a.width),height:Math.round(a.height)},resolvedFrom:t}}resolveAndBuild(e){let t=null,s="unknown";typeof e=="string"&&(e={selector:e});const n=e;if(n.selectedElementRef&&(s="selectedElementRef"),!t&&n.selector)try{const i=this.doc.querySelectorAll(n.selector);if(i.length===0)return{error:`TARGET_NOT_FOUND: selector "${n.selector}" matches no element`};i.length>1?(t=st(i,this.doc)||i[0],s+="+disambiguated"):(t=i[0],s="selector")}catch(i){return{error:`TARGET_INVALID: ${i.message}`}}if(!t&&n.xpath)try{t=this.doc.evaluate(n.xpath,this.doc,null,9,null).singleNodeValue,s="xpath"}catch(i){return{error:`TARGET_INVALID_XPATH: ${i.message}`}}if(!t&&typeof n.nodeId=="number"&&this.registry){const i=this.registry.getNode(n.nodeId);i&&i.nodeType===1&&this.doc.contains(i)&&(t=i,s="nodeId")}return!t&&n.coordinates&&(t=this.doc.elementFromPoint(n.coordinates.x,n.coordinates.y),s="coordinates"),t?{element:t,target:this.buildTarget(t,s)}:{error:"TARGET_NOT_FOUND: no usable resolution strategy succeeded"}}}function st(l,e){for(const t of Array.from(l)){const s=t;try{if(k.inspectElement(s).visibility.isVisible)return s}catch{}}return null}class nt{constructor(e){b(this,"fingerprintEngine",new te);this.doc=e}recover(e,t){var p;const s=[],n=[];let i=null;try{i=this.doc.querySelectorAll(e)}catch(y){s.push(`selector syntax error: ${y.message}`)}if(i&&i.length>0){s.push("selector still matches — no recovery needed");const y=i[0];return{recovered:!0,confidence:1,strategy:"original-selector",resolvedSelector:e,matchedElementInfo:Te(y),alternatives:[],diagnostics:s,recommendation:"Original selector works; the earlier failure was transient (likely a navigation or render race)."}}s.push("selector no longer matches any element");const o=this.collectCandidates(t,s).map(y=>({element:y,score:this.scoreMatch(y,t)})).filter(y=>y.score.score>.35).sort((y,v)=>v.score.score-y.score.score);for(const y of o.slice(0,5)){const v=new Y(this.doc).bestSelector(y.element);n.push({selector:v.selector,confidence:Math.round(y.score.score*100)/100,strategy:"recovery-match"})}if(!o.length)return{recovered:!1,confidence:0,strategy:"none",alternatives:n,diagnostics:s,recommendation:"No sufficiently similar element exists. The region may have been removed, or the page structure changed fundamentally. Re-inspect the page and capture a new target."};const a=o[0],c=o.length>1?a.score.score-o[1].score.score:1;s.push(`best candidate score: ${a.score.score.toFixed(3)} (margin ${c.toFixed(3)})`);for(const y of a.score.components)y.score>0&&s.push(` - ${y.name}: ${(y.score*100).toFixed(0)}%`);if(a.score.score<.62||o.length>1&&c<.15)return{recovered:!1,confidence:Math.round(a.score.score*100)/100,strategy:"recovery-refused",resolvedSelector:(p=n[0])==null?void 0:p.selector,alternatives:n,diagnostics:s,recommendation:"Recovery refused: best match is not confident enough or too close to a competing element. Inspect alternatives manually before acting — refusing to avoid acting on a wrong element."};const g=new Y(this.doc).bestSelector(a.element).selector;return{recovered:!0,confidence:Math.round(a.score.score*100)/100,strategy:"fingerprint-recovery",resolvedSelector:g,matchedElementInfo:Te(a.element),alternatives:n,diagnostics:s,recommendation:`Recovered target with ${(a.score.score*100).toFixed(0)}% confidence. Verify the resolved selector before destructive actions.`}}collectCandidates(e,t){var r,o;const s=new Set,n=this.doc.querySelectorAll(e.tag);let i=0;for(const a of Array.from(n))if(s.add(a),++i>=400)break;if((r=e.classes)!=null&&r.length){const a=e.classes.filter(c=>!ee(c));for(const c of a.slice(0,2))try{for(const u of Array.from(this.doc.querySelectorAll(`.${c}`)).slice(0,100))s.add(u)}catch{}}if((o=e.stableAttributes)!=null&&o.name)try{for(const a of Array.from(this.doc.querySelectorAll(`[name="${e.stableAttributes.name}"]`)))s.add(a)}catch{}if(e.parentSelector)try{for(const a of Array.from(this.doc.querySelectorAll(`${e.parentSelector} > ${e.tag}`)).slice(0,100))s.add(a)}catch{}return t.push(`collected ${s.size} candidate elements for scoring`),Array.from(s)}scoreMatch(e,t){const s=[],n=e.tagName.toLowerCase()===t.tag.toLowerCase()?1:0;s.push({name:"tag",score:n,weight:.15});const i=(t.text||"").trim().slice(0,40),r=q(e).slice(0,40),o=(e.textContent||"").trim().slice(0,40);let a=0;if(i){const d=r?r===i?1:oe(i,r):0,f=o?o===i?1:oe(i,o):0;a=Math.max(d,f)}s.push({name:"text",score:a,weight:.3});const c=new Set((t.classes||[]).filter(d=>!ee(d))),u=Array.from(e.classList||[]),h=c.size?u.filter(d=>c.has(d)).length/c.size:.5;s.push({name:"classes",score:h,weight:.2});const g=t.stableAttributes||{},p=Object.keys(g);let y=.5;if(p.length){let d=0;for(const f of p)e.getAttribute(f)===g[f]&&d++;y=d/p.length}s.push({name:"attributes",score:y,weight:.2});const v=t.childCount!==void 0?e.children.length===t.childCount?1:oe(String(t.childCount),String(e.children.length)):.5;if(s.push({name:"childCount",score:v,weight:.05}),t.fingerprintHash){const d={fingerprintId:"snapshot",hash:t.fingerprintHash,tagHierarchy:[t.tag],stableAttributes:g,meaningfulText:i,classes:t.classes||[],dimensions:{width:0,height:0},ancestorPattern:"",descendantPattern:"",volatilityRisk:"medium",volatilityReasons:[]},f=this.fingerprintEngine.fingerprint(e),w=this.fingerprintEngine.compare(d,f);s.push({name:"fingerprint",score:w.score,weight:.1})}const m=s.reduce((d,f)=>d+f.score*f.weight,0);return{score:Math.max(0,Math.min(1,m)),components:s}}diagnose(e){const t=[];let s=!0,n=0,i,r=[];try{n=this.doc.querySelectorAll(e).length}catch(o){s=!1,i=o.message,t.push("Selector is syntactically invalid CSS.")}if(s&&n===0){t.push("Selector parses but matches nothing — element may be removed, re-rendered, or inside a shadow root."),r=this.relaxSelector(e);for(const o of r)try{if(this.doc.querySelectorAll(o).length>0){t.push(`Relaxed form "${o}" matches — the over-specific part of the selector is stale.`);break}}catch{}}return s&&n>1&&t.push(`Selector matches ${n} elements — it is ambiguous; use a more specific form or index.`),{selector:e,valid:s,matches:n,parseError:i,closestWorkingSelectors:r.filter(o=>{try{return this.doc.querySelectorAll(o).length>0}catch{return!1}}),diagnosis:t}}relaxSelector(e){const t=[],s=e.split(/[ >]+/).filter(Boolean);s.length>1&&(t.push(s.slice(0,-1).join(" ")),t.push(s[s.length-1]));const n=e.replace(/:nth-of-type\(\d+\)/g,"").replace(/\.[^. >#:[]+/g,(i,r,o)=>o[r-1]==="\\"?i:"");return n!==e&&n.trim()&&t.push(n.trim()),t}}function oe(l,e){if(!l||!e)return 0;const t=Se(l),s=Se(e);if(t===s)return 1;if(t.includes(s)||s.includes(t))return .7;const n=new Set(t.split(/\s+/)),i=new Set(s.split(/\s+/));return Array.from(n).filter(o=>i.has(o)).length/Math.max(n.size,i.size)}function Se(l){return l.toLowerCase().replace(/[^a-z0-9 ]/g," ").replace(/\s+/g," ").trim()}function Te(l){return{tag:l.tagName.toLowerCase(),id:l.getAttribute("id")||void 0,text:q(l).slice(0,60),classes:Array.from(l.classList||[])}}class ae{constructor(e){b(this,"state");this.state=e>>>0,this.state===0&&(this.state=2654435769)}next(){this.state=this.state+1831565813>>>0;let e=this.state;return e=Math.imul(e^e>>>15,e|1),e^=e+Math.imul(e^e>>>7,e|61),((e^e>>>14)>>>0)/4294967296}range(e,t){return e+this.next()*(t-e)}int(e,t){return Math.floor(this.range(e,t+1))}chance(e){return this.next() setTimeout(t,e))}chance(){return this.rng.next()<.5}}const rt=[{ruleId:"red_key_password",kind:"key-pattern",pattern:"password|passwd|pwd",description:"Keys containing password/passwd/pwd",enabled:!0,userAdded:!1},{ruleId:"red_key_token",kind:"key-pattern",pattern:"token|jwt|bearer|auth|session.?id|secret|api.?key|client.?secret",description:"Keys containing token/jwt/auth/session-id/secret/api-key",enabled:!0,userAdded:!1},{ruleId:"red_key_credential",kind:"key-pattern",pattern:"credential|login|user.?pass|otp|2fa|mfa|verification",description:"Keys containing credential/login/otp/2fa/verification",enabled:!0,userAdded:!1},{ruleId:"red_key_payment",kind:"key-pattern",pattern:"card|payment|billing|iban|cvv|cvc|pan",description:"Keys containing card/payment/billing/iban/cvv",enabled:!0,userAdded:!1},{ruleId:"red_key_personal",kind:"key-pattern",pattern:"ssn|social.?security|national.?id|passport|tax.?id",description:"Keys containing personal identifier patterns",enabled:!0,userAdded:!1},{ruleId:"red_val_jwt",kind:"value-pattern",pattern:"eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+",description:"JWT-shaped tokens",enabled:!0,userAdded:!1},{ruleId:"red_val_bearer",kind:"value-pattern",pattern:"bearer\\s+[A-Za-z0-9._-]+",description:"Bearer tokens",enabled:!0,userAdded:!1},{ruleId:"red_val_long_hex",kind:"value-pattern",pattern:"\\b[a-f0-9]{32,}\\b",description:"32+ char hex strings (session/API ids)",enabled:!0,userAdded:!1},{ruleId:"red_val_sk",kind:"value-pattern",pattern:"\\b(sk|pk|rk)_[A-Za-z0-9_]{20,}\\b",description:"Stripe-style secret keys (sk_live_…)",enabled:!0,userAdded:!1},{ruleId:"red_attr_input_password",kind:"attribute-name",pattern:"value",description:"value attributes on password inputs handled by PrivacyEngine maskValue",enabled:!0,userAdded:!1},{ruleId:"red_attr_secret",kind:"attribute-name",pattern:"data-secret|data-token|data-api-key|secret|access.?token",description:"Secret-carrying attributes",enabled:!0,userAdded:!1}],ot=[{exclusionId:"excl_mcpdom_overlay",selector:"[data-mcpdom-internal], [data-forensic-internal], #forensic-recorder-floating-host, #forensic-inspect-highlighter",reason:"MCPDOM-injected UI must never contaminate captured DOM (§68 clean capture)",userAdded:!1},{exclusionId:"excl_mcpdom_ids",selector:'[id^="forensic-"], [id^="mcpdom-"]',reason:"MCPDOM-namespaced nodes",userAdded:!1}],ce="[REDACTED]";class le{constructor(e){b(this,"config");b(this,"base",new J);b(this,"compiledKeyPatterns",[]);b(this,"compiledValuePatterns",[]);b(this,"compiledAttrPatterns",[]);this.config={rules:[...rt],exclusions:[...ot],stubMode:!0,...e},this.recompile()}recompile(){this.compiledKeyPatterns=[],this.compiledValuePatterns=[],this.compiledAttrPatterns=[];for(const e of this.config.rules){if(!e.enabled)continue;const t="i";try{switch(e.kind){case"key-pattern":this.compiledKeyPatterns.push(new RegExp(e.pattern,t));break;case"value-pattern":this.compiledValuePatterns.push(new RegExp(e.pattern,"i"));break;case"attribute-name":this.compiledAttrPatterns.push(new RegExp(`^(${e.pattern})$`,"i"));break}}catch{}}}getRules(){return[...this.config.rules]}setRuleEnabled(e,t){const s=this.config.rules.find(n=>n.ruleId===e);return s?(s.enabled=t,this.recompile(),!0):!1}addRule(e){const t=`red_custom_${this.config.rules.length+1}_${Date.now().toString(36)}`,s={...e,ruleId:t,userAdded:!0};return this.config.rules.push(s),this.recompile(),s}removeRule(e){const t=this.config.rules.findIndex(s=>s.ruleId===e);return t<0||!this.config.rules[t].userAdded?!1:(this.config.rules.splice(t,1),this.recompile(),!0)}getExclusions(){return[...this.config.exclusions]}addExclusion(e,t){const n={exclusionId:`excl_custom_${this.config.exclusions.length+1}_${Date.now().toString(36)}`,selector:e,reason:t,userAdded:!0};return this.config.exclusions.push(n),n}removeExclusion(e){const t=this.config.exclusions.findIndex(s=>s.exclusionId===e);return t<0||!this.config.exclusions[t].userAdded?!1:(this.config.exclusions.splice(t,1),!0)}isSensitiveKey(e){return this.compiledKeyPatterns.some(t=>t.test(e))}redactValue(e){let t=e;for(const s of this.compiledValuePatterns)s.test(t)&&(t=t.replace(new RegExp(s.source,"gi"),ce));return t}redactByKeyValue(e,t){return this.isSensitiveKey(e)?this.config.stubMode?ce:t:this.redactValue(t)}isSensitiveAttribute(e){return this.compiledAttrPatterns.some(t=>t.test(e))}redactAttributes(e){const t={};for(const[s,n]of Object.entries(e))this.isSensitiveAttribute(s)?t[s]=ce:t[s]=this.redactValue(n);return t}cleanSubtree(e){const t=e.cloneNode(!0);for(const s of this.config.exclusions){let n=null;try{n=t.querySelectorAll(s.selector)}catch{continue}for(const i of Array.from(n))i.remove();try{if(t.matches(s.selector))return this.doclessEmptyStub(t)}catch{}}return t}isExcluded(e){for(const t of this.config.exclusions)try{if(e.matches(t.selector)||e.closest(t.selector))return!0}catch{}return!1}doclessEmptyStub(e){return e.innerHTML="",e.setAttribute("data-mcpdom-excluded","true"),e}toJSON(){return{rules:this.getRules(),exclusions:this.getExclusions(),stubMode:this.config.stubMode}}static fromJSON(e){return new le({rules:Array.isArray(e==null?void 0:e.rules)?e.rules:void 0,exclusions:Array.isArray(e==null?void 0:e.exclusions)?e.exclusions:void 0,stubMode:typeof(e==null?void 0:e.stubMode)=="boolean"?e.stubMode:void 0})}}const ue='a[href], button, input, select, textarea, [role="button"], [role="link"], [role="tab"], [onclick], [tabindex]';function F(l,e){return{items:l.slice(0,e),truncated:l.length>e}}function _(l,e,t,s,n,i){return{analyzer:l,summary:e,count:t,items:s,warnings:n,truncated:i}}function O(l){try{return k.inspectElement(l).bestSelector}catch{return l.tagName.toLowerCase()}}const at=l=>{const e=Array.from(l.querySelectorAll("form")),t=e.map(n=>{const i=Array.from(n.querySelectorAll("input, select, textarea")).map(r=>({tag:r.tagName.toLowerCase(),type:r.getAttribute("type")||(r.tagName.toLowerCase()==="textarea"?"textarea":r.tagName.toLowerCase()==="select"?"select":"text"),name:r.getAttribute("name")||void 0,id:r.getAttribute("id")||void 0,required:r.hasAttribute("required"),pattern:r.getAttribute("pattern")||void 0,maxLength:r.getAttribute("maxlength")||void 0,placeholder:r.getAttribute("placeholder")||void 0,ariaLabel:r.getAttribute("aria-label")||void 0,autocomplete:r.getAttribute("autocomplete")||void 0,hasLabel:!!(r.getAttribute("id")&&l.querySelector(`label[for="${r.getAttribute("id")}"]`))||!!r.closest("label"),defaultValue:r.value!==void 0&&(r.getAttribute("type")||"text")!=="password"?String(r.value).slice(0,40):void 0}));return{selector:O(n),action:n.getAttribute("action")||void 0,method:(n.getAttribute("method")||"GET").toUpperCase(),id:n.getAttribute("id")||void 0,fieldCount:i.length,submitButton:n.querySelector('button[type="submit"], input[type="submit"]')?O(n.querySelector('button[type="submit"], input[type="submit"]')):void 0,validationAttributes:i.filter(r=>r.required||r.pattern).length,fields:i}}),s=F(t,50);return _("analyze_forms",`${e.length} form(s) with ${t.reduce((n,i)=>n+i.fieldCount,0)} total fields`,e.length,s.items,[],s.truncated)},ct=l=>{const e=Array.from(l.querySelectorAll("a[href]")),t=e.map(n=>({href:n.getAttribute("href")||"",text:q(n).slice(0,60),selector:O(n),rel:n.getAttribute("rel")||void 0,target:n.getAttribute("target")||void 0,download:n.hasAttribute("download"),external:/^https?:\/\//i.test(n.getAttribute("href")||"")&&!lt(n.getAttribute("href")||"",l),anchorOnly:(n.getAttribute("href")||"").startsWith("#")})),s=F(t,200);return _("extract_links",`${e.length} link(s): ${t.filter(n=>n.external).length} external, ${t.filter(n=>n.anchorOnly).length} anchors`,e.length,s.items,[],s.truncated)};function lt(l,e){var t,s,n,i;try{return new URL(l,((s=(t=e.defaultView)==null?void 0:t.location)==null?void 0:s.href)||"http://localhost").origin===(((i=(n=e.defaultView)==null?void 0:n.location)==null?void 0:i.origin)||"")}catch{return!1}}const ut=l=>{const e=Array.from(l.querySelectorAll("img")),t=Array.from(l.querySelectorAll("video")),s=Array.from(l.querySelectorAll("audio")),n=Array.from(l.querySelectorAll("canvas")),i=[],r=[...e.map(c=>({kind:"img",selector:O(c),src:(c.getAttribute("src")||"").slice(0,150),alt:c.getAttribute("alt"),width:c.getAttribute("width")||void 0,height:c.getAttribute("height")||void 0,naturalWidth:c.naturalWidth||void 0,naturalHeight:c.naturalHeight||void 0,lazy:c.getAttribute("loading")==="lazy",missingAlt:!c.hasAttribute("alt")})),...t.map(c=>{var u;return{kind:"video",selector:O(c),src:(c.getAttribute("src")||((u=c.querySelector("source"))==null?void 0:u.getAttribute("src"))||"").slice(0,150),controls:c.hasAttribute("controls"),autoplay:c.hasAttribute("autoplay"),muted:c.hasAttribute("muted"),poster:c.getAttribute("poster")||void 0}}),...s.map(c=>{var u;return{kind:"audio",selector:O(c),src:(c.getAttribute("src")||((u=c.querySelector("source"))==null?void 0:u.getAttribute("src"))||"").slice(0,150),controls:c.hasAttribute("controls")}}),...n.map(c=>({kind:"canvas",selector:O(c),width:c.width,height:c.height}))],o=r.filter(c=>c.missingAlt).length;o&&i.push(`${o} image(s) missing alt text (accessibility risk).`);const a=F(r,200);return _("analyze_media",`${e.length} images, ${t.length} videos, ${s.length} audios, ${n.length} canvases`,r.length,a.items,i,a.truncated)},dt=l=>{const e=l.defaultView,t=[],s={};if(e!=null&&e.getComputedStyle){const i=e.getComputedStyle(l.documentElement);for(let r=0;r ({name:i,value:r}));return _("get_css_variables",`${n.length} CSS custom properties found`,n.length,n,t,!1)},ht=l=>{const e=l.defaultView,t=[],s=new Map;if(e!=null&&e.getComputedStyle)for(const i of Array.from(l.querySelectorAll("body, body *")).slice(0,800)){const r=e.getComputedStyle(i),o=r.fontFamily||"",a=r.fontSize||"",c=`${o.split(",")[0].replace(/["']/g,"").trim()} @ ${a}`;s.set(c,(s.get(c)||0)+1)}else t.push("getComputedStyle unavailable — font usage analysis requires rendered styles.");const n=Array.from(s.entries()).map(([i,r])=>({font:i,usage:r})).sort((i,r)=>r.usage-i.usage);return _("analyze_fonts",`${n.length} distinct font/size combinations`,n.length,n,t,!1)},gt=l=>{const e=l.defaultView,t=[],s=new Map;if(e!=null&&e.getComputedStyle)for(const i of Array.from(l.querySelectorAll("body, body *")).slice(0,800)){const r=e.getComputedStyle(i);for(const o of["color","background-color","border-top-color"]){const a=r.getPropertyValue(o);a&&a!=="rgba(0, 0, 0, 0)"&&s.set(a,(s.get(a)||0)+1)}}else{for(const i of Array.from(l.querySelectorAll("[style]")).slice(0,300)){const r=i.getAttribute("style")||"",o=/(color)\s*:\s*([^;]+)/gi;let a;for(;a=o.exec(r);)s.set(a[2].trim(),(s.get(a[2].trim())||0)+1)}t.push("getComputedStyle unavailable — palette from inline styles only.")}const n=Array.from(s.entries()).map(([i,r])=>({color:i,usage:r})).sort((i,r)=>r.usage-i.usage).slice(0,40);return _("extract_color_palette",`${s.size} distinct colors in use`,s.size,n,t,!1)},pt=l=>{const e=l.defaultView,t=[],s=[];if(!(e!=null&&e.getComputedStyle))return t.push("getComputedStyle unavailable — z-index analysis requires rendered styles."),_("detect_zindex_conflicts","unavailable",0,[],t,!1);const n=[];for(const i of Array.from(l.querySelectorAll("body *")).slice(0,1e3)){const r=e.getComputedStyle(i),o=r.zIndex;o&&o!=="auto"&&parseInt(o,10)>0&&n.push({selector:O(i),z:parseInt(o,10),position:r.position,stacking:r.position==="fixed"||r.position==="sticky"||r.opacity!=="1"||r.transform!=="none"?"creates-stacking-context":"plain"})}for(let i=0;i 1e5&&s.push({zIndex:n[i].z,elements:[n[i].selector],note:"extremely high z-index — competes with platform overlays (MCPDOM uses 2147483640+)."})}return _("detect_zindex_conflicts",`${n.length} z-indexed elements, ${s.length} potential conflict(s)`,s.length,F(s,40).items,t,s.length>40)},mt=l=>{const e=l.defaultView,t=[],s=l.documentElement,n=l.body,i=Math.max((s==null?void 0:s.scrollWidth)||0,(n==null?void 0:n.scrollWidth)||0),r=(e==null?void 0:e.innerWidth)||(s==null?void 0:s.clientWidth)||0,o=i>r+1;if(o&&(t.push({issue:"horizontal-overflow",detail:`document scrollWidth ${i} exceeds viewport ${r}`}),e!=null&&e.getComputedStyle))for(const c of Array.from(l.querySelectorAll("body *")).slice(0,600)){const u=c.getBoundingClientRect();if(u.right>r+2&&u.width>100&&(t.push({issue:"element-exceeds-viewport",selector:O(c),right:Math.round(u.right),width:Math.round(u.width)}),t.length>15))break}let a=0;for(const c of Array.from(l.querySelectorAll(ue)).slice(0,500)){const u=c.getBoundingClientRect();(u.width===0||u.height===0)&&a++}return a&&t.push({issue:"zero-size-interactive-elements",count:a}),_("detect_layout_issues",o?`HORIZONTAL OVERFLOW: page is ${i-r}px wider than viewport`:"No horizontal overflow detected",t.length,t,[],!1)},ft=l=>{const e=Array.from(l.querySelectorAll(ue)),t=new Map,s=e.slice(0,300).map(n=>{const i=de(n),r=i.role||n.tagName.toLowerCase();return t.set(r,(t.get(r)||0)+1),{selector:i.bestSelector,tag:i.tag,role:i.role,text:i.text.slice(0,40),visible:i.visibility.isVisible,disabled:n.disabled||n.hasAttribute("disabled"),inViewport:i.visibility.isInViewport}});return _("census_interactive_elements",`${e.length} interactive elements: ${Array.from(t.entries()).map(([n,i])=>`${n}×${i}`).join(", ")||"none"}`,e.length,s,[],e.length>300)};function de(l){try{return k.inspectElement(l)}catch{return{tag:l.tagName.toLowerCase(),role:void 0,text:"",bestSelector:l.tagName.toLowerCase(),bounds:{x:0,y:0,width:0,height:0,top:0,right:0,bottom:0,left:0},visibility:{isVisible:!1,isInViewport:!1}}}}const bt=l=>{const e=["header","nav","main","aside","footer","article","section","figure","figcaption","mark","time","address","details","summary","dialog"],t=[];for(const i of e){const r=Array.from(l.querySelectorAll(i));if(r.length)for(const o of r.slice(0,20))t.push({tag:i,selector:O(o),role:o.getAttribute("role")||yt(i),text:q(o).slice(0,50),childCount:o.children.length})}const s=t.filter(i=>["banner","navigation","main","complementary","contentinfo"].includes(i.role)),n=[];return t.find(i=>i.tag==="main")||n.push("No element — page lacks a primary landmark."),l.querySelectorAll("header").length>1&&n.push("Multiple elements outside sections — ambiguous banner landmark."),_("detect_semantic_elements",`${t.length} semantic elements, ${s.length} landmarks`,t.length,F(t,100).items,n,t.length>100)};function yt(l){return{header:"banner",nav:"navigation",main:"main",aside:"complementary",footer:"contentinfo",article:"article",section:"region",form:"form"}[l]}const Ce={analyze_forms:at,extract_links:ct,analyze_media:ut,get_css_variables:dt,analyze_fonts:ht,extract_color_palette:gt,detect_zindex_conflicts:pt,detect_layout_issues:mt,census_interactive_elements:ft,detect_semantic_elements:bt,scan_accessibility_issues:l=>{var i;const e=[];for(const r of Array.from(l.querySelectorAll("img")).slice(0,200))r.hasAttribute("alt")||e.push({rule:"img-alt",severity:"error",selector:O(r),message:"Image is missing the alt attribute."});for(const r of Array.from(l.querySelectorAll("input:not([type=hidden]):not([type=submit]):not([type=button])")).slice(0,200)){const o=r.getAttribute("id");o&&l.querySelector(`label[for="${o}"]`)||r.closest("label")||r.getAttribute("aria-label")||r.getAttribute("aria-labelledby")||e.push({rule:"input-label",severity:"error",selector:O(r),message:"Form input has no associated label, aria-label or aria-labelledby."})}for(const r of Array.from(l.querySelectorAll('button, a[href], [role="button"]')).slice(0,300)){const o=q(r).trim(),a=r.getAttribute("aria-label");!o&&!a&&e.push({rule:"accessible-name",severity:"error",selector:O(r),message:"Interactive element has no accessible name (no text, no aria-label).",hint:r.querySelector("img[alt]")?"Contains an image — consider alt text or aria-label.":void 0})}const t=Array.from(l.querySelectorAll("h1, h2, h3, h4, h5, h6")).slice(0,100);let s=0;for(const r of t){const o=parseInt(r.tagName[1],10);s&&o>s+1&&e.push({rule:"heading-order",severity:"warning",selector:O(r),message:`Heading level jumps from h${s} to h${o}.`}),s=o}(i=l.documentElement)!=null&&i.getAttribute("lang")||e.push({rule:"html-lang",severity:"warning",selector:"html",message:"The element has no lang attribute."});const n=e.filter(r=>r.severity==="error").length;return _("scan_accessibility_issues",`${e.length} issue(s): ${n} errors, ${e.length-n} warnings`,e.length,F(e,100).items,[],e.length>100)},detect_dead_click_targets:l=>{const e=l.defaultView,t=[];for(const s of Array.from(l.querySelectorAll(ue)).slice(0,500)){const n=s.getBoundingClientRect(),i=e!=null&&e.getComputedStyle?e.getComputedStyle(s):null,r=n.width===0||n.height===0,o=i?i.pointerEvents==="none":!1,a=i?i.display==="none"||i.visibility==="hidden":!1,c=s.getAttribute("aria-hidden")==="true";(r||o||a||c)&&t.push({selector:O(s),tag:s.tagName.toLowerCase(),text:q(s).slice(0,30),reasons:[r&&"zero-size",o&&"pointer-events:none",a&&`hidden (${i?i.display:"?"}/${i?i.visibility:"?"})`,c&&"aria-hidden"].filter(Boolean)})}return _("detect_dead_click_targets",`${t.length} unreachable interactive element(s)`,t.length,F(t,80).items,[],t.length>80)},inventory_animations:l=>{const e=l.defaultView,t=[],s=[];if(!(e!=null&&e.getComputedStyle))return t.push("getComputedStyle unavailable — animation inventory requires rendered styles."),_("inventory_animations","unavailable",0,[],t,!1);for(const i of Array.from(l.querySelectorAll("body *")).slice(0,800)){const r=e.getComputedStyle(i),o=r.animationName!=="none"?`${r.animationName} ${r.animationDuration}`:null,a=r.transitionProperty!=="none"&&r.transitionProperty!=="all"?`${r.transitionProperty} ${r.transitionDuration}`:r.transitionProperty==="all"?`all ${r.transitionDuration}`:null;(o||a)&&s.push({selector:O(i),animation:o,transition:a,transitionTiming:r.transitionTimingFunction||void 0})}const n=s.filter(i=>i.animation&&i.animation.includes("infinite"));return n.length>5&&t.push(`${n.length} infinitely looping animations — may indicate decorative spinners or a stuck loading state.`),_("inventory_animations",`${s.length} animated/transitioning elements`,s.length,F(s,80).items,t,s.length>80)},map_frame_tree:l=>{const e=[],t=(n,i,r)=>{const o=Array.from(n.querySelectorAll("iframe, frame"));for(const a of o){const c=a.getAttribute("src")||"(no src)";let u=!1,h=null;try{const g=a.contentDocument;g&&(u=!0,h=g.querySelectorAll("*").length,r<3&&t(g,`${i} > ${a.tagName.toLowerCase()}[${c.slice(0,50)}]`,r+1))}catch{u=!1}e.push({path:`${i} > ${a.tagName.toLowerCase()}`,selector:O(a),src:c.slice(0,120),title:a.getAttribute("title")||void 0,name:a.getAttribute("name")||void 0,sandbox:a.getAttribute("sandbox")||void 0,accessible:u,childCount:h,limitation:u?void 0:"Same-origin policy blocks contentDocument access (cross-origin frame)."})}};t(l,"document",0);const s=e.filter(n=>!n.accessible).length;return _("map_frame_tree",`${e.length} frame(s), ${s} inaccessible (cross-origin)`,e.length,e,[],!1)},inventory_shadow_roots:l=>{const e=[],t=(s,n,i)=>{const r=(s instanceof ShadowRoot,Array.from(s.querySelectorAll("*")));for(const o of r)if(o.shadowRoot){const a=o.shadowRoot,c=`${n} > ${o.tagName.toLowerCase()}::shadowRoot(${a.mode})`;e.push({path:c.slice(0,200),hostSelector:O(o),hostTag:o.tagName.toLowerCase(),mode:a.mode,childCount:a.querySelectorAll("*").length,styles:a.querySelectorAll("style").length}),i<4&&t(a,c,i+1)}};return t(l.documentElement,"document",0),_("inventory_shadow_roots",`${e.length} open shadow root(s) found`,e.length,e,[],!1)},inspect_page_storage:l=>{const e=l.defaultView,t=new le,s=[],n=[];if(!(e!=null&&e.localStorage)||!(e!=null&&e.sessionStorage))return _("inspect_page_storage","Web Storage API unavailable in this context",0,[],["localStorage/sessionStorage are not accessible here (JSDOM limitation or sandboxed iframe)."],!1);try{for(let r=0;r r+(o.size||0),0);return _("inspect_page_storage",`${n.length} storage entries (~${i} bytes), sensitive keys redacted`,n.length,F(n,100).items,s,n.length>100)},get_performance_metrics:l=>{var i,r,o,a;const e=l.defaultView,t=[],s=e==null?void 0:e.performance;if(!(s!=null&&s.timing)&&!(s!=null&&s.getEntriesByType))return _("get_performance_metrics","Performance API unavailable",0,[],["window.performance is not exposed in this context."],!1);const n=[];try{const c=(r=(i=s.getEntriesByType)==null?void 0:i.call(s,"navigation"))==null?void 0:r[0];if(c)n.push({metric:"navigation-timing",domContentLoaded:Math.round(c.domContentLoadedEventEnd),loadComplete:Math.round(c.loadEventEnd),domInteractive:Math.round(c.domInteractive),type:c.type,redirectCount:c.redirectCount,sizeTransfer:c.transferSize});else if(s.timing){const g=s.timing;n.push({metric:"navigation-timing-legacy",domContentLoaded:g.domContentLoadedEventEnd-g.navigationStart,loadComplete:g.loadEventEnd-g.navigationStart,domInteractive:g.domInteractive-g.navigationStart})}const u=((o=s.getEntriesByType)==null?void 0:o.call(s,"paint"))||[];for(const g of u)n.push({metric:g.name,startTime:Math.round(g.startTime)});const h=((a=s.getEntriesByType)==null?void 0:a.call(s,"resource"))||[];if(h.length){const g=h.reduce((y,v)=>y+v.duration,0),p=[...h].sort((y,v)=>v.duration-y.duration).slice(0,5).map(y=>({url:String(y.name).slice(0,100),duration:Math.round(y.duration)}));n.push({metric:"resource-summary",count:h.length,totalDuration:Math.round(g),slowest:p})}s.memory&&n.push({metric:"memory",usedJSHeapMB:Math.round(s.memory.usedJSHeapSize/1048576*10)/10,totalJSHeapMB:Math.round(s.memory.totalJSHeapSize/1048576*10)/10})}catch(c){t.push(`performance read failed: ${c.message}`)}return _("get_performance_metrics",`${n.length} metric group(s)`,n.length,n,t,!1)},extract_seo_metadata:l=>{var r,o,a;const e=c=>{var u;return((u=l.querySelector(`meta[name="${c}"]`))==null?void 0:u.getAttribute("content"))||void 0},t=c=>{var u;return((u=l.querySelector(`meta[property="${c}"]`))==null?void 0:u.getAttribute("content"))||void 0},s=[{field:"title",value:l.title||void 0},{field:"description",value:e("description")},{field:"canonical",value:(r=l.querySelector('link[rel="canonical"]'))==null?void 0:r.getAttribute("href")},{field:"robots",value:e("robots")},{field:"viewport",value:e("viewport")},{field:"charset",value:(o=l.querySelector("meta[charset]"))==null?void 0:o.getAttribute("charset")},{field:"og:title",value:t("og:title")},{field:"og:description",value:t("og:description")},{field:"og:image",value:t("og:image")},{field:"og:url",value:t("og:url")},{field:"twitter:card",value:e("twitter:card")},{field:"language",value:(a=l.documentElement)==null?void 0:a.getAttribute("lang")}],n=l.querySelectorAll("h1").length,i=[];return n===0&&i.push("No h1 — page lacks a primary heading."),n>1&&i.push(`Multiple h1 elements (${n}).`),e("description")||i.push("No meta description."),s.push({field:"h1Count",value:n}),_("extract_seo_metadata",`SEO metadata extracted; ${i.length} warning(s)`,s.length,s,i,!1)},extract_structured_data:l=>{var t;const e=[];for(const s of Array.from(l.querySelectorAll('script[type="application/ld+json"]')))try{const n=JSON.parse(s.textContent||"{}");e.push({format:"JSON-LD",type:n["@type"]||(Array.isArray(n)?"array":"unknown"),data:n})}catch(n){e.push({format:"JSON-LD",type:"invalid-json",error:n.message})}for(const s of Array.from(l.querySelectorAll("[itemscope]")).slice(0,30)){const n=s.getAttribute("itemtype")||"unknown",i={};for(const r of Array.from(s.querySelectorAll("[itemprop]"))){const o=r.getAttribute("itemprop")||"",a=r.getAttribute("content")||r.getAttribute("href")||((t=r.textContent)==null?void 0:t.trim())||"";i[o]=a.slice(0,100)}e.push({format:"microdata",type:n.split("/").pop()||n,data:i})}return _("extract_structured_data",`${e.length} structured data block(s)`,e.length,e,[],!1)},extract_tables:l=>{const e=Array.from(l.querySelectorAll("table")),t=e.slice(0,30).map(s=>{var a,c,u;const n=Array.from(s.querySelectorAll("thead th, tr:first-child th")).map(h=>{var g;return((g=h.textContent)==null?void 0:g.trim())||""}),i=Array.from(s.querySelectorAll("tbody tr, tr")).filter(h=>!h.querySelector("th")).slice(0,50),r=i.map(h=>Array.from(h.querySelectorAll("td")).map(g=>(g.textContent||"").trim().slice(0,60))),o=(c=(a=s.querySelector("caption"))==null?void 0:a.textContent)==null?void 0:c.trim();return{selector:O(s),caption:o,columnCount:n.length||((u=r[0])==null?void 0:u.length)||0,rowCount:i.length,headers:n,rows:r}});return _("extract_tables",`${e.length} table(s)`,e.length,t,[],e.length>30)},extract_lists:l=>{const e=Array.from(l.querySelectorAll("ul, ol")),t=e.slice(0,60).map(s=>{const n=Array.from(s.querySelectorAll(":scope > li")).slice(0,40);return{selector:O(s),kind:s.tagName.toLowerCase(),ordered:s.tagName.toLowerCase()==="ol",itemCount:n.length,items:n.map(i=>q(i).slice(0,60)),nested:s.querySelectorAll("ul, ol").length}});return _("extract_lists",`${e.length} list(s)`,e.length,t,[],e.length>60)},analyze_page_content:l=>{const e=l.body,t=(e==null?void 0:e.innerText)||(e==null?void 0:e.textContent)||"",s=t.trim()?t.trim().split(/\s+/).length:0,n=Array.from(l.querySelectorAll("h1, h2, h3, h4, h5, h6")).map(c=>({level:parseInt(c.tagName[1],10),text:q(c).slice(0,80)})),i=l.querySelectorAll("p").length,r=i?Math.round(s/i):0,o=Math.round(s/220*10)/10,a=[{metric:"wordCount",value:s},{metric:"paragraphCount",value:i},{metric:"avgParagraphWords",value:r},{metric:"estimatedReadingMinutes",value:o},{metric:"headingCount",value:n.length},{metric:"imageCount",value:l.querySelectorAll("img").length},{metric:"linkDensity",value:Math.round(l.querySelectorAll("a[href]").length/Math.max(1,s)*1e3)/1e3},{metric:"headings",value:n.slice(0,50)}];return _("analyze_page_content",`${s} words, ${i} paragraphs, ~${o} min read`,a.length,a,[],!1)},search_dom:(l,e)=>{const t=String((e==null?void 0:e.query)||"").trim();if(!t)return _("search_dom","No query supplied",0,[],["Provide a text query; optionally tag/attr filters."],!1);const s=t.toLowerCase(),n=[],i=Math.min((e==null?void 0:e.limit)||50,200),r=Array.from(l.querySelectorAll("*"));for(const o of r){if(n.length>=i)break;if(e!=null&&e.tag&&o.tagName.toLowerCase()!==String(e.tag).toLowerCase())continue;const a=q(o),c=Array.from(o.attributes);let u=0,h="";o.tagName.toLowerCase().includes(s)&&(u+=.2,h="tag match"),a.toLowerCase().includes(s)&&a.length<200&&(u+=.6,h="text match");for(const g of c)if(g.name.toLowerCase().includes(s)||g.value.length<100&&g.value.toLowerCase().includes(s)){u+=.4,h=`attribute ${g.name} match`;break}if(e!=null&&e.attr){const g=String(e.attr).toLowerCase(),p=e.attrValue?String(e.attrValue).toLowerCase():null;if(c.find(v=>v.name.toLowerCase()===g&&(!p||v.value.toLowerCase().includes(p))))u+=.5;else continue}if(u>0){const g=de(o);n.push({selector:g.bestSelector,tag:g.tag,role:g.role,text:g.text.slice(0,60),score:Math.round(u*100)/100,reason:h,visible:g.visibility.isVisible,bounds:{x:Math.round(g.bounds.x),y:Math.round(g.bounds.y),w:Math.round(g.bounds.width),h:Math.round(g.bounds.height)}})}}return n.sort((o,a)=>a.score-o.score),_("search_dom",`${n.length} element(s) match "${t}"`,n.length,n,[],n.length>=i)},inventory_ctas:l=>{var t;const e=[];for(const s of Array.from(l.querySelectorAll('button, a[class*="btn"], a[class*="button"], input[type="submit"], [role="button"]')).slice(0,100)){const n=de(s);e.push({selector:n.bestSelector,tag:n.tag,text:n.text.slice(0,50),styleHint:(t=s.getAttribute("class"))==null?void 0:t.slice(0,60),primary:/primary|cta|submit|main/i.test(s.getAttribute("class")||"")||s.type==="submit",visible:n.visibility.isVisible})}return _("inventory_ctas",`${e.length} call-to-action element(s)`,e.length,e,[],!1)},detect_focus_traps:l=>{const e=[];for(const s of Array.from(l.querySelectorAll('[role="dialog"], [aria-modal="true"], dialog[open], .modal, [class*="modal"]')).slice(0,30)){const n=s.querySelectorAll('a[href], button, input, select, textarea, [tabindex]:not([tabindex="-1"])');e.push({selector:O(s),kind:s.getAttribute("role")||s.tagName.toLowerCase(),ariaModal:s.getAttribute("aria-modal"),focusableCount:n.length,firstFocusable:n[0]?O(n[0]):void 0,note:n.length===0?"Modal container has NO focusable elements — keyboard users are trapped.":void 0})}const t=l.querySelectorAll("[tabindex]>0");for(const s of Array.from(t).slice(0,20))e.push({selector:O(s),kind:"positive-tabindex",note:`tabindex=${s.tabIndex} breaks natural tab order.`});return _("detect_focus_traps",`${e.length} focus-management issue(s)/container(s)`,e.length,e,[],!1)},infer_responsive_breakpoints:l=>{const e=l.defaultView,t=[],s=new Set;for(const o of Array.from(l.querySelectorAll("style"))){const a=o.textContent||"",c=/@media[^{]*?\(\s*(?:min|max)-width\s*:\s*(\d+)(?:\.\d+)?px/g;let u;for(;u=c.exec(a);)s.add(parseInt(u[1],10))}for(const o of Array.from(l.querySelectorAll('link[rel="stylesheet"]')).slice(0,10)){const a=o.getAttribute("href")||"";if(/^\d+px$/.test(a)||a.includes("width=")){const c=a.match(/width=(\d+)/);c&&s.add(parseInt(c[1],10))}}for(const o of Array.from(l.querySelectorAll("img[srcset], source[srcset]")).slice(0,50)){const a=o.getAttribute("srcset")||"";for(const c of a.matchAll(/(\d+)w/g))s.add(parseInt(c[1],10))}e!=null&&e.matchMedia||t.push("matchMedia unavailable — live breakpoint probing skipped.");const n=Array.from(s).sort((o,a)=>o-a),i=n.map(o=>({breakpoint:o,note:o<=768?"mobile-class":o<=1024?"tablet-class":"desktop-class"})),r=e==null?void 0:e.innerWidth;if(r){const o=n.filter(a=>a<=r);i.unshift({breakpoint:`current viewport: ${r}px`,note:o.length?`below breakpoints: ${o.join(", ")}`:"no declared breakpoint below current width"})}return _("infer_responsive_breakpoints",`${n.length} breakpoint(s) inferred from CSS/srcset`,i.length,i,t,!1)},get_selection_state:l=>{var i;const e=l.defaultView,t=(i=e==null?void 0:e.getSelection)==null?void 0:i.call(e),s=l.activeElement,n=[{hasSelection:!!(t!=null&&t.toString()),selectedText:(t==null?void 0:t.toString().slice(0,200))||"",selectionRanges:(t==null?void 0:t.rangeCount)||0,activeElement:s?{tag:s.tagName.toLowerCase(),selector:O(s),editable:s.isContentEditable||["INPUT","TEXTAREA"].includes(s.tagName)}:null}];return _("get_selection_state",t!=null&&t.toString()?`Selection: "${t.toString().slice(0,40)}…"`:"No text selection",1,n,[],!1)}};function Et(l,e,t){const s=Ce[l];return s?s(e,t):{analyzer:l,summary:`Unknown analyzer "${l}". Available: ${Object.keys(Ce).join(", ")}`,count:0,items:[],warnings:[],truncated:!1}}const vt=2e3;class wt{constructor(e=vt){b(this,"events",[]);b(this,"cap");b(this,"counter",0);this.cap=Math.max(10,e)}record(e,t,s={}){this.counter++;const n={eventId:`evt_${Date.now().toString(36)}_${this.counter}`,timestamp:Date.now(),kind:e,operationId:s.operationId,sessionId:s.sessionId,detail:t,data:s.data};return this.events.push(n),this.events.length>this.cap&&this.events.splice(0,this.events.length-this.cap),n}query(e){let t=this.events;e.kind&&(t=t.filter(n=>n.kind===e.kind)),e.operationId&&(t=t.filter(n=>n.operationId===e.operationId)),e.sinceTimestamp&&(t=t.filter(n=>n.timestamp>=e.sinceTimestamp));const s=e.limit&&e.limit>0?e.limit:200;return t.slice(-s)}size(){return this.events.length}toJSON(){return[...this.events]}}class St{constructor(){b(this,"counter",0);b(this,"operations",new Map)}begin(e){this.counter++;const t=`op_${Date.now().toString(36)}_${this.counter}`;return this.operations.set(t,{operationId:t,tool:e,startedAt:Date.now(),status:"RUNNING",timelineEventIds:[]}),t}end(e,t,s){const n=this.operations.get(e);n&&(n.endedAt=Date.now(),n.status=t,n.relatedError=s)}attachEvent(e,t){const s=this.operations.get(e);s&&s.timelineEventIds.push(t)}trace(e){const t=this.operations.get(e);return t?{...t,durationMs:t.endedAt?t.endedAt-t.startedAt:void 0}:null}recent(e=100){return Array.from(this.operations.values()).slice(-e).map(t=>({...t,durationMs:t.endedAt?t.endedAt-t.startedAt:void 0}))}}const Ie=100;class Tt{constructor(e){b(this,"sessionId");b(this,"timeline",new wt);b(this,"operations",new St);b(this,"tabs",new Map);b(this,"activeTabId",null);b(this,"startedAt",Date.now());b(this,"snapshots",[]);b(this,"commandHistory",[]);b(this,"annotationCount",0);b(this,"projectId");b(this,"tabCounter",0);b(this,"commandCounter",0);this.sessionId=e||`sess_${Date.now().toString(36)}`}registerTab(e,t,s){const n=e!==void 0?Array.from(this.tabs.values()).find(o=>o.browserTabId===e):void 0;if(n)return n.lastSeenAt=Date.now(),n.status="OPEN",n.url=t||n.url,n.title=s||n.title,n;this.tabCounter++;const i=`stab_${this.tabCounter}_${Date.now().toString(36)}`,r={sessionTabId:i,browserTabId:e,url:t,title:s,createdAt:Date.now(),lastSeenAt:Date.now(),status:"OPEN"};return this.tabs.set(i,r),this.timeline.record("TAB_OPENED",`tab ${i} registered (${t||"no url"})`,{sessionId:this.sessionId}),r}closeTab(e){const t=this.tabs.get(e);return t?(t.status="CLOSED",t.lastSeenAt=Date.now(),this.timeline.record("TAB_CLOSED",`tab ${e} closed`,{sessionId:this.sessionId}),!0):!1}switchTab(e){const t=this.tabs.get(e);return!t||t.status==="CLOSED"?!1:(this.activeTabId=e,this.timeline.record("TAB_SWITCHED",`active tab → ${e}`,{sessionId:this.sessionId}),!0)}getTabs(){return Array.from(this.tabs.values())}getActiveTab(){if(this.activeTabId){const e=this.tabs.get(this.activeTabId);if(e&&e.status==="OPEN")return e}return Array.from(this.tabs.values()).find(e=>e.status==="OPEN")||null}markAllStale(){let e=0;for(const t of this.tabs.values())t.status==="OPEN"&&(t.status="STALE",e++);return e}captureSnapshot(e,t,s){var a,c,u;const n=e.defaultView,i=((a=e.documentElement)==null?void 0:a.outerHTML)||"",r=e.querySelectorAll('a[href], button, input, select, textarea, [role="button"]').length,o={snapshotId:`snap_${Date.now().toString(36)}_${this.snapshots.length+1}`,timestamp:Date.now(),url:((c=n==null?void 0:n.location)==null?void 0:c.href)||((u=e.location)==null?void 0:u.href)||"",title:e.title||"",viewport:{width:(n==null?void 0:n.innerWidth)||0,height:(n==null?void 0:n.innerHeight)||0,scrollX:(n==null?void 0:n.scrollX)||0,scrollY:(n==null?void 0:n.scrollY)||0,devicePixelRatio:(n==null?void 0:n.devicePixelRatio)||1},domLength:i.length,domHash:be(i),interactiveCount:r,selectedRegions:[],extensionEnabled:t,pendingMutations:s,annotationCount:this.annotationCount};return this.snapshots.push(o),this.snapshots.length>Ie&&this.snapshots.splice(0,this.snapshots.length-Ie),this.timeline.record("SNAPSHOT_CREATED",`snapshot ${o.snapshotId} (dom ${o.domLength}b)`,{sessionId:this.sessionId}),o}getSnapshot(e){return e?this.snapshots.find(t=>t.snapshotId===e)||null:this.snapshots[this.snapshots.length-1]||null}listSnapshots(){return this.snapshots.map(e=>({snapshotId:e.snapshotId,timestamp:e.timestamp,url:e.url,title:e.title,domLength:e.domLength,domHash:e.domHash}))}compareSnapshots(e,t){const s=["url","title","domLength","domHash","interactiveCount","extensionEnabled","annotationCount"],n=[];for(const r of s)e[r]!==t[r]&&n.push({field:r,before:e[r],after:t[r]});(e.viewport.width!==t.viewport.width||e.viewport.height!==t.viewport.height)&&n.push({field:"viewport",before:`${e.viewport.width}x${e.viewport.height}`,after:`${t.viewport.width}x${t.viewport.height}`});const i=t.domLength-e.domLength;return{identical:n.length===0,changes:n,domDelta:{beforeLength:e.domLength,afterLength:t.domLength,delta:i},summary:n.length===0?"States are identical.":`${n.length} field(s) changed; DOM size ${i>=0?"+":""}${i} bytes.`}}recordCommand(e,t,s,n,i){this.commandCounter++;const r=`cmd_${this.commandCounter}_${Date.now().toString(36)}`;return this.commandHistory.push({commandId:r,tool:e,args:t,outcome:s,timestamp:Date.now(),durationMs:n,error:i}),this.timeline.record("COMMAND_EXECUTED",`${e} → ${s}${i?` (${i})`:""}`,{sessionId:this.sessionId,data:{commandId:r}}),r}getCommandHistory(e=100){return this.commandHistory.slice(-e)}noteAnnotations(e){this.annotationCount=e}bindProject(e){this.projectId=e}getProjectId(){return this.projectId}summary(e,t,s,n){var i,r,o;return{sessionId:this.sessionId,startedAt:this.startedAt,url:((r=(i=e.defaultView)==null?void 0:i.location)==null?void 0:r.href)||((o=e.location)==null?void 0:o.href)||"",title:e.title||"",tabs:this.getTabs(),activeTabId:this.activeTabId,viewport:{width:t.width,height:t.height,isModified:t.isModified},extensionEnabled:s,snapshotCount:this.snapshots.length,commandCount:this.commandHistory.length,annotationCount:this.annotationCount,mutationHistoryCount:n.length,timelineEventCount:this.timeline.size(),projectId:this.projectId}}}const Ct=l=>{var e,t;try{const s=l.getBoundingClientRect();if(s.width===0&&s.height===0)return null;const n=((t=(e=l.ownerDocument)==null?void 0:e.defaultView)==null?void 0:t.innerWidth)||1920;return s.y n*1.5?"bottom":s.x n*.8?"right":"center"}catch{return null}},It={navigation:"navigation",banner:"header",contentinfo:"footer",complementary:"sidebar",main:"main",form:"form",search:"search",region:"section",dialog:"modal",alertdialog:"modal",table:"table",list:"list",combobox:"dropdown",button:"button",link:"link",textbox:"input",checkbox:"checkbox",radio:"radio",img:"image",article:"article"},At={nav:"navigation",header:"header",footer:"footer",aside:"sidebar",main:"main",section:"section",article:"article",form:"form",table:"table",ul:"list",ol:"list",figure:"figure",dialog:"modal",button:"button",input:"input",select:"dropdown",textarea:"textarea",canvas:"canvas",video:"video",img:"image",h1:"heading",h2:"heading",h3:"heading"};function Z(l){return l.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"").replace(/_{2,}/g,"_").slice(0,48).replace(/_$/,"")}class xt{generate(e){return this.generateFromMeta({tagName:e.tagName.toLowerCase(),role:e.getAttribute("role")||void 0,text:q(e).trim(),ariaLabel:e.getAttribute("aria-label")||void 0,stableClass:Array.from(e.classList||[]).find(t=>/^[a-z][a-z0-9-]{2,}$/i.test(t)&&!_t.has(t)),position:Ct(e),nearbyHeading:this.nearbyHeading(e)})}generateFromMeta(e){const t=[],s=[],n=e.role||Nt(e.tagName);if(n){const r=It[n]||n;s.push(r),t.push(`role=${n}`)}else{const r=At[e.tagName]||e.tagName;s.push(r),t.push(`tag=${e.tagName}`)}if(e.ariaLabel&&(s.unshift(Z(e.ariaLabel)),t.push(`aria-label="${e.ariaLabel.slice(0,30)}"`)),e.text&&e.text.length<=40){const r=Z(e.text.split(/\s+/).slice(0,3).join(" "));r&&r.length>=2&&(s.push(r),t.push(`text="${e.text.slice(0,30)}"`))}if(e.nearbyHeading){const r=Z(e.nearbyHeading.split(/\s+/).slice(0,3).join(" "));r&&!s.includes(r)&&(s.push(r),t.push(`nearby-heading="${e.nearbyHeading.slice(0,30)}"`))}e.stableClass&&s.length<3&&(s.push(Z(e.stableClass)),t.push(`class=${e.stableClass}`)),e.tagName==="input"&&(s.some(r=>r.includes("input"))||(s.push("input"),t.push("tag=input"))),s.join("_").length<12&&e.position&&(s.push(e.position),t.push(`position=${e.position}`));let i=Z(s.join("_"))||"unnamed_region";return/^\d/.test(i)&&(i=`el_${i}`),{name:i,evidence:t}}nearbyHeading(e){let t=e.parentElement;for(let n=0;t&&n<4;n++){const i=t.querySelector('h1, h2, h3, h4, [role="heading"]');if(i)return q(i).trim().slice(0,40)||null;t=t.parentElement}let s=e.previousElementSibling;for(let n=0;s&&n<4;n++){if(/^H[1-4]$/.test(s.tagName)){const i=q(s).trim();if(i)return i.slice(0,40)}s=s.previousElementSibling}return null}}const _t=new Set(["active","open","visible","hidden","selected","disabled","container","wrapper","root","item","col","row","flex","box","main","div","span","block"]);function Nt(l){switch(l){case"nav":return"navigation";case"header":return"banner";case"footer":return"contentinfo";case"aside":return"complementary";case"main":return"main";case"form":return"form";case"table":return"table";case"button":return"button";case"a":return"link";case"input":return"textbox";case"select":return"combobox";case"textarea":return"textbox";case"img":return"img";default:return null}}const kt=["display","position","flex-direction","grid-template-columns","width","height","background-color","color","font-size","border-radius","overflow"];class Mt{constructor(){b(this,"naming",new xt)}capture(e){const t=e.ownerDocument,s=new Y(t),n=new te,i=s.generateCandidates(e),r=s.bestSelector(e),o=n.fingerprint(e);let a=e,c=0,u="self";for(let d=0;d<3;d++){const f=a.parentElement;if(!f||f===t.body||f===t.documentElement)break;if(this.isMeaningfulContainer(f)){a=f,c=d+1,u="meaningful-ancestor";break}a=f,c=d+1}if(a===e){const d=e.parentElement;d&&d!==t.body&&e.querySelectorAll("*").length<4&&(a=d,c=1,u="direct-parent-fallback")}const h=this.boundedHtml(e,6e4),g=this.boundedHtml(a,12e4);k.inspectElement(e);const p=e.getBoundingClientRect(),y=t.defaultView,v={};if(y!=null&&y.getComputedStyle){const d=y.getComputedStyle(e);for(const f of kt){const w=d.getPropertyValue(f);w&&w!=="none"&&w!=="auto"&&(v[f]=w)}}const m=e.parentElement;return{regionHtml:h,contextHtml:g,boundary:{strategy:u,ancestorLevels:c,note:c===0?"Region captured standalone (no meaningful ancestor within 3 levels).":`Context includes ${c} ancestor level(s) up to a meaningful container.`},selectorCandidates:i,bestSelector:r.selector,xpath:s.buildXPath(e),fingerprintHash:o.hash,dimensions:{width:Math.round(p.width),height:Math.round(p.height)},position:{x:Math.round(p.x),y:Math.round(p.y)},relevantStyles:v,parentInfo:m?{tag:m.tagName.toLowerCase(),selector:Rt(m),text:q(m).slice(0,60)}:void 0,childrenCount:e.children.length,childTags:Array.from(e.children).slice(0,12).map(d=>d.tagName.toLowerCase()),nameHint:this.naming.generate(e),fingerprintVolatility:o.volatilityRisk,volatilityReasons:o.volatilityReasons}}isMeaningfulContainer(e){const t=e.tagName.toLowerCase();if(["section","article","aside","main","nav","header","footer","form"].includes(t)||e.hasAttribute("id")||e.hasAttribute("data-testid")||e.getAttribute("role")||e.children.length>1&&e.querySelector(":scope > *:nth-child(3)"))return!0;const s=e.getAttribute("style")||"";return!!(s.includes("grid")||s.includes("flex"))}boundedHtml(e,t){const s=e.outerHTML;return s.length<=t?s:s.slice(0,t)+` +`}}function Rt(l){try{return new Y(l.ownerDocument).bestSelector(l).selector}catch{return l.tagName.toLowerCase()}}class Ot{constructor(e){b(this,"nodeRegistry");b(this,"snapshotEngine");b(this,"picker");b(this,"interactionEngine");b(this,"observer");b(this,"mutationEngines",new WeakMap);b(this,"viewportControllers",new WeakMap);b(this,"targetingEngines",new WeakMap);b(this,"jsEngine",new Fe);b(this,"fingerprintEngine",new te);b(this,"humanInteraction",new it);b(this,"session",new Tt);b(this,"simulationTabs",[]);b(this,"simulationTabCounter",0);b(this,"simulationExtensions",[{id:"teledom@teledom",name:"TeleDOM Browser Intelligence Platform",version:"4.1.0",description:"The TeleDOM platform extension itself",enabled:!0,installType:"development",isApp:!1}]);b(this,"regionCapture",new Mt);this.nodeRegistry=e||new H;const t=new J,s=new ne;this.snapshotEngine=new he(this.nodeRegistry,t,s),this.picker=new Pe({nodeRegistry:this.nodeRegistry}),this.interactionEngine=new Le(this.nodeRegistry),this.observer=new qe(this.nodeRegistry),this.picker.initGlobalShortcutListener(),this.interactionEngine.setTimingHook(async n=>{const i=this.humanInteraction.delay(n);i>0&&await new Promise(r=>setTimeout(r,i))})}getMutationEngine(e){let t=this.mutationEngines.get(e);return t||(t=new Ue(e,this.nodeRegistry),this.mutationEngines.set(e,t)),t}getViewportController(e){let t=this.viewportControllers.get(e);return t||(t=new Be(e),this.viewportControllers.set(e,t)),t}getTargetingEngine(e){let t=this.targetingEngines.get(e);return t||(t=new tt(e,this.nodeRegistry),this.targetingEngines.set(e,t)),t}isSimulation(){return typeof globalThis.__FORENSIC_SIMULATION__<"u"}getPicker(){return this.picker}getInteractionEngine(){return this.interactionEngine}getObserver(){return this.observer}getNodeRegistry(){return this.nodeRegistry}async handleCommand(e,t=typeof document<"u"?document:{}){var o,a,c,u,h,g,p,y,v;const s=Date.now(),{id:n,command:i,payload:r}=e;try{switch(i){case"LIVE_PAGE_INSPECT":{const m=k.inspectPage(t);return this.success(n,i,m,s)}case"LIVE_ELEMENT_INSPECT":{const m=this.resolveTarget(r,t),d=k.inspectElement(m,this.nodeRegistry);return this.success(n,i,d,s)}case"GET_SELECTED_ELEMENT":{const m=this.picker.getLastSelectedElement();return this.success(n,i,m,s)}case"ELEMENT_PICKER_START":return this.picker.startPicker(),this.success(n,i,{pickerActive:!0},s);case"ELEMENT_PICKER_STOP":return this.picker.stopPicker(),this.success(n,i,{pickerActive:!1},s);case"LIVE_ELEMENT_INTERACT":{const m=r,d=await this.interactionEngine.interact(m,t);return this.success(n,i,d,s)}case"ELEMENT_OBSERVATION_START":{const m=this.resolveTarget(r,t),d=this.observer.startObservation(m,t);return this.success(n,i,d,s)}case"ELEMENT_OBSERVATION_STOP":{const m=this.observer.stopObservation(t);return this.success(n,i,m,s)}case"LIVE_DOM_SNAPSHOT":{if(((r==null?void 0:r.format)||"html")==="html"){const f=((o=t.documentElement)==null?void 0:o.outerHTML)||"";return this.success(n,i,{html:f},s)}const d=this.snapshotEngine.captureSnapshot(t,"live_session");return this.success(n,i,d,s)}case"LIVE_DOM_SUBTREE":{const m=this.resolveTarget(r,t),d=m.outerHTML||"",f=k.inspectElement(m,this.nodeRegistry);return this.success(n,i,{html:d,element:f},s)}case"GET_ELEMENT_VISUAL_STATE":{const m=this.resolveTarget(r,t),d=k.inspectVisualState(m);return this.success(n,i,d,s)}case"LIVE_PAGE_SCREENSHOT":case"LIVE_ELEMENT_SCREENSHOT":{const m=await this.handleScreenshotCapture(i,r,t);return this.success(n,i,m,s)}case"GET_TAB_CONSOLE_LOGS":{const{level:m,searchQuery:d,limit:f=100,clearAfterRead:w}=r||{};let E=typeof window<"u"&&window.__FORENSIC_CONSOLE_BUFFER__||[];if(m&&m!=="all"&&(E=E.filter(S=>S.level===m)),d){const S=String(d).toLowerCase();E=E.filter(T=>{var x,N;return((x=T.text)==null?void 0:x.toLowerCase().includes(S))||((N=T.source)==null?void 0:N.toLowerCase().includes(S))})}return f>0&&(E=E.slice(-f)),w&&typeof window<"u"&&window.__FORENSIC_CONSOLE_BUFFER__&&(window.__FORENSIC_CONSOLE_BUFFER__.length=0),this.success(n,i,{url:typeof window<"u"?window.location.href:"",title:t.title||"",totalCaptured:typeof window<"u"&&((a=window.__FORENSIC_CONSOLE_BUFFER__)==null?void 0:a.length)||E.length,returnedCount:E.length,logs:E},s)}case"GET_TAB_NETWORK_REQUESTS":{const{method:m,searchQuery:d,status:f,onlyErrors:w,limit:E=100,clearAfterRead:S}=r||{};let T=typeof window<"u"&&window.__FORENSIC_NETWORK_BUFFER__||[];if(m&&(T=T.filter(x=>{var N;return((N=x.method)==null?void 0:N.toUpperCase())===String(m).toUpperCase()})),f&&(T=T.filter(x=>x.status===Number(f))),w&&(T=T.filter(x=>x.error||x.status&&x.status>=400)),d){const x=String(d).toLowerCase();T=T.filter(N=>{var D;return(D=N.url)==null?void 0:D.toLowerCase().includes(x)})}return E>0&&(T=T.slice(-E)),S&&typeof window<"u"&&window.__FORENSIC_NETWORK_BUFFER__&&(window.__FORENSIC_NETWORK_BUFFER__.length=0),this.success(n,i,{url:typeof window<"u"?window.location.href:"",title:t.title||"",totalCaptured:typeof window<"u"&&((c=window.__FORENSIC_NETWORK_BUFFER__)==null?void 0:c.length)||T.length,returnedCount:T.length,requests:T},s)}case"CLOSE_TAB":{if(typeof globalThis.chrome<"u"&&((u=globalThis.chrome.runtime)!=null&&u.sendMessage)){const m=await new Promise(d=>{globalThis.chrome.runtime.sendMessage({type:"BROWSER_COMMAND_REQUEST",id:n,command:i,payload:r},f=>d(f))});if(m)return m}return this.isSimulation()?this.simulationCloseTab(r,t,n,i,s):typeof window<"u"?(setTimeout(()=>window.close(),100),this.success(n,i,{closed:!0,url:window.location.href,title:t.title},s)):this.success(n,i,{closed:!0},s)}case"RELOAD_TAB":{if(typeof globalThis.chrome<"u"&&((h=globalThis.chrome.runtime)!=null&&h.sendMessage)){const m=await new Promise(d=>{globalThis.chrome.runtime.sendMessage({type:"BROWSER_COMMAND_REQUEST",id:n,command:i,payload:r},f=>d(f))});if(m)return m}if(this.isSimulation()){const m=(r==null?void 0:r.mode)||"soft";return this.session.timeline.record("NAVIGATED",`tab reloaded (${m} mode)`),this.success(n,i,{reloaded:!0,mode:m,simulated:!0,url:((p=(g=t.defaultView)==null?void 0:g.location)==null?void 0:p.href)||"",title:t.title,note:"Node simulation context: DOM fixture retained; no real navigation occurs."},s)}return typeof window<"u"?(setTimeout(()=>window.location.reload(),100),this.success(n,i,{reloaded:!0,url:window.location.href,title:t.title},s)):this.success(n,i,{reloaded:!0},s)}case"OPEN_TAB":case"LIST_TABS":case"FOCUS_TAB":case"LIST_EXTENSIONS":case"RELOAD_EXTENSION":case"SET_EXTENSION_ENABLED":case"TOGGLE_EXTENSION":{if(this.isSimulation())return this.handleSimulationBackgroundCommand(n,i,r,t,s);if(typeof globalThis.chrome<"u"&&((y=globalThis.chrome.runtime)!=null&&y.sendMessage)){const m=await new Promise(d=>{globalThis.chrome.runtime.sendMessage({type:"BROWSER_COMMAND_REQUEST",id:n,command:i,payload:r},f=>d(f))});if(m)return m}return this.error(n,i,"BACKGROUND_EXECUTION_FAILED",`Command ${i} requires Chrome extension runtime`,s)}case"RESIZE_VIEWPORT":{const m=this.getViewportController(t);let d;if(r!=null&&r.preset)d=m.applyPreset(r.preset);else{const f=Number(r==null?void 0:r.width)||1280,w=Number(r==null?void 0:r.height)||800;d=m.resize(f,w)}return this.session.timeline.record("RESIZED",`viewport → ${d.applied.width}x${d.applied.height}`),this.success(n,i,d,s)}case"RESET_VIEWPORT":{const d=this.getViewportController(t).reset();return this.session.timeline.record("RESIZED",`viewport restored to ${d.applied.width}x${d.applied.height}`),this.success(n,i,d,s)}case"GET_VIEWPORT_STATE":{const m=this.getViewportController(t);return this.success(n,i,m.state(),s)}case"RUN_RESPONSIVE_TEST":{const m=this.getViewportController(t),d=(r==null?void 0:r.sizes)||Pt(),f=m.runResponsiveTest(d,{restore:(r==null?void 0:r.restore)!==!1});return this.success(n,i,f,s)}case"EMULATE_DEVICE":{const d=this.getViewportController(t).emulateDevice((r==null?void 0:r.device)||"pixel-7");return this.success(n,i,d,s)}case"EXECUTE_JS":case"EXECUTE_JS_AND_CAPTURE_CHANGES":{const m=String((r==null?void 0:r.code)||"");if(!m.trim())return this.error(n,i,"SCRIPT_EMPTY","payload.code is required.",s);const d=await this.jsEngine.execute(t,m,{timeoutMs:r==null?void 0:r.timeoutMs,world:(r==null?void 0:r.world)==="MAIN"?"MAIN":"ISOLATED"});return this.session.timeline.record("SCRIPT_EXECUTED",`${d.status} (${d.durationMs}ms)`),this.success(n,i,d,s)}case"DOM_MUTATE":{const d=this.getMutationEngine(t).mutate(r);return this.session.timeline.record("DOM_MUTATED",`${d.operation} on ${d.before.selector} → ${d.success?"OK":d.error}`),this.success(n,i,d,s)}case"DOM_MUTATE_TRANSACTION":{const m=this.getMutationEngine(t),d=(r==null?void 0:r.mode)||"begin";try{if(d==="begin"){const f=m.beginTransaction();return this.success(n,i,{transactionId:f,mode:d,open:!0},s)}if(d==="commit"){const f=m.commitTransaction();return this.session.timeline.record("DOM_MUTATED",`transaction ${f.transactionId} committed (${f.steps.length} steps)`),this.success(n,i,{...f,mode:d},s)}if(d==="rollback"){const f=m.rollbackTransaction(r==null?void 0:r.reason);return this.session.timeline.record("MUTATION_UNDONE",`transaction ${f.transactionId} rolled back`),this.success(n,i,{...f,mode:d},s)}return this.error(n,i,"INVALID_MODE",`mode must be begin|commit|rollback, got "${d}"`,s)}catch(f){return this.error(n,i,"DOM_MUTATION_FAILED",f.message,s)}}case"UNDO_DOM_MUTATION":{const d=this.getMutationEngine(t).undo();return d.success&&this.session.timeline.record("MUTATION_UNDONE",d.message),this.success(n,i,d,s)}case"REDO_DOM_MUTATION":{const d=this.getMutationEngine(t).redo();return d.success&&this.session.timeline.record("MUTATION_REDONE",d.message),this.success(n,i,d,s)}case"GET_MUTATION_HISTORY":{const m=this.getMutationEngine(t);return this.success(n,i,{entries:m.getHistory((r==null?void 0:r.limit)||100),undoDepth:m.getUndoDepth(),redoDepth:m.getRedoDepth(),openTransactionId:m.getOpenTransactionId()},s)}case"PREVIEW_DOM_MUTATION":{const d=this.getMutationEngine(t).preview(r);return this.success(n,i,d,s)}case"GENERATE_ELEMENT_TARGET":{const d=this.getTargetingEngine(t).resolveAndBuild((r==null?void 0:r.target)||(r==null?void 0:r.selector)||"");return"error"in d?this.error(n,i,"TARGET_NOT_FOUND",d.error,s):this.success(n,i,d.target,s)}case"RECOVER_SELECTOR":{const m=new nt(t),d=(r==null?void 0:r.snapshot)||{},f=m.recover((r==null?void 0:r.selector)||"",d);return this.success(n,i,f,s)}case"GET_ELEMENT_ANCESTRY":{const m=this.resolveTarget(r,t);return this.success(n,i,Lt(m,t),s)}case"GET_ELEMENT_FINGERPRINT":{const m=this.resolveTarget(r,t),d=this.fingerprintEngine.fingerprint(m);return this.success(n,i,d,s)}case"GET_ELEMENT_RELATIONSHIPS":{const m=this.resolveTarget(r,t);return this.success(n,i,Dt(m,t),s)}case"GET_ELEMENT_ACCESSIBILITY":{const m=this.resolveTarget(r,t);return this.success(n,i,$t(m),s)}case"GET_COMPUTED_STYLE":{const m=this.resolveTarget(r,t),d=t.defaultView;if(!(d!=null&&d.getComputedStyle))return this.error(n,i,"STYLE_UNAVAILABLE","getComputedStyle is unavailable in this context.",s);const f=d.getComputedStyle(m),w=Array.isArray(r==null?void 0:r.properties)&&r.properties.length?r.properties:["display","position","color","background-color","font-size","font-family","width","height","margin","padding","border","z-index","opacity","visibility","overflow","flex-direction","grid-template-columns"],E={};for(const S of w)E[S]=f.getPropertyValue(S);return this.success(n,i,{selector:k.inspectElement(m,this.nodeRegistry).bestSelector,styles:E},s)}case"ANALYZE_DOM":{const m=String((r==null?void 0:r.analyzer)||"");if(!m)return this.error(n,i,"ANALYZER_REQUIRED",'payload.analyzer is required (e.g. "analyze_forms").',s);const d=Et(m,t,r);return d.count===0&&d.warnings.length===0&&d.items.length===0&&d.summary.startsWith("Unknown analyzer")?this.error(n,i,"UNKNOWN_ANALYZER",d.summary,s):this.success(n,i,d,s)}case"DRAG_ELEMENT":{const m=this.resolveTarget(r==null?void 0:r.source,t),d=r!=null&&r.target?this.resolveTarget(r==null?void 0:r.target,t):null,f=await this.performDrag(m,d,r==null?void 0:r.offsets,t);return this.success(n,i,f,s)}case"SET_INPUT_CHECKED":{const d=this.resolveTarget(r,t);if(d.type!=="checkbox"&&d.type!=="radio")return this.error(n,i,"INPUT_TYPE_UNSUPPORTED",`Target input type "${d.type}" is not checkbox/radio.`,s);const f=d.checked;d.checked=(r==null?void 0:r.checked)!==!1;const w=[];for(const E of["input","change"])try{d.dispatchEvent(new t.defaultView.Event(E,{bubbles:!0})),w.push(E)}catch{}if(d.type==="radio"&&d.name)for(const E of Array.from(t.querySelectorAll(`input[type=radio][name="${d.name}"]`)))E!==d&&(E.checked=!1);return this.success(n,i,{success:!0,selector:k.inspectElement(d,this.nodeRegistry).bestSelector,inputType:d.type,checkedBefore:f,checkedAfter:d.checked,eventsFired:w},s)}case"PRESS_KEYBOARD_SHORTCUT":{const m=Array.isArray(r==null?void 0:r.keys)?r.keys:String((r==null?void 0:r.keys)||"Enter").split("+"),d=r!=null&&r.target?this.resolveTarget(r==null?void 0:r.target,t):t.activeElement||t.body;typeof d.focus=="function"&&d.focus();const f=[],w=t.defaultView;for(const E of m)for(const S of["keydown","keyup"])try{d.dispatchEvent(new((w==null?void 0:w.KeyboardEvent)||KeyboardEvent)(S,{key:E.trim(),bubbles:!0,cancelable:!0,ctrlKey:m.some(T=>/^(ctrl|control|cmd|meta)$/i.test(T))&&E!==m.find(T=>/^(ctrl|control|cmd|meta)$/i.test(T)),shiftKey:m.some(T=>/^shift$/i.test(T))&&E!=="Shift",altKey:m.some(T=>/^alt$/i.test(T))&&E!=="Alt"})),f.push(`${S}:${E}`)}catch{}return this.success(n,i,{success:!0,keys:m,targetSelector:k.inspectElement(d,this.nodeRegistry).bestSelector,eventsFired:f},s)}case"SCROLL_PAGE":{const m=t.defaultView;if(!m)return this.error(n,i,"NO_WINDOW","No window available for scrolling.",s);const d={x:m.scrollX||0,y:m.scrollY||0};let f;if(r!=null&&r.target||r!=null&&r.selector){const E=this.resolveTarget((r==null?void 0:r.target)||(r==null?void 0:r.selector),t);(v=E.scrollIntoView)==null||v.call(E,{behavior:(r==null?void 0:r.behavior)||"auto",block:"center"}),f=k.inspectElement(E,this.nodeRegistry).bestSelector}else m.scrollBy(Number(r==null?void 0:r.x)||0,Number(r==null?void 0:r.y)||0);const w={x:m.scrollX||0,y:m.scrollY||0};return this.success(n,i,{success:!0,scrollBefore:d,scrollAfter:w,requested:{x:Number(r==null?void 0:r.x)||0,y:Number(r==null?void 0:r.y)||0},targetSelector:f},s)}case"WAIT_FOR_CONDITION":return await this.waitForCondition(t,r||{},s,n,i);case"GET_PAGE_STATE":case"CAPTURE_PAGE_STATE":{const m=this.session.captureSnapshot(t,!0,this.getMutationEngine(t).getUndoDepth());return this.success(n,i,m,s)}case"CAPTURE_REGION":{const m=this.resolveTarget((r==null?void 0:r.target)||(r==null?void 0:r.selector),t),d=this.regionCapture.capture(m);return this.success(n,i,d,s)}case"GET_SIMULATION_TAB_STATE":return this.isSimulation()?this.success(n,i,{simulated:!0,tabs:this.simulationTabs,sessionSummary:this.session.getTabs()},s):this.error(n,i,"NOT_SIMULATION","Simulation tab state is only available in the Node simulation context.",s);default:return this.error(n,i,"UNKNOWN_COMMAND",`Unsupported command '${i}'`,s)}}catch(m){return this.error(n,i,"COMMAND_EXECUTION_FAILED",m.message,s,m.details)}}resolveTarget(e,t){if(!e)throw new Error("Target specifier must be provided");return typeof e=="string"?this.interactionEngine.resolveTarget({selector:e},t):typeof e=="number"?this.interactionEngine.resolveTarget({nodeId:e},t):this.interactionEngine.resolveTarget(e,t)}async performDrag(e,t,s,n){const i=n.defaultView,r=[],o=(p,y,v={})=>{try{const m=(i==null?void 0:i.MouseEvent)||(typeof MouseEvent<"u"?MouseEvent:null);m&&(p.dispatchEvent(new m(y,{bubbles:!0,cancelable:!0,...v})),r.push(y))}catch{}},a=e.getBoundingClientRect(),c=a.x+a.width/2,u=a.y+a.height/2;let h=c+((s==null?void 0:s.x)||0),g=u+((s==null?void 0:s.y)||0);if(t){const p=t.getBoundingClientRect();h=p.x+p.width/2,g=p.y+p.height/2}return o(e,"pointerdown",{button:1,clientX:c,clientY:u}),o(e,"mousedown",{button:1,clientX:c,clientY:u}),o(e,"dragstart",{clientX:c,clientY:u}),t&&(o(t,"dragenter",{clientX:h,clientY:g}),o(t,"dragover",{clientX:h,clientY:g}),o(t,"drop",{clientX:h,clientY:g})),o(e,"dragend",{clientX:h,clientY:g}),o(e,"pointerup",{button:1,clientX:h,clientY:g}),o(e,"mouseup",{button:1,clientX:h,clientY:g}),{success:r.length>0,sourceSelector:k.inspectElement(e,this.nodeRegistry).bestSelector,targetSelector:t?k.inspectElement(t,this.nodeRegistry).bestSelector:"(offset drop)",eventsFired:r,finalPosition:{x:Math.round(h),y:Math.round(g)},html5DndUsed:r.includes("dragstart")}}async waitForCondition(e,t,s,n,i){var p,y;const r=t.kind||"dom_stable",o=Math.min(Math.max(Number(t.timeoutMs)||5e3,100),3e4),a=Math.min(Math.max(Number(t.pollIntervalMs)||100,20),1e3),c=Date.now(),u=()=>{var v,m,d,f,w;switch(r){case"dom_stable":return{satisfied:!0,detail:`dom length ${((v=e.documentElement)==null?void 0:v.outerHTML.length)||0}`};case"selector_present":{const E=t.selector?e.querySelectorAll(t.selector).length:0;return{satisfied:E>0,detail:`"${t.selector}" matches ${E} element(s)`}}case"selector_visible":{if(!t.selector)return{satisfied:!1,detail:"no selector supplied"};const E=e.querySelector(t.selector);if(!E)return{satisfied:!1,detail:`"${t.selector}" not present`};try{const S=k.inspectElement(E).visibility.isVisible;return{satisfied:S,detail:`visibility=${S}`}}catch{return{satisfied:!1,detail:"inspection failed"}}}case"selector_absent":{const E=t.selector?e.querySelectorAll(t.selector).length:0;return{satisfied:E===0,detail:`"${t.selector}" matches ${E} element(s)`}}case"text_present":{const E=((m=e.body)==null?void 0:m.innerText)||((d=e.body)==null?void 0:d.textContent)||"",S=t.text?E.includes(String(t.text)):!1;return{satisfied:S,detail:`text "${String(t.text).slice(0,30)}" ${S?"found":"not found"}`}}case"url_contains":{const E=((w=(f=e.defaultView)==null?void 0:f.location)==null?void 0:w.href)||"";return{satisfied:t.text?E.includes(String(t.text)):!1,detail:E}}case"element_count":{const E=t.selector?e.querySelectorAll(t.selector).length:0,S=Number(t.count)||0;return{satisfied:E===S,detail:`${E}/${S} elements`}}case"readiness_state":return{satisfied:e.readyState===(t.state||"complete"),detail:`readyState=${e.readyState}`};default:return{satisfied:!1,detail:`unknown condition kind "${r}"`}}};if(r==="dom_stable"){let v=((p=e.documentElement)==null?void 0:p.outerHTML.length)||0,m=!1,d=0;for(;Date.now()-c setTimeout(E,a));const w=((y=e.documentElement)==null?void 0:y.outerHTML.length)||0;if(d++,w===v){m=!0;break}v=w}const f=Date.now()-c;return m&&this.session.timeline.record("WAIT_SATISFIED",`dom_stable after ${f}ms (${d} polls)`),this.success(n,i,{satisfied:m,condition:r,waitedMs:f,timeoutMs:o,detail:`dom length ${v}, ${d} polls`},s)}let h=u();for(;!h.satisfied&&Date.now()-c setTimeout(v,a)),h=u();const g=Date.now()-c;return h.satisfied&&this.session.timeline.record("WAIT_SATISFIED",`${r} after ${g}ms`),this.success(n,i,{satisfied:h.satisfied,condition:r,waitedMs:g,timeoutMs:o,detail:h.detail},s)}simulationCloseTab(e,t,s,n,i){const r=Number(e==null?void 0:e.tabId),o=Number.isFinite(r)?this.simulationTabs.findIndex(c=>c.browserTabId===r):this.simulationTabs.findIndex(c=>c.active);if(o<0)return this.error(s,n,"TAB_NOT_FOUND",`No simulated tab matches tabId=${r}`,i);const a=this.simulationTabs.splice(o,1)[0];return this.session.closeTab(a.sessionTabId),a.active&&this.simulationTabs.length&&(this.simulationTabs[0].active=!0,this.session.switchTab(this.simulationTabs[0].sessionTabId)),this.success(s,n,{closed:!0,closedTab:{id:a.browserTabId,url:a.url,title:a.title},simulated:!0,remaining:this.simulationTabs.length},i)}handleSimulationBackgroundCommand(e,t,s,n,i){const r=()=>{var o,a;if(!this.simulationTabs.length){this.simulationTabCounter++;const c={sessionTabId:`stab_${this.simulationTabCounter}`,browserTabId:this.simulationTabCounter,url:((a=(o=n.defaultView)==null?void 0:o.location)==null?void 0:a.href)||"about:blank",title:n.title||"Simulated Tab",active:!0,createdAt:Date.now()};this.simulationTabs.push(c),this.session.registerTab(c.browserTabId,c.url,c.title),this.session.switchTab(c.sessionTabId)}};switch(t){case"LIST_TABS":return r(),this.success(e,t,{simulated:!0,environment:"node-simulation",tabs:this.simulationTabs.map((o,a)=>({id:o.browserTabId,index:a,windowId:1,title:o.title,url:o.url,active:o.active,status:"complete",pinned:!1,audited:!1})),note:"Deterministic simulated tab state — a real browser tab list requires the Chrome extension connection."},i);case"OPEN_TAB":{const o=String((s==null?void 0:s.url)||"about:blank");this.simulationTabCounter++;const a={sessionTabId:`stab_${this.simulationTabCounter}`,browserTabId:this.simulationTabCounter,url:o,title:(s==null?void 0:s.title)||`Simulated Tab ${this.simulationTabCounter}`,active:!0,createdAt:Date.now()};this.simulationTabs.forEach(u=>u.active=!1),this.simulationTabs.push(a);const c=this.session.registerTab(a.browserTabId,o,a.title);return this.session.switchTab(c.sessionTabId),this.session.timeline.record("TAB_OPENED",`simulation tab ${a.browserTabId} → ${o}`),this.success(e,t,{opened:!0,tabId:a.browserTabId,url:o,simulated:!0,totalTabs:this.simulationTabs.length},i)}case"FOCUS_TAB":{r();const o=Number(s==null?void 0:s.tabId),a=this.simulationTabs.find(c=>c.browserTabId===o)||this.simulationTabs[0];return a?(this.simulationTabs.forEach(c=>c.active=!1),a.active=!0,this.session.switchTab(a.sessionTabId),this.session.timeline.record("TAB_SWITCHED",`simulation tab ${a.browserTabId} focused`),this.success(e,t,{focused:!0,tabId:a.browserTabId,url:a.url,simulated:!0},i)):this.error(e,t,"TAB_NOT_FOUND",`No simulated tab with tabId=${o}`,i)}case"LIST_EXTENSIONS":return this.success(e,t,{simulated:!0,extensions:this.simulationExtensions.map(o=>({...o,permissions:["activeTab","scripting","storage","tabs","management"]})),note:"Deterministic simulated extension state."},i);case"SET_EXTENSION_ENABLED":{const o=String((s==null?void 0:s.extensionId)||""),a=this.simulationExtensions.find(c=>c.id===o||c.name.toLowerCase().includes(o.toLowerCase()));return a?(a.enabled=!!(s!=null&&s.enabled),this.session.timeline.record("EXTENSION_STATE_CHANGED",`${a.id} → ${a.enabled?"enabled":"disabled"}`),this.success(e,t,{extensionId:a.id,enabled:a.enabled,simulated:!0},i)):this.error(e,t,"EXTENSION_NOT_FOUND",`No simulated extension matches "${o}". Known: ${this.simulationExtensions.map(c=>c.id).join(", ")}`,i)}case"TOGGLE_EXTENSION":{const o=String((s==null?void 0:s.extensionId)||""),a=this.simulationExtensions.find(c=>c.id===o||c.name.toLowerCase().includes(o.toLowerCase()));return a?(a.enabled=!a.enabled,this.session.timeline.record("EXTENSION_STATE_CHANGED",`${a.id} → ${a.enabled?"enabled":"disabled"}`),this.success(e,t,{extensionId:a.id,enabled:a.enabled,simulated:!0},i)):this.error(e,t,"EXTENSION_NOT_FOUND",`No simulated extension matches "${o}".`,i)}case"RELOAD_EXTENSION":{const o=String((s==null?void 0:s.extensionId)||this.simulationExtensions[0].id),a=this.simulationExtensions.find(c=>c.id===o||c.name.toLowerCase().includes(o.toLowerCase()));return a?this.success(e,t,{reloaded:!0,extensionId:a.id,simulated:!0,note:"Simulated reload: extension state preserved."},i):this.error(e,t,"EXTENSION_NOT_FOUND",`No simulated extension matches "${o}".`,i)}default:return this.error(e,t,"UNKNOWN_COMMAND",`Unhandled simulation command '${t}'`,i)}}async handleScreenshotCapture(e,t,s){var y,v,m,d,f;const n=s.defaultView||(typeof window<"u"?window:{}),i=Date.now(),r=`scr_${i}_${Math.random().toString(36).slice(2,6)}`,o=n.devicePixelRatio||1,a={width:n.innerWidth||((y=s.documentElement)==null?void 0:y.clientWidth)||1920,height:n.innerHeight||((v=s.documentElement)==null?void 0:v.clientHeight)||1080,scrollX:n.scrollX||n.pageXOffset||0,scrollY:n.scrollY||n.pageYOffset||0,devicePixelRatio:o};let c,u,h,g={width:a.width,height:a.height};if(e==="LIVE_ELEMENT_SCREENSHOT"){const w=this.resolveTarget(t,s),E=k.inspectElement(w,this.nodeRegistry);c=E.bestSelector,u=((m=E.forensics)==null?void 0:m.logicalNodeId)||void 0,h={x:E.bounds.x,y:E.bounds.y,width:E.bounds.width,height:E.bounds.height},g={width:Math.max(1,Math.round(E.bounds.width*o)),height:Math.max(1,Math.round(E.bounds.height*o))}}let p=(t==null?void 0:t.dataUrl)||"";if(e==="LIVE_ELEMENT_SCREENSHOT"&&p&&h&&typeof Image<"u")try{const w=await new Promise(E=>{const S=new Image;S.onload=()=>{try{const T=s.createElement("canvas"),x=Math.max(0,Math.floor(h.x*o)),N=Math.max(0,Math.floor(h.y*o)),D=Math.max(1,Math.floor(h.width*o)),M=Math.max(1,Math.floor(h.height*o));T.width=D,T.height=M;const L=T.getContext("2d");if(L){L.drawImage(S,x,N,D,M,0,0,D,M),E(T.toDataURL("image/png"));return}}catch{}E(p)},S.onerror=()=>E(p),S.src=p});w&&(p=w)}catch{}if(!p){const w=e==="LIVE_ELEMENT_SCREENSHOT"?Math.max(120,g.width||320):Math.max(800,a.width||1280),E=e==="LIVE_ELEMENT_SCREENSHOT"?Math.max(60,g.height||180):Math.max(600,a.height||800);p=ge.createDataUrl({width:w,height:E,backgroundColor:e==="LIVE_ELEMENT_SCREENSHOT"?[30,41,59,255]:[15,23,42,255],headerColor:[56,189,248,255],borderColor:[99,102,241,255],label:c||(e==="LIVE_ELEMENT_SCREENSHOT"?"Element Screenshot":"Page Screenshot")})}return{screenshotId:r,timestamp:i,url:((d=n.location)==null?void 0:d.href)||((f=s.location)==null?void 0:f.href)||"",viewport:a,targetSelector:c,targetNodeId:u,targetBounds:h,dataUrl:p,imageFormat:"png",dimensions:g,captureType:e==="LIVE_ELEMENT_SCREENSHOT"?"ELEMENT":"FULL_PAGE"}}success(e,t,s,n){return{id:e,command:t,success:!0,data:s,timestamp:Date.now(),durationMs:Date.now()-n}}error(e,t,s,n,i,r){return{id:e,command:t,success:!1,error:{code:s,message:n,details:r},timestamp:Date.now(),durationMs:Date.now()-i}}}function Lt(l,e){const t=[];let s=l.parentElement,n=1;for(;s&&n<=10;){const h=s.parentElement,g=h?Array.from(h.children).filter(p=>p.tagName===s.tagName):[];t.push({tag:s.tagName.toLowerCase(),selector:U(s),role:s.getAttribute("role")||void 0,text:B(s).slice(0,40),childIndex:g.length?g.indexOf(s)+1:1,siblingCount:h?Array.from(h.children).length:0,distance:n}),s=s.parentElement,n++}const i=l.parentElement,r=[];if(i){const h=Array.from(i.children),g=h.indexOf(l);for(let p=g-1;p>=0&&p>=g-5;p--)r.push({tag:h[p].tagName.toLowerCase(),selector:U(h[p]),role:h[p].getAttribute("role")||void 0,text:B(h[p]).slice(0,30),position:"before",distance:g-p});for(let p=g+1;p {o=Math.max(o,g);for(const p of Array.from(h.children))a.push(p.tagName.toLowerCase()),p.matches('a[href], button, input, select, textarea, [role="button"], [onclick]')&&c.push(U(p)),g<6&&u(p,g+1)};return u(l,1),{selector:U(l),ancestors:t,siblings:r,descendants:{count:l.querySelectorAll("*").length,maxDepth:o,tags:Array.from(new Set(a)).slice(0,30),interactive:c.slice(0,30)}}}function Dt(l,e){const t=[{id:"self",selector:U(l),tag:l.tagName.toLowerCase(),role:l.getAttribute("role")||void 0,label:B(l).slice(0,30)||l.tagName.toLowerCase(),relationship:"self",depth:0}],s=[];let n=l.parentElement,i=1;for(;n&&i<=4;){const o=`ancestor_${i}`;t.push({id:o,selector:U(n),tag:n.tagName.toLowerCase(),role:n.getAttribute("role")||void 0,label:B(n).slice(0,30)||n.tagName.toLowerCase(),relationship:"parent",depth:i}),s.push({from:o,to:i===1?"self":`ancestor_${i-1}`,relation:"parent-of"}),n=n.parentElement,i++}for(const o of Array.from(l.children).slice(0,12)){const a=`child_${t.length}`;t.push({id:a,selector:U(o),tag:o.tagName.toLowerCase(),role:o.getAttribute("role")||void 0,label:B(o).slice(0,30)||o.tagName.toLowerCase(),relationship:"child",depth:1}),s.push({from:"self",to:a,relation:"contains"})}const r=l.parentElement;if(r)for(const o of Array.from(r.children).slice(0,12)){if(o===l)continue;const a=`sibling_${t.length}`;t.push({id:a,selector:U(o),tag:o.tagName.toLowerCase(),role:o.getAttribute("role")||void 0,label:B(o).slice(0,30)||o.tagName.toLowerCase(),relationship:"sibling",depth:1}),s.push({from:"self",to:a,relation:"sibling-of"})}return{rootSelector:U(l),nodes:t,edges:s}}function $t(l){const e={};for(const v of Array.from(l.attributes))v.name.startsWith("aria-")&&(e[v.name]=v.value);const t=B(l).trim(),s=l.getAttribute("aria-label"),n=l.getAttribute("aria-labelledby");let i;n&&(i=n.split(/\s+/).map(m=>{var d,f,w;return(w=(f=(d=l.ownerDocument)==null?void 0:d.getElementById(m))==null?void 0:f.textContent)==null?void 0:w.trim()}).filter(Boolean).join(" ").slice(0,60)||void 0);const r=l.getAttribute("title"),o=l.tagName.toLowerCase(),a=[];let c="";s?(c=s,a.push("aria-label")):i?(c=i,a.push("aria-labelledby")):t?(c=t.slice(0,60),a.push("text content")):r&&(c=r,a.push("title"));const u=[];(l.disabled||l.hasAttribute("disabled"))&&u.push("disabled"),l.checked&&u.push("checked");const h=l;h.tagName==="SELECT"&&typeof h.selectedOptions<"u"&&h.selectedOptions.length>0&&u.push("selected"),l.getAttribute("aria-expanded")&&u.push(`expanded=${l.getAttribute("aria-expanded")}`),l.getAttribute("aria-pressed")&&u.push(`pressed=${l.getAttribute("aria-pressed")}`),l.getAttribute("aria-hidden")==="true"&&u.push("hidden"),l.hasAttribute("required")&&u.push("required"),l.readOnly&&u.push("readonly");const g=["a[href]","button","input","select","textarea","[tabindex]"].some(v=>{try{return l.matches(v)}catch{return!1}}),p=[];!c&&g&&p.push("Focusable element has no accessible name."),o==="img"&&!l.hasAttribute("alt")&&p.push("Image has no alt attribute.");const y=/^h([1-6])$/.exec(o);return y&&!t&&p.push(`Heading h${y[1]} is empty.`),{selector:U(l),role:l.getAttribute("role")||void 0,implicitRole:qt(l),name:c,nameSources:a,description:l.getAttribute("aria-describedby")||void 0,value:l.value!==void 0&&(l.getAttribute("type")||"text")!=="password"?String(l.value).slice(0,40):void 0,states:u,level:y?parseInt(y[1],10):void 0,focusable:g,tabIndex:l.tabIndex,ariaAttributes:e,issues:p}}function qt(l){switch(l.tagName.toLowerCase()){case"a":return l.getAttribute("href")?"link":void 0;case"button":return"button";case"nav":return"navigation";case"header":return"banner";case"footer":return"contentinfo";case"main":return"main";case"aside":return"complementary";case"article":return"article";case"form":return"form";case"input":{const t=l.getAttribute("type")||"text";return{checkbox:"checkbox",radio:"radio",button:"button",submit:"button",reset:"button",range:"slider",search:"searchbox",email:"textbox",text:"textbox",password:"textbox",tel:"textbox",url:"textbox",number:"spinbutton"}[t]||"textbox"}case"select":return l.hasAttribute("multiple")?"listbox":"combobox";case"textarea":return"textbox";case"img":return"img";case"table":return"table";case"ul":case"ol":return"list";case"li":return"listitem";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return"heading";case"dialog":return"dialog";default:return}}function U(l){const e=l.getAttribute("id");if(e&&/^[a-zA-Z][\w-]*$/.test(e))return`#${e}`;const t=l.getAttribute("data-testid");if(t)return`${l.tagName.toLowerCase()}[data-testid="${t}"]`;const s=l.tagName.toLowerCase(),n=Array.from(l.classList||[]).slice(0,2);return n.length?`${s}.${n.join(".")}`:s}function B(l){return Array.from(l.childNodes).filter(e=>e.nodeType===3).map(e=>(e.textContent||"").trim()).join(" ").replace(/\s+/g," ")}function Pt(){return[{label:"desktop-1440x900",width:1440,height:900},{label:"laptop-1024x768",width:1024,height:768},{label:"tablet-768x1024",width:768,height:1024},{label:"mobile-375x667",width:375,height:667}]}class Ut{constructor(e){b(this,"hostElement",null);b(this,"shadowRoot",null);b(this,"callbacks");b(this,"isRecording",!1);b(this,"isPaused",!1);b(this,"isMinimized",!1);b(this,"startTime",0);b(this,"eventCount",0);b(this,"timerInterval",null);b(this,"isDragging",!1);b(this,"dragStartX",0);b(this,"dragStartY",0);b(this,"posX",window.innerWidth-340);b(this,"posY",40);this.callbacks=e,this.loadPosition()}mount(){this.hostElement&&document.body.contains(this.hostElement)||(this.hostElement=document.createElement("div"),this.hostElement.id="forensic-recorder-floating-host",this.hostElement.style.all="initial",this.hostElement.style.position="fixed",this.hostElement.style.zIndex="2147483647",this.hostElement.style.left=`${this.posX}px`,this.hostElement.style.top=`${this.posY}px`,this.shadowRoot=this.hostElement.attachShadow({mode:"open"}),this.render(),this.attachEvents(),(document.body||document.documentElement).appendChild(this.hostElement))}unmount(){this.timerInterval&&(clearInterval(this.timerInterval),this.timerInterval=null),this.hostElement&&this.hostElement.parentNode&&this.hostElement.parentNode.removeChild(this.hostElement),this.hostElement=null,this.shadowRoot=null}hide(){this.hostElement&&(this.hostElement.style.setProperty("display","none","important"),this.hostElement.style.setProperty("visibility","hidden","important"),this.hostElement.style.setProperty("opacity","0","important"))}show(){this.hostElement&&(this.hostElement.style.removeProperty("display"),this.hostElement.style.removeProperty("visibility"),this.hostElement.style.removeProperty("opacity"))}updateState(e,t=!1,s=0,n=0){this.isRecording=e,this.isPaused=t,this.startTime=s||(e?Date.now():0),this.eventCount=n,this.shadowRoot&&(this.render(),this.attachEvents()),this.isRecording&&!this.isPaused?this.startTimer():this.stopTimer()}incrementEventCount(){var t;this.eventCount++;const e=(t=this.shadowRoot)==null?void 0:t.querySelector("#evt-badge");e&&(e.textContent=`${this.eventCount} evts`)}startTimer(){this.stopTimer(),this.timerInterval=setInterval(()=>{var t;const e=(t=this.shadowRoot)==null?void 0:t.querySelector("#timer-display");if(e&&this.startTime){const s=(Date.now()-this.startTime)/1e3,n=Math.floor(s/60).toString().padStart(2,"0"),i=(s%60).toFixed(1).padStart(4,"0");e.textContent=`${n}:${i}`}},200)}stopTimer(){this.timerInterval&&(clearInterval(this.timerInterval),this.timerInterval=null)}savePosition(){try{sessionStorage.setItem("forensic_overlay_pos",JSON.stringify({x:this.posX,y:this.posY,min:this.isMinimized}))}catch{}}loadPosition(){try{const e=sessionStorage.getItem("forensic_overlay_pos");if(e){const t=JSON.parse(e);this.posX=Math.max(10,Math.min(window.innerWidth-300,t.x||this.posX)),this.posY=Math.max(10,Math.min(window.innerHeight-150,t.y||this.posY)),this.isMinimized=!!t.min}}catch{}}render(){if(!this.shadowRoot)return;const e=` :host { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; font-size: 12px; @@ -288,4 +288,4 @@ ${t} e.toTimestamp||typeof e.targetNodeId=="number"&&h.targetNodeId!==e.targetNodeId)),typeof e.offset=="number"&&(m=m.slice(e.offset)),typeof e.limit=="number"&&(m=m.slice(0,e.limit))),c(m)},u.onerror=()=>t(u.error)})}async getEventCount(s){const e=await this.openDB();return new Promise((r,c)=>{const a=e.transaction("events","readonly").objectStore("events").index("sessionId").count(IDBKeyRange.only(s));a.onsuccess=()=>r(a.result),a.onerror=()=>c(a.error)})}async saveCheckpoint(s){const e=await this.openDB();return new Promise((r,c)=>{const t=e.transaction("checkpoints","readwrite");t.objectStore("checkpoints").put(s),t.oncomplete=()=>r(),t.onerror=()=>c(t.error)})}async getCheckpoints(s){const e=await this.openDB();return new Promise((r,c)=>{const o=e.transaction("checkpoints","readonly").objectStore("checkpoints").index("sessionId").getAll(IDBKeyRange.only(s));o.onsuccess=()=>{const a=o.result||[];a.sort((u,m)=>u.sequence-m.sequence),r(a)},o.onerror=()=>c(o.error)})}async saveInitialSnapshot(s,e){const r=await this.openDB();return new Promise((c,t)=>{const n=r.transaction("snapshots","readwrite");n.objectStore("snapshots").put({sessionId:s,snapshot:e}),n.oncomplete=()=>c(),n.onerror=()=>t(n.error)})}async getInitialSnapshot(s){const e=await this.openDB();return new Promise((r,c)=>{const n=e.transaction("snapshots","readonly").objectStore("snapshots").get(s);n.onsuccess=()=>r(n.result?n.result.snapshot:null),n.onerror=()=>c(n.error)})}async addAnnotation(s){const e=await this.openDB();return new Promise((r,c)=>{const t=e.transaction("annotations","readwrite");t.objectStore("annotations").put(s),t.oncomplete=()=>r(),t.onerror=()=>c(t.error)})}async getAnnotations(s){const e=await this.openDB();return new Promise((r,c)=>{const o=e.transaction("annotations","readonly").objectStore("annotations").index("sessionId").getAll(IDBKeyRange.only(s));o.onsuccess=()=>r(o.result||[]),o.onerror=()=>c(o.error)})}}const l=new E("ForensicExtensionDB");let d=null,S=null;const w=new Map,g=new Map;async function A(){return new Promise(i=>{try{chrome.tabs.query({active:!0,currentWindow:!0},s=>{if(chrome.runtime.lastError||!s||s.length===0)return i(null);i(s[0].id??null)})}catch{i(null)}})}try{(_=(T=chrome.debugger)==null?void 0:T.onEvent)==null||_.addListener((i,s,e)=>{try{for(const[r,c]of g.entries())if((i==null?void 0:i.tabId)===c||(i==null?void 0:i.targetId)===`tab_${c}`){d==null||d.send(JSON.stringify({type:"CDP_EVENT",sessionId:r,method:s,params:e,timestamp:Date.now()}));return}}catch{}})}catch{}async function O(i,s){if(i==="LIST_TABS")return new Promise((e,r)=>{chrome.tabs.query({},c=>{if(chrome.runtime.lastError)return r(new Error(chrome.runtime.lastError.message));const t=(c||[]).map(n=>({id:n.id,index:n.index,windowId:n.windowId,title:n.title||"Untitled",url:n.url||"",active:!!n.active,status:n.status,pinned:!!n.pinned,favIconUrl:n.favIconUrl,audited:n.id?w.has(n.id):!1,incognito:!!n.incognito,width:n.width,height:n.height}));e({totalTabs:t.length,tabs:t})})});if(i==="FOCUS_TAB"){const e=Number(s==null?void 0:s.tabId);if(!e)throw new Error("tabId is required for focus_tab");return new Promise((r,c)=>{chrome.tabs.update(e,{active:!0},t=>{var n;if(chrome.runtime.lastError||!t)return c(new Error(((n=chrome.runtime.lastError)==null?void 0:n.message)||`Tab ${e} not found`));t.windowId?chrome.windows.update(t.windowId,{focused:!0},()=>{r({focused:!0,tab:{id:t.id,windowId:t.windowId,title:t.title,url:t.url,active:t.active}})}):r({focused:!0,tab:{id:t.id,title:t.title,url:t.url,active:t.active}})})})}if(i==="RELOAD_TAB"){const e=!!(s!=null&&s.bypassCache),r=s!=null&&s.tabId?Number(s.tabId):void 0;return new Promise((c,t)=>{const n=o=>{chrome.tabs.reload(o,{bypassCache:e},()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message));chrome.tabs.get(o,a=>{c({reloaded:!0,tabId:o,bypassCache:e,url:a==null?void 0:a.url,title:a==null?void 0:a.title})})})};r?chrome.tabs.get(r,o=>{chrome.runtime.lastError||!o?chrome.tabs.query({active:!0,lastFocusedWindow:!0},a=>{const u=a&&a[0]?a[0]:null;u!=null&&u.id?n(u.id):t(new Error("No active tab found to reload"))}):n(r)}):chrome.tabs.query({active:!0,lastFocusedWindow:!0},o=>{const a=o&&o[0]?o[0]:null;if(!(a!=null&&a.id))return t(new Error("No active tab found to reload"));n(a.id)})})}if(i==="CLOSE_TAB"){const e=s!=null&&s.tabId?Number(s.tabId):void 0,r=s!=null&&s.url?String(s.url).toLowerCase():void 0;return new Promise((c,t)=>{const n=o=>{chrome.tabs.remove(o,()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message));c({closed:!0,tabIds:o,count:o.length})})};e?n([e]):r?chrome.tabs.query({},o=>{const u=(o||[]).filter(m=>{var h,f;return((h=m.url)==null?void 0:h.toLowerCase().includes(r))||((f=m.title)==null?void 0:f.toLowerCase().includes(r))}).map(m=>m.id).filter(Boolean);if(u.length===0)return c({closed:!1,message:`No open tab matched '${r}'`});n(u)}):chrome.tabs.query({active:!0,lastFocusedWindow:!0},o=>{const a=o&&o[0]?o[0]:null;if(!(a!=null&&a.id))return t(new Error("No active tab found to close"));n([a.id])})})}if(i==="OPEN_TAB"){const e=s==null?void 0:s.url;if(!e)throw new Error("url is required for open_tab");let r=String(e).trim();!r.startsWith("http://")&&!r.startsWith("https://")&&!r.startsWith("file://")&&!r.startsWith("chrome://")&&!r.startsWith("about:")&&(r.includes("meet.google.com")||r.includes("localhost")||r.includes(".com")||r.includes(".org")||r.includes(".net")||r.includes(".ir")||r.includes(".io")||r.includes(".app"))&&(r="https://"+r);const c=s.active!==!1,t=!!s.pinned;return new Promise((n,o)=>{chrome.tabs.create({url:r,active:c,pinned:t},a=>{if(chrome.runtime.lastError)return o(new Error(chrome.runtime.lastError.message));n({opened:!0,tabId:a.id,windowId:a.windowId,url:a.url||r,title:a.title||"New Tab",active:a.active,status:a.status})})})}if(i==="LIST_EXTENSIONS")return new Promise((e,r)=>{var c;if(!((c=chrome.management)!=null&&c.getAll))return r(new Error("chrome.management API not available"));chrome.management.getAll(t=>{if(chrome.runtime.lastError)return r(new Error(chrome.runtime.lastError.message));const n=(t||[]).map(o=>({id:o.id,name:o.name,version:o.version,description:o.description,enabled:o.enabled,installType:o.installType,isApp:o.isApp,homepageUrl:o.homepageUrl,permissions:o.permissions}));e({totalExtensions:n.length,extensions:n})})});if(i==="SET_EXTENSION_ENABLED"){const e=s==null?void 0:s.extensionId,r=!!(s!=null&&s.enabled);if(!e)throw new Error("extensionId is required for SET_EXTENSION_ENABLED");return new Promise((c,t)=>{var n;if(!((n=chrome.management)!=null&&n.setEnabled))return t(new Error("chrome.management API not available"));chrome.management.setEnabled(e,r,()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message||`Failed to set enabled state for ${e}`));c({success:!0,extensionId:e,enabled:r,message:`Extension ${e} successfully ${r?"enabled":"disabled"}.`})})})}if(i==="TOGGLE_EXTENSION"){const e=s==null?void 0:s.extensionId;if(!e)throw new Error("extensionId is required for TOGGLE_EXTENSION");return new Promise((r,c)=>{var t,n;if(!((t=chrome.management)!=null&&t.get)||!((n=chrome.management)!=null&&n.setEnabled))return c(new Error("chrome.management API not available"));chrome.management.get(e,o=>{var u;if(chrome.runtime.lastError||!o)return c(new Error(((u=chrome.runtime.lastError)==null?void 0:u.message)||`Extension ${e} not found`));const a=!o.enabled;chrome.management.setEnabled(e,a,()=>{if(chrome.runtime.lastError)return c(new Error(chrome.runtime.lastError.message||`Failed to toggle ${e}`));r({success:!0,extensionId:e,enabled:a,name:o.name,message:`Extension ${o.name} (${e}) toggled to ${a?"enabled":"disabled"}.`})})})})}if(i==="RESIZE_VIEWPORT"){const e=Math.max(200,Math.min(7680,Number(s==null?void 0:s.width)||1280)),r=Math.max(200,Math.min(4320,Number(s==null?void 0:s.height)||800));return new Promise((c,t)=>{chrome.windows.getCurrent({populate:!1},n=>{var o;if(chrome.runtime.lastError||!n)return t(new Error(((o=chrome.runtime.lastError)==null?void 0:o.message)||"No current window"));chrome.windows.update(n.id??chrome.windows.WINDOW_ID_CURRENT,{width:e,height:r,state:"normal"},a=>{var u;if(chrome.runtime.lastError||!a)return t(new Error(((u=chrome.runtime.lastError)==null?void 0:u.message)||"Window resize failed"));c({success:!0,applied:{width:a.width,height:a.height},previous:{width:n.width,height:n.height},original:{width:n.width,height:n.height},reversible:!0,mode:"browser-window",note:"Reset with reset_viewport — the content script tracks the original size."})})})})}if(i==="RESET_VIEWPORT")return new Promise((e,r)=>{chrome.windows.getCurrent({populate:!1},c=>{var t;if(chrome.runtime.lastError||!c)return r(new Error(((t=chrome.runtime.lastError)==null?void 0:t.message)||"No current window"));chrome.windows.update(c.id??chrome.windows.WINDOW_ID_CURRENT,{state:"maximized"},n=>{var o;if(chrome.runtime.lastError||!n)return r(new Error(((o=chrome.runtime.lastError)==null?void 0:o.message)||"Window restore failed"));e({success:!0,applied:{width:n.width,height:n.height},previous:{width:c.width,height:c.height},original:{width:n.width,height:n.height},reversible:!1,mode:"browser-window",note:"Window restored to maximized state."})})})});if(i==="RELOAD_EXTENSION"){const e=s==null?void 0:s.extensionId,r=chrome.runtime.id;return!e||e===r?(setTimeout(()=>chrome.runtime.reload(),150),{reloaded:!0,extensionId:r,isSelf:!0,message:"Forensic Recorder extension is reloading now."}):new Promise((c,t)=>{var n;if(!((n=chrome.management)!=null&&n.setEnabled))return t(new Error("chrome.management API not available"));chrome.management.setEnabled(e,!1,()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message||`Failed to disable ${e}`));setTimeout(()=>{chrome.management.setEnabled(e,!0,()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message||`Failed to re-enable ${e}`));c({reloaded:!0,extensionId:e,isSelf:!1,message:`Extension ${e} successfully reloaded.`})})},150)})})}if(i==="CDP_ATTACH"){const e=(s==null?void 0:s.tabId)!==void 0?Number(s.tabId):await A();if(e===null)throw new Error("No target tab available for CDP attach.");return new Promise((r,c)=>{var t;if(!((t=chrome.debugger)!=null&&t.attach))return c(new Error('CDP_UNAVAILABLE: chrome.debugger API not available (check the "debugger" permission).'));chrome.debugger.attach({tabId:e},"1.3",()=>{if(chrome.runtime.lastError)return c(new Error(`CDP_ATTACH failed: ${chrome.runtime.lastError.message}`));s!=null&&s.sessionId&&g.set(String(s.sessionId),e),chrome.debugger.getTargets(n=>{const o=(n||[]).find(a=>a.tabId===e)||{};r({attached:!0,sessionId:s==null?void 0:s.sessionId,tabId:e,targetId:o.id||`tab_${e}`,type:o.type||"page"})})})})}if(i==="CDP_COMMAND"){const{sessionId:e,method:r,params:c}=s||{};if(!r)throw new Error("CDP_COMMAND requires method");return new Promise((t,n)=>{var a;if(!((a=chrome.debugger)!=null&&a.sendCommand))return n(new Error('CDP_UNAVAILABLE: chrome.debugger API not available (check the "debugger" permission).'));const o=g.get(e);if(o===void 0)return n(new Error(`CDP_SESSION_NOT_FOUND: no tab bound to session '${e}' — attach first.`));chrome.debugger.sendCommand({tabId:o},r,c||{},u=>{if(chrome.runtime.lastError){t({__cdpError:!0,code:"CDP_PROTOCOL_ERROR",message:chrome.runtime.lastError.message,method:r});return}t({result:u??{}})})})}if(i==="CDP_DETACH"){const{sessionId:e}=s||{},r=g.get(e);return g.delete(e),r===void 0?{detached:!1,reason:"session not found"}:new Promise((c,t)=>{var n;if(!((n=chrome.debugger)!=null&&n.detach))return c({detached:!1,reason:"chrome.debugger unavailable"});chrome.debugger.detach({tabId:r},()=>{if(chrome.runtime.lastError)return c({detached:!1,reason:chrome.runtime.lastError.message});c({detached:!0,sessionId:e,tabId:r})})})}throw new Error(`Unsupported background command: ${i}`)}function I(){if(!(typeof WebSocket>"u"))try{const i=new WebSocket("ws://127.0.0.1:3847");let s=null;i.onopen=()=>{var e;d=i,console.log("[Forensic Extension] Connected to MCP Bridge on ws://127.0.0.1:3847"),S&&(clearInterval(S),S=null),i.send(JSON.stringify({type:"REGISTER_CLIENT",clientType:"SERVICE_WORKER",url:typeof chrome<"u"&&((e=chrome.runtime)!=null&&e.id)?`chrome-extension://${chrome.runtime.id}`:"service-worker",title:"Forensic Service Worker"})),s&&clearInterval(s),s=setInterval(()=>{if(i&&i.readyState===WebSocket.OPEN)try{i.send(JSON.stringify({type:"HEARTBEAT",timestamp:Date.now()}))}catch(r){console.warn("[TeleDOM SW] non-critical operation failed:",(r==null?void 0:r.message)??r)}},15e3)},i.onclose=()=>{s&&clearInterval(s),d=null,N()},i.onerror=()=>{s&&clearInterval(s),d=null,N()},i.onmessage=async e=>{try{const r=JSON.parse(e.data.toString());if(r.type==="BROWSER_COMMAND_REQUEST"){const{id:c,command:t,payload:n}=r;if(typeof chrome>"u"||!chrome.tabs){i.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"NO_CHROME_TABS_API",message:"chrome.tabs API not available in this context"}}));return}if(["LIST_TABS","FOCUS_TAB","RELOAD_TAB","CLOSE_TAB","OPEN_TAB","LIST_EXTENSIONS","RELOAD_EXTENSION","SET_EXTENSION_ENABLED","TOGGLE_EXTENSION","CDP_ATTACH","CDP_COMMAND","CDP_DETACH"].includes(t)){try{const u=await O(t,n);i.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!0,data:u}))}catch(u){i.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"COMMAND_ERROR",message:u.message}}))}return}const o=n!=null&&n.tabId?Number(n.tabId):void 0,a=u=>{if(t==="LIVE_PAGE_SCREENSHOT"||t==="LIVE_ELEMENT_SCREENSHOT"){chrome.tabs.sendMessage(u,{type:"HIDE_FORENSIC_OVERLAYS"},()=>{setTimeout(()=>{chrome.tabs.captureVisibleTab({format:"png"},m=>{var h;if(chrome.tabs.sendMessage(u,{type:"RESTORE_FORENSIC_OVERLAYS"}),chrome.runtime.lastError||!m){i.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"SCREENSHOT_FAILED",message:((h=chrome.runtime.lastError)==null?void 0:h.message)||"captureVisibleTab failed"}}));return}chrome.tabs.sendMessage(u,{type:"BROWSER_COMMAND_REQUEST",id:c,command:t,payload:{...n,dataUrl:m}},f=>{const C=f||{id:c,command:t,success:!0,data:{dataUrl:m,captureType:t==="LIVE_ELEMENT_SCREENSHOT"?"ELEMENT":"FULL_PAGE"}};i.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",...C}))})})},150)});return}chrome.tabs.sendMessage(u,r,m=>{if(chrome.runtime.lastError){i.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"CONTENT_SCRIPT_UNREACHABLE",message:chrome.runtime.lastError.message||`Content script unreachable on tab ${u}`}}));return}i.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",...m||{id:c,command:t,success:!0}}))})};o?a(o):chrome.tabs.query({active:!0,lastFocusedWindow:!0},async u=>{const m=u&&u[0]?u[0]:null,h=m==null?void 0:m.id;if(!h){i.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"NO_ACTIVE_TAB",message:"No active browser tab found"}}));return}a(h)})}}catch(r){console.error("[ServiceWorker] Bridge message handling error:",r)}}}catch{d=null,N()}}function N(){S||(S=setInterval(()=>{(!d||d.readyState!==WebSocket.OPEN)&&I()},5e3))}I(),typeof chrome<"u"&&((p=chrome.webNavigation)!=null&&p.onCommitted)&&chrome.webNavigation.onCommitted.addListener(async i=>{var t;if(i.frameId!==0)return;const s=i.tabId,e=w.get(s);if(!e||!e.isRecording)return;let r="NAV_OTHER";i.transitionType==="reload"?r="NAV_RELOAD":(t=i.transitionQualifiers)!=null&&t.includes("forward_back")?r="NAV_FORWARD_BACK":i.transitionType==="link"&&(r="NAV_LINK");const c={id:`nav_${Date.now()}_${Math.random().toString(36).slice(2,6)}`,sessionId:e.sessionId,timestamp:Date.now()-e.startTime,sequence:999999,wallClockTime:Date.now(),type:r,category:"NAVIGATION",source:"USER_INTERACTION",payload:{url:i.url,transitionType:i.transitionType,transitionQualifiers:i.transitionQualifiers,tabId:i.tabId}};try{await l.appendEvents(e.sessionId,[c]),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify({type:"FORENSIC_EVENTS_CHUNK",sessionId:e.sessionId,events:[c]}))}catch{}}),typeof chrome<"u"&&((R=chrome.runtime)!=null&&R.onMessage)&&chrome.runtime.onMessage.addListener((i,s,e)=>((async()=>{var r,c,t;try{const n=((r=s.tab)==null?void 0:r.id)??i.tabId;if(i.type==="FORENSIC_SESSION_START")n&&w.set(n,{sessionId:i.metadata.id,sessionName:i.metadata.name,startTime:i.metadata.startTime,initialUrl:i.metadata.url,isRecording:!0}),await l.saveSession(i.metadata),i.initialSnapshot&&await l.saveInitialSnapshot(i.metadata.id,i.initialSnapshot),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(i)),e({success:!0,sessionId:i.metadata.id});else if(i.type==="GET_TAB_RECORDING_STATE"){const o=n?w.get(n):null;e({isRecording:!!(o!=null&&o.isRecording),recording:o||null})}else if(i.type==="FORENSIC_EVENTS_CHUNK")await l.appendEvents(i.sessionId,i.events),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(i)),e({success:!0});else if(i.type==="FORENSIC_CHECKPOINT")await l.saveCheckpoint(i.checkpoint),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(i)),e({success:!0});else if(i.type==="FORENSIC_SESSION_STOP"){n&&w.delete(n);const o=await l.getSession(i.sessionId);o&&(o.status="stopped",o.endTime=Date.now(),(c=i.metadata)!=null&&c.durationMs&&(o.durationMs=i.metadata.durationMs),await l.saveSession(o)),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(i)),e({success:!0})}else if(i.type==="OPEN_DASHBOARD_TAB"){const o=chrome.runtime.getURL(`dist/src/ui/index.html${i.sessionId?`?session=${i.sessionId}`:""}`);chrome.tabs.create({url:o}),e({success:!0,url:o})}else if(i.type==="CAPTURE_SCREENSHOT"){if((t=chrome.tabs)!=null&&t.captureVisibleTab){chrome.tabs.captureVisibleTab({format:"png"},o=>{e({success:!!o,dataUrl:o})});return}e({success:!1,error:"Screenshot capture unsupported"})}else if(i.type==="ELEMENT_SELECTED")d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(i)),e({success:!0});else if(i.type==="BROWSER_COMMAND_REQUEST")try{const o=await O(i.command,i.payload);e({id:i.id,command:i.command,success:!0,data:o})}catch(o){e({id:i.id,command:i.command,success:!1,error:{code:"COMMAND_ERROR",message:o.message}})}}catch(n){e({success:!1,error:n.message})}})(),!0)),I()})(); +var v=Object.defineProperty;var P=(E,h,d)=>h in E?v(E,h,{enumerable:!0,configurable:!0,writable:!0,value:d}):E[h]=d;var I=(E,h,d)=>P(E,typeof h!="symbol"?h+"":h,d);(function(){"use strict";var T,_,p,A;class E{constructor(s="ForensicRecorderDB"){I(this,"dbName");I(this,"dbVersion",1);I(this,"db",null);this.dbName=s}async openDB(){if(this.db)return this.db;if(typeof indexedDB>"u")throw new Error("IndexedDB is not available in current runtime environment");return new Promise((s,e)=>{const n=indexedDB.open(this.dbName,this.dbVersion);n.onupgradeneeded=c=>{const t=c.target.result;if(t.objectStoreNames.contains("sessions")||t.createObjectStore("sessions",{keyPath:"id"}),!t.objectStoreNames.contains("events")){const r=t.createObjectStore("events",{keyPath:"id"});r.createIndex("sessionId","sessionId",{unique:!1}),r.createIndex("sequence","sequence",{unique:!1})}t.objectStoreNames.contains("checkpoints")||t.createObjectStore("checkpoints",{keyPath:"checkpointId"}).createIndex("sessionId","sessionId",{unique:!1}),t.objectStoreNames.contains("snapshots")||t.createObjectStore("snapshots",{keyPath:"sessionId"}),t.objectStoreNames.contains("annotations")||t.createObjectStore("annotations",{keyPath:"id"}).createIndex("sessionId","sessionId",{unique:!1})},n.onsuccess=()=>{this.db=n.result,s(this.db)},n.onerror=()=>e(n.error)})}async saveSession(s){const e=await this.openDB();return new Promise((n,c)=>{const t=e.transaction("sessions","readwrite");t.objectStore("sessions").put(s),t.oncomplete=()=>n(),t.onerror=()=>c(t.error)})}async getSession(s){const e=await this.openDB();return new Promise((n,c)=>{const i=e.transaction("sessions","readonly").objectStore("sessions").get(s);i.onsuccess=()=>n(i.result||null),i.onerror=()=>c(i.error)})}async listSessions(){const s=await this.openDB();return new Promise((e,n)=>{const r=s.transaction("sessions","readonly").objectStore("sessions").getAll();r.onsuccess=()=>{const i=r.result||[];i.sort((a,u)=>u.startTime-a.startTime),e(i)},r.onerror=()=>n(r.error)})}async deleteSession(s){const e=await this.openDB();return new Promise((n,c)=>{const t=e.transaction(["sessions","events","checkpoints","snapshots","annotations"],"readwrite");t.objectStore("sessions").delete(s),t.objectStore("snapshots").delete(s);const a=t.objectStore("events").index("sessionId").openCursor(IDBKeyRange.only(s));a.onsuccess=()=>{const u=a.result;u&&(u.delete(),u.continue())},t.oncomplete=()=>n(!0),t.onerror=()=>c(t.error)})}async appendEvents(s,e){if(e.length===0)return;const n=await this.openDB();return new Promise((c,t)=>{const r=n.transaction("events","readwrite"),i=r.objectStore("events");for(const a of e)i.put(a);r.oncomplete=()=>c(),r.onerror=()=>t(r.error)})}async getEvents(s,e){const n=await this.openDB();return new Promise((c,t)=>{const u=n.transaction("events","readonly").objectStore("events").index("sessionId").getAll(IDBKeyRange.only(s));u.onsuccess=()=>{let m=u.result||[];m.sort((l,f)=>l.sequence-f.sequence),e&&(m=m.filter(l=>!(e.category&&l.category!==e.category||e.type&&l.type!==e.type||typeof e.fromTimestamp=="number"&&l.timestamp e.toTimestamp||typeof e.targetNodeId=="number"&&l.targetNodeId!==e.targetNodeId)),typeof e.offset=="number"&&(m=m.slice(e.offset)),typeof e.limit=="number"&&(m=m.slice(0,e.limit))),c(m)},u.onerror=()=>t(u.error)})}async getEventCount(s){const e=await this.openDB();return new Promise((n,c)=>{const a=e.transaction("events","readonly").objectStore("events").index("sessionId").count(IDBKeyRange.only(s));a.onsuccess=()=>n(a.result),a.onerror=()=>c(a.error)})}async saveCheckpoint(s){const e=await this.openDB();return new Promise((n,c)=>{const t=e.transaction("checkpoints","readwrite");t.objectStore("checkpoints").put(s),t.oncomplete=()=>n(),t.onerror=()=>c(t.error)})}async getCheckpoints(s){const e=await this.openDB();return new Promise((n,c)=>{const i=e.transaction("checkpoints","readonly").objectStore("checkpoints").index("sessionId").getAll(IDBKeyRange.only(s));i.onsuccess=()=>{const a=i.result||[];a.sort((u,m)=>u.sequence-m.sequence),n(a)},i.onerror=()=>c(i.error)})}async saveInitialSnapshot(s,e){const n=await this.openDB();return new Promise((c,t)=>{const r=n.transaction("snapshots","readwrite");r.objectStore("snapshots").put({sessionId:s,snapshot:e}),r.oncomplete=()=>c(),r.onerror=()=>t(r.error)})}async getInitialSnapshot(s){const e=await this.openDB();return new Promise((n,c)=>{const r=e.transaction("snapshots","readonly").objectStore("snapshots").get(s);r.onsuccess=()=>n(r.result?r.result.snapshot:null),r.onerror=()=>c(r.error)})}async addAnnotation(s){const e=await this.openDB();return new Promise((n,c)=>{const t=e.transaction("annotations","readwrite");t.objectStore("annotations").put(s),t.oncomplete=()=>n(),t.onerror=()=>c(t.error)})}async getAnnotations(s){const e=await this.openDB();return new Promise((n,c)=>{const i=e.transaction("annotations","readonly").objectStore("annotations").index("sessionId").getAll(IDBKeyRange.only(s));i.onsuccess=()=>n(i.result||[]),i.onerror=()=>c(i.error)})}}const h=new E("ForensicExtensionDB");let d=null,S=null;const w=new Map,g=new Map;async function R(){return new Promise(o=>{try{chrome.tabs.query({active:!0,currentWindow:!0},s=>{if(chrome.runtime.lastError||!s||s.length===0)return o(null);o(s[0].id??null)})}catch{o(null)}})}try{(_=(T=chrome.debugger)==null?void 0:T.onEvent)==null||_.addListener((o,s,e)=>{try{for(const[n,c]of g.entries())if((o==null?void 0:o.tabId)===c||(o==null?void 0:o.targetId)===`tab_${c}`){d==null||d.send(JSON.stringify({type:"CDP_EVENT",sessionId:n,method:s,params:e,timestamp:Date.now()}));return}}catch{}})}catch{}async function O(o,s){if(o==="LIST_TABS")return new Promise((e,n)=>{chrome.tabs.query({},c=>{if(chrome.runtime.lastError)return n(new Error(chrome.runtime.lastError.message));const t=(c||[]).map(r=>({id:r.id,index:r.index,windowId:r.windowId,title:r.title||"Untitled",url:r.url||"",active:!!r.active,status:r.status,pinned:!!r.pinned,favIconUrl:r.favIconUrl,audited:r.id?w.has(r.id):!1,incognito:!!r.incognito,width:r.width,height:r.height}));e({totalTabs:t.length,tabs:t})})});if(o==="FOCUS_TAB"){const e=Number(s==null?void 0:s.tabId);if(!e)throw new Error("tabId is required for focus_tab");return new Promise((n,c)=>{chrome.tabs.update(e,{active:!0},t=>{var r;if(chrome.runtime.lastError||!t)return c(new Error(((r=chrome.runtime.lastError)==null?void 0:r.message)||`Tab ${e} not found`));t.windowId?chrome.windows.update(t.windowId,{focused:!0},()=>{n({focused:!0,tab:{id:t.id,windowId:t.windowId,title:t.title,url:t.url,active:t.active}})}):n({focused:!0,tab:{id:t.id,title:t.title,url:t.url,active:t.active}})})})}if(o==="RELOAD_TAB"){const e=!!(s!=null&&s.bypassCache),n=s!=null&&s.tabId?Number(s.tabId):void 0;return new Promise((c,t)=>{const r=i=>{chrome.tabs.reload(i,{bypassCache:e},()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message));chrome.tabs.get(i,a=>{c({reloaded:!0,tabId:i,bypassCache:e,url:a==null?void 0:a.url,title:a==null?void 0:a.title})})})};n?chrome.tabs.get(n,i=>{chrome.runtime.lastError||!i?chrome.tabs.query({active:!0,lastFocusedWindow:!0},a=>{const u=a&&a[0]?a[0]:null;u!=null&&u.id?r(u.id):t(new Error("No active tab found to reload"))}):r(n)}):chrome.tabs.query({active:!0,lastFocusedWindow:!0},i=>{const a=i&&i[0]?i[0]:null;if(!(a!=null&&a.id))return t(new Error("No active tab found to reload"));r(a.id)})})}if(o==="CLOSE_TAB"){const e=s!=null&&s.tabId?Number(s.tabId):void 0,n=s!=null&&s.url?String(s.url).toLowerCase():void 0;return new Promise((c,t)=>{const r=i=>{chrome.tabs.remove(i,()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message));c({closed:!0,tabIds:i,count:i.length})})};e?r([e]):n?chrome.tabs.query({},i=>{const u=(i||[]).filter(m=>{var l,f;return((l=m.url)==null?void 0:l.toLowerCase().includes(n))||((f=m.title)==null?void 0:f.toLowerCase().includes(n))}).map(m=>m.id).filter(Boolean);if(u.length===0)return c({closed:!1,message:`No open tab matched '${n}'`});r(u)}):chrome.tabs.query({active:!0,lastFocusedWindow:!0},i=>{const a=i&&i[0]?i[0]:null;if(!(a!=null&&a.id))return t(new Error("No active tab found to close"));r([a.id])})})}if(o==="OPEN_TAB"){const e=s==null?void 0:s.url;if(!e)throw new Error("url is required for open_tab");let n=String(e).trim();!n.startsWith("http://")&&!n.startsWith("https://")&&!n.startsWith("file://")&&!n.startsWith("chrome://")&&!n.startsWith("about:")&&(n.includes("meet.google.com")||n.includes("localhost")||n.includes(".com")||n.includes(".org")||n.includes(".net")||n.includes(".ir")||n.includes(".io")||n.includes(".app"))&&(n="https://"+n);const c=s.active!==!1,t=!!s.pinned;return new Promise((r,i)=>{chrome.tabs.create({url:n,active:c,pinned:t},a=>{if(chrome.runtime.lastError)return i(new Error(chrome.runtime.lastError.message));r({opened:!0,tabId:a.id,windowId:a.windowId,url:a.url||n,title:a.title||"New Tab",active:a.active,status:a.status})})})}if(o==="LIST_EXTENSIONS")return new Promise((e,n)=>{var c;if(!((c=chrome.management)!=null&&c.getAll))return n(new Error("chrome.management API not available"));chrome.management.getAll(t=>{if(chrome.runtime.lastError)return n(new Error(chrome.runtime.lastError.message));const r=(t||[]).map(i=>({id:i.id,name:i.name,version:i.version,description:i.description,enabled:i.enabled,installType:i.installType,isApp:i.isApp,homepageUrl:i.homepageUrl,permissions:i.permissions}));e({totalExtensions:r.length,extensions:r})})});if(o==="SET_EXTENSION_ENABLED"){const e=s==null?void 0:s.extensionId,n=!!(s!=null&&s.enabled);if(!e)throw new Error("extensionId is required for SET_EXTENSION_ENABLED");return new Promise((c,t)=>{var r;if(!((r=chrome.management)!=null&&r.setEnabled))return t(new Error("chrome.management API not available"));chrome.management.setEnabled(e,n,()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message||`Failed to set enabled state for ${e}`));c({success:!0,extensionId:e,enabled:n,message:`Extension ${e} successfully ${n?"enabled":"disabled"}.`})})})}if(o==="TOGGLE_EXTENSION"){const e=s==null?void 0:s.extensionId;if(!e)throw new Error("extensionId is required for TOGGLE_EXTENSION");return new Promise((n,c)=>{var t,r;if(!((t=chrome.management)!=null&&t.get)||!((r=chrome.management)!=null&&r.setEnabled))return c(new Error("chrome.management API not available"));chrome.management.get(e,i=>{var u;if(chrome.runtime.lastError||!i)return c(new Error(((u=chrome.runtime.lastError)==null?void 0:u.message)||`Extension ${e} not found`));const a=!i.enabled;chrome.management.setEnabled(e,a,()=>{if(chrome.runtime.lastError)return c(new Error(chrome.runtime.lastError.message||`Failed to toggle ${e}`));n({success:!0,extensionId:e,enabled:a,name:i.name,message:`Extension ${i.name} (${e}) toggled to ${a?"enabled":"disabled"}.`})})})})}if(o==="RESIZE_VIEWPORT"){const e=Math.max(200,Math.min(7680,Number(s==null?void 0:s.width)||1280)),n=Math.max(200,Math.min(4320,Number(s==null?void 0:s.height)||800));return new Promise((c,t)=>{chrome.windows.getCurrent({populate:!1},r=>{var i;if(chrome.runtime.lastError||!r)return t(new Error(((i=chrome.runtime.lastError)==null?void 0:i.message)||"No current window"));chrome.windows.update(r.id??chrome.windows.WINDOW_ID_CURRENT,{width:e,height:n,state:"normal"},a=>{var u;if(chrome.runtime.lastError||!a)return t(new Error(((u=chrome.runtime.lastError)==null?void 0:u.message)||"Window resize failed"));c({success:!0,applied:{width:a.width,height:a.height},previous:{width:r.width,height:r.height},original:{width:r.width,height:r.height},reversible:!0,mode:"browser-window",note:"Reset with reset_viewport — the content script tracks the original size."})})})})}if(o==="RESET_VIEWPORT")return new Promise((e,n)=>{chrome.windows.getCurrent({populate:!1},c=>{var t;if(chrome.runtime.lastError||!c)return n(new Error(((t=chrome.runtime.lastError)==null?void 0:t.message)||"No current window"));chrome.windows.update(c.id??chrome.windows.WINDOW_ID_CURRENT,{state:"maximized"},r=>{var i;if(chrome.runtime.lastError||!r)return n(new Error(((i=chrome.runtime.lastError)==null?void 0:i.message)||"Window restore failed"));e({success:!0,applied:{width:r.width,height:r.height},previous:{width:c.width,height:c.height},original:{width:r.width,height:r.height},reversible:!1,mode:"browser-window",note:"Window restored to maximized state."})})})});if(o==="RELOAD_EXTENSION"){const e=s==null?void 0:s.extensionId,n=chrome.runtime.id;return!e||e===n?(setTimeout(()=>chrome.runtime.reload(),150),{reloaded:!0,extensionId:n,isSelf:!0,message:"Forensic Recorder extension is reloading now."}):new Promise((c,t)=>{var r;if(!((r=chrome.management)!=null&&r.setEnabled))return t(new Error("chrome.management API not available"));chrome.management.setEnabled(e,!1,()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message||`Failed to disable ${e}`));setTimeout(()=>{chrome.management.setEnabled(e,!0,()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message||`Failed to re-enable ${e}`));c({reloaded:!0,extensionId:e,isSelf:!1,message:`Extension ${e} successfully reloaded.`})})},150)})})}if(o==="CDP_ATTACH"){const e=(s==null?void 0:s.tabId)!==void 0?Number(s.tabId):await R();if(e===null)throw new Error("No target tab available for CDP attach.");return new Promise((n,c)=>{var t;if(!((t=chrome.debugger)!=null&&t.attach))return c(new Error('CDP_UNAVAILABLE: chrome.debugger API not available (check the "debugger" permission).'));chrome.debugger.attach({tabId:e},"1.3",()=>{if(chrome.runtime.lastError){const r=chrome.runtime.lastError.message||"";return r.includes("Another debugger is already attached")?c(new Error(`CDP_ATTACH failed: Chrome DevTools (F12) is already open on tab ${e}. Please close the F12 panel on that tab so TeleDOM can attach.`)):c(new Error(`CDP_ATTACH failed: ${r}`))}s!=null&&s.sessionId&&g.set(String(s.sessionId),e),chrome.debugger.getTargets(r=>{const i=(r||[]).find(a=>a.tabId===e)||{};n({attached:!0,sessionId:s==null?void 0:s.sessionId,tabId:e,targetId:i.id||`tab_${e}`,type:i.type||"page"})})})})}if(o==="CDP_COMMAND"){const{sessionId:e,method:n,params:c}=s||{};if(!n)throw new Error("CDP_COMMAND requires method");return new Promise((t,r)=>{var a;if(!((a=chrome.debugger)!=null&&a.sendCommand))return r(new Error('CDP_UNAVAILABLE: chrome.debugger API not available (check the "debugger" permission).'));const i=g.get(e);if(i===void 0)return r(new Error(`CDP_SESSION_NOT_FOUND: no tab bound to session '${e}' — attach first.`));chrome.debugger.sendCommand({tabId:i},n,c||{},u=>{if(chrome.runtime.lastError){t({__cdpError:!0,code:"CDP_PROTOCOL_ERROR",message:chrome.runtime.lastError.message,method:n});return}t({result:u??{}})})})}if(o==="CDP_DETACH"){const{sessionId:e}=s||{},n=g.get(e);return g.delete(e),n===void 0?{detached:!1,reason:"session not found"}:new Promise((c,t)=>{var r;if(!((r=chrome.debugger)!=null&&r.detach))return c({detached:!1,reason:"chrome.debugger unavailable"});chrome.debugger.detach({tabId:n},()=>{if(chrome.runtime.lastError)return c({detached:!1,reason:chrome.runtime.lastError.message});c({detached:!0,sessionId:e,tabId:n})})})}throw new Error(`Unsupported background command: ${o}`)}function b(){if(!(typeof WebSocket>"u"))try{const o=new WebSocket("ws://127.0.0.1:3847");let s=null;o.onopen=()=>{var e;d=o,console.log("[Forensic Extension] Connected to MCP Bridge on ws://127.0.0.1:3847"),S&&(clearInterval(S),S=null),o.send(JSON.stringify({type:"REGISTER_CLIENT",clientType:"SERVICE_WORKER",url:typeof chrome<"u"&&((e=chrome.runtime)!=null&&e.id)?`chrome-extension://${chrome.runtime.id}`:"service-worker",title:"Forensic Service Worker"})),s&&clearInterval(s),s=setInterval(()=>{if(o&&o.readyState===WebSocket.OPEN)try{o.send(JSON.stringify({type:"HEARTBEAT",timestamp:Date.now()}))}catch(n){console.warn("[TeleDOM SW] non-critical operation failed:",(n==null?void 0:n.message)??n)}},15e3)},o.onclose=()=>{s&&clearInterval(s),d=null,N()},o.onerror=()=>{s&&clearInterval(s),d=null,N()},o.onmessage=async e=>{try{const n=JSON.parse(e.data.toString());if(n.type==="BROWSER_COMMAND_REQUEST"){const{id:c,command:t,payload:r}=n;if(typeof chrome>"u"||!chrome.tabs){o.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"NO_CHROME_TABS_API",message:"chrome.tabs API not available in this context"}}));return}if(["LIST_TABS","FOCUS_TAB","RELOAD_TAB","CLOSE_TAB","OPEN_TAB","LIST_EXTENSIONS","RELOAD_EXTENSION","SET_EXTENSION_ENABLED","TOGGLE_EXTENSION","CDP_ATTACH","CDP_COMMAND","CDP_DETACH"].includes(t)){try{const u=await O(t,r);o.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!0,data:u}))}catch(u){o.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"COMMAND_ERROR",message:u.message}}))}return}const i=r!=null&&r.tabId?Number(r.tabId):void 0,a=u=>{if(t==="LIVE_PAGE_SCREENSHOT"||t==="LIVE_ELEMENT_SCREENSHOT"){chrome.tabs.sendMessage(u,{type:"HIDE_FORENSIC_OVERLAYS"},()=>{setTimeout(()=>{chrome.tabs.captureVisibleTab({format:"png"},m=>{var l;if(chrome.tabs.sendMessage(u,{type:"RESTORE_FORENSIC_OVERLAYS"}),chrome.runtime.lastError||!m){o.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"SCREENSHOT_FAILED",message:((l=chrome.runtime.lastError)==null?void 0:l.message)||"captureVisibleTab failed"}}));return}chrome.tabs.sendMessage(u,{type:"BROWSER_COMMAND_REQUEST",id:c,command:t,payload:{...r,dataUrl:m}},f=>{const C=f||{id:c,command:t,success:!0,data:{dataUrl:m,captureType:t==="LIVE_ELEMENT_SCREENSHOT"?"ELEMENT":"FULL_PAGE"}};o.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",...C}))})})},150)});return}chrome.tabs.sendMessage(u,n,m=>{if(chrome.runtime.lastError){o.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"CONTENT_SCRIPT_UNREACHABLE",message:chrome.runtime.lastError.message||`Content script unreachable on tab ${u}`}}));return}o.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",...m||{id:c,command:t,success:!0}}))})};i?a(i):chrome.tabs.query({active:!0,lastFocusedWindow:!0},async u=>{const m=u&&u[0]?u[0]:null,l=m==null?void 0:m.id;if(!l){o.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"NO_ACTIVE_TAB",message:"No active browser tab found"}}));return}a(l)})}}catch(n){console.error("[ServiceWorker] Bridge message handling error:",n)}}}catch{d=null,N()}}function N(){S||(S=setInterval(()=>{(!d||d.readyState!==WebSocket.OPEN)&&b()},5e3))}if(typeof chrome<"u"&&chrome.alarms)try{chrome.alarms.create("teledom_bridge_keepalive",{periodInMinutes:.4}),chrome.alarms.onAlarm.addListener(o=>{if(o.name==="teledom_bridge_keepalive")if(!d||d.readyState!==WebSocket.OPEN)b();else try{d.send(JSON.stringify({type:"HEARTBEAT",timestamp:Date.now()}))}catch{b()}})}catch(o){console.warn("[ServiceWorker] Alarms keepalive setup failed:",o==null?void 0:o.message)}b(),typeof chrome<"u"&&((p=chrome.webNavigation)!=null&&p.onCommitted)&&chrome.webNavigation.onCommitted.addListener(async o=>{var t;if(o.frameId!==0)return;const s=o.tabId,e=w.get(s);if(!e||!e.isRecording)return;let n="NAV_OTHER";o.transitionType==="reload"?n="NAV_RELOAD":(t=o.transitionQualifiers)!=null&&t.includes("forward_back")?n="NAV_FORWARD_BACK":o.transitionType==="link"&&(n="NAV_LINK");const c={id:`nav_${Date.now()}_${Math.random().toString(36).slice(2,6)}`,sessionId:e.sessionId,timestamp:Date.now()-e.startTime,sequence:999999,wallClockTime:Date.now(),type:n,category:"NAVIGATION",source:"USER_INTERACTION",payload:{url:o.url,transitionType:o.transitionType,transitionQualifiers:o.transitionQualifiers,tabId:o.tabId}};try{await h.appendEvents(e.sessionId,[c]),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify({type:"FORENSIC_EVENTS_CHUNK",sessionId:e.sessionId,events:[c]}))}catch{}}),typeof chrome<"u"&&((A=chrome.runtime)!=null&&A.onMessage)&&chrome.runtime.onMessage.addListener((o,s,e)=>((async()=>{var n,c,t;try{const r=((n=s.tab)==null?void 0:n.id)??o.tabId;if(o.type==="FORENSIC_SESSION_START")r&&w.set(r,{sessionId:o.metadata.id,sessionName:o.metadata.name,startTime:o.metadata.startTime,initialUrl:o.metadata.url,isRecording:!0}),await h.saveSession(o.metadata),o.initialSnapshot&&await h.saveInitialSnapshot(o.metadata.id,o.initialSnapshot),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(o)),e({success:!0,sessionId:o.metadata.id});else if(o.type==="GET_TAB_RECORDING_STATE"){const i=r?w.get(r):null;e({isRecording:!!(i!=null&&i.isRecording),recording:i||null})}else if(o.type==="FORENSIC_EVENTS_CHUNK")await h.appendEvents(o.sessionId,o.events),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(o)),e({success:!0});else if(o.type==="FORENSIC_CHECKPOINT")await h.saveCheckpoint(o.checkpoint),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(o)),e({success:!0});else if(o.type==="FORENSIC_SESSION_STOP"){r&&w.delete(r);const i=await h.getSession(o.sessionId);i&&(i.status="stopped",i.endTime=Date.now(),(c=o.metadata)!=null&&c.durationMs&&(i.durationMs=o.metadata.durationMs),await h.saveSession(i)),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(o)),e({success:!0})}else if(o.type==="OPEN_DASHBOARD_TAB"){const i=chrome.runtime.getURL(`dist/src/ui/index.html${o.sessionId?`?session=${o.sessionId}`:""}`);chrome.tabs.create({url:i}),e({success:!0,url:i})}else if(o.type==="CAPTURE_SCREENSHOT"){if((t=chrome.tabs)!=null&&t.captureVisibleTab){chrome.tabs.captureVisibleTab({format:"png"},i=>{e({success:!!i,dataUrl:i})});return}e({success:!1,error:"Screenshot capture unsupported"})}else if(o.type==="ELEMENT_SELECTED")d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(o)),e({success:!0});else if(o.type==="BROWSER_COMMAND_REQUEST")try{const i=await O(o.command,o.payload);e({id:o.id,command:o.command,success:!0,data:i})}catch(i){e({id:o.id,command:o.command,success:!1,error:{code:"COMMAND_ERROR",message:i.message}})}}catch(r){e({success:!1,error:r.message})}})(),!0)),b()})(); diff --git a/chrome-extension/dist/server/bridge-server.js b/chrome-extension/dist/server/bridge-server.js index a5935064..67ebe9f7 100644 --- a/chrome-extension/dist/server/bridge-server.js +++ b/chrome-extension/dist/server/bridge-server.js @@ -123,41 +123,49 @@ class FileStorageProvider { async saveSession(metadata) { const dir = this.getSessionDir(metadata.id); const metaPath = path.join(dir, "metadata.json"); - fs.writeFileSync(metaPath, JSON.stringify(metadata, null, 2), "utf-8"); + await fs.promises.writeFile(metaPath, JSON.stringify(metadata, null, 2), "utf-8"); } async getSession(sessionId) { const dir = path.join(this.baseDir, sessionId); const metaPath = path.join(dir, "metadata.json"); - if (!fs.existsSync(metaPath)) return null; try { - const data = fs.readFileSync(metaPath, "utf-8"); + const data = await fs.promises.readFile(metaPath, "utf-8"); return JSON.parse(data); - } catch { + } catch (err) { + if (err?.code !== "ENOENT") { + console.warn(`[FileStorage] Warning: Failed to read session ${sessionId}: ${err?.message}`); + } return null; } } async listSessions() { if (!fs.existsSync(this.baseDir)) return []; - const entries = fs.readdirSync(this.baseDir, { withFileTypes: true }); - const sessions = []; - for (const entry of entries) { - if (entry.isDirectory()) { - const metaPath = path.join(this.baseDir, entry.name, "metadata.json"); - if (fs.existsSync(metaPath)) { + try { + const entries = await fs.promises.readdir(this.baseDir, { withFileTypes: true }); + const sessions = []; + for (const entry of entries) { + if (entry.isDirectory()) { + const metaPath = path.join(this.baseDir, entry.name, "metadata.json"); try { - const data = fs.readFileSync(metaPath, "utf-8"); + const data = await fs.promises.readFile(metaPath, "utf-8"); sessions.push(JSON.parse(data)); - } catch { + } catch (err) { + if (err?.code !== "ENOENT") { + console.warn(`[FileStorage] Warning: Corrupt or unreadable session metadata at ${metaPath}: ${err?.message}`); + } } } } + return sessions.sort((a, b) => b.startTime - a.startTime); + } catch (err) { + console.error(`[FileStorage] Failed to list sessions from ${this.baseDir}:`, err?.message); + return []; } - return sessions.sort((a, b) => b.startTime - a.startTime); } async deleteSession(sessionId) { const dir = path.join(this.baseDir, sessionId); if (fs.existsSync(dir)) { - fs.rmSync(dir, { recursive: true, force: true }); + await fs.promises.rm(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 50 }); return true; } return false; @@ -167,7 +175,7 @@ class FileStorageProvider { const dir = this.getSessionDir(sessionId); const eventsPath = path.join(dir, "events.jsonl"); const lines = events.map((e) => JSON.stringify(e)).join("\n") + "\n"; - fs.appendFileSync(eventsPath, lines, "utf-8"); + await fs.promises.appendFile(eventsPath, lines, "utf-8"); } async getEvents(sessionId, filter) { const dir = path.join(this.baseDir, sessionId); @@ -182,42 +190,46 @@ class FileStorageProvider { let matchedCount = 0; const offset = typeof filter?.offset === "number" ? filter.offset : 0; const limit = typeof filter?.limit === "number" ? filter.limit : Infinity; - for await (const line of rl) { - const trimmed = line.trim(); - if (!trimmed) continue; - let e; - try { - e = JSON.parse(trimmed); - } catch { - continue; - } - if (filter) { - if (filter.category && e.category !== filter.category) continue; - if (filter.type && e.type !== filter.type) continue; - if (typeof filter.fromTimestamp === "number" && e.timestamp < filter.fromTimestamp) continue; - if (typeof filter.toTimestamp === "number" && e.timestamp > filter.toTimestamp) continue; - if (typeof filter.fromSequence === "number" && e.sequence < filter.fromSequence) continue; - if (typeof filter.toSequence === "number" && e.sequence > filter.toSequence) continue; - if (typeof filter.targetNodeId === "number" && e.targetNodeId !== filter.targetNodeId) continue; - if (filter.targetSelector && e.targetSelector && !e.targetSelector.includes(filter.targetSelector)) continue; - if (filter.searchQuery) { - const query = filter.searchQuery.toLowerCase(); - const strPayload = JSON.stringify(e.payload || {}).toLowerCase(); - if (!strPayload.includes(query) && !e.type.toLowerCase().includes(query)) { - continue; + try { + for await (const line of rl) { + const trimmed = line.trim(); + if (!trimmed) continue; + let e; + try { + e = JSON.parse(trimmed); + } catch (parseErr) { + console.warn(`[FileStorage] Skipping malformed event line in session ${sessionId}:`, parseErr); + continue; + } + if (filter) { + if (filter.category && e.category !== filter.category) continue; + if (filter.type && e.type !== filter.type) continue; + if (typeof filter.fromTimestamp === "number" && e.timestamp < filter.fromTimestamp) continue; + if (typeof filter.toTimestamp === "number" && e.timestamp > filter.toTimestamp) continue; + if (typeof filter.fromSequence === "number" && e.sequence < filter.fromSequence) continue; + if (typeof filter.toSequence === "number" && e.sequence > filter.toSequence) continue; + if (typeof filter.targetNodeId === "number" && e.targetNodeId !== filter.targetNodeId) continue; + if (filter.targetSelector && e.targetSelector && !e.targetSelector.includes(filter.targetSelector)) continue; + if (filter.searchQuery) { + const query = filter.searchQuery.toLowerCase(); + const strPayload = JSON.stringify(e.payload || {}).toLowerCase(); + if (!strPayload.includes(query) && !e.type.toLowerCase().includes(query)) { + continue; + } } } + matchedCount++; + if (matchedCount <= offset) { + continue; + } + results.push(e); + if (results.length >= limit) { + break; + } } - matchedCount++; - if (matchedCount <= offset) { - continue; - } - results.push(e); - if (results.length >= limit) { - rl.close(); - fileStream.destroy(); - break; - } + } finally { + rl.close(); + fileStream.destroy(); } return results; } @@ -231,44 +243,59 @@ class FileStorageProvider { crlfDelay: Infinity }); let count = 0; - for await (const line of rl) { - if (line.trim()) count++; + try { + for await (const line of rl) { + if (line.trim()) count++; + } + } finally { + rl.close(); + fileStream.destroy(); } return count; } async saveCheckpoint(checkpoint) { const dir = this.getSessionDir(checkpoint.sessionId); const chkDir = path.join(dir, "checkpoints"); - if (!fs.existsSync(chkDir)) fs.mkdirSync(chkDir, { recursive: true }); + await fs.promises.mkdir(chkDir, { recursive: true }); const file = path.join(chkDir, `${checkpoint.checkpointId}.json`); - fs.writeFileSync(file, JSON.stringify(checkpoint, null, 2), "utf-8"); + await fs.promises.writeFile(file, JSON.stringify(checkpoint, null, 2), "utf-8"); } async getCheckpoints(sessionId) { const dir = path.join(this.baseDir, sessionId, "checkpoints"); - if (!fs.existsSync(dir)) return []; - const files = fs.readdirSync(dir).filter((f) => f.endsWith(".json")); - const checkpoints = []; - for (const f of files) { - try { - const data = fs.readFileSync(path.join(dir, f), "utf-8"); - checkpoints.push(JSON.parse(data)); - } catch { + try { + const files = (await fs.promises.readdir(dir)).filter((f) => f.endsWith(".json")); + const checkpoints = []; + for (const f of files) { + try { + const data = await fs.promises.readFile(path.join(dir, f), "utf-8"); + checkpoints.push(JSON.parse(data)); + } catch (err) { + console.warn(`[FileStorage] Failed to read/parse checkpoint file ${f} in session ${sessionId}:`, err); + } } + return checkpoints.sort((a, b) => a.sequence - b.sequence); + } catch (err) { + if (err?.code !== "ENOENT") { + console.warn(`[FileStorage] Error accessing checkpoints directory for session ${sessionId}:`, err); + } + return []; } - return checkpoints.sort((a, b) => a.sequence - b.sequence); } async saveInitialSnapshot(sessionId, snapshot) { const dir = this.getSessionDir(sessionId); const file = path.join(dir, "initial_snapshot.json"); - fs.writeFileSync(file, JSON.stringify(snapshot, null, 2), "utf-8"); + await fs.promises.writeFile(file, JSON.stringify(snapshot, null, 2), "utf-8"); } async getInitialSnapshot(sessionId) { const dir = path.join(this.baseDir, sessionId); const file = path.join(dir, "initial_snapshot.json"); - if (!fs.existsSync(file)) return null; try { - return JSON.parse(fs.readFileSync(file, "utf-8")); - } catch { + const content = await fs.promises.readFile(file, "utf-8"); + return JSON.parse(content); + } catch (err) { + if (err?.code !== "ENOENT") { + console.warn(`[FileStorage] Error reading initial snapshot for session ${sessionId}:`, err); + } return null; } } @@ -276,23 +303,28 @@ class FileStorageProvider { const dir = this.getSessionDir(annotation.sessionId); const annPath = path.join(dir, "annotations.json"); let list = []; - if (fs.existsSync(annPath)) { - try { - list = JSON.parse(fs.readFileSync(annPath, "utf-8")); - } catch { - list = []; + try { + const content = await fs.promises.readFile(annPath, "utf-8"); + list = JSON.parse(content); + } catch (err) { + if (err?.code !== "ENOENT") { + console.warn(`[FileStorage] Corrupted annotations file for session ${annotation.sessionId}, starting fresh:`, err); } + list = []; } list.push(annotation); - fs.writeFileSync(annPath, JSON.stringify(list, null, 2), "utf-8"); + await fs.promises.writeFile(annPath, JSON.stringify(list, null, 2), "utf-8"); } async getAnnotations(sessionId) { const dir = path.join(this.baseDir, sessionId); const annPath = path.join(dir, "annotations.json"); - if (!fs.existsSync(annPath)) return []; try { - return JSON.parse(fs.readFileSync(annPath, "utf-8")); - } catch { + const content = await fs.promises.readFile(annPath, "utf-8"); + return JSON.parse(content); + } catch (err) { + if (err?.code !== "ENOENT") { + console.warn(`[FileStorage] Failed to read annotations for session ${sessionId}:`, err); + } return []; } } @@ -8997,7 +9029,18 @@ class LiveToolsHandler { } ] }; - } catch { + } catch (saveErr) { + return { + content: [ + { + type: "text", + text: JSON.stringify({ + ...finalSummary, + fileSaveError: `Failed to write pipeline output to ${args.outputPath}: ${saveErr?.message || saveErr}` + }, null, 2) + } + ] + }; } } return { @@ -9403,7 +9446,8 @@ class ProjectManager { try { const manifest = JSON.parse(fs__default.readFileSync(manifestPath, "utf-8")); out.push({ ...manifest, projectDir: path__default.join(this.baseDir, entry.name), pageCount: manifest.pages?.length || 0 }); - } catch { + } catch (err) { + console.warn(`[ProjectManager] Warning: Skipped corrupt project manifest at ${manifestPath}:`, err); } } return out.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0)); @@ -9664,7 +9708,8 @@ class ProjectManager { if (fs__default.existsSync(p)) { try { out.push(JSON.parse(fs__default.readFileSync(p, "utf-8"))); - } catch { + } catch (err) { + console.warn(`[ProjectManager] Warning: Skipped corrupt region file ${p}:`, err); } } } @@ -10026,7 +10071,8 @@ class CommandRecordingStorage { try { const raw = JSON.parse(fs__default.readFileSync(file, "utf-8")); return raw.recording || raw; - } catch { + } catch (err) { + console.warn(`[RecordingStorage] Warning: Failed to parse recording file ${file}:`, err); return null; } } @@ -10054,7 +10100,8 @@ class CommandRecordingStorage { tags: rec.tags || [], file: path__default.join(this.baseDir, entry.name) }); - } catch { + } catch (err) { + console.warn(`[RecordingStorage] Warning: Skipped corrupt recording file ${entry.name}:`, err); } } return out.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0)); @@ -10471,6 +10518,111 @@ function buildToolCatalog() { } return catalog; } +const TELEDOM_PROFILE_TOOLS = { + // Minimal profile: strictly essential browser actions (~22 tools, ~2.5k tokens) + minimal: [ + "td_browser_navigate", + "td_browser_back", + "td_browser_forward", + "td_browser_refresh", + "td_dom_inspect", + "td_dom_query", + "td_dom_extract", + "td_dom_snapshot", + "td_target_find", + "td_target_check", + "td_action_click", + "td_action_type", + "td_action_select", + "td_action_press", + "td_action_scroll", + "td_wait", + "td_screenshot", + "td_execute_script", + "list_tabs", + "focus_tab", + "close_tab", + "open_tab" + ], + // Core profile: browser primitives + workflow runtime + target memory (~44 tools, ~4.8k tokens) + core: [ + "td_browser_navigate", + "td_browser_back", + "td_browser_forward", + "td_browser_refresh", + "td_dom_inspect", + "td_dom_query", + "td_dom_extract", + "td_dom_snapshot", + "td_target_find", + "td_target_check", + "td_target_describe", + "td_action_click", + "td_action_type", + "td_action_select", + "td_action_hover", + "td_action_press", + "td_action_scroll", + "td_wait", + "td_screenshot", + "td_execute_script", + "td_network_inspect", + "td_console_read", + "td_workflow_save", + "td_workflow_get", + "td_workflow_list", + "td_workflow_update", + "td_workflow_delete", + "td_workflow_validate", + "td_workflow_run", + "td_workflow_runs", + "td_workflow_replay", + "td_target_memory_save", + "td_target_memory_get", + "td_target_memory_list", + "td_target_memory_delete", + "list_tabs", + "focus_tab", + "reload_tab", + "close_tab", + "open_tab", + "inspect_live_page", + "inspect_live_element" + ], + // Forensics profile: historical forensics + diffs + causality + live inspection (~50 tools) + forensics: [ + "list_sessions", + "get_session", + "export_session", + "import_session", + "delete_session", + "get_timeline", + "get_events", + "get_events_around", + "get_dom_state", + "get_dom_node", + "get_dom_subtree", + "diff_dom", + "trace_element", + "find_disappearing_elements", + "why_did_element_disappear", + "get_diagnostics", + "get_network_events", + "get_screenshots", + "td_browser_navigate", + "td_dom_inspect", + "td_dom_query", + "td_dom_extract", + "td_screenshot", + "td_action_click", + "td_action_type", + "td_workflow_run", + "list_tabs", + "focus_tab" + ], + // Full profile: all 350 tools (null means no filtering) + full: null +}; const MCPDOM_V3_TOOLS = [ // ================================================================== // Targeting & forensics @@ -18593,7 +18745,8 @@ class ForensicsToolsHandler { try { const res = await unifiedRuntime.bridgeCommand("LIVE_DOM_SNAPSHOT", { format: "json" }); return { snapshot: res }; - } catch { + } catch (err) { + console.warn(`[ForensicsHandler] Could not capture live snapshot: ${err?.message || err}`); return { snapshot: null }; } } @@ -18602,7 +18755,8 @@ async function runInPageSafe(code, tabId) { try { const { runInPage: runInPage2 } = await Promise.resolve().then(() => interactionCore); return await runInPage2(code, tabId); - } catch { + } catch (err) { + console.warn(`[ForensicsHandler] runInPageSafe failed for tab ${tabId}: ${err?.message || err}`); return null; } } @@ -22506,14 +22660,20 @@ class AgentStore { readJson(file) { try { return JSON.parse(fs.readFileSync(file, "utf-8")); - } catch { + } catch (err) { + if (err?.code !== "ENOENT") { + console.warn(`[WorkflowStore] Warning: Failed to read or parse ${file}:`, err?.message || err); + } return null; } } listJsonNames(dir) { try { return fs.readdirSync(dir).filter((f) => f.endsWith(".json")).sort(); - } catch { + } catch (err) { + if (err?.code !== "ENOENT") { + console.warn(`[WorkflowStore] Warning: Failed to list directory ${dir}:`, err?.message || err); + } return []; } } @@ -25415,12 +25575,14 @@ class MCPBridgeServer { if (targets.length === 0) { for (const [sock, meta] of this.socketMetadata.entries()) { if (meta.clientType === "CONTENT_SCRIPT" && sock.readyState === WebSocket.OPEN) { - targets.push(sock); + targets = [sock]; + break; } } } - if (targets.length === 0) { - targets = Array.from(this.activeSockets); + if (targets.length === 0 && this.activeSockets.size > 0) { + const first = Array.from(this.activeSockets).find((s) => s.readyState === WebSocket.OPEN); + if (first) targets = [first]; } let sentCount = 0; for (const ws of targets) { @@ -25443,17 +25605,53 @@ class MCPBridgeServer { } start() { return new Promise((resolve, reject) => { + const isTrustedOrigin = (origin) => { + if (!origin) return true; + if (origin.startsWith("chrome-extension://")) return true; + if (/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(origin)) return true; + return false; + }; this.httpServer = http.createServer(async (req, res) => { - res.setHeader("Access-Control-Allow-Origin", "*"); + const origin = req.headers.origin; + if (origin) { + if (isTrustedOrigin(origin)) { + res.setHeader("Access-Control-Allow-Origin", origin); + res.setHeader("Access-Control-Allow-Credentials", "true"); + res.setHeader("Vary", "Origin"); + } else if (req.method === "OPTIONS") { + res.writeHead(403, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ error: "CORS Forbidden: Untrusted cross-origin request rejected" })); + return; + } + } res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); - res.setHeader("Access-Control-Allow-Headers", "Content-Type"); + res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, x-teledom-token"); if (req.method === "OPTIONS") { res.writeHead(204); res.end(); return; } const url = req.url || ""; - if (url === "/health" && req.method === "GET") { + const isAuthValid = () => { + if (!isTrustedOrigin(origin)) return false; + const expectedToken = process.env.TELEDOM_BRIDGE_TOKEN; + if (!expectedToken) return true; + const authHeader = req.headers.authorization; + const tokenHeader = req.headers["x-teledom-token"]; + let queryToken = null; + try { + const parsed = new URL(url, "http://127.0.0.1"); + queryToken = parsed.searchParams.get("token"); + } catch { + } + if (authHeader && authHeader.startsWith("Bearer ")) { + return authHeader.slice(7).trim() === expectedToken; + } + if (tokenHeader && tokenHeader === expectedToken) return true; + if (queryToken && queryToken === expectedToken) return true; + return false; + }; + if (url.startsWith("/health") && req.method === "GET") { res.writeHead(200, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -25465,6 +25663,13 @@ class MCPBridgeServer { ); return; } + if (["/api/mcp/tool", "/api/tabs/close", "/api/sessions/upload"].some((p) => url.startsWith(p))) { + if (!isAuthValid()) { + res.writeHead(403, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ error: "Forbidden: Invalid or missing authorization credentials" })); + return; + } + } const MAX_PAYLOAD_BYTES = 50 * 1024 * 1024; if (url === "/api/sessions/upload" && req.method === "POST") { let body = ""; @@ -25583,7 +25788,13 @@ class MCPBridgeServer { } }, 3e4); this.healthSweepInterval?.unref?.(); - this.wss.on("connection", (ws) => { + this.wss.on("connection", (ws, req) => { + const origin = req?.headers?.origin; + if (origin && !isTrustedOrigin(origin)) { + console.error(`[MCP Bridge] WebSocket connection rejected from untrusted origin: ${origin}`); + ws.close(4403, "Forbidden origin"); + return; + } this.activeSockets.add(ws); console.error(`[MCP Bridge] Client connected. Total active clients: ${this.activeSockets.size}`); ws.on("close", () => { @@ -25711,8 +25922,10 @@ export { FORENSICS_TOOLS as F, MCPDOM_V3_TOOLS as M, MCPBridgeServer, + PNGBuilder as P, TELEDOM_INTELLIGENCE_TOOLS as T, TELEDOM_VERSION as a, FileStorageProvider as b, - MCPToolsHandler as c + MCPToolsHandler as c, + TELEDOM_PROFILE_TOOLS as d }; diff --git a/chrome-extension/dist/server/mcp-server.js b/chrome-extension/dist/server/mcp-server.js index bf9f2d9e..4f33d5fa 100644 --- a/chrome-extension/dist/server/mcp-server.js +++ b/chrome-extension/dist/server/mcp-server.js @@ -1,6 +1,7 @@ import * as readline from "readline"; import * as fs from "fs"; -import { M as MCPDOM_V3_TOOLS, D as DEVTOOLS_TOOLS, F as FORENSICS_TOOLS, T as TELEDOM_INTELLIGENCE_TOOLS, a as TELEDOM_VERSION, b as FileStorageProvider, c as MCPToolsHandler, MCPBridgeServer } from "./bridge-server.js"; +import { M as MCPDOM_V3_TOOLS, D as DEVTOOLS_TOOLS, F as FORENSICS_TOOLS, T as TELEDOM_INTELLIGENCE_TOOLS, a as TELEDOM_VERSION, b as FileStorageProvider, c as MCPToolsHandler, MCPBridgeServer, d as TELEDOM_PROFILE_TOOLS } from "./bridge-server.js"; +import { P } from "./bridge-server.js"; import "http"; import "ws"; import "path"; @@ -872,9 +873,15 @@ class ForensicMCPServer { const disableDevTools = process.env.FORENSIC_DISABLE_DEVTOOLS === "true"; const disableForensics = process.env.FORENSIC_DISABLE_FORENSICS === "true"; const disableIntelligence = process.env.FORENSIC_DISABLE_INTELLIGENCE === "true"; - const tools = FORENSIC_MCP_TOOLS.filter( + const profile = (process.env.TELEDOM_PROFILE || "full").toLowerCase(); + const profileAllowed = TELEDOM_PROFILE_TOOLS[profile]; + let tools = FORENSIC_MCP_TOOLS.filter( (t) => !(disableDevTools && t.name.startsWith("dt_")) && !(disableForensics && t.name.startsWith("fx_")) && !(disableIntelligence && t.name.startsWith("td_")) ); + if (profileAllowed && Array.isArray(profileAllowed)) { + const allowedSet = new Set(profileAllowed); + tools = tools.filter((t) => allowedSet.has(t.name)); + } return { jsonrpc: "2.0", id, @@ -1077,5 +1084,7 @@ export { FORENSIC_MCP_TOOLS, FileStorageProvider, ForensicMCPServer, - MCPToolsHandler + MCPToolsHandler, + P as PNGBuilder, + TELEDOM_PROFILE_TOOLS }; diff --git a/chrome-extension/dist/src/extension/devtools/devtools.html b/chrome-extension/dist/src/extension/devtools/devtools.html index e5ead51c..ec623abe 100644 --- a/chrome-extension/dist/src/extension/devtools/devtools.html +++ b/chrome-extension/dist/src/extension/devtools/devtools.html @@ -1,10 +1,10 @@ - - - - + + + + - - - - + + + + diff --git a/chrome-extension/dist/src/extension/popup/popup.html b/chrome-extension/dist/src/extension/popup/popup.html index 9f991f9c..6b4f597e 100644 --- a/chrome-extension/dist/src/extension/popup/popup.html +++ b/chrome-extension/dist/src/extension/popup/popup.html @@ -1,54 +1,54 @@ - - - - - Forensic Recorder + + + + +Forensic Recorder - - --- - + + +- - -- -- READY -Forensic Recorder
----- - - -Target: Current Active Tab
-- 0 Events - 0.0s --- - -- -
- - -++ + diff --git a/chrome-extension/dist/src/ui/index.html b/chrome-extension/dist/src/ui/index.html index e82ee8a9..0412e036 100644 --- a/chrome-extension/dist/src/ui/index.html +++ b/chrome-extension/dist/src/ui/index.html @@ -1,243 +1,243 @@ - - - - - -+ + ++ ++ READY +Forensic Recorder
+++++ + + +Target: Current Active Tab
++ 0 Events + 0.0s +++ + ++ +
+ + +Browser Forensic Recorder & Time-Travel Debugger + + + + + +Browser Forensic Recorder & Time-Travel Debugger - - - -- - - --- -⚡-- Browser Forensic Debugger - v2.0 MCP ---- -- - --- - - - - - - --- - - - - - - -- - - - -- - - -- ---- - -----Load or record a session to inspect DOM.---Select an element from the DOM tree or replay viewport.--- - ---- - - - - - -- ---Select timestamps and click Compare States.--- - -----Disappearing UI Forensic Diagnosis
-- - ----Enter a CSS selector or node ID to run root-cause diagnosis.--- - ---No console or error events recorded.--- - ---No network events recorded.--- - ---- - -- ------- --- -⚡ Agent-Owned Workflows-TeleDOM stores and executes; the agent designs and repairs. Teach once · Reuse forever · Prove what happened.-Recent Runs- --- - - - - + + + +----Search Session Events & Nodes
- -- - --+ + + +++ +⚡++ Browser Forensic Debugger + v2.0 MCP ++++ ++ + +++ + + + + + + +++ + + + + + + ++ + + + ++ + + ++ ++++ + +++++Load or record a session to inspect DOM.+++Select an element from the DOM tree or replay viewport.+++ + ++++ + + + + + ++ +++Select timestamps and click Compare States.+++ + +++++Disappearing UI Forensic Diagnosis
++ + ++++Enter a CSS selector or node ID to run root-cause diagnosis.+++ + +++No console or error events recorded.+++ + +++No network events recorded.+++ + ++++ + ++ +++++++ +++ +⚡ Agent-Owned Workflows+TeleDOM stores and executes; the agent designs and repairs. Teach once · Reuse forever · Prove what happened.+Recent Runs+ +++ + + + + diff --git a/chrome-extension/manifest.json b/chrome-extension/manifest.json index 63066493..5c230ce8 100644 --- a/chrome-extension/manifest.json +++ b/chrome-extension/manifest.json @@ -16,7 +16,8 @@ "tabs", "webNavigation", "management", - "debugger" + "debugger", + "alarms" ], "host_permissions": [ "++++Search Session Events & Nodes
+ ++ + ++" diff --git a/dist/extension/content-script.js b/dist/extension/content-script.js index 85ef3552..faa564d3 100644 --- a/dist/extension/content-script.js +++ b/dist/extension/content-script.js @@ -1,10 +1,10 @@ -var Bt=Object.defineProperty;var Ft=(U,z,Y)=>z in U?Bt(U,z,{enumerable:!0,configurable:!0,writable:!0,value:Y}):U[z]=Y;var f=(U,z,Y)=>Ft(U,typeof z!="symbol"?z+"":z,Y);(function(){"use strict";var U=(l=>(l[l.ELEMENT_NODE=1]="ELEMENT_NODE",l[l.ATTRIBUTE_NODE=2]="ATTRIBUTE_NODE",l[l.TEXT_NODE=3]="TEXT_NODE",l[l.CDATA_SECTION_NODE=4]="CDATA_SECTION_NODE",l[l.PROCESSING_INSTRUCTION_NODE=7]="PROCESSING_INSTRUCTION_NODE",l[l.COMMENT_NODE=8]="COMMENT_NODE",l[l.DOCUMENT_NODE=9]="DOCUMENT_NODE",l[l.DOCUMENT_TYPE_NODE=10]="DOCUMENT_TYPE_NODE",l[l.DOCUMENT_FRAGMENT_NODE=11]="DOCUMENT_FRAGMENT_NODE",l))(U||{});class z{constructor(){f(this,"nextId",1);f(this,"nodeToIdMap",new WeakMap);f(this,"idToNodeMap",new Map);f(this,"identities",new Map);f(this,"parentHistory",new Map)}getOrCreateId(e,t=0){if(this.nodeToIdMap.has(e))return this.nodeToIdMap.get(e);const s=this.nextId++;this.nodeToIdMap.set(e,s),this.idToNodeMap.set(s,e);const i=e.nodeType===U.ELEMENT_NODE||e.nodeType===1?e:null,r=i&&i.tagName?i.tagName.toLowerCase():void 0,o=r?r.includes("-"):!1,a={id:s,nodeType:e.nodeType,tagName:r,createdAt:t,initialSelectorHint:i?this.computeSelector(i):void 0,isCustomElement:o};return this.identities.set(s,a),s}getId(e){return this.nodeToIdMap.get(e)}getNode(e){return this.idToNodeMap.get(e)}getIdentity(e){return this.identities.get(e)}recordParent(e,t){if(!t)return;const s=this.parentHistory.get(e)||[];s[s.length-1]!==t&&(s.push(t),this.parentHistory.set(e,s))}getParentHistory(e){return this.parentHistory.get(e)||[]}computeSelector(e){try{const t=typeof e.id=="string"?e.id:e.getAttribute?e.getAttribute("id"):"";if(t&&/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(t))return`#${t}`;const s=e.tagName?e.tagName.toLowerCase():"element";if(s==="body"||s==="html"||s==="head")return s;let n=[];e.classList&&typeof e.classList.forEach=="function"?n=Array.from(e.classList):typeof e.className=="string"?n=e.className.split(/\s+/):e.className&&typeof e.className.baseVal=="string"&&(n=e.className.baseVal.split(/\s+/));let i="";if(n.length>0){const r=n.filter(o=>typeof o=="string"&&/^[a-zA-Z0-9_-]+$/.test(o)&&!o.startsWith("ng-")&&!o.startsWith("_ng")).slice(0,3);r.length>0&&(i="."+r.join("."))}if(e.parentElement&&e.parentElement.children){const r=Array.from(e.parentElement.children).filter(o=>o.tagName&&o.tagName.toLowerCase()===s);if(r.length>1){const o=r.indexOf(e)+1;if(o>0)return`${s}${i}:nth-of-type(${o})`}}return`${s}${i}`}catch{return e.tagName?e.tagName.toLowerCase():"element"}}computeFullSelectorPath(e){const t=[];let s=e;for(;s&&s.tagName&&s.tagName.toLowerCase()!=="html";){const n=this.computeSelector(s);if(t.unshift(n),s.id&&/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(s.id))break;s=s.parentElement}return t.join(" > ")}removeNode(e){this.idToNodeMap.get(e)&&this.idToNodeMap.delete(e)}reset(){this.nextId=1,this.nodeToIdMap=new WeakMap,this.idToNodeMap.clear(),this.identities.clear(),this.parentHistory.clear()}}const Y={maskAllInputs:!1,maskInputTypes:["password","hidden","tel","email"],maskSelectors:["[data-private]",".private-data",".sensitive",'[data-testid="sensitive"]'],blockSelectors:[".recording-blocked","[data-recording-ignore]"],redactHeaders:["authorization","cookie","set-cookie","x-api-key","proxy-authorization","token"],redactQueryParams:["token","key","auth","secret","password","access_token","apiKey","bearer"],maxTextLength:1e5};class se{constructor(e={}){f(this,"config");this.config={...Y,...e}}shouldBlockNode(e){if(!e||!e.matches)return!1;for(const t of this.config.blockSelectors)try{if(e.matches(t)||e.closest(t))return!0}catch{}return!1}shouldMaskText(e){if(!e||!e.matches)return!1;for(const t of this.config.maskSelectors)try{if(e.matches(t)||e.closest(t))return!0}catch{}return!1}maskValue(e,t,s){return e&&(this.config.maskAllInputs?"*".repeat(Math.min(e.length,12)):t&&this.config.maskInputTypes.includes(t.toLowerCase())||s&&/(password|token|secret|cvv|credit|auth|ssn)/i.test(s)?"••••••••":e)}sanitizeText(e,t=!1){return e&&(t?e.replace(/[^\s\n\r\t]/g,"*"):e.length>this.config.maxTextLength?e.substring(0,this.config.maxTextLength)+"... [TRUNCATED]":e)}sanitizeHeaders(e){if(!e)return;const t={};for(const[s,n]of Object.entries(e)){const i=s.toLowerCase();this.config.redactHeaders.some(r=>i.includes(r))?t[s]="[REDACTED]":t[s]=n}return t}sanitizeUrl(e){try{const t=new URL(e);for(const s of this.config.redactQueryParams)t.searchParams.has(s)&&t.searchParams.set(s,"[REDACTED]");return t.toString()}catch{return e}}}class oe{constructor(){f(this,"currentSequence",0);f(this,"sessionStartTime");f(this,"sessionStartWallClock");this.sessionStartTime=typeof performance<"u"?performance.now():0,this.sessionStartWallClock=Date.now()}nextSequence(){return this.currentSequence+=1,this.currentSequence}getSequence(){return this.currentSequence}getRelativeTimestamp(){return typeof performance<"u"?Math.round((performance.now()-this.sessionStartTime)*100)/100:Date.now()-this.sessionStartWallClock}getWallClock(){return Date.now()}generateEventId(e="evt",t){const s=t!==void 0?t:this.nextSequence(),n=Math.random().toString(36).substring(2,8);return`${e}_${s}_${n}`}reset(){this.currentSequence=0,this.sessionStartTime=typeof performance<"u"?performance.now():0,this.sessionStartWallClock=Date.now()}}class me{constructor(e,t,s){f(this,"registry");f(this,"privacy");f(this,"sequenceCounter");this.registry=e,this.privacy=t,this.sequenceCounter=s}captureSnapshot(e=document,t=""){const s=this.sequenceCounter.getRelativeTimestamp(),n=this.sequenceCounter.nextSequence(),i={},r=e.documentElement||e.body,o=this.registry.getOrCreateId(e,s);if(i[o]={id:o,nodeType:U.DOCUMENT_NODE,tagName:"#document",children:[],parentId:null},e.doctype){const c=this.registry.getOrCreateId(e.doctype,s);i[c]={id:c,nodeType:U.DOCUMENT_TYPE_NODE,tagName:e.doctype.name||"html",parentId:o},i[o].children.push(c)}if(r){const c=this.serializeNode(r,o,i,s);c&&i[o].children.push(c)}const a=this.getViewportInfo();return{snapshotId:`snap_${n}_${Date.now()}`,sessionId:t,timestamp:s,sequence:n,rootId:o,nodes:i,title:e.title||"",url:typeof window<"u"?window.location.href:"",origin:typeof window<"u"?window.location.origin:"",viewport:a,doctype:e.doctype?e.doctype.name:void 0,totalNodeCount:Object.keys(i).length}}serializeNode(e,t,s,n){if(!e||e.nodeType===Node.ELEMENT_NODE&&this.privacy.shouldBlockNode(e))return null;const i=this.registry.getOrCreateId(e,n);this.registry.recordParent(i,t);const r={id:i,nodeType:e.nodeType,parentId:t};if(e.nodeType===Node.ELEMENT_NODE){const o=e;r.tagName=o.tagName.toLowerCase(),r.isCustomElement=r.tagName.includes("-"),r.namespaceURI=o.namespaceURI;const a={};if(o.attributes)for(let c=0;c "u"?{width:1920,height:1080,scrollX:0,scrollY:0,devicePixelRatio:1}:{width:window.innerWidth||((e=document.documentElement)==null?void 0:e.clientWidth)||1920,height:window.innerHeight||((t=document.documentElement)==null?void 0:t.clientHeight)||1080,scrollX:window.scrollX||window.pageXOffset||0,scrollY:window.scrollY||window.pageYOffset||0,devicePixelRatio:window.devicePixelRatio||1}}}class Re{constructor(e,t,s,n,i,r=""){f(this,"observer",null);f(this,"registry");f(this,"privacy");f(this,"sequenceCounter");f(this,"snapshotEngine");f(this,"callback");f(this,"sessionId");f(this,"isObserving",!1);this.registry=e,this.privacy=t,this.sequenceCounter=s,this.snapshotEngine=n,this.callback=i,this.sessionId=r}setSessionId(e){this.sessionId=e}start(e=document){this.isObserving||typeof MutationObserver>"u"||(this.observer=new MutationObserver(this.handleMutations.bind(this)),this.observer.observe(e,{childList:!0,attributes:!0,characterData:!0,subtree:!0,attributeOldValue:!0,characterDataOldValue:!0}),this.isObserving=!0)}stop(){this.observer&&(this.observer.disconnect(),this.observer=null),this.isObserving=!1}takeRecords(){if(this.observer){const e=this.observer.takeRecords();e.length>0&&this.handleMutations(e)}}handleMutations(e){const t=this.sequenceCounter.getRelativeTimestamp(),s=this.sequenceCounter.getWallClock();for(let n=0;n 0)for(let o=0;o 0)for(let o=0;o "u"||typeof document>"u"||(this.isListening=!0,this.cleanups=[],this.attachUserEventListeners(),this.attachNavigationListeners(),this.attachViewportListeners())}stop(){this.cleanups.forEach(e=>{try{e()}catch{}}),this.cleanups=[],this.isListening=!1}attachUserEventListeners(){[{type:"click",handler:t=>this.handlePointerEvent(t,"USER_CLICK"),options:{capture:!0,passive:!0}},{type:"dblclick",handler:t=>this.handlePointerEvent(t,"USER_DBLCLICK"),options:{capture:!0,passive:!0}},{type:"input",handler:t=>this.handleInputEvent(t),options:{capture:!0,passive:!0}},{type:"change",handler:t=>this.handleInputEvent(t,"USER_CHANGE"),options:{capture:!0,passive:!0}},{type:"submit",handler:t=>this.handleSubmitEvent(t),options:{capture:!0,passive:!0}},{type:"keydown",handler:t=>this.handleKeyboardEvent(t,"USER_KEYDOWN"),options:{capture:!0,passive:!0}},{type:"keyup",handler:t=>this.handleKeyboardEvent(t,"USER_KEYUP"),options:{capture:!0,passive:!0}},{type:"focus",handler:t=>this.handleFocusBlurEvent(t,"USER_FOCUS"),options:{capture:!0,passive:!0}},{type:"blur",handler:t=>this.handleFocusBlurEvent(t,"USER_BLUR"),options:{capture:!0,passive:!0}}].forEach(({type:t,handler:s,options:n})=>{document.addEventListener(t,s,n),this.cleanups.push(()=>document.removeEventListener(t,s,n))})}handlePointerEvent(e,t){const s=e,n=e.target,i=this.sequenceCounter.getRelativeTimestamp(),r=this.sequenceCounter.getWallClock(),o=n?this.registry.getOrCreateId(n,i):void 0,a=n&&n.nodeType===Node.ELEMENT_NODE?this.registry.computeSelector(n):void 0,c=this.sequenceCounter.nextSequence(),u={id:this.sequenceCounter.generateEventId("usr_clk",c),sessionId:this.sessionId,timestamp:i,sequence:c,wallClockTime:r,type:t,category:"USER",source:"USER_INTERACTION",targetNodeId:o,targetSelector:a,payload:{eventType:e.type,targetNodeId:o,targetSelector:a,clientX:s.clientX,clientY:s.clientY,button:s.button,isTrusted:e.isTrusted}};this.callback(u)}handleInputEvent(e,t="USER_INPUT"){const s=e.target;if(!s)return;const n=this.sequenceCounter.getRelativeTimestamp(),i=this.sequenceCounter.getWallClock(),r=this.registry.getOrCreateId(s,n),o=this.registry.computeSelector(s);let a="";if(s.tagName.toLowerCase()==="input"){const d=s;a=this.privacy.maskValue(d.value,d.type,d.name)}else if(s.tagName.toLowerCase()==="textarea"){const d=s;a=this.privacy.maskValue(d.value,"textarea",d.name)}else s.tagName.toLowerCase()==="select"&&(a=s.value);const c=this.sequenceCounter.nextSequence(),u={id:this.sequenceCounter.generateEventId("usr_inp",c),sessionId:this.sessionId,timestamp:n,sequence:c,wallClockTime:i,type:t,category:"USER",source:"USER_INTERACTION",targetNodeId:r,targetSelector:o,payload:{eventType:e.type,targetNodeId:r,targetSelector:o,inputValue:a,isTrusted:e.isTrusted}};this.callback(u)}handleSubmitEvent(e){const t=e.target,s=this.sequenceCounter.getRelativeTimestamp(),n=this.sequenceCounter.getWallClock(),i=t?this.registry.getOrCreateId(t,s):void 0,r=t?this.registry.computeSelector(t):void 0,o=this.sequenceCounter.nextSequence(),a={id:this.sequenceCounter.generateEventId("usr_sub",o),sessionId:this.sessionId,timestamp:s,sequence:o,wallClockTime:n,type:"USER_SUBMIT",category:"USER",source:"USER_INTERACTION",targetNodeId:i,targetSelector:r,payload:{eventType:"submit",targetNodeId:i,targetSelector:r}};this.callback(a)}handleKeyboardEvent(e,t){const s=e.target,n=this.sequenceCounter.getRelativeTimestamp(),i=this.sequenceCounter.getWallClock(),r=s?this.registry.getOrCreateId(s,n):void 0,o=s?this.registry.computeSelector(s):void 0;let a=e.key;s&&s.tagName.toLowerCase()==="input"&&s.type==="password"&&(a="*");const c=this.sequenceCounter.nextSequence(),u={id:this.sequenceCounter.generateEventId("usr_key",c),sessionId:this.sessionId,timestamp:n,sequence:c,wallClockTime:i,type:t,category:"USER",source:"USER_INTERACTION",targetNodeId:r,targetSelector:o,payload:{eventType:e.type,targetNodeId:r,targetSelector:o,key:a,code:e.code,isTrusted:e.isTrusted}};this.callback(u)}handleFocusBlurEvent(e,t){const s=e.target,n=this.sequenceCounter.getRelativeTimestamp(),i=this.sequenceCounter.getWallClock(),r=s?this.registry.getOrCreateId(s,n):void 0,o=s?this.registry.computeSelector(s):void 0,a=this.sequenceCounter.nextSequence(),c={id:this.sequenceCounter.generateEventId("usr_foc",a),sessionId:this.sessionId,timestamp:n,sequence:a,wallClockTime:i,type:t,category:"USER",source:"USER_INTERACTION",targetNodeId:r,targetSelector:o,payload:{eventType:e.type,targetNodeId:r,targetSelector:o}};this.callback(c)}attachNavigationListeners(){if(typeof window>"u"||!window.history)return;const e=window.history.pushState,t=window.history.replaceState;window.history.pushState=(...r)=>{const o=e.apply(window.history,r);return this.recordNavigation("pushState",window.location.href,r[0],r[2]?String(r[2]):void 0),o},window.history.replaceState=(...r)=>{const o=t.apply(window.history,r);return this.recordNavigation("replaceState",window.location.href,r[0],r[2]?String(r[2]):void 0),o};const s=r=>{this.recordNavigation("popstate",window.location.href,r.state)};window.addEventListener("popstate",s);const n=r=>{this.recordNavigation("hashchange",r.newURL,void 0,void 0,r.oldURL)};window.addEventListener("hashchange",n);const i=()=>{this.recordNavigation("visibilitychange",window.location.href,{visibilityState:document.visibilityState,hidden:document.hidden})};document.addEventListener("visibilitychange",i),this.cleanups.push(()=>{window.history.pushState=e,window.history.replaceState=t,window.removeEventListener("popstate",s),window.removeEventListener("hashchange",n),document.removeEventListener("visibilitychange",i)})}recordNavigation(e,t,s,n,i){const r=this.sequenceCounter.getRelativeTimestamp(),o=this.sequenceCounter.getWallClock(),a=this.sequenceCounter.nextSequence(),c={id:this.sequenceCounter.generateEventId("nav",a),sessionId:this.sessionId,timestamp:r,sequence:a,wallClockTime:o,type:`NAV_${e.toUpperCase()}`,category:"NAVIGATION",source:"PAGE",payload:{navigationType:e,url:this.privacy.sanitizeUrl(t),previousUrl:i?this.privacy.sanitizeUrl(i):void 0,state:s,title:n||document.title}};this.callback(c)}attachViewportListeners(){if(typeof window>"u")return;let e=null;const t=()=>{e&&clearTimeout(e),e=setTimeout(()=>{const i=this.sequenceCounter.getRelativeTimestamp(),r=this.sequenceCounter.getWallClock(),o=this.sequenceCounter.nextSequence(),a={id:this.sequenceCounter.generateEventId("vp_res",o),sessionId:this.sessionId,timestamp:i,sequence:o,wallClockTime:r,type:"VIEWPORT_RESIZE",category:"VIEWPORT",source:"BROWSER_RUNTIME",payload:{width:window.innerWidth,height:window.innerHeight,devicePixelRatio:window.devicePixelRatio}};this.callback(a)},100)};window.addEventListener("resize",t,{passive:!0});let s=null;const n=()=>{s&&clearTimeout(s),s=setTimeout(()=>{const i=this.sequenceCounter.getRelativeTimestamp(),r=this.sequenceCounter.getWallClock(),o=this.sequenceCounter.nextSequence(),a={id:this.sequenceCounter.generateEventId("vp_scr",o),sessionId:this.sessionId,timestamp:i,sequence:o,wallClockTime:r,type:"VIEWPORT_SCROLL",category:"VIEWPORT",source:"BROWSER_RUNTIME",payload:{scrollX:window.scrollX,scrollY:window.scrollY}};this.callback(a)},100)};window.addEventListener("scroll",n,{passive:!0}),this.cleanups.push(()=>{e&&clearTimeout(e),s&&clearTimeout(s),window.removeEventListener("resize",t),window.removeEventListener("scroll",n)})}}class ke{constructor(e,t,s,n=""){f(this,"privacy");f(this,"sequenceCounter");f(this,"callback");f(this,"sessionId");f(this,"isInstrumented",!1);f(this,"originalConsole",{});f(this,"originalOnError",null);f(this,"cleanups",[]);this.privacy=e,this.sequenceCounter=t,this.callback=s,this.sessionId=n}setSessionId(e){this.sessionId=e}start(){this.isInstrumented||typeof window>"u"||(this.isInstrumented=!0,this.cleanups=[],this.instrumentConsole(),this.instrumentGlobalErrors(),this.instrumentUnhandledRejections())}stop(){this.cleanups.forEach(e=>{try{e()}catch{}}),this.cleanups=[],this.isInstrumented=!1}instrumentConsole(){if(typeof console>"u")return;["log","warn","error","info","debug"].forEach(t=>{const s=console[t];s&&(this.originalConsole[t]=s,console[t]=(...n)=>{try{this.recordConsole(t,n)}catch{}return s.apply(console,n)},this.cleanups.push(()=>{console[t]=s}))})}recordConsole(e,t){const s=this.sequenceCounter.getRelativeTimestamp(),n=this.sequenceCounter.getWallClock(),i=this.sequenceCounter.nextSequence(),r=t.map(u=>{const d=typeof u;let h="";try{u instanceof Error?h=`${u.name}: ${u.message} -${u.stack||""}`:d==="object"&&u!==null?h=JSON.stringify(u,(p,y)=>typeof y=="function"?"[Function]":y):h=String(u)}catch{h="[Unserializable Object]"}return{type:d,value:this.privacy.sanitizeText(h)}}),o=r.map(u=>u.value).join(" ");let a;try{const u=new Error().stack;u&&(a=u.split(` +var Ft=Object.defineProperty;var Vt=($,H,W)=>H in $?Ft($,H,{enumerable:!0,configurable:!0,writable:!0,value:W}):$[H]=W;var b=($,H,W)=>Vt($,typeof H!="symbol"?H+"":H,W);(function(){"use strict";var $=(l=>(l[l.ELEMENT_NODE=1]="ELEMENT_NODE",l[l.ATTRIBUTE_NODE=2]="ATTRIBUTE_NODE",l[l.TEXT_NODE=3]="TEXT_NODE",l[l.CDATA_SECTION_NODE=4]="CDATA_SECTION_NODE",l[l.PROCESSING_INSTRUCTION_NODE=7]="PROCESSING_INSTRUCTION_NODE",l[l.COMMENT_NODE=8]="COMMENT_NODE",l[l.DOCUMENT_NODE=9]="DOCUMENT_NODE",l[l.DOCUMENT_TYPE_NODE=10]="DOCUMENT_TYPE_NODE",l[l.DOCUMENT_FRAGMENT_NODE=11]="DOCUMENT_FRAGMENT_NODE",l))($||{});class H{constructor(){b(this,"nextId",1);b(this,"nodeToIdMap",new WeakMap);b(this,"idToNodeMap",new Map);b(this,"identities",new Map);b(this,"parentHistory",new Map)}getOrCreateId(e,t=0){if(this.nodeToIdMap.has(e))return this.nodeToIdMap.get(e);const s=this.nextId++;this.nodeToIdMap.set(e,s),this.idToNodeMap.set(s,e);const i=e.nodeType===$.ELEMENT_NODE||e.nodeType===1?e:null,r=i&&i.tagName?i.tagName.toLowerCase():void 0,o=r?r.includes("-"):!1,a={id:s,nodeType:e.nodeType,tagName:r,createdAt:t,initialSelectorHint:i?this.computeSelector(i):void 0,isCustomElement:o};return this.identities.set(s,a),s}getId(e){return this.nodeToIdMap.get(e)}getNode(e){return this.idToNodeMap.get(e)}getIdentity(e){return this.identities.get(e)}recordParent(e,t){if(!t)return;const s=this.parentHistory.get(e)||[];s[s.length-1]!==t&&(s.push(t),this.parentHistory.set(e,s))}getParentHistory(e){return this.parentHistory.get(e)||[]}computeSelector(e){try{const t=typeof e.id=="string"?e.id:e.getAttribute?e.getAttribute("id"):"";if(t&&/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(t))return`#${t}`;const s=e.tagName?e.tagName.toLowerCase():"element";if(s==="body"||s==="html"||s==="head")return s;let n=[];e.classList&&typeof e.classList.forEach=="function"?n=Array.from(e.classList):typeof e.className=="string"?n=e.className.split(/\s+/):e.className&&typeof e.className.baseVal=="string"&&(n=e.className.baseVal.split(/\s+/));let i="";if(n.length>0){const r=n.filter(o=>typeof o=="string"&&/^[a-zA-Z0-9_-]+$/.test(o)&&!o.startsWith("ng-")&&!o.startsWith("_ng")).slice(0,3);r.length>0&&(i="."+r.join("."))}if(e.parentElement&&e.parentElement.children){const r=Array.from(e.parentElement.children).filter(o=>o.tagName&&o.tagName.toLowerCase()===s);if(r.length>1){const o=r.indexOf(e)+1;if(o>0)return`${s}${i}:nth-of-type(${o})`}}return`${s}${i}`}catch{return e.tagName?e.tagName.toLowerCase():"element"}}computeFullSelectorPath(e){const t=[];let s=e;for(;s&&s.tagName&&s.tagName.toLowerCase()!=="html";){const n=this.computeSelector(s);if(t.unshift(n),s.id&&/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(s.id))break;s=s.parentElement}return t.join(" > ")}removeNode(e){this.idToNodeMap.get(e)&&this.idToNodeMap.delete(e)}reset(){this.nextId=1,this.nodeToIdMap=new WeakMap,this.idToNodeMap.clear(),this.identities.clear(),this.parentHistory.clear()}}const W={maskAllInputs:!1,maskInputTypes:["password","hidden","tel","email"],maskSelectors:["[data-private]",".private-data",".sensitive",'[data-testid="sensitive"]'],blockSelectors:[".recording-blocked","[data-recording-ignore]"],redactHeaders:["authorization","cookie","set-cookie","x-api-key","proxy-authorization","token"],redactQueryParams:["token","key","auth","secret","password","access_token","apiKey","bearer"],maxTextLength:1e5};class J{constructor(e={}){b(this,"config");this.config={...W,...e}}shouldBlockNode(e){if(!e||!e.matches)return!1;for(const t of this.config.blockSelectors)try{if(e.matches(t)||e.closest(t))return!0}catch{}return!1}shouldMaskText(e){if(!e||!e.matches)return!1;for(const t of this.config.maskSelectors)try{if(e.matches(t)||e.closest(t))return!0}catch{}return!1}maskValue(e,t,s){return e&&(this.config.maskAllInputs?"*".repeat(Math.min(e.length,12)):t&&this.config.maskInputTypes.includes(t.toLowerCase())||s&&/(password|token|secret|cvv|credit|auth|ssn)/i.test(s)?"••••••••":e)}sanitizeText(e,t=!1){return e&&(t?e.replace(/[^\s\n\r\t]/g,"*"):e.length>this.config.maxTextLength?e.substring(0,this.config.maxTextLength)+"... [TRUNCATED]":e)}sanitizeHeaders(e){if(!e)return;const t={};for(const[s,n]of Object.entries(e)){const i=s.toLowerCase();this.config.redactHeaders.some(r=>i.includes(r))?t[s]="[REDACTED]":t[s]=n}return t}sanitizeUrl(e){try{const t=new URL(e);for(const s of this.config.redactQueryParams)t.searchParams.has(s)&&t.searchParams.set(s,"[REDACTED]");return t.toString()}catch{return e}}}class ne{constructor(){b(this,"currentSequence",0);b(this,"sessionStartTime");b(this,"sessionStartWallClock");this.sessionStartTime=typeof performance<"u"?performance.now():0,this.sessionStartWallClock=Date.now()}nextSequence(){return this.currentSequence+=1,this.currentSequence}getSequence(){return this.currentSequence}getRelativeTimestamp(){return typeof performance<"u"?Math.round((performance.now()-this.sessionStartTime)*100)/100:Date.now()-this.sessionStartWallClock}getWallClock(){return Date.now()}generateEventId(e="evt",t){const s=t!==void 0?t:this.nextSequence(),n=Math.random().toString(36).substring(2,8);return`${e}_${s}_${n}`}reset(){this.currentSequence=0,this.sessionStartTime=typeof performance<"u"?performance.now():0,this.sessionStartWallClock=Date.now()}}class he{constructor(e,t,s){b(this,"registry");b(this,"privacy");b(this,"sequenceCounter");this.registry=e,this.privacy=t,this.sequenceCounter=s}captureSnapshot(e=document,t=""){const s=this.sequenceCounter.getRelativeTimestamp(),n=this.sequenceCounter.nextSequence(),i={},r=e.documentElement||e.body,o=this.registry.getOrCreateId(e,s);if(i[o]={id:o,nodeType:$.DOCUMENT_NODE,tagName:"#document",children:[],parentId:null},e.doctype){const c=this.registry.getOrCreateId(e.doctype,s);i[c]={id:c,nodeType:$.DOCUMENT_TYPE_NODE,tagName:e.doctype.name||"html",parentId:o},i[o].children.push(c)}if(r){const c=this.serializeNode(r,o,i,s);c&&i[o].children.push(c)}const a=this.getViewportInfo();return{snapshotId:`snap_${n}_${Date.now()}`,sessionId:t,timestamp:s,sequence:n,rootId:o,nodes:i,title:e.title||"",url:typeof window<"u"?window.location.href:"",origin:typeof window<"u"?window.location.origin:"",viewport:a,doctype:e.doctype?e.doctype.name:void 0,totalNodeCount:Object.keys(i).length}}serializeNode(e,t,s,n){if(!e||e.nodeType===Node.ELEMENT_NODE&&this.privacy.shouldBlockNode(e))return null;const i=this.registry.getOrCreateId(e,n);this.registry.recordParent(i,t);const r={id:i,nodeType:e.nodeType,parentId:t};if(e.nodeType===Node.ELEMENT_NODE){const o=e;r.tagName=o.tagName.toLowerCase(),r.isCustomElement=r.tagName.includes("-"),r.namespaceURI=o.namespaceURI;const a={};if(o.attributes)for(let c=0;c "u"?{width:1920,height:1080,scrollX:0,scrollY:0,devicePixelRatio:1}:{width:window.innerWidth||((e=document.documentElement)==null?void 0:e.clientWidth)||1920,height:window.innerHeight||((t=document.documentElement)==null?void 0:t.clientHeight)||1080,scrollX:window.scrollX||window.pageXOffset||0,scrollY:window.scrollY||window.pageYOffset||0,devicePixelRatio:window.devicePixelRatio||1}}}class Ne{constructor(e,t,s,n,i,r=""){b(this,"observer",null);b(this,"registry");b(this,"privacy");b(this,"sequenceCounter");b(this,"snapshotEngine");b(this,"callback");b(this,"sessionId");b(this,"isObserving",!1);this.registry=e,this.privacy=t,this.sequenceCounter=s,this.snapshotEngine=n,this.callback=i,this.sessionId=r}setSessionId(e){this.sessionId=e}start(e=document){this.isObserving||typeof MutationObserver>"u"||(this.observer=new MutationObserver(this.handleMutations.bind(this)),this.observer.observe(e,{childList:!0,attributes:!0,characterData:!0,subtree:!0,attributeOldValue:!0,characterDataOldValue:!0}),this.isObserving=!0)}stop(){this.observer&&(this.observer.disconnect(),this.observer=null),this.isObserving=!1}takeRecords(){if(this.observer){const e=this.observer.takeRecords();e.length>0&&this.handleMutations(e)}}handleMutations(e){const t=this.sequenceCounter.getRelativeTimestamp(),s=this.sequenceCounter.getWallClock();for(let n=0;n 0)for(let o=0;o 0)for(let o=0;o "u"||typeof document>"u"||(this.isListening=!0,this.cleanups=[],this.attachUserEventListeners(),this.attachNavigationListeners(),this.attachViewportListeners())}stop(){this.cleanups.forEach(e=>{try{e()}catch{}}),this.cleanups=[],this.isListening=!1}attachUserEventListeners(){[{type:"click",handler:t=>this.handlePointerEvent(t,"USER_CLICK"),options:{capture:!0,passive:!0}},{type:"dblclick",handler:t=>this.handlePointerEvent(t,"USER_DBLCLICK"),options:{capture:!0,passive:!0}},{type:"input",handler:t=>this.handleInputEvent(t),options:{capture:!0,passive:!0}},{type:"change",handler:t=>this.handleInputEvent(t,"USER_CHANGE"),options:{capture:!0,passive:!0}},{type:"submit",handler:t=>this.handleSubmitEvent(t),options:{capture:!0,passive:!0}},{type:"keydown",handler:t=>this.handleKeyboardEvent(t,"USER_KEYDOWN"),options:{capture:!0,passive:!0}},{type:"keyup",handler:t=>this.handleKeyboardEvent(t,"USER_KEYUP"),options:{capture:!0,passive:!0}},{type:"focus",handler:t=>this.handleFocusBlurEvent(t,"USER_FOCUS"),options:{capture:!0,passive:!0}},{type:"blur",handler:t=>this.handleFocusBlurEvent(t,"USER_BLUR"),options:{capture:!0,passive:!0}}].forEach(({type:t,handler:s,options:n})=>{document.addEventListener(t,s,n),this.cleanups.push(()=>document.removeEventListener(t,s,n))})}handlePointerEvent(e,t){const s=e,n=e.target,i=this.sequenceCounter.getRelativeTimestamp(),r=this.sequenceCounter.getWallClock(),o=n?this.registry.getOrCreateId(n,i):void 0,a=n&&n.nodeType===Node.ELEMENT_NODE?this.registry.computeSelector(n):void 0,c=this.sequenceCounter.nextSequence(),u={id:this.sequenceCounter.generateEventId("usr_clk",c),sessionId:this.sessionId,timestamp:i,sequence:c,wallClockTime:r,type:t,category:"USER",source:"USER_INTERACTION",targetNodeId:o,targetSelector:a,payload:{eventType:e.type,targetNodeId:o,targetSelector:a,clientX:s.clientX,clientY:s.clientY,button:s.button,isTrusted:e.isTrusted}};this.callback(u)}handleInputEvent(e,t="USER_INPUT"){const s=e.target;if(!s)return;const n=this.sequenceCounter.getRelativeTimestamp(),i=this.sequenceCounter.getWallClock(),r=this.registry.getOrCreateId(s,n),o=this.registry.computeSelector(s);let a="";if(s.tagName.toLowerCase()==="input"){const h=s;a=this.privacy.maskValue(h.value,h.type,h.name)}else if(s.tagName.toLowerCase()==="textarea"){const h=s;a=this.privacy.maskValue(h.value,"textarea",h.name)}else s.tagName.toLowerCase()==="select"&&(a=s.value);const c=this.sequenceCounter.nextSequence(),u={id:this.sequenceCounter.generateEventId("usr_inp",c),sessionId:this.sessionId,timestamp:n,sequence:c,wallClockTime:i,type:t,category:"USER",source:"USER_INTERACTION",targetNodeId:r,targetSelector:o,payload:{eventType:e.type,targetNodeId:r,targetSelector:o,inputValue:a,isTrusted:e.isTrusted}};this.callback(u)}handleSubmitEvent(e){const t=e.target,s=this.sequenceCounter.getRelativeTimestamp(),n=this.sequenceCounter.getWallClock(),i=t?this.registry.getOrCreateId(t,s):void 0,r=t?this.registry.computeSelector(t):void 0,o=this.sequenceCounter.nextSequence(),a={id:this.sequenceCounter.generateEventId("usr_sub",o),sessionId:this.sessionId,timestamp:s,sequence:o,wallClockTime:n,type:"USER_SUBMIT",category:"USER",source:"USER_INTERACTION",targetNodeId:i,targetSelector:r,payload:{eventType:"submit",targetNodeId:i,targetSelector:r}};this.callback(a)}handleKeyboardEvent(e,t){const s=e.target,n=this.sequenceCounter.getRelativeTimestamp(),i=this.sequenceCounter.getWallClock(),r=s?this.registry.getOrCreateId(s,n):void 0,o=s?this.registry.computeSelector(s):void 0;let a=e.key;s&&s.tagName.toLowerCase()==="input"&&s.type==="password"&&(a="*");const c=this.sequenceCounter.nextSequence(),u={id:this.sequenceCounter.generateEventId("usr_key",c),sessionId:this.sessionId,timestamp:n,sequence:c,wallClockTime:i,type:t,category:"USER",source:"USER_INTERACTION",targetNodeId:r,targetSelector:o,payload:{eventType:e.type,targetNodeId:r,targetSelector:o,key:a,code:e.code,isTrusted:e.isTrusted}};this.callback(u)}handleFocusBlurEvent(e,t){const s=e.target,n=this.sequenceCounter.getRelativeTimestamp(),i=this.sequenceCounter.getWallClock(),r=s?this.registry.getOrCreateId(s,n):void 0,o=s?this.registry.computeSelector(s):void 0,a=this.sequenceCounter.nextSequence(),c={id:this.sequenceCounter.generateEventId("usr_foc",a),sessionId:this.sessionId,timestamp:n,sequence:a,wallClockTime:i,type:t,category:"USER",source:"USER_INTERACTION",targetNodeId:r,targetSelector:o,payload:{eventType:e.type,targetNodeId:r,targetSelector:o}};this.callback(c)}attachNavigationListeners(){if(typeof window>"u"||!window.history)return;const e=window.history.pushState,t=window.history.replaceState;window.history.pushState=(...r)=>{const o=e.apply(window.history,r);return this.recordNavigation("pushState",window.location.href,r[0],r[2]?String(r[2]):void 0),o},window.history.replaceState=(...r)=>{const o=t.apply(window.history,r);return this.recordNavigation("replaceState",window.location.href,r[0],r[2]?String(r[2]):void 0),o};const s=r=>{this.recordNavigation("popstate",window.location.href,r.state)};window.addEventListener("popstate",s);const n=r=>{this.recordNavigation("hashchange",r.newURL,void 0,void 0,r.oldURL)};window.addEventListener("hashchange",n);const i=()=>{this.recordNavigation("visibilitychange",window.location.href,{visibilityState:document.visibilityState,hidden:document.hidden})};document.addEventListener("visibilitychange",i),this.cleanups.push(()=>{window.history.pushState=e,window.history.replaceState=t,window.removeEventListener("popstate",s),window.removeEventListener("hashchange",n),document.removeEventListener("visibilitychange",i)})}recordNavigation(e,t,s,n,i){const r=this.sequenceCounter.getRelativeTimestamp(),o=this.sequenceCounter.getWallClock(),a=this.sequenceCounter.nextSequence(),c={id:this.sequenceCounter.generateEventId("nav",a),sessionId:this.sessionId,timestamp:r,sequence:a,wallClockTime:o,type:`NAV_${e.toUpperCase()}`,category:"NAVIGATION",source:"PAGE",payload:{navigationType:e,url:this.privacy.sanitizeUrl(t),previousUrl:i?this.privacy.sanitizeUrl(i):void 0,state:s,title:n||document.title}};this.callback(c)}attachViewportListeners(){if(typeof window>"u")return;let e=null;const t=()=>{e&&clearTimeout(e),e=setTimeout(()=>{const i=this.sequenceCounter.getRelativeTimestamp(),r=this.sequenceCounter.getWallClock(),o=this.sequenceCounter.nextSequence(),a={id:this.sequenceCounter.generateEventId("vp_res",o),sessionId:this.sessionId,timestamp:i,sequence:o,wallClockTime:r,type:"VIEWPORT_RESIZE",category:"VIEWPORT",source:"BROWSER_RUNTIME",payload:{width:window.innerWidth,height:window.innerHeight,devicePixelRatio:window.devicePixelRatio}};this.callback(a)},100)};window.addEventListener("resize",t,{passive:!0});let s=null;const n=()=>{s&&clearTimeout(s),s=setTimeout(()=>{const i=this.sequenceCounter.getRelativeTimestamp(),r=this.sequenceCounter.getWallClock(),o=this.sequenceCounter.nextSequence(),a={id:this.sequenceCounter.generateEventId("vp_scr",o),sessionId:this.sessionId,timestamp:i,sequence:o,wallClockTime:r,type:"VIEWPORT_SCROLL",category:"VIEWPORT",source:"BROWSER_RUNTIME",payload:{scrollX:window.scrollX,scrollY:window.scrollY}};this.callback(a)},100)};window.addEventListener("scroll",n,{passive:!0}),this.cleanups.push(()=>{e&&clearTimeout(e),s&&clearTimeout(s),window.removeEventListener("resize",t),window.removeEventListener("scroll",n)})}}class Me{constructor(e,t,s,n=""){b(this,"privacy");b(this,"sequenceCounter");b(this,"callback");b(this,"sessionId");b(this,"isInstrumented",!1);b(this,"originalConsole",{});b(this,"originalOnError",null);b(this,"cleanups",[]);this.privacy=e,this.sequenceCounter=t,this.callback=s,this.sessionId=n}setSessionId(e){this.sessionId=e}start(){this.isInstrumented||typeof window>"u"||(this.isInstrumented=!0,this.cleanups=[],this.instrumentConsole(),this.instrumentGlobalErrors(),this.instrumentUnhandledRejections())}stop(){this.cleanups.forEach(e=>{try{e()}catch{}}),this.cleanups=[],this.isInstrumented=!1}instrumentConsole(){if(typeof console>"u")return;["log","warn","error","info","debug"].forEach(t=>{const s=console[t];s&&(this.originalConsole[t]=s,console[t]=(...n)=>{try{this.recordConsole(t,n)}catch{}return s.apply(console,n)},this.cleanups.push(()=>{console[t]=s}))})}recordConsole(e,t){const s=this.sequenceCounter.getRelativeTimestamp(),n=this.sequenceCounter.getWallClock(),i=this.sequenceCounter.nextSequence(),r=t.map(u=>{const h=typeof u;let g="";try{u instanceof Error?g=`${u.name}: ${u.message} +${u.stack||""}`:h==="object"&&u!==null?g=JSON.stringify(u,(p,y)=>typeof y=="function"?"[Function]":y):g=String(u)}catch{g="[Unserializable Object]"}return{type:h,value:this.privacy.sanitizeText(g)}}),o=r.map(u=>u.value).join(" ");let a;try{const u=new Error().stack;u&&(a=u.split(` `).slice(2,8).join(` -`))}catch{}const c={id:this.sequenceCounter.generateEventId("con",i),sessionId:this.sessionId,timestamp:s,sequence:i,wallClockTime:n,type:`RUNTIME_CONSOLE_${e.toUpperCase()}`,category:e==="error"?"ERROR":"CONSOLE",source:"PAGE",payload:{level:e,args:r,formattedMessage:o,stackTrace:a}};this.callback(c)}instrumentGlobalErrors(){if(typeof window>"u")return;const e=t=>{var o,a;const s=this.sequenceCounter.getRelativeTimestamp(),n=this.sequenceCounter.getWallClock(),i=this.sequenceCounter.nextSequence(),r={id:this.sequenceCounter.generateEventId("err",i),sessionId:this.sessionId,timestamp:s,sequence:i,wallClockTime:n,type:"RUNTIME_ERROR",category:"ERROR",source:"PAGE",payload:{message:t.message||"Unknown runtime error",filename:t.filename,lineno:t.lineno,colno:t.colno,stack:((o=t.error)==null?void 0:o.stack)||void 0,name:((a=t.error)==null?void 0:a.name)||"Error"}};this.callback(r)};window.addEventListener("error",e),this.cleanups.push(()=>window.removeEventListener("error",e))}instrumentUnhandledRejections(){if(typeof window>"u")return;const e=t=>{const s=this.sequenceCounter.getRelativeTimestamp(),n=this.sequenceCounter.getWallClock(),i=this.sequenceCounter.nextSequence();let r="Unhandled Promise Rejection",o;if(t.reason instanceof Error)r=t.reason.message,o=t.reason.stack;else if(typeof t.reason=="string")r=t.reason;else if(t.reason)try{r=JSON.stringify(t.reason)}catch{r=String(t.reason)}const a={id:this.sequenceCounter.generateEventId("rej",i),sessionId:this.sessionId,timestamp:s,sequence:i,wallClockTime:n,type:"RUNTIME_UNHANDLED_REJECTION",category:"ERROR",source:"PAGE",payload:{message:r,stack:o,isUnhandledRejection:!0}};this.callback(a)};window.addEventListener("unhandledrejection",e),this.cleanups.push(()=>window.removeEventListener("unhandledrejection",e))}}class Oe{constructor(e,t,s,n=""){f(this,"privacy");f(this,"sequenceCounter");f(this,"callback");f(this,"sessionId");f(this,"isInstrumented",!1);f(this,"originalFetch",null);f(this,"originalXHROpen",null);f(this,"originalXHRSend",null);f(this,"cleanups",[]);this.privacy=e,this.sequenceCounter=t,this.callback=s,this.sessionId=n}setSessionId(e){this.sessionId=e}start(){this.isInstrumented||typeof window>"u"||(this.isInstrumented=!0,this.cleanups=[],this.instrumentFetch(),this.instrumentXHR())}stop(){this.cleanups.forEach(e=>{try{e()}catch{}}),this.cleanups=[],this.isInstrumented=!1}instrumentFetch(){if(typeof window.fetch!="function")return;this.originalFetch=window.fetch;const e=this;window.fetch=async function(...t){const s=e.sequenceCounter.generateEventId("req_f"),n=t[0],i=t[1];let r="";typeof n=="string"?r=n:n instanceof URL?r=n.toString():n&&typeof n=="object"&&"url"in n&&(r=n.url);const o=((i==null?void 0:i.method)||(typeof n=="object"&&"method"in n?n.method:"GET")).toUpperCase(),a=e.privacy.sanitizeUrl(r),c=e.sequenceCounter.getRelativeTimestamp(),u=e.sequenceCounter.getWallClock(),d=e.sequenceCounter.nextSequence(),h={id:s,sessionId:e.sessionId,timestamp:c,sequence:d,wallClockTime:u,type:"NETWORK_REQUEST_START",category:"NETWORK",source:"PAGE",payload:{requestId:s,url:a,method:o,resourceType:"fetch",hasBody:!!(i!=null&&i.body)}};e.callback(h);try{const p=await e.originalFetch.apply(this,t),y=e.sequenceCounter.getRelativeTimestamp(),v=e.sequenceCounter.getWallClock(),m=e.sequenceCounter.nextSequence(),g=Math.max(0,Math.round((y-c)*100)/100),b={id:e.sequenceCounter.generateEventId("res_f",m),sessionId:e.sessionId,timestamp:y,sequence:m,wallClockTime:v,type:"NETWORK_RESPONSE_COMPLETE",category:"NETWORK",source:"PAGE",causality:{triggeredBy:s,precededBy:s},payload:{requestId:s,url:a,method:o,status:p.status,statusText:p.statusText,durationMs:g}};return e.callback(b),p}catch(p){const y=e.sequenceCounter.getRelativeTimestamp(),v=e.sequenceCounter.getWallClock(),m=e.sequenceCounter.nextSequence(),g=Math.max(0,Math.round((y-c)*100)/100),b={id:e.sequenceCounter.generateEventId("res_err",m),sessionId:e.sessionId,timestamp:y,sequence:m,wallClockTime:v,type:"NETWORK_REQUEST_FAILED",category:"NETWORK",source:"PAGE",causality:{triggeredBy:s,precededBy:s},payload:{requestId:s,url:a,method:o,status:0,statusText:"Failed",durationMs:g,error:(p==null?void 0:p.message)||"Network request failed"}};throw e.callback(b),p}},this.cleanups.push(()=>{this.originalFetch&&(window.fetch=this.originalFetch)})}instrumentXHR(){if(typeof XMLHttpRequest>"u")return;this.originalXHROpen=XMLHttpRequest.prototype.open,this.originalXHRSend=XMLHttpRequest.prototype.send;const e=this;XMLHttpRequest.prototype.open=function(t,s,...n){return this._forensicRequestId=e.sequenceCounter.generateEventId("req_x"),this._forensicMethod=(t||"GET").toUpperCase(),this._forensicUrl=typeof s=="string"?s:s.toString(),e.originalXHROpen.apply(this,[t,s,...n])},XMLHttpRequest.prototype.send=function(t){const s=this._forensicRequestId||e.sequenceCounter.generateEventId("req_x"),n=this._forensicMethod||"GET",i=e.privacy.sanitizeUrl(this._forensicUrl||""),r=e.sequenceCounter.getRelativeTimestamp(),o=e.sequenceCounter.getWallClock(),a=e.sequenceCounter.nextSequence();this._forensicStartTime=r;const c={id:s,sessionId:e.sessionId,timestamp:r,sequence:a,wallClockTime:o,type:"NETWORK_REQUEST_START",category:"NETWORK",source:"PAGE",payload:{requestId:s,url:i,method:n,resourceType:"xhr",hasBody:!!t}};e.callback(c);const u=()=>{const d=e.sequenceCounter.getRelativeTimestamp(),h=e.sequenceCounter.getWallClock(),p=e.sequenceCounter.nextSequence(),y=Math.max(0,Math.round((d-(this._forensicStartTime||r))*100)/100),v={id:e.sequenceCounter.generateEventId("res_x",p),sessionId:e.sessionId,timestamp:d,sequence:p,wallClockTime:h,type:this.status>=200&&this.status<400?"NETWORK_RESPONSE_COMPLETE":"NETWORK_REQUEST_FAILED",category:"NETWORK",source:"PAGE",causality:{triggeredBy:s,precededBy:s},payload:{requestId:s,url:i,method:n,status:this.status,statusText:this.statusText,durationMs:y,error:this.status===0?"XHR Network Error or Aborted":void 0}};e.callback(v)};return this.addEventListener("load",u),this.addEventListener("error",u),this.addEventListener("abort",u),e.originalXHRSend.apply(this,[t])},this.cleanups.push(()=>{this.originalXHROpen&&(XMLHttpRequest.prototype.open=this.originalXHROpen),this.originalXHRSend&&(XMLHttpRequest.prototype.send=this.originalXHRSend)})}}class Le{constructor(e={}){f(this,"sequenceCounter");f(this,"registry");f(this,"privacy");f(this,"snapshotEngine");f(this,"mutationObserver");f(this,"eventCollector");f(this,"diagnostics");f(this,"networkMonitor");f(this,"metadata");f(this,"isRecording",!1);f(this,"isPaused",!1);f(this,"eventListeners",new Set);f(this,"checkpointListeners",new Set);f(this,"lastCheckpointSequence",0);f(this,"lastCheckpointTimestamp",0);f(this,"checkpointTimer",null);f(this,"checkpointIntervalEvents",200);f(this,"checkpointIntervalMs",3e4);this.sequenceCounter=new oe,this.registry=new z,this.privacy=new se(e.privacy),this.snapshotEngine=new me(this.registry,this.privacy,this.sequenceCounter);const t=n=>this.handleEvent(n);this.mutationObserver=new Re(this.registry,this.privacy,this.sequenceCounter,this.snapshotEngine,t),this.eventCollector=new Me(this.registry,this.privacy,this.sequenceCounter,t),this.diagnostics=new ke(this.privacy,this.sequenceCounter,t),this.networkMonitor=new Oe(this.privacy,this.sequenceCounter,t),e.checkpointIntervalEvents&&(this.checkpointIntervalEvents=e.checkpointIntervalEvents),e.checkpointIntervalMs&&(this.checkpointIntervalMs=e.checkpointIntervalMs);const s=e.sessionId||`session_${Date.now()}_${Math.random().toString(36).substring(2,7)}`;this.metadata=this.createInitialMetadata(s,e.sessionName)}getSessionId(){return this.metadata.id}getMetadata(){return{...this.metadata,durationMs:this.sequenceCounter.getRelativeTimestamp(),endTime:this.metadata.endTime||Date.now()}}getRegistry(){return this.registry}onEvent(e){return this.eventListeners.add(e),()=>this.eventListeners.delete(e)}onCheckpoint(e){return this.checkpointListeners.add(e),()=>this.checkpointListeners.delete(e)}start(e=typeof document<"u"?document:{}){if(this.isRecording)throw new Error(`Recorder session ${this.metadata.id} is already active`);this.sequenceCounter.reset(),this.registry.reset(),this.isRecording=!0,this.isPaused=!1,this.metadata.status="recording",this.metadata.startTime=Date.now(),this.mutationObserver.setSessionId(this.metadata.id),this.eventCollector.setSessionId(this.metadata.id),this.diagnostics.setSessionId(this.metadata.id),this.networkMonitor.setSessionId(this.metadata.id);const t=this.snapshotEngine.captureSnapshot(e,this.metadata.id);this.metadata.stats.nodeCount=t.totalNodeCount;const s={id:this.sequenceCounter.generateEventId("snap_init",t.sequence),sessionId:this.metadata.id,timestamp:t.timestamp,sequence:t.sequence,wallClockTime:Date.now(),type:"DOM_SNAPSHOT",category:"DOM",source:"PAGE",payload:{snapshot:t}};return this.createCheckpoint(t,"INITIAL"),this.mutationObserver.start(e),this.eventCollector.start(),this.diagnostics.start(),this.networkMonitor.start(),this.handleEvent(s),this.checkpointIntervalMs>0&&typeof setInterval<"u"&&(this.checkpointTimer=setInterval(()=>{this.isRecording&&!this.isPaused&&this.captureCheckpoint("PERIODIC",e)},this.checkpointIntervalMs)),t}stop(){return this.isRecording?(this.mutationObserver.takeRecords(),this.mutationObserver.stop(),this.eventCollector.stop(),this.diagnostics.stop(),this.networkMonitor.stop(),this.checkpointTimer&&(clearInterval(this.checkpointTimer),this.checkpointTimer=null),this.isRecording=!1,this.metadata.status="stopped",this.metadata.endTime=Date.now(),this.metadata.durationMs=this.sequenceCounter.getRelativeTimestamp(),this.getMetadata()):this.getMetadata()}pause(){!this.isRecording||this.isPaused||(this.isPaused=!0,this.metadata.status="paused")}resume(){!this.isRecording||!this.isPaused||(this.isPaused=!1,this.metadata.status="recording")}captureCheckpoint(e="MANUAL",t=document){if(!this.isRecording)return null;const s=this.snapshotEngine.captureSnapshot(t,this.metadata.id);return this.createCheckpoint(s,e)}recordCustomEvent(e,t,s,n){const i=this.sequenceCounter.getRelativeTimestamp(),r=this.sequenceCounter.getWallClock(),o=this.sequenceCounter.nextSequence(),a={id:this.sequenceCounter.generateEventId("ext",o),sessionId:this.metadata.id,timestamp:i,sequence:o,wallClockTime:r,type:e,category:"EXTENSION",source:"CONTENT_SCRIPT",targetNodeId:s,targetSelector:n,payload:t};return this.handleEvent(a),a}recordScreenshot(e,t="MANUAL"){const s=this.sequenceCounter.getRelativeTimestamp(),n=this.sequenceCounter.getWallClock(),i=this.sequenceCounter.nextSequence(),r={id:this.sequenceCounter.generateEventId("scr",i),sessionId:this.metadata.id,timestamp:s,sequence:i,wallClockTime:n,type:"SCREENSHOT_CHECKPOINT",category:"SCREENSHOT",source:"BROWSER_RUNTIME",payload:{screenshotId:`shot_${i}`,dataUrl:e,viewport:{width:typeof window<"u"?window.innerWidth:1920,height:typeof window<"u"?window.innerHeight:1080,scrollX:typeof window<"u"?window.scrollX:0,scrollY:typeof window<"u"?window.scrollY:0,devicePixelRatio:typeof window<"u"?window.devicePixelRatio:1},triggerReason:t}};return this.handleEvent(r),r}addAnnotation(e,t,s="AGENT",n){const i=this.sequenceCounter.getRelativeTimestamp(),r=this.sequenceCounter.nextSequence(),o={id:`ann_${r}_${Math.random().toString(36).substring(2,6)}`,sessionId:this.metadata.id,timestamp:i,sequence:r,nodeId:n,author:s,label:e,comment:t,createdAt:Date.now()},a={id:o.id,sessionId:this.metadata.id,timestamp:i,sequence:r,wallClockTime:Date.now(),type:"ANNOTATION",category:"ANNOTATION",source:s==="USER"?"USER_INTERACTION":"BROWSER_RUNTIME",targetNodeId:n,payload:{annotation:o}};return this.handleEvent(a),o}createCheckpoint(e,t){const s=this.sequenceCounter.getSequence()-this.lastCheckpointSequence;this.lastCheckpointSequence=this.sequenceCounter.getSequence(),this.lastCheckpointTimestamp=e.timestamp,this.metadata.stats.checkpointCount+=1;const n={checkpointId:`chk_${e.sequence}_${Date.now()}`,sessionId:this.metadata.id,timestamp:e.timestamp,sequence:e.sequence,wallClockTime:Date.now(),snapshot:e,eventIndex:this.metadata.stats.eventCount,eventsSinceLastCheckpoint:s,trigger:t},i={id:n.checkpointId,sessionId:this.metadata.id,timestamp:e.timestamp,sequence:e.sequence,wallClockTime:n.wallClockTime,type:"CHECKPOINT",category:"CHECKPOINT",source:"BROWSER_RUNTIME",payload:{checkpointId:n.checkpointId,snapshot:e,eventsSinceLastCheckpoint:s,totalEventsSoFar:this.metadata.stats.eventCount}};return this.checkpointListeners.forEach(r=>{try{r(n)}catch(o){console.error("[ForensicRecorder] Checkpoint listener error:",o)}}),this.handleEvent(i),n}handleEvent(e){this.isPaused&&e.type!=="CHECKPOINT"&&e.type!=="ANNOTATION"||(this.metadata.stats.eventCount+=1,e.category==="DOM"&&(this.metadata.stats.mutationCount+=1),e.category==="ERROR"&&(this.metadata.stats.errorCount+=1),e.category==="CONSOLE"&&(this.metadata.stats.consoleCount+=1),e.category==="NETWORK"&&(this.metadata.stats.networkCount+=1),e.category==="SCREENSHOT"&&(this.metadata.stats.screenshotCount+=1),this.isRecording&&e.type!=="CHECKPOINT"&&e.type!=="DOM_SNAPSHOT"&&this.sequenceCounter.getSequence()-this.lastCheckpointSequence>=this.checkpointIntervalEvents&&typeof document<"u"&&this.captureCheckpoint("PERIODIC"),this.eventListeners.forEach(t=>{try{t(e)}catch(s){console.error("[ForensicRecorder] Event listener error:",s)}}))}createInitialMetadata(e,t){const s={domRecording:typeof MutationObserver<"u"?"HEALTHY":"UNAVAILABLE",userEvents:typeof window<"u"?"HEALTHY":"UNAVAILABLE",console:typeof console<"u"?"HEALTHY":"UNAVAILABLE",network:typeof window<"u"&&typeof window.fetch<"u"?"HEALTHY":"PARTIAL",screenshots:"HEALTHY",shadowDom:typeof Element<"u"&&"attachShadow"in Element.prototype?"HEALTHY":"RESTRICTED",iframes:"PARTIAL"},n={eventCount:0,mutationCount:0,errorCount:0,consoleCount:0,networkCount:0,checkpointCount:0,screenshotCount:0,nodeCount:0};return{id:e,name:t||`Recording ${new Date().toLocaleTimeString()}`,url:typeof window<"u"?window.location.href:"about:blank",origin:typeof window<"u"?window.location.origin:"",title:typeof document<"u"?document.title:"Forensic Session",userAgent:typeof navigator<"u"?navigator.userAgent:"Node.js/ForensicAgent",schemaVersion:"2.0.0",recorderVersion:"2.0.0",extensionVersion:"2.0.0",startTime:Date.now(),status:"recording",health:s,stats:n}}}class L{static inspectPage(e=document){var n,i,r,o,a,c,u,d,h,p,y,v,m,g;const t=e.defaultView||(typeof window<"u"?window:{}),s=e.activeElement;return{url:((n=t.location)==null?void 0:n.href)||((i=e.location)==null?void 0:i.href)||"",title:e.title||"",origin:((r=t.location)==null?void 0:r.origin)||"",viewport:{width:t.innerWidth||((o=e.documentElement)==null?void 0:o.clientWidth)||1920,height:t.innerHeight||((a=e.documentElement)==null?void 0:a.clientHeight)||1080,scrollX:t.scrollX||t.pageXOffset||((c=e.documentElement)==null?void 0:c.scrollLeft)||0,scrollY:t.scrollY||t.pageYOffset||((u=e.documentElement)==null?void 0:u.scrollTop)||0,devicePixelRatio:t.devicePixelRatio||1},documentDimensions:{width:Math.max(((d=e.body)==null?void 0:d.scrollWidth)||0,((h=e.documentElement)==null?void 0:h.scrollWidth)||0),height:Math.max(((p=e.body)==null?void 0:p.scrollHeight)||0,((y=e.documentElement)==null?void 0:y.scrollHeight)||0)},activeElement:s?{tag:((v=s.tagName)==null?void 0:v.toLowerCase())||"",selector:this.computeBestSelector(s),text:(m=s.textContent)==null?void 0:m.slice(0,100).trim()}:void 0,focusedElement:typeof e.hasFocus=="function"&&e.hasFocus()&&s?{tag:((g=s.tagName)==null?void 0:g.toLowerCase())||"",selector:this.computeBestSelector(s)}:void 0,visibilityState:e.visibilityState||"visible",readyState:e.readyState||"complete",framesCount:e.querySelectorAll?e.querySelectorAll("iframe, frame").length:0}}static inspectElement(e,t){var te,Ne;const s=e.ownerDocument||document,n=s.defaultView||(typeof window<"u"?window:{}),i=e,r=e.tagName?e.tagName.toLowerCase():"element",o=this.extractClasses(e),{bestSelector:a,candidates:c}=this.generateSelectorCandidates(e),u={},d={};if(e.attributes)for(let G=0;G 0||w.height>0||w.right>0||w.bottom>0,M=!S||w.right>0&&w.bottom>0&&w.left =q||w.top>=A),_=!O&&C!=="none"&&N!=="hidden"&&I>0&&M,P={disabled:i.disabled??e.hasAttribute("disabled"),readOnly:i.readOnly??e.hasAttribute("readonly"),checked:i.checked,selected:i.selected,focused:s.activeElement===e,isShadowHost:!!e.shadowRoot,hasShadowRoot:!!e.shadowRoot},H=[];let $=e.parentElement;for(;$&&$.tagName&&$.tagName.toLowerCase()!=="html";)H.push(this.computeBestSelector($)),$=$.parentElement;const F={count:e.children?e.children.length:0,tags:e.children?Array.from(e.children).slice(0,10).map(G=>G.tagName.toLowerCase()):[]};let W;if(t){const G=t.getId(e);W={logicalNodeId:G??null,creationSequence:null,lastMutationSequence:null,eventCount:0,isRecorded:G!=null}}return{tag:r,id:e.id||void 0,classes:o,role:h||void 0,ariaAttributes:Object.keys(d).length>0?d:void 0,text:v.slice(0,200),normalizedText:m.slice(0,200),value:g,type:b.type||void 0,selector:a,bestSelector:a,selectorCandidates:c,bounds:w,visibility:{isVisible:_,display:C,visibility:N,opacity:I,pointerEvents:R,isClipped:O,isInViewport:M,zIndex:x},computedStyle:E?{display:C,visibility:N,opacity:String(I),position:E.position,zIndex:String(x),pointerEvents:R,overflow:E.overflow,boxSizing:E.boxSizing,color:E.color,backgroundColor:E.backgroundColor,fontSize:E.fontSize}:{},attributes:u,state:P,context:{parentChain:H,parentSelector:H[0]||void 0,childrenSummary:F,containingBlock:(E==null?void 0:E.position)==="fixed"?"viewport":H[0]||void 0,iframe:null,shadowRoot:e.shadowRoot?"open":null},forensics:W}}static inspectVisualState(e){var b,T;const t=e.ownerDocument||document,s=t.defaultView||(typeof window<"u"?window:{}),n=e.getBoundingClientRect?e.getBoundingClientRect():{x:0,y:0,width:0,height:0,top:0,right:0,bottom:0,left:0},i=s.getComputedStyle?s.getComputedStyle(e):null,r=s.innerWidth||((b=t.documentElement)==null?void 0:b.clientWidth)||1920,o=s.innerHeight||((T=t.documentElement)==null?void 0:T.clientHeight)||1080,a=s.scrollX||s.pageXOffset||0,c=s.scrollY||s.pageYOffset||0,u=s.devicePixelRatio||1,d=(i==null?void 0:i.display)||"block",h=(i==null?void 0:i.visibility)||"visible",p=i&&parseFloat(i.opacity)||1,y=n.right>0&&n.bottom>0&&n.left=r||n.top>=o;let g=null;if(t.elementFromPoint&&y&&!v&&d!=="none"){const w=Math.max(0,Math.min(r-1,n.left+n.width/2)),E=Math.max(0,Math.min(o-1,n.top+n.height/2));try{const C=t.elementFromPoint(w,E);C&&C!==e&&!e.contains(C)&&!C.contains(e)&&(g=this.computeBestSelector(C))}catch{}}return{selector:this.computeBestSelector(e),bounds:{x:n.x??n.left??0,y:n.y??n.top??0,width:n.width??0,height:n.height??0,top:n.top??0,right:n.right??0,bottom:n.bottom??0,left:n.left??0},viewport:{scrollX:a,scrollY:c,width:r,height:o,devicePixelRatio:u},layout:{display:d,position:(i==null?void 0:i.position)||"static",zIndex:(i==null?void 0:i.zIndex)||"auto",opacity:p,visibility:h,overflow:(i==null?void 0:i.overflow)||"visible",boxSizing:(i==null?void 0:i.boxSizing)||"content-box",pointerEvents:(i==null?void 0:i.pointerEvents)||"auto"},occlusion:{isInViewport:y,isClipped:v||m,isZeroDimension:v,isTransparent:p===0,isDisplayNone:d==="none",isVisibilityHidden:h==="hidden",isOffscreen:m,occludedBy:g},computedStyleSummary:i?{display:d,position:i.position,zIndex:i.zIndex,opacity:String(p),visibility:h,pointerEvents:i.pointerEvents}:{}}}static generateSelectorCandidates(e){const t=e.ownerDocument||document,s=e.tagName?e.tagName.toLowerCase():"element",n=[];if(e.id&&/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(e.id)){const c=`#${e.id}`;try{t.querySelectorAll&&t.querySelectorAll(c).length===1&&n.push(c)}catch{n.push(c)}}const i=["data-testid","data-test","data-id","data-qa","data-cy","aria-label","name"];for(const c of i){const u=e.getAttribute(c);if(u&&/^[a-zA-Z0-9_-]+$/.test(u)){const d=`${s}[${c}="${u}"]`;try{t.querySelectorAll&&t.querySelectorAll(d).length===1&&n.push(d)}catch{n.push(d)}}}const r=this.extractClasses(e).filter(c=>/^[a-zA-Z0-9_-]+$/.test(c)&&!c.startsWith("ng-")&&!c.startsWith("_ng"));if(r.length>0){const c=`${s}.${r.slice(0,3).join(".")}`;try{t.querySelectorAll&&t.querySelectorAll(c).length===1&&n.push(c)}catch{n.push(c)}}if(e.parentElement&&e.parentElement.children){const c=Array.from(e.parentElement.children).filter(u=>u.tagName&&u.tagName.toLowerCase()===s);if(c.length>1){const u=c.indexOf(e)+1;if(u>0){const d=this.computeBestSelector(e.parentElement);n.push(`${d} > ${s}:nth-of-type(${u})`)}}}const o=r.length>0?`${s}.${r[0]}`:s;return n.push(o),{bestSelector:n[0]||s,candidates:n}}static computeBestSelector(e){return this.generateSelectorCandidates(e).bestSelector}static extractClasses(e){return e.classList&&typeof e.classList.forEach=="function"?Array.from(e.classList):typeof e.className=="string"?e.className.split(/\s+/).filter(Boolean):e.className&&typeof e.className.baseVal=="string"?e.className.baseVal.split(/\s+/).filter(Boolean):[]}static inferImplicitRole(e){switch(e.tagName?e.tagName.toLowerCase():""){case"a":return e.hasAttribute("href")?"link":void 0;case"button":return"button";case"input":{const s=e.type||"text";return s==="button"||s==="submit"||s==="reset"?"button":s==="checkbox"?"checkbox":s==="radio"?"radio":"textbox"}case"select":return"combobox";case"textarea":return"textbox";case"nav":return"navigation";case"header":return"banner";case"footer":return"contentinfo";case"main":return"main";case"article":return"article";case"section":return"region";default:return}}}f(L,"privacyEngine",new se);class De{constructor(e){f(this,"registry");f(this,"lastSelectedElementRef");f(this,"timingHook",null);f(this,"lastTrajectory",[]);this.registry=e}setLastSelectedElement(e){this.lastSelectedElementRef=e}setTimingHook(e){this.timingHook=e}getLastTrajectory(){return this.lastTrajectory}async timing(e){this.timingHook&&await this.timingHook(e)}resolveTarget(e,t=document){if(e.selectedElementRef&&this.lastSelectedElementRef&&t.contains(this.lastSelectedElementRef))return this.lastSelectedElementRef;if(typeof e.nodeId=="number"&&this.registry){const s=this.registry.getNode(e.nodeId);if(s&&s instanceof Element&&t.contains(s))return s}if(e.selector)try{const s=t.querySelectorAll(e.selector);if(s.length>1){for(let n=0;n {r+=T.length});try{d.observe(t.body||t.documentElement,{childList:!0,attributes:!0,characterData:!0,subtree:!0})}catch{}const h=T=>{o.push(T.message||"Runtime Error")};typeof window<"u"&&window.addEventListener("error",h);try{await this.dispatchAction(n,e)}finally{typeof window<"u"&&window.removeEventListener("error",h)}let p=!0;if((b=e.options)!=null&&b.waitForStabilization){const T=e.options.stabilizationTimeoutMs||300;await new Promise(w=>setTimeout(w,Math.min(2e3,T)))}d.disconnect();let y;t.contains(n)&&(y=L.inspectElement(n,this.registry));const v=Date.now()-s,m=a!=null&&a.__FORENSIC_CONSOLE_BUFFER__?a.__FORENSIC_CONSOLE_BUFFER__.slice(c).filter(T=>(T==null?void 0:T.level)==="error").length:0,g=a!=null&&a.__FORENSIC_NETWORK_BUFFER__?a.__FORENSIC_NETWORK_BUFFER__.slice(u).length:0;return{success:!0,action:e.action,target:y||i,beforeState:i,afterState:y,effects:{domMutations:r,consoleErrors:m,networkRequests:g,runtimeErrors:o},durationMs:v,stabilized:p}}async dispatchAction(e,t){var n,i,r,o,a,c;const s=e;switch(t.action){case"click":{this.scrollIntoViewIfNeeded(e),await this.timing("move"),await this.timing("click"),this.dispatchMouseEvent(e,"pointerdown"),this.dispatchMouseEvent(e,"mousedown"),typeof s.focus=="function"&&s.focus(),this.dispatchMouseEvent(e,"pointerup"),this.dispatchMouseEvent(e,"mouseup"),typeof s.click=="function"?s.click():this.dispatchMouseEvent(e,"click");break}case"double_click":{this.scrollIntoViewIfNeeded(e),await this.timing("click"),this.dispatchMouseEvent(e,"click"),await this.timing("click"),this.dispatchMouseEvent(e,"click"),this.dispatchMouseEvent(e,"dblclick");break}case"right_click":{this.scrollIntoViewIfNeeded(e),await this.timing("click"),this.dispatchMouseEvent(e,"pointerdown",{button:2}),this.dispatchMouseEvent(e,"mousedown",{button:2}),this.dispatchMouseEvent(e,"contextmenu",{button:2});break}case"hover":{await this.timing("move"),this.dispatchMouseEvent(e,"pointerenter"),this.dispatchMouseEvent(e,"mouseenter"),this.dispatchMouseEvent(e,"mouseover"),await this.timing("move"),this.dispatchMouseEvent(e,"mousemove");break}case"focus":{typeof s.focus=="function"&&s.focus(),e.dispatchEvent(new FocusEvent("focus",{bubbles:!0}));break}case"blur":{typeof s.blur=="function"&&s.blur(),e.dispatchEvent(new FocusEvent("blur",{bubbles:!0}));break}case"type":{const u=t.text||"",d=e,h=((n=e.ownerDocument)==null?void 0:n.defaultView)||(typeof window<"u"?window:null);typeof s.focus=="function"&&s.focus();for(const y of u){await this.timing("type");const v=g=>{try{const T=(h==null?void 0:h.KeyboardEvent)||(typeof KeyboardEvent<"u"?KeyboardEvent:null);if(T)return new T(g,{key:y,bubbles:!0})}catch{}const b=(h==null?void 0:h.CustomEvent)||(h==null?void 0:h.Event)||CustomEvent;return new b(g,{bubbles:!0,cancelable:!0})},m=(g,b)=>{try{const w=(h==null?void 0:h.InputEvent)||(typeof InputEvent<"u"?InputEvent:null);if(w)return new w(g,b)}catch{}const T=(h==null?void 0:h.CustomEvent)||(h==null?void 0:h.Event)||CustomEvent;return new T(g,{bubbles:!0,cancelable:!0})};e.dispatchEvent(v("keydown")),e.dispatchEvent(v("keypress")),"value"in d&&(d.value=(d.value||"")+y),e.dispatchEvent(m("input",{data:y,inputType:"insertText",bubbles:!0})),e.dispatchEvent(v("keyup"))}const p=(h==null?void 0:h.Event)||Event;e.dispatchEvent(new p("change",{bubbles:!0}));break}case"clear":{const u=e,d=((i=e.ownerDocument)==null?void 0:i.defaultView)||(typeof window<"u"?window:null);if("value"in u){u.value="";const h=(y,v)=>{try{const g=(d==null?void 0:d.InputEvent)||(typeof InputEvent<"u"?InputEvent:null);if(g)return new g(y,v)}catch{}const m=(d==null?void 0:d.CustomEvent)||(d==null?void 0:d.Event)||CustomEvent;return new m(y,{bubbles:!0,cancelable:!0})};e.dispatchEvent(h("input",{inputType:"deleteContentBackward",bubbles:!0}));const p=(d==null?void 0:d.Event)||Event;e.dispatchEvent(new p("change",{bubbles:!0}))}break}case"press_key":{const u=t.key||"Enter",d=((r=e.ownerDocument)==null?void 0:r.defaultView)||(typeof window<"u"?window:null),h=p=>{try{const v=(d==null?void 0:d.KeyboardEvent)||(typeof KeyboardEvent<"u"?KeyboardEvent:null);if(v)return new v(p,{key:u,bubbles:!0})}catch{}const y=(d==null?void 0:d.CustomEvent)||(d==null?void 0:d.Event)||CustomEvent;return new y(p,{bubbles:!0,cancelable:!0})};e.dispatchEvent(h("keydown")),e.dispatchEvent(h("keypress")),e.dispatchEvent(h("keyup"));break}case"select_option":{const u=e;((o=u.tagName)==null?void 0:o.toLowerCase())==="select"&&t.optionValue&&(u.value=t.optionValue,e.dispatchEvent(new Event("change",{bubbles:!0})));break}case"scroll_into_view":{this.scrollIntoViewIfNeeded(e,!0);break}case"scroll":{const u=((a=t.scrollDelta)==null?void 0:a.x)||0,d=((c=t.scrollDelta)==null?void 0:c.y)||0;typeof e.scrollBy=="function"&&e.scrollBy(u,d);break}default:throw new Error(`Unsupported interaction action: ${t.action}`)}}scrollIntoViewIfNeeded(e,t=!1){if(typeof e.scrollIntoView=="function")try{e.scrollIntoView({behavior:"auto",block:"center",inline:"center"})}catch{e.scrollIntoView(t)}}dispatchMouseEvent(e,t,s={}){const n=e.getBoundingClientRect?e.getBoundingClientRect():{left:0,top:0,width:0,height:0},i=n.left+n.width/2,r=n.top+n.height/2,o=new MouseEvent(t,{bubbles:s.bubbles!==void 0?s.bubbles:!0,cancelable:s.cancelable!==void 0?s.cancelable:!0,clientX:i,clientY:r,button:s.button||0,buttons:s.button===2?2:1});e.dispatchEvent(o)}}class ae{static matches(e,t){if(!e||e.nodeType!==U.ELEMENT_NODE)return!1;const s=t.trim();return s?s.includes(",")?s.split(",").some(n=>this.matchesSimple(e,n.trim())):this.matchesCompound(e,s):!1}static querySelector(e,t,s){const n=this.querySelectorAll(e,t,s,1);return n.length>0?n[0]:null}static querySelectorAll(e,t,s,n=1/0){const i=[],r=s[t];if(!r)return i;const o=[...r.children||[]],a=new Set;for(;o.length>0&&i.length =n))break;u.children&&u.children.length>0&&o.push(...u.children)}}return i}static getElementById(e,t){for(const s of Object.values(t))if(s.nodeType===U.ELEMENT_NODE&&!s.isDetached&&s.attributes&&s.attributes.id===e&&this.isNodeConnected(s,t))return s;return null}static isNodeConnected(e,t){if(e.isDetached)return!1;let s=e;const n=new Set;for(;s&&s.parentId;){if(n.has(s.id))return!1;n.add(s.id);const i=t[s.parentId];if(!i||i.isDetached)return!1;s=i}return!0}static computeSelector(e,t){var r,o;if(!e)return"";if(e.nodeType!==U.ELEMENT_NODE)return e.tagName||`#node-${e.id}`;if((r=e.attributes)!=null&&r.id)return`#${e.attributes.id}`;const s=e.tagName||"div",n=(((o=e.attributes)==null?void 0:o.class)||"").split(/\s+/).filter(a=>a&&!a.startsWith("ng-")).slice(0,2),i=n.length>0?"."+n.join("."):"";if(e.parentId&&t[e.parentId]){const c=(t[e.parentId].children||[]).map(u=>t[u]).filter(u=>u&&u.nodeType===U.ELEMENT_NODE&&u.tagName===s);if(c.length>1){const u=c.findIndex(d=>d.id===e.id)+1;return`${s}${i}:nth-of-type(${u})`}}return`${s}${i}`}static matchesCompound(e,t){return this.matchesSimple(e,t)}static matchesSimple(e,t){var i,r,o,a,c,u,d;const s=((i=e.tagName)==null?void 0:i.toLowerCase())||"";if(t==="*")return!0;if(t.startsWith("#")){const h=t.substring(1);return((r=e.attributes)==null?void 0:r.id)===h}if(t.startsWith(".")){const h=t.substring(1);return(((o=e.attributes)==null?void 0:o.class)||"").split(/\s+/).includes(h)}if(t.startsWith("[")&&t.endsWith("]")){const h=t.substring(1,t.length-1);if(h.includes("=")){const[p,y]=h.split("="),v=y.replace(/^["']|["']$/g,"");return((a=e.attributes)==null?void 0:a[p.trim()])===v}return!!((c=e.attributes)!=null&&c[h.trim()])}const n=t.match(/^([a-zA-Z0-9_-]+)(.*)$/);if(n){const h=n[1].toLowerCase(),p=n[2];if(h!==s&&h!=="*")return!1;if(!p)return!0;if(p.startsWith("#"))return((u=e.attributes)==null?void 0:u.id)===p.substring(1);if(p.startsWith("."))return(((d=e.attributes)==null?void 0:d.class)||"").split(/\s+/).includes(p.substring(1));if(p.startsWith("["))return this.matchesSimple(e,p)}return!1}}class $e{static traceElement(e,t,s){var x,q;const n=[...t].sort((A,S)=>A.sequence-S.sequence);let i=e.nodeId,r="unknown",o=e.selector||"",a={},c=0,u=0,d="init";if(!i&&e.selector&&s){const A=ae.querySelector(e.selector,s.rootId,s.nodes);A&&(i=A.id,r=A.tagName||"element",a={...A.attributes||{}},o=e.selector)}if(!i&&e.selector){for(const A of n)if(A.type==="DOM_MUTATION_ADD"){const S=A.payload;if(S.node&&ae.matches(S.node,e.selector)){i=S.node.id,r=S.node.tagName||"element",a={...S.node.attributes||{}},c=A.timestamp,u=A.sequence,d=A.id;break}}}if(!i)return null;const h=[];let p=!0,y=null,v=null,m,g=0;if(s&&s.nodes[i]){const A=s.nodes[i];r=A.tagName||r,a={...A.attributes||{}},o||(o=ae.computeSelector(A,s.nodes)),h.push({timestamp:s.timestamp,sequence:s.sequence,wallClockTime:Date.now(),stage:"CREATED",eventId:s.snapshotId,eventType:"DOM_SNAPSHOT",description:`Element <${r}> existed in initial baseline snapshot [ID: ${i}]`,details:{initialParentId:A.parentId,attributes:a},nodeSnapshot:A})}const b=new Map;if(s)for(const[A,S]of Object.entries(s.nodes))b.set(Number(A),S.parentId??null);const T=(A,S)=>{let M=b.get(S);const O=new Set;for(;M&&!O.has(M);){if(M===A)return!0;O.add(M),M=b.get(M)}return!1};for(const A of n){const S=A.timestamp,M=A.sequence,O=A.wallClockTime;if(A.type==="DOM_MUTATION_ADD"){const _=A.payload;(x=_.node)!=null&&x.id&&b.set(_.node.id,_.parentId??null),((q=_.node)==null?void 0:q.id)===i&&(p=!0,r=_.node.tagName||r,c=S,u=M,d=A.id,a={..._.node.attributes||{}},h.push({timestamp:S,sequence:M,wallClockTime:O,stage:"ATTACHED_TO_DOM",eventId:A.id,eventType:A.type,description:`Element <${r}> added to DOM under parent ID ${_.parentId}`,details:{parentId:_.parentId,index:_.index},nodeSnapshot:_.node}))}if(A.type==="DOM_MUTATION_REMOVE"){const _=A.payload;_.nodeId===i?(p=!1,y=S,v=M,m=A.id,h.push({timestamp:S,sequence:M,wallClockTime:O,stage:"REMOVED_FROM_DOM",eventId:A.id,eventType:A.type,description:`Element <${r}> explicitly removed from parent ID ${_.parentId}`,details:{parentId:_.parentId,removedIndex:_.index}})):T(_.nodeId,i)&&(p=!1,y=S,v=M,m=A.id,h.push({timestamp:S,sequence:M,wallClockTime:O,stage:"PARENT_SUBTREE_REPLACED",eventId:A.id,eventType:A.type,description:`Ancestor element [ID: ${_.nodeId}] was removed, causing target element [ID: ${i}] to detach from DOM`,details:{removedAncestorId:_.nodeId,parentId:_.parentId}}))}if(A.type==="DOM_MUTATION_MOVE"){const _=A.payload;_.nodeId&&b.set(_.nodeId,_.newParentId??null),_.nodeId===i&&(g++,h.push({timestamp:S,sequence:M,wallClockTime:O,stage:"REPARENTED",eventId:A.id,eventType:A.type,description:`Element reparented from parent ${_.oldParentId} to ${_.newParentId}`,details:{oldParentId:_.oldParentId,newParentId:_.newParentId}}))}if(A.type==="DOM_MUTATION_ATTR"){const _=A.payload;if(_.nodeId===i){g++;const P=_.attributeName.toLowerCase();let H="ATTRIBUTE_MODIFIED";P==="class"&&(H="CLASS_MODIFIED"),P==="style"&&(H="STYLE_MODIFIED"),h.push({timestamp:S,sequence:M,wallClockTime:O,stage:H,eventId:A.id,eventType:A.type,description:`Attribute '${_.attributeName}' changed from '${_.oldValue??""}' to '${_.newValue??""}'`,details:{attributeName:_.attributeName,oldValue:_.oldValue,newValue:_.newValue}})}}if(A.type==="DOM_MUTATION_TEXT"){const _=A.payload;_.nodeId===i&&(g++,h.push({timestamp:S,sequence:M,wallClockTime:O,stage:"TEXT_MODIFIED",eventId:A.id,eventType:A.type,description:`Text content changed: "${_.oldText}" → "${_.newText}"`,details:{oldText:_.oldText,newText:_.newText}}))}}const w=y??c,E=500,C=n.filter(A=>(A.category==="ERROR"||A.category==="CONSOLE")&&Math.abs(A.timestamp-w)<=E),N=n.filter(A=>A.category==="NETWORK"&&Math.abs(A.timestamp-w)<=E),I=n.length>0?n[n.length-1].timestamp:c,R=Math.max(0,(y??I)-c);return{targetNodeId:i,tagName:r,selectorHint:o,initialAttributes:a,createdAt:c,createdSequence:u,createdEventId:d,removedAt:y,removedSequence:v,removedEventId:m,isCurrentlyAlive:p,lifespanMs:Math.round(R*100)/100,mutationCount:g,entries:h,correlatedDiagnostics:C,correlatedNetwork:N}}}class qe{static analyze(e,t,s){var R,x,q,A;const n=typeof e=="number"?{nodeId:e}:{selector:e},i=$e.traceElement(n,t,s);if(!i)return{targetQuery:e,found:!1,disappearanceMechanism:"UNKNOWN",likelyRootCause:"Target element could not be found in recording baseline or event stream",confidenceScore:0,detailedExplanation:`No element matching "${e}" was ever created, recorded in the initial DOM snapshot, or observed in mutation events.`,evidentiaryTrail:[],precedingEvents:[],followingEvents:[],correlatedErrors:[],correlatedNetworkCalls:[],alternativeHypotheses:[{hypothesis:"Element was injected into an unmonitored isolated iframe or ShadowRoot closed mode",likelihood:40,evidenceFor:["Element query yielded zero matches in monitored document"],evidenceAgainst:["Iframes/ShadowRoots were accessible in this session"]},{hypothesis:"Selector typo or timing mismatch",likelihood:60,evidenceFor:["Target selector did not match any recorded tag or class"],evidenceAgainst:[]}]};const r=[...t].sort((S,M)=>S.sequence-M.sequence),o=[],a=[];let c="UNKNOWN",u="Unknown disappearance mechanism",d=50,h="",p=i.removedAt??void 0;const y=i.entries.find(S=>S.stage==="REMOVED_FROM_DOM"),v=i.entries.find(S=>S.stage==="PARENT_SUBTREE_REPLACED"),m=i.entries.find(S=>S.stage==="CLASS_MODIFIED"&&/\b(hidden|hide|d-none|invisible|collapsed)\b/i.test(String(S.details.newValue||""))),g=i.entries.find(S=>S.stage==="STYLE_MODIFIED"&&/display\s*:\s*none|visibility\s*:\s*hidden|opacity\s*:\s*0/i.test(String(S.details.newValue||"")));y?(c="DIRECT_NODE_REMOVAL",p=y.timestamp,u=`Element [ID: ${i.targetNodeId}] <${i.tagName}> was directly removed from its parent [ID: ${y.details.parentId}] via DOM removeChild/replaceChild`,d=95,o.push({timestamp:y.timestamp,sequence:y.sequence,eventId:y.eventId,eventType:y.eventType,evidenceType:"DIRECT",description:`Direct DOM removal mutation: element detached from parent ID ${y.details.parentId}`,confidenceContribution:50})):v?(c="PARENT_SUBTREE_REPLACED",p=v.timestamp,u=`Host framework (e.g. React/Vue re-render) destroyed and replaced Ancestor container [ID: ${v.details.removedAncestorId}], causing injected element to be unmounted`,d=92,o.push({timestamp:v.timestamp,sequence:v.sequence,eventId:v.eventId,eventType:v.eventType,evidenceType:"DIRECT",description:`Ancestor container [ID: ${v.details.removedAncestorId}] was removed, wiping out all child subtrees`,confidenceContribution:50})):g?(c="STYLE_DISPLAY_NONE",p=g.timestamp,u=`Element was visually hidden by an inline style modification: "${g.details.newValue}"`,d=88,o.push({timestamp:g.timestamp,sequence:g.sequence,eventId:g.eventId,eventType:g.eventType,evidenceType:"DIRECT",description:`Inline style changed to "${g.details.newValue}"`,confidenceContribution:45})):m?(c="CLASS_TRIGGERED_HIDDEN",p=m.timestamp,u=`Element was visually hidden because its CSS class list was modified to include "${m.details.newValue}"`,d=85,o.push({timestamp:m.timestamp,sequence:m.sequence,eventId:m.eventId,eventType:m.eventType,evidenceType:"DIRECT",description:`Class list changed from "${m.details.oldValue??""}" to "${m.details.newValue??""}"`,confidenceContribution:45})):i.isCurrentlyAlive&&(c="UNKNOWN",u=`Element [ID: ${i.targetNodeId}] is currently alive and attached to the DOM tree (no unmount mutation detected)`,d=70,h="The element exists in the current DOM state. If it is not visible on screen, it may be clipped by viewport boundaries, z-index stacking context, or 0x0 pixel dimensions.");const b=p??i.createdAt,T=500,w=r.filter(S=>S.timestamp>=b-T&&S.timestampS.timestamp>b&&S.timestamp<=b+T),C=w.filter(S=>S.category==="ERROR");if(C.length>0){const S=C[0],M=((R=S.payload)==null?void 0:R.message)||"Unknown runtime error";o.push({timestamp:S.timestamp,sequence:S.sequence,eventId:S.id,eventType:S.type,evidenceType:"PRECEDING",description:`Runtime error occurred ${(b-S.timestamp).toFixed(1)}ms before disappearance: "${M}"`,confidenceContribution:20,rawEvent:S}),u+=` (preceded by runtime error: "${M}")`}const N=w.filter(S=>S.type==="NETWORK_RESPONSE_COMPLETE"||S.type==="NETWORK_REQUEST_FAILED");if(N.length>0){const S=N[0],M=((x=S.payload)==null?void 0:x.url)||"network request";o.push({timestamp:S.timestamp,sequence:S.sequence,eventId:S.id,eventType:S.type,evidenceType:"PRECEDING",description:`Network response completed ${(b-S.timestamp).toFixed(1)}ms before disappearance: ${M}`,confidenceContribution:15,rawEvent:S})}const I=w.filter(S=>S.category==="NAVIGATION");if(I.length>0){const S=I[0];o.push({timestamp:S.timestamp,sequence:S.sequence,eventId:S.id,eventType:S.type,evidenceType:"PRECEDING",description:`Navigation event (${(q=S.payload)==null?void 0:q.navigationType}) occurred ${(b-S.timestamp).toFixed(1)}ms before disappearance`,confidenceContribution:25,rawEvent:S}),u+=` following SPA navigation to "${(A=S.payload)==null?void 0:A.url}"`}return h||(h=[`Element <${i.tagName}> (Logical ID: ${i.targetNodeId}, selector: "${i.selectorHint}") was created at ${i.createdAt.toFixed(1)}ms.`,`It remained alive in the DOM for ${i.lifespanMs.toFixed(1)}ms and experienced ${i.mutationCount} mutations.`,`At timestamp ${b.toFixed(1)}ms, it disappeared via [${c}].`,`Diagnosis: ${u}.`].join(" ")),c==="PARENT_SUBTREE_REPLACED"?(a.push({hypothesis:"Direct cleanup called by extension code",likelihood:25,evidenceFor:["Element was unmounted shortly after creation"],evidenceAgainst:["Ancestor container mutation was recorded from host page context"]}),a.push({hypothesis:"Host single-page app route change destroyed component tree",likelihood:35,evidenceFor:I.length>0?["Preceding navigation event recorded"]:[],evidenceAgainst:I.length===0?["No navigation events occurred in temporal window"]:[]})):c==="DIRECT_NODE_REMOVAL"&&a.push({hypothesis:"Third-party script or ad-blocker removed the injected node",likelihood:30,evidenceFor:["Direct node removal occurred without ancestor replacement"],evidenceAgainst:["No ad-blocker signatures or extension error logs observed"]}),{targetQuery:e,targetNodeId:i.targetNodeId,found:!0,tagName:i.tagName,selectorHint:i.selectorHint,createdAt:i.createdAt,firstVisibleAt:i.createdAt,lastKnownGoodStateAt:Math.max(0,b-1),disappearedAt:p,lifespanMs:i.lifespanMs,disappearanceMechanism:c,likelyRootCause:u,confidenceScore:Math.min(99,d),detailedExplanation:h,evidentiaryTrail:o,precedingEvents:w,followingEvents:E,correlatedErrors:C,correlatedNetworkCalls:N,alternativeHypotheses:a}}}class Pe{constructor(e){f(this,"activeObservation",null);f(this,"registry");f(this,"sequenceCounter");this.registry=e,this.sequenceCounter=new oe}isObserving(){return this.activeObservation!==null}startObservation(e,t=document){this.activeObservation&&this.stopObservation(t);const s=`obs_${Date.now()}_${Math.random().toString(36).slice(2,6)}`,n=Date.now(),i=L.inspectElement(e,this.registry),r=i.bestSelector,o=[],a=this.registry?this.registry.getOrCreateId(e,0):100;o.push({id:`evt_init_${s}`,sessionId:s,timestamp:0,sequence:1,wallClockTime:n,type:"DOM_MUTATION_ADD",category:"DOM",source:"BROWSER_RUNTIME",targetNodeId:a,targetSelector:r,payload:{node:{id:a,nodeType:1,tagName:i.tag,attributes:i.attributes,textContent:i.text,children:[],parentId:null},parentId:null,index:0}});const c=new MutationObserver(u=>{const d=Date.now()-n;for(const h of u)if(h.type==="childList"){for(let p=0;p 0&&(m=qe.analyze(n,a)),{observationId:t,targetSelector:n,targetNodeId:((g=r.forensics)==null?void 0:g.logicalNodeId)||void 0,startTime:i,endTime:u,durationMs:d,initialState:r,finalState:p,disappeared:y,disappearanceReason:v,mutations:a.filter(b=>b.category==="DOM"),diagnostics:a.filter(b=>b.category==="ERROR"||b.category==="CONSOLE"),networkEvents:a.filter(b=>b.category==="NETWORK"),screenshots:c,correlationReport:m}}}class Ue{constructor(e={}){f(this,"isExplicitModeActive",!1);f(this,"isGlobalShortcutActive",!1);f(this,"highlighterEl",null);f(this,"badgeEl",null);f(this,"lastSelectedElement",null);f(this,"options",{});f(this,"onMouseMoveBound");f(this,"onClickBound");f(this,"onKeyDownBound");f(this,"onGlobalClickBound");this.options=e,this.onMouseMoveBound=this.handleMouseMove.bind(this),this.onClickBound=this.handleClick.bind(this),this.onKeyDownBound=this.handleKeyDown.bind(this),this.onGlobalClickBound=this.handleGlobalCtrlShiftClick.bind(this),this.initGlobalShortcutListener()}initGlobalShortcutListener(){typeof window>"u"||this.isGlobalShortcutActive||(window.addEventListener("click",this.onGlobalClickBound,!0),this.isGlobalShortcutActive=!0)}startPicker(e){typeof document>"u"||(e&&(this.options={...this.options,...e}),!this.isExplicitModeActive&&(this.isExplicitModeActive=!0,this.ensureHighlighter(),document.body&&(document.body.style.cursor="crosshair"),window.addEventListener("mousemove",this.onMouseMoveBound,!0),window.addEventListener("click",this.onClickBound,!0),window.addEventListener("keydown",this.onKeyDownBound,!0)))}stopPicker(){this.isExplicitModeActive&&(this.isExplicitModeActive=!1,typeof document<"u"&&document.body&&(document.body.style.cursor="default"),this.removeHighlighter(),typeof window<"u"&&(window.removeEventListener("mousemove",this.onMouseMoveBound,!0),window.removeEventListener("click",this.onClickBound,!0),window.removeEventListener("keydown",this.onKeyDownBound,!0)))}getLastSelectedElement(){return this.lastSelectedElement}setSelectedElement(e){let t;return"tag"in e&&"bestSelector"in e&&typeof e.getAttribute!="function"?t=e:(t=L.inspectElement(e,this.options.nodeRegistry),this.flashSelection(e)),this.lastSelectedElement=t,this.options.onSelected&&this.options.onSelected(t),t}handleGlobalCtrlShiftClick(e){if(!e.ctrlKey||!e.shiftKey)return;const t=e.target;if(!t||this.isExtensionOwned(t))return;e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation();const s=this.setSelectedElement(t);this.notifyExtension(s)}handleMouseMove(e){if(!this.isExplicitModeActive)return;const t=e.target;if(!t||this.isExtensionOwned(t)){this.hideHighlighter();return}this.updateHighlighter(t)}handleClick(e){if(!this.isExplicitModeActive)return;const t=e.target;if(!t||this.isExtensionOwned(t))return;e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation();const s=this.setSelectedElement(t);this.notifyExtension(s),this.stopPicker()}handleKeyDown(e){e.key==="Escape"&&this.isExplicitModeActive&&(e.preventDefault(),this.stopPicker(),this.options.onCanceled&&this.options.onCanceled())}isExtensionOwned(e){return!!(e.id==="forensic-recorder-floating-host"||e.id==="forensic-inspect-highlighter"||e.closest("#forensic-recorder-floating-host")||e.closest("#forensic-inspect-highlighter")||e.hasAttribute("data-forensic-internal")||e.closest("[data-forensic-internal]"))}ensureHighlighter(){if(typeof document>"u"||this.highlighterEl)return;const e=this.options.highlightColor||"#0ea5e9",t=document.createElement("div");t.id="forensic-inspect-highlighter",t.setAttribute("data-forensic-internal","true"),t.style.position="fixed",t.style.pointerEvents="none",t.style.zIndex="2147483640",t.style.border=`2px solid ${e}`,t.style.background="rgba(14, 165, 233, 0.18)",t.style.borderRadius="3px",t.style.boxShadow=`0 0 12px ${e}88`,t.style.transition="all 0.05s ease-out",t.style.display="none";const s=document.createElement("div");s.setAttribute("data-forensic-internal","true"),s.style.position="absolute",s.style.bottom="100%",s.style.left="0",s.style.transform="translateY(-4px)",s.style.background="#0f172a",s.style.color="#38bdf8",s.style.fontSize="11px",s.style.fontFamily="monospace",s.style.fontWeight="bold",s.style.padding="2px 6px",s.style.borderRadius="3px",s.style.boxShadow="0 2px 6px rgba(0,0,0,0.5)",s.style.whiteSpace="nowrap",s.style.pointerEvents="none",t.appendChild(s),document.body.appendChild(t),this.highlighterEl=t,this.badgeEl=s}updateHighlighter(e){if(this.ensureHighlighter(),!this.highlighterEl||!this.badgeEl)return;const t=e.getBoundingClientRect();this.highlighterEl.style.display="block",this.highlighterEl.style.left=`${t.left}px`,this.highlighterEl.style.top=`${t.top}px`,this.highlighterEl.style.width=`${Math.max(1,t.width)}px`,this.highlighterEl.style.height=`${Math.max(1,t.height)}px`;const s=e.tagName.toLowerCase(),n=e.id?`#${e.id}`:"",i=e.className&&typeof e.className=="string"?"."+e.className.split(/\s+/)[0]:"",r=`${Math.round(t.width)}×${Math.round(t.height)}`;this.badgeEl.textContent=`<${s}${n}${i}> [${r}]`}hideHighlighter(){this.highlighterEl&&(this.highlighterEl.style.display="none")}removeHighlighter(){this.highlighterEl&&this.highlighterEl.parentElement&&this.highlighterEl.remove(),this.highlighterEl=null,this.badgeEl=null}flashSelection(e){if(typeof document>"u"||!e.getBoundingClientRect)return;const t=e.getBoundingClientRect(),s=document.createElement("div");s.setAttribute("data-forensic-internal","true"),s.style.position="fixed",s.style.left=`${t.left}px`,s.style.top=`${t.top}px`,s.style.width=`${Math.max(1,t.width)}px`,s.style.height=`${Math.max(1,t.height)}px`,s.style.border="2px solid #22c55e",s.style.background="rgba(34, 197, 94, 0.25)",s.style.zIndex="2147483645",s.style.pointerEvents="none",s.style.transition="opacity 0.6s ease-out",document.body.appendChild(s),setTimeout(()=>{s.style.opacity="0",setTimeout(()=>s.remove(),600)},400)}notifyExtension(e){var t;try{typeof chrome<"u"&&((t=chrome.runtime)!=null&&t.sendMessage)&&chrome.runtime.sendMessage({type:"ELEMENT_SELECTED",elementInfo:e,timestamp:Date.now()})}catch{}}destroy(){this.stopPicker(),typeof window<"u"&&window.removeEventListener("click",this.onGlobalClickBound,!0),this.isGlobalShortcutActive=!1}}class fe{static getCrcTable(){if(this.crcTable)return this.crcTable;const e=new Uint32Array(256);for(let t=0;t<256;t++){let s=t;for(let n=0;n<8;n++)s=s&1?3988292384^s>>>1:s>>>1;e[t]=s>>>0}return this.crcTable=e,e}static crc32(e,t=0,s=e.length){const n=this.getCrcTable();let i=4294967295;for(let r=t;r >>8^n[(i^e[r])&255];return(i^4294967295)>>>0}static adler32(e){let t=1,s=0;for(let n=0;n >>0}static createPNG(e){const t=Math.max(1,Math.min(1920,Math.floor(e.width))),s=Math.max(1,Math.min(1080,Math.floor(e.height))),n=e.backgroundColor||[15,23,42,255],i=e.headerColor||[56,189,248,255],r=e.borderColor||[99,102,241,255],o=1+t*4,a=new Uint8Array(o*s),c=Math.min(30,Math.floor(s*.2));for(let g=0;g =e.length,h=new Uint8Array(5+u);h[0]=d?1:0,h[1]=u&255,h[2]=u>>>8&255;const p=~u&65535;h[3]=p&255,h[4]=p>>>8&255,h.set(e.subarray(n,n+u),5),t.push(h),n+=u}const i=t.reduce((c,u)=>c+u.length,0)+2+4,r=new Uint8Array(i);let o=0;r[o++]=120,r[o++]=1;for(const c of t)r.set(c,o),o+=c.length;const a=this.adler32(e);return r[o++]=a>>>24&255,r[o++]=a>>>16&255,r[o++]=a>>>8&255,r[o++]=a&255,r}static writeChunk(e,t,s,n){const i=n.length,r=new DataView(e.buffer,e.byteOffset,e.byteLength);r.setUint32(t,i,!1),t+=4;const o=new Uint8Array(4+i);for(let c=0;c<4;c++){const u=s.charCodeAt(c);e[t+c]=u,o[c]=u}t+=4,i>0&&(e.set(n,t),o.set(n,4),t+=i);const a=this.crc32(o);return r.setUint32(t,a,!1),t+=4,t}}f(fe,"crcTable",null);const ne=500;class He{constructor(e,t){f(this,"history",[]);f(this,"undoStack",[]);f(this,"redoStack",[]);f(this,"counter",0);f(this,"transaction",null);this.doc=e,this.registry=t}mutate(e){var d;const t=`mut_${Date.now().toString(36)}_${++this.counter}`,s=Date.now();let n;try{n=this.resolveTarget(e.target)}catch(h){return this.failure(t,e,null,h.message,Date.now()-s)}const i=this.snapshotState(n);let r=null,o=null,a,c=!0;try{const h=this.applyOperation(t,e,n);h&&(this.transaction?this.transaction.undoRecords.push(h):(this.undoStack.push(h),this.redoStack=[]));const y=(n.isConnected!==void 0?n.isConnected:this.doc.contains(n))?n:this.doc.querySelector(i.selector)||n;r=this.snapshotState(y),o=this.quickDiff(i,r,n)}catch(h){c=!1,a=h.message,r=null}const u={mutationId:t,operation:e.operation,success:c,before:i,after:r,diff:o,affectedSelector:c?i.selector:null,durationMs:Date.now()-s,error:a,undoable:c&&(this.transaction?this.transaction.undoRecords.length>0:this.undoStack.length>0)};return this.transaction&&this.transaction.steps.push({stepId:`step_${this.transaction.steps.length+1}`,mutation:u}),this.pushHistory({mutationId:t,transactionId:(d=this.transaction)==null?void 0:d.id,timestamp:Date.now(),operation:e.operation,targetSelector:i.selector,success:c,summary:`${e.operation} on ${i.selector}${o?` (+${o.added}/-${o.removed}/~${o.changed})`:""}`,undoApplied:!1,redoApplied:!1}),u}beginTransaction(){if(this.transaction)throw new Error(`TRANSACTION_ALREADY_OPEN: ${this.transaction.id} — commit or rollback first.`);return this.transaction={id:`tx_${Date.now().toString(36)}_${++this.counter}`,steps:[],undoRecords:[]},this.transaction.id}commitTransaction(e){if(!this.transaction)throw new Error("NO_OPEN_TRANSACTION: begin a transaction before committing.");const t=this.transaction,s=Date.now();let n=!0,i;if(e)try{n=e({id:t.id,steps:t.steps})!==!1,n||(i="VERIFY_FAILED: caller verification rejected the transaction state.")}catch(o){n=!1,i=`VERIFY_ERROR: ${o.message}`}if(!n)return this.rollbackInternal(t,i||"VERIFY_FAILED",s);this.undoStack.push(...t.undoRecords),this.undoStack.length>ne&&this.undoStack.splice(0,this.undoStack.length-ne),this.redoStack=[];const r=this.summaryOf(t);return this.transaction=null,{transactionId:t.id,committed:!0,rolledBack:!1,steps:t.steps,durationMs:Date.now()-s,finalStateSummary:r}}rollbackTransaction(e){if(!this.transaction)throw new Error("NO_OPEN_TRANSACTION: begin a transaction before rolling back.");const t=this.transaction;return this.rollbackInternal(t,e||"ROLLBACK_REQUESTED",Date.now())}rollbackInternal(e,t,s){for(const i of[...e.undoRecords].reverse())try{this.applyUndo(i)}catch{}const n=this.summaryOf(e);return this.transaction=null,{transactionId:e.id,committed:!1,rolledBack:!0,steps:e.steps,error:t,durationMs:Date.now()-s,finalStateSummary:n}}undo(){const e=this.transaction?this.transaction.undoRecords:this.undoStack,t=e.pop();if(!t)return{success:!1,message:"Nothing to undo — the mutation history is empty."};try{this.applyUndo(t)}catch(s){return e.push(t),{success:!1,mutationId:t.mutationId,message:`UNDO_FAILED: ${s.message}`}}return this.redoStack.push(t),this.markHistory(t.mutationId,"undo"),{success:!0,mutationId:t.mutationId,message:`Undid ${t.operation} on ${t.targetSelector}.`}}redo(){const e=this.redoStack.pop();if(!e)return{success:!1,message:"Nothing to redo — no undone mutation is pending."};try{const t=this.resolveTarget({selector:e.targetSelector}),s={operation:e.operation,target:{selector:e.targetSelector}};return this.reapplyRecord(e,t,s)?((this.transaction?this.transaction.undoRecords:this.undoStack).push(e),this.markHistory(e.mutationId,"redo"),{success:!0,mutationId:e.mutationId,message:`Redid ${e.operation} on ${e.targetSelector}.`}):(this.redoStack.push(e),{success:!1,mutationId:e.mutationId,message:"REDO_FAILED: target state diverged — cannot safely reapply."})}catch(t){return this.redoStack.push(e),{success:!1,mutationId:e.mutationId,message:`REDO_FAILED: ${t.message}`}}}getHistory(e=100){return this.history.slice(-e)}getUndoDepth(){return this.transaction?this.transaction.undoRecords.length:this.undoStack.length}getRedoDepth(){return this.redoStack.length}getOpenTransactionId(){var e;return((e=this.transaction)==null?void 0:e.id)||null}preview(e){var t;try{const s=this.resolveTarget(e.target),n=[];let i=1;(e.operation==="set_inner_html"||e.operation==="set_outer_html")&&(n.push("HTML replacement can destroy descendant node identity — captured regions targeting children may become stale."),i=s.querySelectorAll("*").length+1),(e.operation==="remove_element"||e.operation==="unwrap_element")&&(n.push("Removal is destructive; the undo record preserves the full serialized subtree."),i=s.querySelectorAll("*").length+1),e.operation==="move_element"&&!e.parent&&n.push("No parent target supplied — move requires payload.parent."),e.operation==="wrap_element"&&!e.newElementHtml&&n.push("No wrapper HTML supplied — a neutralwrapper will be generated.");const r=Be(e,s);return{valid:n.filter(o=>o.includes("requires")||o.includes("No parent")).length===0,operation:e.operation,target:{selector:this.snapshotState(s).selector,tag:s.tagName.toLowerCase()},expectedChange:r,affectedNodes:i,warnings:n}}catch(s){return{valid:!1,operation:e.operation,target:{selector:String(((t=e.target)==null?void 0:t.selector)||""),tag:""},expectedChange:"—",affectedNodes:0,warnings:[],error:s.message}}}applyOperation(e,t,s){var r;const n=this.snapshotState(s).selector,i=t.operation;switch(i){case"set_attribute":{if(!t.attribute)throw new Error("ATTRIBUTE_REQUIRED: payload.attribute is missing.");const o=s.getAttribute(t.attribute);return s.setAttribute(t.attribute,t.value??""),this.undoFor(e,i,n,{kind:o===null?"remove-attribute":"restore-attribute",attribute:t.attribute,value:o})}case"remove_attribute":{if(!t.attribute)throw new Error("ATTRIBUTE_REQUIRED: payload.attribute is missing.");const o=s.getAttribute(t.attribute);if(o===null)throw new Error(`ATTRIBUTE_NOT_PRESENT: "${t.attribute}" is not set on ${n}.`);return s.removeAttribute(t.attribute),this.undoFor(e,i,n,{kind:"restore-attribute",attribute:t.attribute,value:o})}case"set_text":{const o=s.textContent||"";return s.textContent=t.text??"",this.undoFor(e,i,n,{kind:"restore-text",text:o})}case"replace_text":{if(!t.text||!t.replacement)throw new Error("TEXT_PATTERNS_REQUIRED: payload.text (search) and payload.replacement are required.");const o=s.textContent||"";return s.textContent=o.split(t.text).join(t.replacement),this.undoFor(e,i,n,{kind:"restore-text",text:o})}case"set_inner_html":{const o=s.innerHTML;return s.innerHTML=t.html??"",this.undoFor(e,i,n,{kind:"restore-outer-html",outerHtml:s.outerHTML.replace(t.html??"",o)||void 0,text:o,attribute:"__inner"})}case"set_outer_html":{const o=s.outerHTML,a=s.parentElement;if(!a)throw new Error("ORPHAN_ELEMENT: element has no parent — cannot replace outer HTML.");const c=this.doc.createComment(`mcpdom_undo_${e}`);s.replaceWith(c);const u=this.doc.createElement("template");u.innerHTML=t.html??"";const d=u.content.firstElementChild;return d?c.replaceWith(d):c.replaceWith(this.doc.createTextNode(t.html??"")),this.undoFor(e,i,n,{kind:"reinsert-node",outerHtml:o,parentSelector:this.snapshotState(a).selector,nextSiblingSelector:this.siblingSelector(d||s)})}case"add_class":{const o=Array.from(s.classList);for(const a of t.classes||[])s.classList.add(a);return this.undoFor(e,i,n,{kind:"restore-classes",classes:o})}case"remove_class":{const o=Array.from(s.classList);for(const a of t.classes||[])s.classList.remove(a);return this.undoFor(e,i,n,{kind:"restore-classes",classes:o})}case"replace_class":{const o=Array.from(s.classList);for(const a of t.classes||[])s.classList.remove(a);return t.value&&s.classList.add(t.value),this.undoFor(e,i,n,{kind:"restore-classes",classes:o})}case"set_style":{const o=this.doc.defaultView;if(!(o!=null&&o.getComputedStyle))throw new Error("STYLE_UNAVAILABLE: computed style API is unavailable in this context.");const a={};for(const c of Object.keys(t.style||{}))a[c]=o.getComputedStyle(s).getPropertyValue(c),s.style.setProperty(c,t.style[c]);return this.undoFor(e,i,n,{kind:"restore-style",style:a})}case"remove_style":{const o={};for(const a of t.classes||[])o[a]=s.style.getPropertyValue(a),s.style.removeProperty(a);return this.undoFor(e,i,n,{kind:"restore-style",style:o})}case"add_element":{const o=t.parent?this.resolveTarget(t.parent):s,a=this.doc.createElement("template");a.innerHTML=t.newElementHtml??"";const c=a.content.firstElementChild;if(!c)throw new Error("INVALID_HTML: payload.newElementHtml does not produce an element.");switch(t.position||"append"){case"before":s.before(c);break;case"after":s.after(c);break;case"prepend":o.prepend(c);break;default:o.appendChild(c)}return this.undoFor(e,i,n,{kind:"remove-node",attribute:this.snapshotState(c).selector})}case"remove_element":{const o=s.outerHTML,a=s.parentElement,c=s.nextElementSibling;return s.remove(),this.undoFor(e,i,n,{kind:"reinsert-node",outerHtml:o,parentSelector:a?this.snapshotState(a).selector:void 0,nextSiblingSelector:c?this.snapshotState(c).selector:null})}case"replace_element":{const o=s.outerHTML,a=s.parentElement,c=this.doc.createElement("template");c.innerHTML=t.newElementHtml??"";const u=c.content.firstElementChild;if(!u)throw new Error("INVALID_HTML: payload.newElementHtml does not produce an element.");const d=s.nextElementSibling;return s.replaceWith(u),this.undoFor(e,i,n,{kind:"reinsert-node",outerHtml:o,parentSelector:a?this.snapshotState(a).selector:void 0,nextSiblingSelector:d?this.snapshotState(d).selector:null})}case"move_element":{if(!t.parent)throw new Error("PARENT_REQUIRED: payload.parent is required for move_element.");const o=this.resolveTarget(t.parent),a=s.outerHTML,c=s.parentElement,u=s.nextElementSibling,d=t.position==="before"||t.position==="prepend"?o.firstElementChild:null;return o[t.position==="prepend"?"prepend":"appendChild"](s),this.undoFor(e,i,n,{kind:"restore-position",parentSelector:c?this.snapshotState(c).selector:void 0,nextSiblingSelector:u?this.snapshotState(u).selector:d?this.snapshotState(d).selector:null,outerHtml:a})}case"wrap_element":{const o=this.doc.createElement("template");o.innerHTML=t.newElementHtml||'';const a=o.content.firstElementChild;if(!a)throw new Error("INVALID_HTML: wrapper template produced no element.");const c=s.parentElement,u=s.nextElementSibling;return s.replaceWith(a),a.appendChild(s),this.undoFor(e,i,n,{kind:"restore-position",parentSelector:c?this.snapshotState(c).selector:void 0,nextSiblingSelector:u?this.snapshotState(u).selector:null})}case"unwrap_element":{const o=s.outerHTML,a=s.parentElement;if(!a)throw new Error("ORPHAN_ELEMENT: cannot unwrap a root-level element.");const c=s.nextElementSibling,u=Array.from(s.children);for(const d of u)a.insertBefore(d,s);return s.remove(),this.undoFor(e,i,n,{kind:"reinsert-node",outerHtml:o,parentSelector:this.snapshotState(a).selector,nextSiblingSelector:c?this.snapshotState(c).selector:null})}case"clone_subtree":{const o=t.parent?this.resolveTarget(t.parent):s.parentElement||s,a=s.cloneNode(!0);if(t.copyAttributes!==!1)for(const c of Array.from(a.attributes))c.name==="id"&&a.removeAttribute("id");return(r=o.appendChild)==null||r.call(o,a),this.undoFor(e,i,n,{kind:"remove-node",attribute:this.snapshotState(a).selector})}default:throw new Error(`UNKNOWN_OPERATION: ${i} is not a supported DOM mutation.`)}}applyUndo(e){const t=e.inverse;switch(t.kind){case"restore-outer-html":{const s=this.resolveTarget({selector:e.targetSelector});if(t.outerHtml!==void 0){const n=this.doc.createElement("template");n.innerHTML=t.outerHtml;const i=n.content.firstElementChild;i&&s.replaceWith(i)}else t.attribute==="__inner"&&(s.innerHTML=t.text||"");break}case"reinsert-node":{const s=t.parentSelector?this.resolveTarget({selector:t.parentSelector}):this.doc.body,n=this.doc.createElement("template");n.innerHTML=t.outerHtml||"";const i=n.content.firstElementChild;if(!i)throw new Error("UNDO_CORRUPT: serialized subtree could not be restored.");const r=t.nextSiblingSelector?this.safeResolve(t.nextSiblingSelector):null;s.insertBefore(i,r);break}case"remove-node":{const s=this.safeResolve(t.attribute||e.targetSelector);s&&s.remove();break}case"restore-attribute":{this.resolveTarget({selector:e.targetSelector}).setAttribute(t.attribute,t.value??"");break}case"remove-attribute":{this.resolveTarget({selector:e.targetSelector}).removeAttribute(t.attribute);break}case"restore-text":{const s=this.resolveTarget({selector:e.targetSelector});s.textContent=t.text||"";break}case"restore-classes":{const s=this.resolveTarget({selector:e.targetSelector});s.removeAttribute("class");for(const n of t.classes||[])s.classList.add(n);break}case"restore-style":{const s=this.resolveTarget({selector:e.targetSelector});s.style.removeProperty("all");for(const[n,i]of Object.entries(t.style||{}))s.style.setProperty(n,i);break}case"restore-position":{const s=this.doc.createElement("template");s.innerHTML=t.outerHtml||"";const n=s.content.firstElementChild;if(!n)throw new Error("UNDO_CORRUPT: serialized subtree could not be restored.");const i=this.safeResolve(e.targetSelector);i&&i.remove();const r=t.parentSelector?this.safeResolve(t.parentSelector):this.doc.body,o=t.nextSiblingSelector?this.safeResolve(t.nextSiblingSelector):null;(r||this.doc.body).insertBefore(n,o);break}}}reapplyRecord(e,t,s){var i;const n=e.inverse;switch(e.operation){case"set_attribute":return(n.kind==="restore-attribute"||n.kind==="remove-attribute")&&s.value!==void 0?(t.setAttribute(s.attribute||n.attribute||"",s.value),!0):!1;case"add_class":{for(const r of s.classes||[])t.classList.add(r);return(((i=s.classes)==null?void 0:i.length)||0)>0}case"remove_class":{for(const r of s.classes||n.classes||[])t.classList.remove(r);return!0}case"set_text":return s.text!==void 0?(t.textContent=s.text,!0):!1;case"set_inner_html":return s.html!==void 0?(t.innerHTML=s.html,!0):!1;default:return!1}}resolveTarget(e){if(!e)throw new Error("TARGET_REQUIRED: mutation requires a target.");if(typeof e=="string"&&(e={selector:e}),e.selector){try{const t=this.doc.querySelectorAll(e.selector);if(t.length===1)return t[0];if(t.length>1)return Array.from(t).find(n=>{try{return L.inspectElement(n).visibility.isVisible}catch{return!1}})||t[0]}catch(t){throw new Error(`TARGET_INVALID: ${t.message}`)}throw new Error(`TARGET_NOT_FOUND: selector "${e.selector}" matches no element.`)}if(e.xpath){try{const s=this.doc.evaluate(e.xpath,this.doc,null,9,null).singleNodeValue;if(s)return s}catch(t){throw new Error(`TARGET_INVALID_XPATH: ${t.message}`)}throw new Error("TARGET_NOT_FOUND: xpath matches no element.")}if(typeof e.nodeId=="number"&&this.registry){const t=this.registry.getNode(e.nodeId);if(t&&t.nodeType===1&&this.doc.contains(t))return t;throw new Error("TARGET_STALE: logical node id no longer resolves to an attached element.")}throw new Error("TARGET_INVALID: target has neither selector, xpath nor nodeId.")}safeResolve(e){try{return this.doc.querySelector(e)}catch{return null}}snapshotState(e){const t=L.inspectElement(e,this.registry),s=e.outerHTML.length>2e4?e.outerHTML.slice(0,2e4)+"…[truncated]":e.outerHTML;return{selector:t.bestSelector,outerHtml:s,attributes:this.attrsOf(e)}}attrsOf(e){const t={};for(const s of Array.from(e.attributes))t[s.name]=s.value.length>300?s.value.slice(0,300)+"…":s.value;return t}quickDiff(e,t,s){if(!t)return null;let n=0,i=0,r=0;const o=new Set(Object.keys(e.attributes)),a=new Set(Object.keys(t.attributes||{}));for(const u of o)a.has(u)||i++;for(const u of a)o.has(u)?e.attributes[u]!==t.attributes[u]&&r++:n++;e.outerHtml!==t.outerHtml&&n+i+r===0&&r++;const c=s.querySelectorAll?s.querySelectorAll("*").length:0;return{added:n,removed:i,changed:r,summary:`attributes +${n}/-${i}/~${r}; subtree nodes: ${c}`}}undoFor(e,t,s,n){return{mutationId:e,operation:t,targetSelector:s,inverse:n}}siblingSelector(e){try{return this.snapshotState(e).selector}catch{return null}}pushHistory(e){this.history.push(e),this.history.length>ne&&this.history.splice(0,this.history.length-ne)}markHistory(e,t){for(let s=this.history.length-1;s>=0;s--)if(this.history[s].mutationId===e){t==="undo"?this.history[s].undoApplied=!0:this.history[s].redoApplied=!0;return}}summaryOf(e){var n;const t=((n=this.doc.documentElement)==null?void 0:n.outerHTML.length)||0,s=e.steps.filter(i=>i.mutation.success).length;return{domLength:t,diffSummary:`${s}/${e.steps.length} mutations applied`}}failure(e,t,s,n,i){var r;return{mutationId:e,operation:t.operation,success:!1,before:s||{selector:String(((r=t.target)==null?void 0:r.selector)||"?"),outerHtml:"",attributes:{}},after:null,diff:null,affectedSelector:null,durationMs:i,error:n,undoable:!1}}}function Be(l,e){switch(l.operation){case"set_attribute":return`attribute "${l.attribute}" will be set to "${(l.value??"").slice(0,40)}"`;case"remove_attribute":return`attribute "${l.attribute}" will be removed`;case"set_text":return`text content will be replaced (${(l.text||"").length} chars)`;case"replace_text":return`every occurrence of "${l.text}" will become "${l.replacement}"`;case"set_inner_html":return`inner HTML will be replaced (${(l.html||"").length} chars)`;case"set_outer_html":return"element (and subtree) will be replaced with provided HTML";case"add_class":return`classes ${(l.classes||[]).join(", ")} will be added`;case"remove_class":return`classes ${(l.classes||[]).join(", ")} will be removed`;case"replace_class":return`classes ${(l.classes||[]).join(", ")} will be replaced with "${l.value}"`;case"set_style":return`inline styles ${Object.keys(l.style||{}).join(", ")} will be set`;case"remove_style":return`inline styles ${(l.classes||[]).join(", ")} will be removed`;case"add_element":return`a new element will be inserted ${l.position||"append"} the target`;case"remove_element":return"the element and its subtree will be removed";case"replace_element":return"the element will be replaced with new HTML";case"move_element":return"the element will be moved into the specified parent";case"wrap_element":return"the element will be wrapped in a new container";case"unwrap_element":return"children will be lifted out and the wrapper removed";case"clone_subtree":return"a deep clone of the subtree will be appended";default:return"unknown operation"}}class Fe{constructor(){f(this,"executionCounter",0)}async execute(e,t,s={}){const n=Math.min(Math.max(s.timeoutMs??5e3,100),3e4),i=`js_${Date.now().toString(36)}_${++this.executionCounter}`,r=e.defaultView;if(!r)return this.result(i,"BLOCKED_BY_CONTEXT",0,t,[],{name:"NoWindow",message:"The document has no associated window — execution context unavailable."});const o=e.documentElement?e.documentElement.outerHTML.length:0,a=[],c=this.hookConsole(r,a);let u="EXECUTED_SUCCESSFULLY",d,h,p=o,y=!1;const v=Date.now();try{const b=this.buildRunner(r,t),T=new Promise((w,E)=>{var N;const C=setTimeout(()=>{y=!0,E(new Error(`Script timed out after ${n}ms`))},n);(N=C==null?void 0:C.unref)==null||N.call(C)});d=await Promise.race([b,T])}catch(b){y?u="TIMED_OUT":u="EXECUTED_WITH_ERROR",h={name:(b==null?void 0:b.name)||"Error",message:(b==null?void 0:b.message)||String(b),stack:b!=null&&b.stack?String(b.stack).slice(0,2e3):void 0}}const m=Date.now()-v;p=e.documentElement?e.documentElement.outerHTML.length:0,c();const g=this.serialize(d);return u==="EXECUTED_SUCCESSFULLY"&&g.serializationFailed&&(u="SERIALIZATION_FAILED",h={name:"SerializationError",message:g.message||"Result could not be serialized."}),{status:u,executionId:i,durationMs:m,result:u==="EXECUTED_SUCCESSFULLY"?g.text:void 0,error:h,consoleOutput:a.slice(0,100),domChanged:o!==p,domLengthBefore:o,domLengthAfter:p,world:s.world||"ISOLATED",timeoutMs:n,codePreview:t.length>300?t.slice(0,300)+"…":t}}buildRunner(e,t){const s=`(async function() { +`))}catch{}const c={id:this.sequenceCounter.generateEventId("con",i),sessionId:this.sessionId,timestamp:s,sequence:i,wallClockTime:n,type:`RUNTIME_CONSOLE_${e.toUpperCase()}`,category:e==="error"?"ERROR":"CONSOLE",source:"PAGE",payload:{level:e,args:r,formattedMessage:o,stackTrace:a}};this.callback(c)}instrumentGlobalErrors(){if(typeof window>"u")return;const e=t=>{var o,a;const s=this.sequenceCounter.getRelativeTimestamp(),n=this.sequenceCounter.getWallClock(),i=this.sequenceCounter.nextSequence(),r={id:this.sequenceCounter.generateEventId("err",i),sessionId:this.sessionId,timestamp:s,sequence:i,wallClockTime:n,type:"RUNTIME_ERROR",category:"ERROR",source:"PAGE",payload:{message:t.message||"Unknown runtime error",filename:t.filename,lineno:t.lineno,colno:t.colno,stack:((o=t.error)==null?void 0:o.stack)||void 0,name:((a=t.error)==null?void 0:a.name)||"Error"}};this.callback(r)};window.addEventListener("error",e),this.cleanups.push(()=>window.removeEventListener("error",e))}instrumentUnhandledRejections(){if(typeof window>"u")return;const e=t=>{const s=this.sequenceCounter.getRelativeTimestamp(),n=this.sequenceCounter.getWallClock(),i=this.sequenceCounter.nextSequence();let r="Unhandled Promise Rejection",o;if(t.reason instanceof Error)r=t.reason.message,o=t.reason.stack;else if(typeof t.reason=="string")r=t.reason;else if(t.reason)try{r=JSON.stringify(t.reason)}catch{r=String(t.reason)}const a={id:this.sequenceCounter.generateEventId("rej",i),sessionId:this.sessionId,timestamp:s,sequence:i,wallClockTime:n,type:"RUNTIME_UNHANDLED_REJECTION",category:"ERROR",source:"PAGE",payload:{message:r,stack:o,isUnhandledRejection:!0}};this.callback(a)};window.addEventListener("unhandledrejection",e),this.cleanups.push(()=>window.removeEventListener("unhandledrejection",e))}}class Re{constructor(e,t,s,n=""){b(this,"privacy");b(this,"sequenceCounter");b(this,"callback");b(this,"sessionId");b(this,"isInstrumented",!1);b(this,"originalFetch",null);b(this,"originalXHROpen",null);b(this,"originalXHRSend",null);b(this,"cleanups",[]);this.privacy=e,this.sequenceCounter=t,this.callback=s,this.sessionId=n}setSessionId(e){this.sessionId=e}start(){this.isInstrumented||typeof window>"u"||(this.isInstrumented=!0,this.cleanups=[],this.instrumentFetch(),this.instrumentXHR())}stop(){this.cleanups.forEach(e=>{try{e()}catch{}}),this.cleanups=[],this.isInstrumented=!1}instrumentFetch(){if(typeof window.fetch!="function")return;this.originalFetch=window.fetch;const e=this;window.fetch=async function(...t){const s=e.sequenceCounter.generateEventId("req_f"),n=t[0],i=t[1];let r="";typeof n=="string"?r=n:n instanceof URL?r=n.toString():n&&typeof n=="object"&&"url"in n&&(r=n.url);const o=((i==null?void 0:i.method)||(typeof n=="object"&&"method"in n?n.method:"GET")).toUpperCase(),a=e.privacy.sanitizeUrl(r),c=e.sequenceCounter.getRelativeTimestamp(),u=e.sequenceCounter.getWallClock(),h=e.sequenceCounter.nextSequence(),g={id:s,sessionId:e.sessionId,timestamp:c,sequence:h,wallClockTime:u,type:"NETWORK_REQUEST_START",category:"NETWORK",source:"PAGE",payload:{requestId:s,url:a,method:o,resourceType:"fetch",hasBody:!!(i!=null&&i.body)}};e.callback(g);try{const p=await e.originalFetch.apply(this,t),y=e.sequenceCounter.getRelativeTimestamp(),v=e.sequenceCounter.getWallClock(),m=e.sequenceCounter.nextSequence(),d=Math.max(0,Math.round((y-c)*100)/100),f={id:e.sequenceCounter.generateEventId("res_f",m),sessionId:e.sessionId,timestamp:y,sequence:m,wallClockTime:v,type:"NETWORK_RESPONSE_COMPLETE",category:"NETWORK",source:"PAGE",causality:{triggeredBy:s,precededBy:s},payload:{requestId:s,url:a,method:o,status:p.status,statusText:p.statusText,durationMs:d}};return e.callback(f),p}catch(p){const y=e.sequenceCounter.getRelativeTimestamp(),v=e.sequenceCounter.getWallClock(),m=e.sequenceCounter.nextSequence(),d=Math.max(0,Math.round((y-c)*100)/100),f={id:e.sequenceCounter.generateEventId("res_err",m),sessionId:e.sessionId,timestamp:y,sequence:m,wallClockTime:v,type:"NETWORK_REQUEST_FAILED",category:"NETWORK",source:"PAGE",causality:{triggeredBy:s,precededBy:s},payload:{requestId:s,url:a,method:o,status:0,statusText:"Failed",durationMs:d,error:(p==null?void 0:p.message)||"Network request failed"}};throw e.callback(f),p}},this.cleanups.push(()=>{this.originalFetch&&(window.fetch=this.originalFetch)})}instrumentXHR(){if(typeof XMLHttpRequest>"u")return;this.originalXHROpen=XMLHttpRequest.prototype.open,this.originalXHRSend=XMLHttpRequest.prototype.send;const e=this;XMLHttpRequest.prototype.open=function(t,s,...n){return this._forensicRequestId=e.sequenceCounter.generateEventId("req_x"),this._forensicMethod=(t||"GET").toUpperCase(),this._forensicUrl=typeof s=="string"?s:s.toString(),e.originalXHROpen.apply(this,[t,s,...n])},XMLHttpRequest.prototype.send=function(t){const s=this._forensicRequestId||e.sequenceCounter.generateEventId("req_x"),n=this._forensicMethod||"GET",i=e.privacy.sanitizeUrl(this._forensicUrl||""),r=e.sequenceCounter.getRelativeTimestamp(),o=e.sequenceCounter.getWallClock(),a=e.sequenceCounter.nextSequence();this._forensicStartTime=r;const c={id:s,sessionId:e.sessionId,timestamp:r,sequence:a,wallClockTime:o,type:"NETWORK_REQUEST_START",category:"NETWORK",source:"PAGE",payload:{requestId:s,url:i,method:n,resourceType:"xhr",hasBody:!!t}};e.callback(c);const u=()=>{const h=e.sequenceCounter.getRelativeTimestamp(),g=e.sequenceCounter.getWallClock(),p=e.sequenceCounter.nextSequence(),y=Math.max(0,Math.round((h-(this._forensicStartTime||r))*100)/100),v={id:e.sequenceCounter.generateEventId("res_x",p),sessionId:e.sessionId,timestamp:h,sequence:p,wallClockTime:g,type:this.status>=200&&this.status<400?"NETWORK_RESPONSE_COMPLETE":"NETWORK_REQUEST_FAILED",category:"NETWORK",source:"PAGE",causality:{triggeredBy:s,precededBy:s},payload:{requestId:s,url:i,method:n,status:this.status,statusText:this.statusText,durationMs:y,error:this.status===0?"XHR Network Error or Aborted":void 0}};e.callback(v)};return this.addEventListener("load",u),this.addEventListener("error",u),this.addEventListener("abort",u),e.originalXHRSend.apply(this,[t])},this.cleanups.push(()=>{this.originalXHROpen&&(XMLHttpRequest.prototype.open=this.originalXHROpen),this.originalXHRSend&&(XMLHttpRequest.prototype.send=this.originalXHRSend)})}}class Oe{constructor(e={}){b(this,"sequenceCounter");b(this,"registry");b(this,"privacy");b(this,"snapshotEngine");b(this,"mutationObserver");b(this,"eventCollector");b(this,"diagnostics");b(this,"networkMonitor");b(this,"metadata");b(this,"isRecording",!1);b(this,"isPaused",!1);b(this,"eventListeners",new Set);b(this,"checkpointListeners",new Set);b(this,"lastCheckpointSequence",0);b(this,"lastCheckpointTimestamp",0);b(this,"checkpointTimer",null);b(this,"checkpointIntervalEvents",200);b(this,"checkpointIntervalMs",3e4);this.sequenceCounter=new ne,this.registry=new H,this.privacy=new J(e.privacy),this.snapshotEngine=new he(this.registry,this.privacy,this.sequenceCounter);const t=n=>this.handleEvent(n);this.mutationObserver=new Ne(this.registry,this.privacy,this.sequenceCounter,this.snapshotEngine,t),this.eventCollector=new ke(this.registry,this.privacy,this.sequenceCounter,t),this.diagnostics=new Me(this.privacy,this.sequenceCounter,t),this.networkMonitor=new Re(this.privacy,this.sequenceCounter,t),e.checkpointIntervalEvents&&(this.checkpointIntervalEvents=e.checkpointIntervalEvents),e.checkpointIntervalMs&&(this.checkpointIntervalMs=e.checkpointIntervalMs);const s=e.sessionId||`session_${Date.now()}_${Math.random().toString(36).substring(2,7)}`;this.metadata=this.createInitialMetadata(s,e.sessionName)}getSessionId(){return this.metadata.id}getMetadata(){return{...this.metadata,durationMs:this.sequenceCounter.getRelativeTimestamp(),endTime:this.metadata.endTime||Date.now()}}getRegistry(){return this.registry}onEvent(e){return this.eventListeners.add(e),()=>this.eventListeners.delete(e)}onCheckpoint(e){return this.checkpointListeners.add(e),()=>this.checkpointListeners.delete(e)}start(e=typeof document<"u"?document:{}){if(this.isRecording)throw new Error(`Recorder session ${this.metadata.id} is already active`);this.sequenceCounter.reset(),this.registry.reset(),this.isRecording=!0,this.isPaused=!1,this.metadata.status="recording",this.metadata.startTime=Date.now(),this.mutationObserver.setSessionId(this.metadata.id),this.eventCollector.setSessionId(this.metadata.id),this.diagnostics.setSessionId(this.metadata.id),this.networkMonitor.setSessionId(this.metadata.id);const t=this.snapshotEngine.captureSnapshot(e,this.metadata.id);this.metadata.stats.nodeCount=t.totalNodeCount;const s={id:this.sequenceCounter.generateEventId("snap_init",t.sequence),sessionId:this.metadata.id,timestamp:t.timestamp,sequence:t.sequence,wallClockTime:Date.now(),type:"DOM_SNAPSHOT",category:"DOM",source:"PAGE",payload:{snapshot:t}};return this.createCheckpoint(t,"INITIAL"),this.mutationObserver.start(e),this.eventCollector.start(),this.diagnostics.start(),this.networkMonitor.start(),this.handleEvent(s),this.checkpointIntervalMs>0&&typeof setInterval<"u"&&(this.checkpointTimer=setInterval(()=>{this.isRecording&&!this.isPaused&&this.captureCheckpoint("PERIODIC",e)},this.checkpointIntervalMs)),t}stop(){return this.isRecording?(this.mutationObserver.takeRecords(),this.mutationObserver.stop(),this.eventCollector.stop(),this.diagnostics.stop(),this.networkMonitor.stop(),this.checkpointTimer&&(clearInterval(this.checkpointTimer),this.checkpointTimer=null),this.isRecording=!1,this.metadata.status="stopped",this.metadata.endTime=Date.now(),this.metadata.durationMs=this.sequenceCounter.getRelativeTimestamp(),this.getMetadata()):this.getMetadata()}pause(){!this.isRecording||this.isPaused||(this.isPaused=!0,this.metadata.status="paused")}resume(){!this.isRecording||!this.isPaused||(this.isPaused=!1,this.metadata.status="recording")}captureCheckpoint(e="MANUAL",t=document){if(!this.isRecording)return null;const s=this.snapshotEngine.captureSnapshot(t,this.metadata.id);return this.createCheckpoint(s,e)}recordCustomEvent(e,t,s,n){const i=this.sequenceCounter.getRelativeTimestamp(),r=this.sequenceCounter.getWallClock(),o=this.sequenceCounter.nextSequence(),a={id:this.sequenceCounter.generateEventId("ext",o),sessionId:this.metadata.id,timestamp:i,sequence:o,wallClockTime:r,type:e,category:"EXTENSION",source:"CONTENT_SCRIPT",targetNodeId:s,targetSelector:n,payload:t};return this.handleEvent(a),a}recordScreenshot(e,t="MANUAL"){const s=this.sequenceCounter.getRelativeTimestamp(),n=this.sequenceCounter.getWallClock(),i=this.sequenceCounter.nextSequence(),r={id:this.sequenceCounter.generateEventId("scr",i),sessionId:this.metadata.id,timestamp:s,sequence:i,wallClockTime:n,type:"SCREENSHOT_CHECKPOINT",category:"SCREENSHOT",source:"BROWSER_RUNTIME",payload:{screenshotId:`shot_${i}`,dataUrl:e,viewport:{width:typeof window<"u"?window.innerWidth:1920,height:typeof window<"u"?window.innerHeight:1080,scrollX:typeof window<"u"?window.scrollX:0,scrollY:typeof window<"u"?window.scrollY:0,devicePixelRatio:typeof window<"u"?window.devicePixelRatio:1},triggerReason:t}};return this.handleEvent(r),r}addAnnotation(e,t,s="AGENT",n){const i=this.sequenceCounter.getRelativeTimestamp(),r=this.sequenceCounter.nextSequence(),o={id:`ann_${r}_${Math.random().toString(36).substring(2,6)}`,sessionId:this.metadata.id,timestamp:i,sequence:r,nodeId:n,author:s,label:e,comment:t,createdAt:Date.now()},a={id:o.id,sessionId:this.metadata.id,timestamp:i,sequence:r,wallClockTime:Date.now(),type:"ANNOTATION",category:"ANNOTATION",source:s==="USER"?"USER_INTERACTION":"BROWSER_RUNTIME",targetNodeId:n,payload:{annotation:o}};return this.handleEvent(a),o}createCheckpoint(e,t){const s=this.sequenceCounter.getSequence()-this.lastCheckpointSequence;this.lastCheckpointSequence=this.sequenceCounter.getSequence(),this.lastCheckpointTimestamp=e.timestamp,this.metadata.stats.checkpointCount+=1;const n={checkpointId:`chk_${e.sequence}_${Date.now()}`,sessionId:this.metadata.id,timestamp:e.timestamp,sequence:e.sequence,wallClockTime:Date.now(),snapshot:e,eventIndex:this.metadata.stats.eventCount,eventsSinceLastCheckpoint:s,trigger:t},i={id:n.checkpointId,sessionId:this.metadata.id,timestamp:e.timestamp,sequence:e.sequence,wallClockTime:n.wallClockTime,type:"CHECKPOINT",category:"CHECKPOINT",source:"BROWSER_RUNTIME",payload:{checkpointId:n.checkpointId,snapshot:e,eventsSinceLastCheckpoint:s,totalEventsSoFar:this.metadata.stats.eventCount}};return this.checkpointListeners.forEach(r=>{try{r(n)}catch(o){console.error("[ForensicRecorder] Checkpoint listener error:",o)}}),this.handleEvent(i),n}handleEvent(e){this.isPaused&&e.type!=="CHECKPOINT"&&e.type!=="ANNOTATION"||(this.metadata.stats.eventCount+=1,e.category==="DOM"&&(this.metadata.stats.mutationCount+=1),e.category==="ERROR"&&(this.metadata.stats.errorCount+=1),e.category==="CONSOLE"&&(this.metadata.stats.consoleCount+=1),e.category==="NETWORK"&&(this.metadata.stats.networkCount+=1),e.category==="SCREENSHOT"&&(this.metadata.stats.screenshotCount+=1),this.isRecording&&e.type!=="CHECKPOINT"&&e.type!=="DOM_SNAPSHOT"&&this.sequenceCounter.getSequence()-this.lastCheckpointSequence>=this.checkpointIntervalEvents&&typeof document<"u"&&this.captureCheckpoint("PERIODIC"),this.eventListeners.forEach(t=>{try{t(e)}catch(s){console.error("[ForensicRecorder] Event listener error:",s)}}))}createInitialMetadata(e,t){const s={domRecording:typeof MutationObserver<"u"?"HEALTHY":"UNAVAILABLE",userEvents:typeof window<"u"?"HEALTHY":"UNAVAILABLE",console:typeof console<"u"?"HEALTHY":"UNAVAILABLE",network:typeof window<"u"&&typeof window.fetch<"u"?"HEALTHY":"PARTIAL",screenshots:"HEALTHY",shadowDom:typeof Element<"u"&&"attachShadow"in Element.prototype?"HEALTHY":"RESTRICTED",iframes:"PARTIAL"},n={eventCount:0,mutationCount:0,errorCount:0,consoleCount:0,networkCount:0,checkpointCount:0,screenshotCount:0,nodeCount:0};return{id:e,name:t||`Recording ${new Date().toLocaleTimeString()}`,url:typeof window<"u"?window.location.href:"about:blank",origin:typeof window<"u"?window.location.origin:"",title:typeof document<"u"?document.title:"Forensic Session",userAgent:typeof navigator<"u"?navigator.userAgent:"Node.js/ForensicAgent",schemaVersion:"2.0.0",recorderVersion:"2.0.0",extensionVersion:"2.0.0",startTime:Date.now(),status:"recording",health:s,stats:n}}}class k{static inspectPage(e=document){var n,i,r,o,a,c,u,h,g,p,y,v,m,d;const t=e.defaultView||(typeof window<"u"?window:{}),s=e.activeElement;return{url:((n=t.location)==null?void 0:n.href)||((i=e.location)==null?void 0:i.href)||"",title:e.title||"",origin:((r=t.location)==null?void 0:r.origin)||"",viewport:{width:t.innerWidth||((o=e.documentElement)==null?void 0:o.clientWidth)||1920,height:t.innerHeight||((a=e.documentElement)==null?void 0:a.clientHeight)||1080,scrollX:t.scrollX||t.pageXOffset||((c=e.documentElement)==null?void 0:c.scrollLeft)||0,scrollY:t.scrollY||t.pageYOffset||((u=e.documentElement)==null?void 0:u.scrollTop)||0,devicePixelRatio:t.devicePixelRatio||1},documentDimensions:{width:Math.max(((h=e.body)==null?void 0:h.scrollWidth)||0,((g=e.documentElement)==null?void 0:g.scrollWidth)||0),height:Math.max(((p=e.body)==null?void 0:p.scrollHeight)||0,((y=e.documentElement)==null?void 0:y.scrollHeight)||0)},activeElement:s?{tag:((v=s.tagName)==null?void 0:v.toLowerCase())||"",selector:this.computeBestSelector(s),text:(m=s.textContent)==null?void 0:m.slice(0,100).trim()}:void 0,focusedElement:typeof e.hasFocus=="function"&&e.hasFocus()&&s?{tag:((d=s.tagName)==null?void 0:d.toLowerCase())||"",selector:this.computeBestSelector(s)}:void 0,visibilityState:e.visibilityState||"visible",readyState:e.readyState||"complete",framesCount:e.querySelectorAll?e.querySelectorAll("iframe, frame").length:0}}static inspectElement(e,t){var xe,_e;const s=e.ownerDocument||document,n=s.defaultView||(typeof window<"u"?window:{}),i=e,r=e.tagName?e.tagName.toLowerCase():"element",o=this.extractClasses(e),{bestSelector:a,candidates:c}=this.generateSelectorCandidates(e),u={},h={};if(e.attributes)for(let V=0;V- `}attachEvents(){if(!this.shadowRoot)return;const e=this.shadowRoot.querySelector("#drag-header");e&&e.addEventListener("mousedown",c=>{this.isDragging=!0,this.dragStartX=c.clientX-this.posX,this.dragStartY=c.clientY-this.posY;const u=h=>{!this.isDragging||!this.hostElement||(this.posX=Math.max(10,Math.min(window.innerWidth-80,h.clientX-this.dragStartX)),this.posY=Math.max(10,Math.min(window.innerHeight-50,h.clientY-this.dragStartY)),this.hostElement.style.left=`${this.posX}px`,this.hostElement.style.top=`${this.posY}px`)},d=()=>{this.isDragging=!1,window.removeEventListener("mousemove",u),window.removeEventListener("mouseup",d),this.savePosition()};window.addEventListener("mousemove",u),window.addEventListener("mouseup",d)});const t=this.shadowRoot.querySelector("#btn-toggle-min");t==null||t.addEventListener("click",()=>{this.isMinimized=!this.isMinimized,this.savePosition(),this.render(),this.attachEvents()});const s=this.shadowRoot.querySelector("#btn-close");s==null||s.addEventListener("click",()=>{this.unmount()});const n=this.shadowRoot.querySelector("#btn-record");n==null||n.addEventListener("click",()=>{this.isRecording?this.callbacks.onStopRecord():this.callbacks.onStartRecord()});const i=this.shadowRoot.querySelector("#btn-checkpoint");i==null||i.addEventListener("click",()=>{if(this.callbacks.onCaptureCheckpoint(),i){const c=i.textContent;i.textContent="✔ Saved!",setTimeout(()=>i.textContent=c,1e3)}});const r=this.shadowRoot.querySelector("#btn-inspect");r==null||r.addEventListener("click",()=>{this.callbacks.onInspectElement()});const o=this.shadowRoot.querySelector("#btn-annotate");o==null||o.addEventListener("click",()=>{const c=prompt("Enter observation, bug note, or hypothesis at this exact moment:");c&&c.trim()&&this.callbacks.onAddAnnotation(c.trim())});const a=this.shadowRoot.querySelector("#btn-dashboard");a==null||a.addEventListener("click",()=>{this.callbacks.onOpenDashboard()})}}(function(){var w;let l=null;const e=new Lt;let t=[],s=null,n=null,i=!1;const r=500,o=[],a=[];window.addEventListener("message",E=>{var C;if(((C=E.data)==null?void 0:C._forensicOrigin)==="PAGE_MAIN"){const{type:N,payload:I}=E.data;if(N==="CONSOLE_ENTRY")o.push(I),o.length>r&&o.shift();else if(N==="NETWORK_ENTRY"){const R=a.findIndex(x=>x.requestId===I.requestId);R>=0?a[R]={...a[R],...I}:(a.push(I),a.length>r&&a.shift())}}});function c(){var E;try{if(typeof chrome<"u"&&((E=chrome.runtime)!=null&&E.getURL)){const C=document.createElement("script");C.src=chrome.runtime.getURL("dist/extension/page-script.js"),C.onload=()=>C.remove(),(document.head||document.documentElement).appendChild(C)}}catch{}}function u(){var C;if(t.length===0||!l)return;const E=[...t];t=[];try{typeof chrome<"u"&&((C=chrome.runtime)!=null&&C.sendMessage)&&chrome.runtime.sendMessage({type:"FORENSIC_EVENTS_CHUNK",sessionId:l.getSessionId(),events:E})}catch{}}function d(E,C,N){var R;if(l)return l.getMetadata();l=new Le({sessionId:C,sessionName:E||`Recording on ${document.title||window.location.hostname}`}),l.onEvent(x=>{t.push(x),n&&n.incrementEventCount(),t.length>=25&&u()}),l.onCheckpoint(x=>{var q;try{typeof chrome<"u"&&((q=chrome.runtime)!=null&&q.sendMessage)&&chrome.runtime.sendMessage({type:"FORENSIC_CHECKPOINT",sessionId:x.sessionId,checkpoint:x})}catch{}});const I=l.start(document);try{typeof chrome<"u"&&((R=chrome.runtime)!=null&&R.sendMessage)&&chrome.runtime.sendMessage({type:"FORENSIC_SESSION_START",metadata:l.getMetadata(),initialSnapshot:I})}catch{}return s||(s=setInterval(u,1e3)),n&&n.updateState(!0,!1,N||Date.now(),0),l.getMetadata()}function h(){var N;if(!l)return null;u(),s&&(clearInterval(s),s=null);const E=l.stop();try{typeof chrome<"u"&&((N=chrome.runtime)!=null&&N.sendMessage)&&chrome.runtime.sendMessage({type:"FORENSIC_SESSION_STOP",sessionId:E.id,metadata:E})}catch{}const C={...E};return l=null,n&&n.updateState(!1,!1,0,0),C}function p(){if(i){i=!1,document.body.style.cursor="default";return}i=!0,document.body.style.cursor="crosshair";const E=document.createElement("div");E.id="forensic-inspect-highlighter",E.style.position="fixed",E.style.pointerEvents="none",E.style.zIndex="2147483640",E.style.border="2px dashed #38bdf8",E.style.background="rgba(56, 189, 248, 0.15)",E.style.transition="all 0.05s ease",document.body.appendChild(E);const C=I=>{if(!i)return;const R=I.target;if(!R||R.id==="forensic-recorder-floating-host"||R.closest("#forensic-recorder-floating-host")){E.style.display="none";return}const x=R.getBoundingClientRect();E.style.display="block",E.style.left=`${x.left}px`,E.style.top=`${x.top}px`,E.style.width=`${x.width}px`,E.style.height=`${x.height}px`},N=I=>{if(!i)return;const R=I.target;if(!R.closest("#forensic-recorder-floating-host")&&(I.preventDefault(),I.stopPropagation(),i=!1,document.body.style.cursor="default",E.remove(),window.removeEventListener("mousemove",C,!0),window.removeEventListener("click",N,!0),l)){const x=R.id?`#${R.id}`:R.className?`.${R.className.split(" ")[0]}`:R.tagName.toLowerCase();l.addAnnotation("Inspect Element",`Inspected element <${R.tagName.toLowerCase()}> with selector '${x}'`,"USER"),alert(`🎯 Inspected element <${R.tagName.toLowerCase()}> recorded! Checkpoint saved.`)}};window.addEventListener("mousemove",C,!0),window.addEventListener("click",N,!0)}function y(){return n||(n=new Ht({onStartRecord:()=>{d()},onStopRecord:()=>{h()},onTogglePause:()=>{l&&(l.getMetadata().status==="recording"?l.pause():l.resume())},onCaptureCheckpoint:()=>{l&&l.captureCheckpoint("MANUAL",document)},onAddAnnotation:E=>{l&&l.addAnnotation("User Note",E,"USER")},onInspectElement:()=>{p()},onOpenDashboard:()=>{const E=l?l.getSessionId():void 0;chrome.runtime.sendMessage({type:"OPEN_DASHBOARD_TAB",sessionId:E})}})),n}function v(){var E;try{typeof chrome<"u"&&((E=chrome.runtime)!=null&&E.sendMessage)&&chrome.runtime.sendMessage({type:"GET_TAB_RECORDING_STATE"},C=>{chrome.runtime.lastError||!C||C.isRecording&&C.recording&&(y().mount(),d(C.recording.sessionName,C.recording.sessionId,C.recording.startTime))})}catch{}}typeof chrome<"u"&&((w=chrome.runtime)!=null&&w.onMessage)&&chrome.runtime.onMessage.addListener((E,C,N)=>{if(E.type==="HIDE_FORENSIC_OVERLAYS")return n&&n.hide(),document.querySelectorAll('#forensic-recorder-floating-host, #forensic-inspect-highlighter, [id^="forensic-"]').forEach(R=>{const x=R;x.style.setProperty("display","none","important"),x.style.setProperty("visibility","hidden","important"),x.style.setProperty("opacity","0","important")}),N({success:!0}),!0;if(E.type==="RESTORE_FORENSIC_OVERLAYS")return n&&n.show(),document.querySelectorAll('#forensic-recorder-floating-host, #forensic-inspect-highlighter, [id^="forensic-"]').forEach(R=>{const x=R;x.style.removeProperty("display"),x.style.removeProperty("visibility"),x.style.removeProperty("opacity")}),N({success:!0}),!0;if(E.type==="BROWSER_COMMAND_REQUEST"){if(["LIST_TABS","FOCUS_TAB","RELOAD_TAB","LIST_EXTENSIONS","RELOAD_EXTENSION","CLOSE_TAB","OPEN_TAB","RESIZE_VIEWPORT","RESET_VIEWPORT"].includes(E.command))return!1;if(E.command==="GET_TAB_CONSOLE_LOGS"){const{level:I,searchQuery:R,limit:x=100,clearAfterRead:q}=E.payload||{};let A=[...o];if(I&&I!=="all"&&(A=A.filter(S=>S.level===I)),R){const S=String(R).toLowerCase();A=A.filter(M=>{var O,_;return((O=M.text)==null?void 0:O.toLowerCase().includes(S))||((_=M.source)==null?void 0:_.toLowerCase().includes(S))})}return x>0&&(A=A.slice(-x)),q&&(o.length=0),N({id:E.id,command:E.command,success:!0,data:{url:window.location.href,title:document.title,totalCaptured:o.length,returnedCount:A.length,logs:A}}),!0}if(E.command==="GET_TAB_NETWORK_REQUESTS"){const{method:I,searchQuery:R,status:x,onlyErrors:q,limit:A=100,clearAfterRead:S}=E.payload||{};let M=[...a];if(I&&(M=M.filter(O=>{var _;return((_=O.method)==null?void 0:_.toUpperCase())===String(I).toUpperCase()})),x&&(M=M.filter(O=>O.status===Number(x))),q&&(M=M.filter(O=>O.error||O.status&&O.status>=400)),R){const O=String(R).toLowerCase();M=M.filter(_=>{var P;return(P=_.url)==null?void 0:P.toLowerCase().includes(O)})}return A>0&&(M=M.slice(-A)),S&&(a.length=0),N({id:E.id,command:E.command,success:!0,data:{url:window.location.href,title:document.title,totalCaptured:a.length,returnedCount:M.length,requests:M}}),!0}return e.handleCommand(E,document).then(I=>{N(I)}),!0}else if(E.type==="START_RECORDING"){const I=d(E.sessionName);y().mount(),N({success:!0,metadata:I})}else if(E.type==="STOP_RECORDING"){const I=h();N({success:!0,metadata:I})}else if(E.type==="TOGGLE_FLOATING_OVERLAY"){const I=y();document.getElementById("forensic-recorder-floating-host")?(I.unmount(),N({isOpen:!1})):(I.mount(),I.updateState((l==null?void 0:l.getMetadata().status)==="recording",!1,(l==null?void 0:l.getMetadata().startTime)||0,0),N({isOpen:!0}))}else if(E.type==="GET_RECORDER_STATUS")N({isRecording:(l==null?void 0:l.getMetadata().status)==="recording",metadata:(l==null?void 0:l.getMetadata())||null});else if(E.type==="CAPTURE_CHECKPOINT")if(l){const I=l.captureCheckpoint("MANUAL",document);N({success:!0,checkpoint:I})}else N({success:!1,error:"Not currently recording"});return!0});let m=null,g=null;function b(){if(!(typeof WebSocket>"u"))try{const E=new WebSocket("ws://127.0.0.1:3847");E.onopen=()=>{m=E,console.log("[Forensic ContentScript] Connected directly to MCP Bridge on ws://127.0.0.1:3847"),g&&(clearInterval(g),g=null),E.send(JSON.stringify({type:"REGISTER_CLIENT",clientType:"CONTENT_SCRIPT",url:window.location.href,title:document.title}))},E.onclose=()=>{m=null,T()},E.onerror=()=>{m=null,T()},E.onmessage=async C=>{var N;try{const I=JSON.parse(C.data.toString());if(I.type==="BROWSER_COMMAND_REQUEST"){const{id:R,command:x,payload:q}=I;if(["LIST_TABS","OPEN_TAB","LIST_EXTENSIONS","RELOAD_EXTENSION","CLOSE_TAB","FOCUS_TAB","RELOAD_TAB","RESIZE_VIEWPORT","RESET_VIEWPORT"].includes(x)){if(typeof chrome<"u"&&((N=chrome.runtime)!=null&&N.sendMessage)){chrome.runtime.sendMessage(I,S=>{if(chrome.runtime.lastError){if(x==="CLOSE_TAB"){E.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:R,command:x,success:!0,data:{closed:!0,url:window.location.href,title:document.title}})),setTimeout(()=>window.close(),100);return}if(x==="RELOAD_TAB"){E.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:R,command:x,success:!0,data:{reloaded:!0,url:window.location.href,title:document.title}})),setTimeout(()=>window.location.reload(),100);return}E.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:R,command:x,success:!1,error:{code:"FORWARD_ERROR",message:chrome.runtime.lastError.message}}))}else E.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",...S||{id:R,command:x,success:!0}}))});return}if(x==="CLOSE_TAB"){E.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:R,command:x,success:!0,data:{closed:!0,url:window.location.href,title:document.title}})),setTimeout(()=>window.close(),100);return}if(x==="RELOAD_TAB"){E.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:R,command:x,success:!0,data:{reloaded:!0,url:window.location.href,title:document.title}})),setTimeout(()=>window.location.reload(),100);return}}if(x==="GET_TAB_CONSOLE_LOGS"){const{level:S,searchQuery:M,limit:O=100,clearAfterRead:_}=q||{};let P=[...o];if(S&&S!=="all"&&(P=P.filter(H=>H.level===S)),M){const H=String(M).toLowerCase();P=P.filter($=>{var F,W;return((F=$.text)==null?void 0:F.toLowerCase().includes(H))||((W=$.source)==null?void 0:W.toLowerCase().includes(H))})}O>0&&(P=P.slice(-O)),_&&(o.length=0),E.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:R,command:x,success:!0,data:{url:window.location.href,title:document.title,totalCaptured:o.length,returnedCount:P.length,logs:P}}));return}if(x==="GET_TAB_NETWORK_REQUESTS"){const{method:S,searchQuery:M,status:O,onlyErrors:_,limit:P=100,clearAfterRead:H}=q||{};let $=[...a];if(S&&($=$.filter(F=>{var W;return((W=F.method)==null?void 0:W.toUpperCase())===String(S).toUpperCase()})),O&&($=$.filter(F=>F.status===Number(O))),_&&($=$.filter(F=>F.error||F.status&&F.status>=400)),M){const F=String(M).toLowerCase();$=$.filter(W=>{var te;return(te=W.url)==null?void 0:te.toLowerCase().includes(F)})}P>0&&($=$.slice(-P)),H&&(a.length=0),E.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:R,command:x,success:!0,data:{url:window.location.href,title:document.title,totalCaptured:a.length,returnedCount:$.length,requests:$}}));return}const A=await e.handleCommand(I,document);E.send(JSON.stringify(A))}}catch(I){console.error("[Forensic ContentScript] Bridge message error:",I)}}}catch{m=null,T()}}function T(){g||(g=setInterval(()=>{(!m||m.readyState!==WebSocket.OPEN)&&b()},4e3))}c(),b(),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",v):v()})()})(); + `}attachEvents(){if(!this.shadowRoot)return;const e=this.shadowRoot.querySelector("#drag-header");e&&e.addEventListener("mousedown",c=>{this.isDragging=!0,this.dragStartX=c.clientX-this.posX,this.dragStartY=c.clientY-this.posY;const u=g=>{!this.isDragging||!this.hostElement||(this.posX=Math.max(10,Math.min(window.innerWidth-80,g.clientX-this.dragStartX)),this.posY=Math.max(10,Math.min(window.innerHeight-50,g.clientY-this.dragStartY)),this.hostElement.style.left=`${this.posX}px`,this.hostElement.style.top=`${this.posY}px`)},h=()=>{this.isDragging=!1,window.removeEventListener("mousemove",u),window.removeEventListener("mouseup",h),this.savePosition()};window.addEventListener("mousemove",u),window.addEventListener("mouseup",h)});const t=this.shadowRoot.querySelector("#btn-toggle-min");t==null||t.addEventListener("click",()=>{this.isMinimized=!this.isMinimized,this.savePosition(),this.render(),this.attachEvents()});const s=this.shadowRoot.querySelector("#btn-close");s==null||s.addEventListener("click",()=>{this.unmount()});const n=this.shadowRoot.querySelector("#btn-record");n==null||n.addEventListener("click",()=>{this.isRecording?this.callbacks.onStopRecord():this.callbacks.onStartRecord()});const i=this.shadowRoot.querySelector("#btn-checkpoint");i==null||i.addEventListener("click",()=>{if(this.callbacks.onCaptureCheckpoint(),i){const c=i.textContent;i.textContent="✔ Saved!",setTimeout(()=>i.textContent=c,1e3)}});const r=this.shadowRoot.querySelector("#btn-inspect");r==null||r.addEventListener("click",()=>{this.callbacks.onInspectElement()});const o=this.shadowRoot.querySelector("#btn-annotate");o==null||o.addEventListener("click",()=>{const c=prompt("Enter observation, bug note, or hypothesis at this exact moment:");c&&c.trim()&&this.callbacks.onAddAnnotation(c.trim())});const a=this.shadowRoot.querySelector("#btn-dashboard");a==null||a.addEventListener("click",()=>{this.callbacks.onOpenDashboard()})}}(function(){var m;let l=null;const e=new Ot;let t=[],s=null,n=null,i=!1;const r=500,o=[],a=[];window.addEventListener("message",d=>{var f;if(((f=d.data)==null?void 0:f._forensicOrigin)==="PAGE_MAIN"){const{type:w,payload:E}=d.data;if(w==="CONSOLE_ENTRY")o.push(E),o.length>r&&o.shift();else if(w==="NETWORK_ENTRY"){const S=a.findIndex(T=>T.requestId===E.requestId);S>=0?a[S]={...a[S],...E}:(a.push(E),a.length>r&&a.shift())}}});function c(){var d;try{if(typeof chrome<"u"&&((d=chrome.runtime)!=null&&d.getURL)){const f=document.createElement("script");f.src=chrome.runtime.getURL("dist/extension/page-script.js"),f.onload=()=>f.remove(),(document.head||document.documentElement).appendChild(f)}}catch{}}function u(){var f;if(t.length===0||!l)return;const d=[...t];t=[];try{typeof chrome<"u"&&((f=chrome.runtime)!=null&&f.sendMessage)&&chrome.runtime.sendMessage({type:"FORENSIC_EVENTS_CHUNK",sessionId:l.getSessionId(),events:d})}catch{}}function h(d,f,w){var S;if(l)return l.getMetadata();l=new Oe({sessionId:f,sessionName:d||`Recording on ${document.title||window.location.hostname}`}),l.onEvent(T=>{t.push(T),n&&n.incrementEventCount(),t.length>=25&&u()}),l.onCheckpoint(T=>{var x;try{typeof chrome<"u"&&((x=chrome.runtime)!=null&&x.sendMessage)&&chrome.runtime.sendMessage({type:"FORENSIC_CHECKPOINT",sessionId:T.sessionId,checkpoint:T})}catch{}});const E=l.start(document);try{typeof chrome<"u"&&((S=chrome.runtime)!=null&&S.sendMessage)&&chrome.runtime.sendMessage({type:"FORENSIC_SESSION_START",metadata:l.getMetadata(),initialSnapshot:E})}catch{}return s||(s=setInterval(u,1e3)),n&&n.updateState(!0,!1,w||Date.now(),0),l.getMetadata()}function g(){var w;if(!l)return null;u(),s&&(clearInterval(s),s=null);const d=l.stop();try{typeof chrome<"u"&&((w=chrome.runtime)!=null&&w.sendMessage)&&chrome.runtime.sendMessage({type:"FORENSIC_SESSION_STOP",sessionId:d.id,metadata:d})}catch{}const f={...d};return l=null,n&&n.updateState(!1,!1,0,0),f}function p(){if(i){i=!1,document.body.style.cursor="default";return}i=!0,document.body.style.cursor="crosshair";const d=document.createElement("div");d.id="forensic-inspect-highlighter",d.style.position="fixed",d.style.pointerEvents="none",d.style.zIndex="2147483640",d.style.border="2px dashed #38bdf8",d.style.background="rgba(56, 189, 248, 0.15)",d.style.transition="all 0.05s ease",document.body.appendChild(d);const f=E=>{if(!i)return;const S=E.target;if(!S||S.id==="forensic-recorder-floating-host"||S.closest("#forensic-recorder-floating-host")){d.style.display="none";return}const T=S.getBoundingClientRect();d.style.display="block",d.style.left=`${T.left}px`,d.style.top=`${T.top}px`,d.style.width=`${T.width}px`,d.style.height=`${T.height}px`},w=E=>{if(!i)return;const S=E.target;if(!S.closest("#forensic-recorder-floating-host")&&(E.preventDefault(),E.stopPropagation(),i=!1,document.body.style.cursor="default",d.remove(),window.removeEventListener("mousemove",f,!0),window.removeEventListener("click",w,!0),l)){const T=S.id?`#${S.id}`:S.className?`.${S.className.split(" ")[0]}`:S.tagName.toLowerCase();l.addAnnotation("Inspect Element",`Inspected element <${S.tagName.toLowerCase()}> with selector '${T}'`,"USER"),alert(`🎯 Inspected element <${S.tagName.toLowerCase()}> recorded! Checkpoint saved.`)}};window.addEventListener("mousemove",f,!0),window.addEventListener("click",w,!0)}function y(){return n||(n=new Ut({onStartRecord:()=>{h()},onStopRecord:()=>{g()},onTogglePause:()=>{l&&(l.getMetadata().status==="recording"?l.pause():l.resume())},onCaptureCheckpoint:()=>{l&&l.captureCheckpoint("MANUAL",document)},onAddAnnotation:d=>{l&&l.addAnnotation("User Note",d,"USER")},onInspectElement:()=>{p()},onOpenDashboard:()=>{const d=l?l.getSessionId():void 0;chrome.runtime.sendMessage({type:"OPEN_DASHBOARD_TAB",sessionId:d})}})),n}function v(){var d;try{typeof chrome<"u"&&((d=chrome.runtime)!=null&&d.sendMessage)&&chrome.runtime.sendMessage({type:"GET_TAB_RECORDING_STATE"},f=>{chrome.runtime.lastError||!f||f.isRecording&&f.recording&&(y().mount(),h(f.recording.sessionName,f.recording.sessionId,f.recording.startTime))})}catch{}}typeof chrome<"u"&&((m=chrome.runtime)!=null&&m.onMessage)&&chrome.runtime.onMessage.addListener((d,f,w)=>{if(d.type==="HIDE_FORENSIC_OVERLAYS")return n&&n.hide(),document.querySelectorAll('#forensic-recorder-floating-host, #forensic-inspect-highlighter, [id^="forensic-"]').forEach(S=>{const T=S;T.style.setProperty("display","none","important"),T.style.setProperty("visibility","hidden","important"),T.style.setProperty("opacity","0","important")}),w({success:!0}),!0;if(d.type==="RESTORE_FORENSIC_OVERLAYS")return n&&n.show(),document.querySelectorAll('#forensic-recorder-floating-host, #forensic-inspect-highlighter, [id^="forensic-"]').forEach(S=>{const T=S;T.style.removeProperty("display"),T.style.removeProperty("visibility"),T.style.removeProperty("opacity")}),w({success:!0}),!0;if(d.type==="BROWSER_COMMAND_REQUEST"){if(["LIST_TABS","FOCUS_TAB","RELOAD_TAB","LIST_EXTENSIONS","RELOAD_EXTENSION","CLOSE_TAB","OPEN_TAB","RESIZE_VIEWPORT","RESET_VIEWPORT"].includes(d.command))return!1;if(d.command==="GET_TAB_CONSOLE_LOGS"){const{level:E,searchQuery:S,limit:T=100,clearAfterRead:x}=d.payload||{};let N=[...o];if(E&&E!=="all"&&(N=N.filter(D=>D.level===E)),S){const D=String(S).toLowerCase();N=N.filter(M=>{var L,I;return((L=M.text)==null?void 0:L.toLowerCase().includes(D))||((I=M.source)==null?void 0:I.toLowerCase().includes(D))})}return T>0&&(N=N.slice(-T)),x&&(o.length=0),w({id:d.id,command:d.command,success:!0,data:{url:window.location.href,title:document.title,totalCaptured:o.length,returnedCount:N.length,logs:N}}),!0}if(d.command==="GET_TAB_NETWORK_REQUESTS"){const{method:E,searchQuery:S,status:T,onlyErrors:x,limit:N=100,clearAfterRead:D}=d.payload||{};let M=[...a];if(E&&(M=M.filter(L=>{var I;return((I=L.method)==null?void 0:I.toUpperCase())===String(E).toUpperCase()})),T&&(M=M.filter(L=>L.status===Number(T))),x&&(M=M.filter(L=>L.error||L.status&&L.status>=400)),S){const L=String(S).toLowerCase();M=M.filter(I=>{var C;return(C=I.url)==null?void 0:C.toLowerCase().includes(L)})}return N>0&&(M=M.slice(-N)),D&&(a.length=0),w({id:d.id,command:d.command,success:!0,data:{url:window.location.href,title:document.title,totalCaptured:a.length,returnedCount:M.length,requests:M}}),!0}return e.handleCommand(d,document).then(E=>{w(E)}),!0}else if(d.type==="START_RECORDING"){const E=h(d.sessionName);y().mount(),w({success:!0,metadata:E})}else if(d.type==="STOP_RECORDING"){const E=g();w({success:!0,metadata:E})}else if(d.type==="TOGGLE_FLOATING_OVERLAY"){const E=y();document.getElementById("forensic-recorder-floating-host")?(E.unmount(),w({isOpen:!1})):(E.mount(),E.updateState((l==null?void 0:l.getMetadata().status)==="recording",!1,(l==null?void 0:l.getMetadata().startTime)||0,0),w({isOpen:!0}))}else if(d.type==="GET_RECORDER_STATUS")w({isRecording:(l==null?void 0:l.getMetadata().status)==="recording",metadata:(l==null?void 0:l.getMetadata())||null});else if(d.type==="CAPTURE_CHECKPOINT")if(l){const E=l.captureCheckpoint("MANUAL",document);w({success:!0,checkpoint:E})}else w({success:!1,error:"Not currently recording"});return!0}),c(),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",v):v()})()})(); diff --git a/dist/extension/service-worker.js b/dist/extension/service-worker.js index 8a07840c..3df46b93 100644 --- a/dist/extension/service-worker.js +++ b/dist/extension/service-worker.js @@ -1 +1 @@ -var v=Object.defineProperty;var P=(E,l,d)=>l in E?v(E,l,{enumerable:!0,configurable:!0,writable:!0,value:d}):E[l]=d;var b=(E,l,d)=>P(E,typeof l!="symbol"?l+"":l,d);(function(){"use strict";var T,_,p,R;class E{constructor(s="ForensicRecorderDB"){b(this,"dbName");b(this,"dbVersion",1);b(this,"db",null);this.dbName=s}async openDB(){if(this.db)return this.db;if(typeof indexedDB>"u")throw new Error("IndexedDB is not available in current runtime environment");return new Promise((s,e)=>{const r=indexedDB.open(this.dbName,this.dbVersion);r.onupgradeneeded=c=>{const t=c.target.result;if(t.objectStoreNames.contains("sessions")||t.createObjectStore("sessions",{keyPath:"id"}),!t.objectStoreNames.contains("events")){const n=t.createObjectStore("events",{keyPath:"id"});n.createIndex("sessionId","sessionId",{unique:!1}),n.createIndex("sequence","sequence",{unique:!1})}t.objectStoreNames.contains("checkpoints")||t.createObjectStore("checkpoints",{keyPath:"checkpointId"}).createIndex("sessionId","sessionId",{unique:!1}),t.objectStoreNames.contains("snapshots")||t.createObjectStore("snapshots",{keyPath:"sessionId"}),t.objectStoreNames.contains("annotations")||t.createObjectStore("annotations",{keyPath:"id"}).createIndex("sessionId","sessionId",{unique:!1})},r.onsuccess=()=>{this.db=r.result,s(this.db)},r.onerror=()=>e(r.error)})}async saveSession(s){const e=await this.openDB();return new Promise((r,c)=>{const t=e.transaction("sessions","readwrite");t.objectStore("sessions").put(s),t.oncomplete=()=>r(),t.onerror=()=>c(t.error)})}async getSession(s){const e=await this.openDB();return new Promise((r,c)=>{const o=e.transaction("sessions","readonly").objectStore("sessions").get(s);o.onsuccess=()=>r(o.result||null),o.onerror=()=>c(o.error)})}async listSessions(){const s=await this.openDB();return new Promise((e,r)=>{const n=s.transaction("sessions","readonly").objectStore("sessions").getAll();n.onsuccess=()=>{const o=n.result||[];o.sort((a,u)=>u.startTime-a.startTime),e(o)},n.onerror=()=>r(n.error)})}async deleteSession(s){const e=await this.openDB();return new Promise((r,c)=>{const t=e.transaction(["sessions","events","checkpoints","snapshots","annotations"],"readwrite");t.objectStore("sessions").delete(s),t.objectStore("snapshots").delete(s);const a=t.objectStore("events").index("sessionId").openCursor(IDBKeyRange.only(s));a.onsuccess=()=>{const u=a.result;u&&(u.delete(),u.continue())},t.oncomplete=()=>r(!0),t.onerror=()=>c(t.error)})}async appendEvents(s,e){if(e.length===0)return;const r=await this.openDB();return new Promise((c,t)=>{const n=r.transaction("events","readwrite"),o=n.objectStore("events");for(const a of e)o.put(a);n.oncomplete=()=>c(),n.onerror=()=>t(n.error)})}async getEvents(s,e){const r=await this.openDB();return new Promise((c,t)=>{const u=r.transaction("events","readonly").objectStore("events").index("sessionId").getAll(IDBKeyRange.only(s));u.onsuccess=()=>{let m=u.result||[];m.sort((h,f)=>h.sequence-f.sequence),e&&(m=m.filter(h=>!(e.category&&h.category!==e.category||e.type&&h.type!==e.type||typeof e.fromTimestamp=="number"&&h.timestamp0||E.height>0||E.right>0||E.bottom>0,R=!C||E.right>0&&E.bottom>0&&E.left =L||E.top>=I),A=!P&&T!=="none"&&x!=="hidden"&&N>0&&R,se={disabled:i.disabled??e.hasAttribute("disabled"),readOnly:i.readOnly??e.hasAttribute("readonly"),checked:i.checked,selected:i.selected,focused:s.activeElement===e,isShadowHost:!!e.shadowRoot,hasShadowRoot:!!e.shadowRoot},z=[];let G=e.parentElement;for(;G&&G.tagName&&G.tagName.toLowerCase()!=="html";)z.push(this.computeBestSelector(G)),G=G.parentElement;const Ht={count:e.children?e.children.length:0,tags:e.children?Array.from(e.children).slice(0,10).map(V=>V.tagName.toLowerCase()):[]};let Ae;if(t){const V=t.getId(e);Ae={logicalNodeId:V??null,creationSequence:null,lastMutationSequence:null,eventCount:0,isRecorded:V!=null}}return{tag:r,id:e.id||void 0,classes:o,role:g||void 0,ariaAttributes:Object.keys(h).length>0?h:void 0,text:v.slice(0,200),normalizedText:m.slice(0,200),value:d,type:f.type||void 0,selector:a,bestSelector:a,selectorCandidates:c,bounds:E,visibility:{isVisible:A,display:T,visibility:x,opacity:N,pointerEvents:D,isClipped:P,isInViewport:R,zIndex:M},computedStyle:S?{display:T,visibility:x,opacity:String(N),position:S.position,zIndex:String(M),pointerEvents:D,overflow:S.overflow,boxSizing:S.boxSizing,color:S.color,backgroundColor:S.backgroundColor,fontSize:S.fontSize}:{},attributes:u,state:se,context:{parentChain:z,parentSelector:z[0]||void 0,childrenSummary:Ht,containingBlock:(S==null?void 0:S.position)==="fixed"?"viewport":z[0]||void 0,iframe:null,shadowRoot:e.shadowRoot?"open":null},forensics:Ae}}static inspectVisualState(e){var f,w;const t=e.ownerDocument||document,s=t.defaultView||(typeof window<"u"?window:{}),n=e.getBoundingClientRect?e.getBoundingClientRect():{x:0,y:0,width:0,height:0,top:0,right:0,bottom:0,left:0},i=s.getComputedStyle?s.getComputedStyle(e):null,r=s.innerWidth||((f=t.documentElement)==null?void 0:f.clientWidth)||1920,o=s.innerHeight||((w=t.documentElement)==null?void 0:w.clientHeight)||1080,a=s.scrollX||s.pageXOffset||0,c=s.scrollY||s.pageYOffset||0,u=s.devicePixelRatio||1,h=(i==null?void 0:i.display)||"block",g=(i==null?void 0:i.visibility)||"visible",p=i&&parseFloat(i.opacity)||1,y=n.right>0&&n.bottom>0&&n.left =r||n.top>=o;let d=null;if(t.elementFromPoint&&y&&!v&&h!=="none"){const E=Math.max(0,Math.min(r-1,n.left+n.width/2)),S=Math.max(0,Math.min(o-1,n.top+n.height/2));try{const T=t.elementFromPoint(E,S);T&&T!==e&&!e.contains(T)&&!T.contains(e)&&(d=this.computeBestSelector(T))}catch{}}return{selector:this.computeBestSelector(e),bounds:{x:n.x??n.left??0,y:n.y??n.top??0,width:n.width??0,height:n.height??0,top:n.top??0,right:n.right??0,bottom:n.bottom??0,left:n.left??0},viewport:{scrollX:a,scrollY:c,width:r,height:o,devicePixelRatio:u},layout:{display:h,position:(i==null?void 0:i.position)||"static",zIndex:(i==null?void 0:i.zIndex)||"auto",opacity:p,visibility:g,overflow:(i==null?void 0:i.overflow)||"visible",boxSizing:(i==null?void 0:i.boxSizing)||"content-box",pointerEvents:(i==null?void 0:i.pointerEvents)||"auto"},occlusion:{isInViewport:y,isClipped:v||m,isZeroDimension:v,isTransparent:p===0,isDisplayNone:h==="none",isVisibilityHidden:g==="hidden",isOffscreen:m,occludedBy:d},computedStyleSummary:i?{display:h,position:i.position,zIndex:i.zIndex,opacity:String(p),visibility:g,pointerEvents:i.pointerEvents}:{}}}static generateSelectorCandidates(e){const t=e.ownerDocument||document,s=e.tagName?e.tagName.toLowerCase():"element",n=[];if(e.id&&/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(e.id)){const c=`#${e.id}`;try{t.querySelectorAll&&t.querySelectorAll(c).length===1&&n.push(c)}catch{n.push(c)}}const i=["data-testid","data-test","data-id","data-qa","data-cy","aria-label","name"];for(const c of i){const u=e.getAttribute(c);if(u&&/^[a-zA-Z0-9_-]+$/.test(u)){const h=`${s}[${c}="${u}"]`;try{t.querySelectorAll&&t.querySelectorAll(h).length===1&&n.push(h)}catch{n.push(h)}}}const r=this.extractClasses(e).filter(c=>/^[a-zA-Z0-9_-]+$/.test(c)&&!c.startsWith("ng-")&&!c.startsWith("_ng"));if(r.length>0){const c=`${s}.${r.slice(0,3).join(".")}`;try{t.querySelectorAll&&t.querySelectorAll(c).length===1&&n.push(c)}catch{n.push(c)}}if(e.parentElement&&e.parentElement.children){const c=Array.from(e.parentElement.children).filter(u=>u.tagName&&u.tagName.toLowerCase()===s);if(c.length>1){const u=c.indexOf(e)+1;if(u>0){const h=this.computeBestSelector(e.parentElement);n.push(`${h} > ${s}:nth-of-type(${u})`)}}}const o=r.length>0?`${s}.${r[0]}`:s;return n.push(o),{bestSelector:n[0]||s,candidates:n}}static computeBestSelector(e){return this.generateSelectorCandidates(e).bestSelector}static extractClasses(e){return e.classList&&typeof e.classList.forEach=="function"?Array.from(e.classList):typeof e.className=="string"?e.className.split(/\s+/).filter(Boolean):e.className&&typeof e.className.baseVal=="string"?e.className.baseVal.split(/\s+/).filter(Boolean):[]}static inferImplicitRole(e){switch(e.tagName?e.tagName.toLowerCase():""){case"a":return e.hasAttribute("href")?"link":void 0;case"button":return"button";case"input":{const s=e.type||"text";return s==="button"||s==="submit"||s==="reset"?"button":s==="checkbox"?"checkbox":s==="radio"?"radio":"textbox"}case"select":return"combobox";case"textarea":return"textbox";case"nav":return"navigation";case"header":return"banner";case"footer":return"contentinfo";case"main":return"main";case"article":return"article";case"section":return"region";default:return}}}b(k,"privacyEngine",new J);class Le{constructor(e){b(this,"registry");b(this,"lastSelectedElementRef");b(this,"timingHook",null);b(this,"lastTrajectory",[]);this.registry=e}setLastSelectedElement(e){this.lastSelectedElementRef=e}setTimingHook(e){this.timingHook=e}getLastTrajectory(){return this.lastTrajectory}async timing(e){this.timingHook&&await this.timingHook(e)}resolveTarget(e,t=document){if(e.selectedElementRef&&this.lastSelectedElementRef&&t.contains(this.lastSelectedElementRef))return this.lastSelectedElementRef;if(typeof e.nodeId=="number"&&this.registry){const s=this.registry.getNode(e.nodeId);if(s&&s instanceof Element&&t.contains(s))return s}if(e.selector)try{const s=t.querySelectorAll(e.selector);if(s.length>1){for(let n=0;n {r+=w.length});try{h.observe(t.body||t.documentElement,{childList:!0,attributes:!0,characterData:!0,subtree:!0})}catch{}const g=w=>{o.push(w.message||"Runtime Error")};typeof window<"u"&&window.addEventListener("error",g);try{await this.dispatchAction(n,e)}finally{typeof window<"u"&&window.removeEventListener("error",g)}let p=!0;if((f=e.options)!=null&&f.waitForStabilization){const w=e.options.stabilizationTimeoutMs||300;await new Promise(E=>setTimeout(E,Math.min(2e3,w)))}h.disconnect();let y;t.contains(n)&&(y=k.inspectElement(n,this.registry));const v=Date.now()-s,m=a!=null&&a.__FORENSIC_CONSOLE_BUFFER__?a.__FORENSIC_CONSOLE_BUFFER__.slice(c).filter(w=>(w==null?void 0:w.level)==="error").length:0,d=a!=null&&a.__FORENSIC_NETWORK_BUFFER__?a.__FORENSIC_NETWORK_BUFFER__.slice(u).length:0;return{success:!0,action:e.action,target:y||i,beforeState:i,afterState:y,effects:{domMutations:r,consoleErrors:m,networkRequests:d,runtimeErrors:o},durationMs:v,stabilized:p}}async dispatchAction(e,t){var n,i,r,o,a,c;const s=e;switch(t.action){case"click":{this.scrollIntoViewIfNeeded(e),await this.timing("move"),await this.timing("click"),this.dispatchMouseEvent(e,"pointerdown"),this.dispatchMouseEvent(e,"mousedown"),typeof s.focus=="function"&&s.focus(),this.dispatchMouseEvent(e,"pointerup"),this.dispatchMouseEvent(e,"mouseup"),typeof s.click=="function"?s.click():this.dispatchMouseEvent(e,"click");break}case"double_click":{this.scrollIntoViewIfNeeded(e),await this.timing("click"),this.dispatchMouseEvent(e,"click"),await this.timing("click"),this.dispatchMouseEvent(e,"click"),this.dispatchMouseEvent(e,"dblclick");break}case"right_click":{this.scrollIntoViewIfNeeded(e),await this.timing("click"),this.dispatchMouseEvent(e,"pointerdown",{button:2}),this.dispatchMouseEvent(e,"mousedown",{button:2}),this.dispatchMouseEvent(e,"contextmenu",{button:2});break}case"hover":{await this.timing("move"),this.dispatchMouseEvent(e,"pointerenter"),this.dispatchMouseEvent(e,"mouseenter"),this.dispatchMouseEvent(e,"mouseover"),await this.timing("move"),this.dispatchMouseEvent(e,"mousemove");break}case"focus":{typeof s.focus=="function"&&s.focus(),e.dispatchEvent(new FocusEvent("focus",{bubbles:!0}));break}case"blur":{typeof s.blur=="function"&&s.blur(),e.dispatchEvent(new FocusEvent("blur",{bubbles:!0}));break}case"type":{const u=t.text||"",h=e,g=((n=e.ownerDocument)==null?void 0:n.defaultView)||(typeof window<"u"?window:null);typeof s.focus=="function"&&s.focus();for(const y of u){await this.timing("type");const v=d=>{try{const w=(g==null?void 0:g.KeyboardEvent)||(typeof KeyboardEvent<"u"?KeyboardEvent:null);if(w)return new w(d,{key:y,bubbles:!0})}catch{}const f=(g==null?void 0:g.CustomEvent)||(g==null?void 0:g.Event)||CustomEvent;return new f(d,{bubbles:!0,cancelable:!0})},m=(d,f)=>{try{const E=(g==null?void 0:g.InputEvent)||(typeof InputEvent<"u"?InputEvent:null);if(E)return new E(d,f)}catch{}const w=(g==null?void 0:g.CustomEvent)||(g==null?void 0:g.Event)||CustomEvent;return new w(d,{bubbles:!0,cancelable:!0})};e.dispatchEvent(v("keydown")),e.dispatchEvent(v("keypress")),"value"in h&&(h.value=(h.value||"")+y),e.dispatchEvent(m("input",{data:y,inputType:"insertText",bubbles:!0})),e.dispatchEvent(v("keyup"))}const p=(g==null?void 0:g.Event)||Event;e.dispatchEvent(new p("change",{bubbles:!0}));break}case"clear":{const u=e,h=((i=e.ownerDocument)==null?void 0:i.defaultView)||(typeof window<"u"?window:null);if("value"in u){u.value="";const g=(y,v)=>{try{const d=(h==null?void 0:h.InputEvent)||(typeof InputEvent<"u"?InputEvent:null);if(d)return new d(y,v)}catch{}const m=(h==null?void 0:h.CustomEvent)||(h==null?void 0:h.Event)||CustomEvent;return new m(y,{bubbles:!0,cancelable:!0})};e.dispatchEvent(g("input",{inputType:"deleteContentBackward",bubbles:!0}));const p=(h==null?void 0:h.Event)||Event;e.dispatchEvent(new p("change",{bubbles:!0}))}break}case"press_key":{const u=t.key||"Enter",h=((r=e.ownerDocument)==null?void 0:r.defaultView)||(typeof window<"u"?window:null),g=p=>{try{const v=(h==null?void 0:h.KeyboardEvent)||(typeof KeyboardEvent<"u"?KeyboardEvent:null);if(v)return new v(p,{key:u,bubbles:!0})}catch{}const y=(h==null?void 0:h.CustomEvent)||(h==null?void 0:h.Event)||CustomEvent;return new y(p,{bubbles:!0,cancelable:!0})};e.dispatchEvent(g("keydown")),e.dispatchEvent(g("keypress")),e.dispatchEvent(g("keyup"));break}case"select_option":{const u=e;((o=u.tagName)==null?void 0:o.toLowerCase())==="select"&&t.optionValue&&(u.value=t.optionValue,e.dispatchEvent(new Event("change",{bubbles:!0})));break}case"scroll_into_view":{this.scrollIntoViewIfNeeded(e,!0);break}case"scroll":{const u=((a=t.scrollDelta)==null?void 0:a.x)||0,h=((c=t.scrollDelta)==null?void 0:c.y)||0;typeof e.scrollBy=="function"&&e.scrollBy(u,h);break}default:throw new Error(`Unsupported interaction action: ${t.action}`)}}scrollIntoViewIfNeeded(e,t=!1){if(typeof e.scrollIntoView=="function")try{e.scrollIntoView({behavior:"auto",block:"center",inline:"center"})}catch{e.scrollIntoView(t)}}dispatchMouseEvent(e,t,s={}){const n=e.getBoundingClientRect?e.getBoundingClientRect():{left:0,top:0,width:0,height:0},i=n.left+n.width/2,r=n.top+n.height/2,o=new MouseEvent(t,{bubbles:s.bubbles!==void 0?s.bubbles:!0,cancelable:s.cancelable!==void 0?s.cancelable:!0,clientX:i,clientY:r,button:s.button||0,buttons:s.button===2?2:1});e.dispatchEvent(o)}}class ie{static matches(e,t){if(!e||e.nodeType!==$.ELEMENT_NODE)return!1;const s=t.trim();return s?s.includes(",")?s.split(",").some(n=>this.matchesSimple(e,n.trim())):this.matchesCompound(e,s):!1}static querySelector(e,t,s){const n=this.querySelectorAll(e,t,s,1);return n.length>0?n[0]:null}static querySelectorAll(e,t,s,n=1/0){const i=[],r=s[t];if(!r)return i;const o=[...r.children||[]],a=new Set;for(;o.length>0&&i.length =n))break;u.children&&u.children.length>0&&o.push(...u.children)}}return i}static getElementById(e,t){for(const s of Object.values(t))if(s.nodeType===$.ELEMENT_NODE&&!s.isDetached&&s.attributes&&s.attributes.id===e&&this.isNodeConnected(s,t))return s;return null}static isNodeConnected(e,t){if(e.isDetached)return!1;let s=e;const n=new Set;for(;s&&s.parentId;){if(n.has(s.id))return!1;n.add(s.id);const i=t[s.parentId];if(!i||i.isDetached)return!1;s=i}return!0}static computeSelector(e,t){var r,o;if(!e)return"";if(e.nodeType!==$.ELEMENT_NODE)return e.tagName||`#node-${e.id}`;if((r=e.attributes)!=null&&r.id)return`#${e.attributes.id}`;const s=e.tagName||"div",n=(((o=e.attributes)==null?void 0:o.class)||"").split(/\s+/).filter(a=>a&&!a.startsWith("ng-")).slice(0,2),i=n.length>0?"."+n.join("."):"";if(e.parentId&&t[e.parentId]){const c=(t[e.parentId].children||[]).map(u=>t[u]).filter(u=>u&&u.nodeType===$.ELEMENT_NODE&&u.tagName===s);if(c.length>1){const u=c.findIndex(h=>h.id===e.id)+1;return`${s}${i}:nth-of-type(${u})`}}return`${s}${i}`}static matchesCompound(e,t){return this.matchesSimple(e,t)}static matchesSimple(e,t){var i,r,o,a,c,u,h;const s=((i=e.tagName)==null?void 0:i.toLowerCase())||"";if(t==="*")return!0;if(t.startsWith("#")){const g=t.substring(1);return((r=e.attributes)==null?void 0:r.id)===g}if(t.startsWith(".")){const g=t.substring(1);return(((o=e.attributes)==null?void 0:o.class)||"").split(/\s+/).includes(g)}if(t.startsWith("[")&&t.endsWith("]")){const g=t.substring(1,t.length-1);if(g.includes("=")){const[p,y]=g.split("="),v=y.replace(/^["']|["']$/g,"");return((a=e.attributes)==null?void 0:a[p.trim()])===v}return!!((c=e.attributes)!=null&&c[g.trim()])}const n=t.match(/^([a-zA-Z0-9_-]+)(.*)$/);if(n){const g=n[1].toLowerCase(),p=n[2];if(g!==s&&g!=="*")return!1;if(!p)return!0;if(p.startsWith("#"))return((u=e.attributes)==null?void 0:u.id)===p.substring(1);if(p.startsWith("."))return(((h=e.attributes)==null?void 0:h.class)||"").split(/\s+/).includes(p.substring(1));if(p.startsWith("["))return this.matchesSimple(e,p)}return!1}}class De{static traceElement(e,t,s){var M,L;const n=[...t].sort((I,C)=>I.sequence-C.sequence);let i=e.nodeId,r="unknown",o=e.selector||"",a={},c=0,u=0,h="init";if(!i&&e.selector&&s){const I=ie.querySelector(e.selector,s.rootId,s.nodes);I&&(i=I.id,r=I.tagName||"element",a={...I.attributes||{}},o=e.selector)}if(!i&&e.selector){for(const I of n)if(I.type==="DOM_MUTATION_ADD"){const C=I.payload;if(C.node&&ie.matches(C.node,e.selector)){i=C.node.id,r=C.node.tagName||"element",a={...C.node.attributes||{}},c=I.timestamp,u=I.sequence,h=I.id;break}}}if(!i)return null;const g=[];let p=!0,y=null,v=null,m,d=0;if(s&&s.nodes[i]){const I=s.nodes[i];r=I.tagName||r,a={...I.attributes||{}},o||(o=ie.computeSelector(I,s.nodes)),g.push({timestamp:s.timestamp,sequence:s.sequence,wallClockTime:Date.now(),stage:"CREATED",eventId:s.snapshotId,eventType:"DOM_SNAPSHOT",description:`Element <${r}> existed in initial baseline snapshot [ID: ${i}]`,details:{initialParentId:I.parentId,attributes:a},nodeSnapshot:I})}const f=new Map;if(s)for(const[I,C]of Object.entries(s.nodes))f.set(Number(I),C.parentId??null);const w=(I,C)=>{let R=f.get(C);const P=new Set;for(;R&&!P.has(R);){if(R===I)return!0;P.add(R),R=f.get(R)}return!1};for(const I of n){const C=I.timestamp,R=I.sequence,P=I.wallClockTime;if(I.type==="DOM_MUTATION_ADD"){const A=I.payload;(M=A.node)!=null&&M.id&&f.set(A.node.id,A.parentId??null),((L=A.node)==null?void 0:L.id)===i&&(p=!0,r=A.node.tagName||r,c=C,u=R,h=I.id,a={...A.node.attributes||{}},g.push({timestamp:C,sequence:R,wallClockTime:P,stage:"ATTACHED_TO_DOM",eventId:I.id,eventType:I.type,description:`Element <${r}> added to DOM under parent ID ${A.parentId}`,details:{parentId:A.parentId,index:A.index},nodeSnapshot:A.node}))}if(I.type==="DOM_MUTATION_REMOVE"){const A=I.payload;A.nodeId===i?(p=!1,y=C,v=R,m=I.id,g.push({timestamp:C,sequence:R,wallClockTime:P,stage:"REMOVED_FROM_DOM",eventId:I.id,eventType:I.type,description:`Element <${r}> explicitly removed from parent ID ${A.parentId}`,details:{parentId:A.parentId,removedIndex:A.index}})):w(A.nodeId,i)&&(p=!1,y=C,v=R,m=I.id,g.push({timestamp:C,sequence:R,wallClockTime:P,stage:"PARENT_SUBTREE_REPLACED",eventId:I.id,eventType:I.type,description:`Ancestor element [ID: ${A.nodeId}] was removed, causing target element [ID: ${i}] to detach from DOM`,details:{removedAncestorId:A.nodeId,parentId:A.parentId}}))}if(I.type==="DOM_MUTATION_MOVE"){const A=I.payload;A.nodeId&&f.set(A.nodeId,A.newParentId??null),A.nodeId===i&&(d++,g.push({timestamp:C,sequence:R,wallClockTime:P,stage:"REPARENTED",eventId:I.id,eventType:I.type,description:`Element reparented from parent ${A.oldParentId} to ${A.newParentId}`,details:{oldParentId:A.oldParentId,newParentId:A.newParentId}}))}if(I.type==="DOM_MUTATION_ATTR"){const A=I.payload;if(A.nodeId===i){d++;const se=A.attributeName.toLowerCase();let z="ATTRIBUTE_MODIFIED";se==="class"&&(z="CLASS_MODIFIED"),se==="style"&&(z="STYLE_MODIFIED"),g.push({timestamp:C,sequence:R,wallClockTime:P,stage:z,eventId:I.id,eventType:I.type,description:`Attribute '${A.attributeName}' changed from '${A.oldValue??""}' to '${A.newValue??""}'`,details:{attributeName:A.attributeName,oldValue:A.oldValue,newValue:A.newValue}})}}if(I.type==="DOM_MUTATION_TEXT"){const A=I.payload;A.nodeId===i&&(d++,g.push({timestamp:C,sequence:R,wallClockTime:P,stage:"TEXT_MODIFIED",eventId:I.id,eventType:I.type,description:`Text content changed: "${A.oldText}" → "${A.newText}"`,details:{oldText:A.oldText,newText:A.newText}}))}}const E=y??c,S=500,T=n.filter(I=>(I.category==="ERROR"||I.category==="CONSOLE")&&Math.abs(I.timestamp-E)<=S),x=n.filter(I=>I.category==="NETWORK"&&Math.abs(I.timestamp-E)<=S),N=n.length>0?n[n.length-1].timestamp:c,D=Math.max(0,(y??N)-c);return{targetNodeId:i,tagName:r,selectorHint:o,initialAttributes:a,createdAt:c,createdSequence:u,createdEventId:h,removedAt:y,removedSequence:v,removedEventId:m,isCurrentlyAlive:p,lifespanMs:Math.round(D*100)/100,mutationCount:d,entries:g,correlatedDiagnostics:T,correlatedNetwork:x}}}class $e{static analyze(e,t,s){var D,M,L,I;const n=typeof e=="number"?{nodeId:e}:{selector:e},i=De.traceElement(n,t,s);if(!i)return{targetQuery:e,found:!1,disappearanceMechanism:"UNKNOWN",likelyRootCause:"Target element could not be found in recording baseline or event stream",confidenceScore:0,detailedExplanation:`No element matching "${e}" was ever created, recorded in the initial DOM snapshot, or observed in mutation events.`,evidentiaryTrail:[],precedingEvents:[],followingEvents:[],correlatedErrors:[],correlatedNetworkCalls:[],alternativeHypotheses:[{hypothesis:"Element was injected into an unmonitored isolated iframe or ShadowRoot closed mode",likelihood:40,evidenceFor:["Element query yielded zero matches in monitored document"],evidenceAgainst:["Iframes/ShadowRoots were accessible in this session"]},{hypothesis:"Selector typo or timing mismatch",likelihood:60,evidenceFor:["Target selector did not match any recorded tag or class"],evidenceAgainst:[]}]};const r=[...t].sort((C,R)=>C.sequence-R.sequence),o=[],a=[];let c="UNKNOWN",u="Unknown disappearance mechanism",h=50,g="",p=i.removedAt??void 0;const y=i.entries.find(C=>C.stage==="REMOVED_FROM_DOM"),v=i.entries.find(C=>C.stage==="PARENT_SUBTREE_REPLACED"),m=i.entries.find(C=>C.stage==="CLASS_MODIFIED"&&/\b(hidden|hide|d-none|invisible|collapsed)\b/i.test(String(C.details.newValue||""))),d=i.entries.find(C=>C.stage==="STYLE_MODIFIED"&&/display\s*:\s*none|visibility\s*:\s*hidden|opacity\s*:\s*0/i.test(String(C.details.newValue||"")));y?(c="DIRECT_NODE_REMOVAL",p=y.timestamp,u=`Element [ID: ${i.targetNodeId}] <${i.tagName}> was directly removed from its parent [ID: ${y.details.parentId}] via DOM removeChild/replaceChild`,h=95,o.push({timestamp:y.timestamp,sequence:y.sequence,eventId:y.eventId,eventType:y.eventType,evidenceType:"DIRECT",description:`Direct DOM removal mutation: element detached from parent ID ${y.details.parentId}`,confidenceContribution:50})):v?(c="PARENT_SUBTREE_REPLACED",p=v.timestamp,u=`Host framework (e.g. React/Vue re-render) destroyed and replaced Ancestor container [ID: ${v.details.removedAncestorId}], causing injected element to be unmounted`,h=92,o.push({timestamp:v.timestamp,sequence:v.sequence,eventId:v.eventId,eventType:v.eventType,evidenceType:"DIRECT",description:`Ancestor container [ID: ${v.details.removedAncestorId}] was removed, wiping out all child subtrees`,confidenceContribution:50})):d?(c="STYLE_DISPLAY_NONE",p=d.timestamp,u=`Element was visually hidden by an inline style modification: "${d.details.newValue}"`,h=88,o.push({timestamp:d.timestamp,sequence:d.sequence,eventId:d.eventId,eventType:d.eventType,evidenceType:"DIRECT",description:`Inline style changed to "${d.details.newValue}"`,confidenceContribution:45})):m?(c="CLASS_TRIGGERED_HIDDEN",p=m.timestamp,u=`Element was visually hidden because its CSS class list was modified to include "${m.details.newValue}"`,h=85,o.push({timestamp:m.timestamp,sequence:m.sequence,eventId:m.eventId,eventType:m.eventType,evidenceType:"DIRECT",description:`Class list changed from "${m.details.oldValue??""}" to "${m.details.newValue??""}"`,confidenceContribution:45})):i.isCurrentlyAlive&&(c="UNKNOWN",u=`Element [ID: ${i.targetNodeId}] is currently alive and attached to the DOM tree (no unmount mutation detected)`,h=70,g="The element exists in the current DOM state. If it is not visible on screen, it may be clipped by viewport boundaries, z-index stacking context, or 0x0 pixel dimensions.");const f=p??i.createdAt,w=500,E=r.filter(C=>C.timestamp>=f-w&&C.timestamp C.timestamp>f&&C.timestamp<=f+w),T=E.filter(C=>C.category==="ERROR");if(T.length>0){const C=T[0],R=((D=C.payload)==null?void 0:D.message)||"Unknown runtime error";o.push({timestamp:C.timestamp,sequence:C.sequence,eventId:C.id,eventType:C.type,evidenceType:"PRECEDING",description:`Runtime error occurred ${(f-C.timestamp).toFixed(1)}ms before disappearance: "${R}"`,confidenceContribution:20,rawEvent:C}),u+=` (preceded by runtime error: "${R}")`}const x=E.filter(C=>C.type==="NETWORK_RESPONSE_COMPLETE"||C.type==="NETWORK_REQUEST_FAILED");if(x.length>0){const C=x[0],R=((M=C.payload)==null?void 0:M.url)||"network request";o.push({timestamp:C.timestamp,sequence:C.sequence,eventId:C.id,eventType:C.type,evidenceType:"PRECEDING",description:`Network response completed ${(f-C.timestamp).toFixed(1)}ms before disappearance: ${R}`,confidenceContribution:15,rawEvent:C})}const N=E.filter(C=>C.category==="NAVIGATION");if(N.length>0){const C=N[0];o.push({timestamp:C.timestamp,sequence:C.sequence,eventId:C.id,eventType:C.type,evidenceType:"PRECEDING",description:`Navigation event (${(L=C.payload)==null?void 0:L.navigationType}) occurred ${(f-C.timestamp).toFixed(1)}ms before disappearance`,confidenceContribution:25,rawEvent:C}),u+=` following SPA navigation to "${(I=C.payload)==null?void 0:I.url}"`}return g||(g=[`Element <${i.tagName}> (Logical ID: ${i.targetNodeId}, selector: "${i.selectorHint}") was created at ${i.createdAt.toFixed(1)}ms.`,`It remained alive in the DOM for ${i.lifespanMs.toFixed(1)}ms and experienced ${i.mutationCount} mutations.`,`At timestamp ${f.toFixed(1)}ms, it disappeared via [${c}].`,`Diagnosis: ${u}.`].join(" ")),c==="PARENT_SUBTREE_REPLACED"?(a.push({hypothesis:"Direct cleanup called by extension code",likelihood:25,evidenceFor:["Element was unmounted shortly after creation"],evidenceAgainst:["Ancestor container mutation was recorded from host page context"]}),a.push({hypothesis:"Host single-page app route change destroyed component tree",likelihood:35,evidenceFor:N.length>0?["Preceding navigation event recorded"]:[],evidenceAgainst:N.length===0?["No navigation events occurred in temporal window"]:[]})):c==="DIRECT_NODE_REMOVAL"&&a.push({hypothesis:"Third-party script or ad-blocker removed the injected node",likelihood:30,evidenceFor:["Direct node removal occurred without ancestor replacement"],evidenceAgainst:["No ad-blocker signatures or extension error logs observed"]}),{targetQuery:e,targetNodeId:i.targetNodeId,found:!0,tagName:i.tagName,selectorHint:i.selectorHint,createdAt:i.createdAt,firstVisibleAt:i.createdAt,lastKnownGoodStateAt:Math.max(0,f-1),disappearedAt:p,lifespanMs:i.lifespanMs,disappearanceMechanism:c,likelyRootCause:u,confidenceScore:Math.min(99,h),detailedExplanation:g,evidentiaryTrail:o,precedingEvents:E,followingEvents:S,correlatedErrors:T,correlatedNetworkCalls:x,alternativeHypotheses:a}}}class qe{constructor(e){b(this,"activeObservation",null);b(this,"registry");b(this,"sequenceCounter");this.registry=e,this.sequenceCounter=new ne}isObserving(){return this.activeObservation!==null}startObservation(e,t=document){this.activeObservation&&this.stopObservation(t);const s=`obs_${Date.now()}_${Math.random().toString(36).slice(2,6)}`,n=Date.now(),i=k.inspectElement(e,this.registry),r=i.bestSelector,o=[],a=this.registry?this.registry.getOrCreateId(e,0):100;o.push({id:`evt_init_${s}`,sessionId:s,timestamp:0,sequence:1,wallClockTime:n,type:"DOM_MUTATION_ADD",category:"DOM",source:"BROWSER_RUNTIME",targetNodeId:a,targetSelector:r,payload:{node:{id:a,nodeType:1,tagName:i.tag,attributes:i.attributes,textContent:i.text,children:[],parentId:null},parentId:null,index:0}});const c=new MutationObserver(u=>{const h=Date.now()-n;for(const g of u)if(g.type==="childList"){for(let p=0;p 0&&(m=$e.analyze(n,a)),{observationId:t,targetSelector:n,targetNodeId:((d=r.forensics)==null?void 0:d.logicalNodeId)||void 0,startTime:i,endTime:u,durationMs:h,initialState:r,finalState:p,disappeared:y,disappearanceReason:v,mutations:a.filter(f=>f.category==="DOM"),diagnostics:a.filter(f=>f.category==="ERROR"||f.category==="CONSOLE"),networkEvents:a.filter(f=>f.category==="NETWORK"),screenshots:c,correlationReport:m}}}class Pe{constructor(e={}){b(this,"isExplicitModeActive",!1);b(this,"isGlobalShortcutActive",!1);b(this,"highlighterEl",null);b(this,"badgeEl",null);b(this,"lastSelectedElement",null);b(this,"options",{});b(this,"onMouseMoveBound");b(this,"onClickBound");b(this,"onKeyDownBound");b(this,"onGlobalClickBound");this.options=e,this.onMouseMoveBound=this.handleMouseMove.bind(this),this.onClickBound=this.handleClick.bind(this),this.onKeyDownBound=this.handleKeyDown.bind(this),this.onGlobalClickBound=this.handleGlobalCtrlShiftClick.bind(this),this.initGlobalShortcutListener()}initGlobalShortcutListener(){typeof window>"u"||this.isGlobalShortcutActive||(window.addEventListener("click",this.onGlobalClickBound,!0),this.isGlobalShortcutActive=!0)}startPicker(e){typeof document>"u"||(e&&(this.options={...this.options,...e}),!this.isExplicitModeActive&&(this.isExplicitModeActive=!0,this.ensureHighlighter(),document.body&&(document.body.style.cursor="crosshair"),window.addEventListener("mousemove",this.onMouseMoveBound,!0),window.addEventListener("click",this.onClickBound,!0),window.addEventListener("keydown",this.onKeyDownBound,!0)))}stopPicker(){this.isExplicitModeActive&&(this.isExplicitModeActive=!1,typeof document<"u"&&document.body&&(document.body.style.cursor="default"),this.removeHighlighter(),typeof window<"u"&&(window.removeEventListener("mousemove",this.onMouseMoveBound,!0),window.removeEventListener("click",this.onClickBound,!0),window.removeEventListener("keydown",this.onKeyDownBound,!0)))}getLastSelectedElement(){return this.lastSelectedElement}setSelectedElement(e){let t;return"tag"in e&&"bestSelector"in e&&typeof e.getAttribute!="function"?t=e:(t=k.inspectElement(e,this.options.nodeRegistry),this.flashSelection(e)),this.lastSelectedElement=t,this.options.onSelected&&this.options.onSelected(t),t}handleGlobalCtrlShiftClick(e){if(!e.ctrlKey||!e.shiftKey)return;const t=e.target;if(!t||this.isExtensionOwned(t))return;e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation();const s=this.setSelectedElement(t);this.notifyExtension(s)}handleMouseMove(e){if(!this.isExplicitModeActive)return;const t=e.target;if(!t||this.isExtensionOwned(t)){this.hideHighlighter();return}this.updateHighlighter(t)}handleClick(e){if(!this.isExplicitModeActive)return;const t=e.target;if(!t||this.isExtensionOwned(t))return;e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation();const s=this.setSelectedElement(t);this.notifyExtension(s),this.stopPicker()}handleKeyDown(e){e.key==="Escape"&&this.isExplicitModeActive&&(e.preventDefault(),this.stopPicker(),this.options.onCanceled&&this.options.onCanceled())}isExtensionOwned(e){return!!(e.id==="forensic-recorder-floating-host"||e.id==="forensic-inspect-highlighter"||e.closest("#forensic-recorder-floating-host")||e.closest("#forensic-inspect-highlighter")||e.hasAttribute("data-forensic-internal")||e.closest("[data-forensic-internal]"))}ensureHighlighter(){if(typeof document>"u"||this.highlighterEl)return;const e=this.options.highlightColor||"#0ea5e9",t=document.createElement("div");t.id="forensic-inspect-highlighter",t.setAttribute("data-forensic-internal","true"),t.style.position="fixed",t.style.pointerEvents="none",t.style.zIndex="2147483640",t.style.border=`2px solid ${e}`,t.style.background="rgba(14, 165, 233, 0.18)",t.style.borderRadius="3px",t.style.boxShadow=`0 0 12px ${e}88`,t.style.transition="all 0.05s ease-out",t.style.display="none";const s=document.createElement("div");s.setAttribute("data-forensic-internal","true"),s.style.position="absolute",s.style.bottom="100%",s.style.left="0",s.style.transform="translateY(-4px)",s.style.background="#0f172a",s.style.color="#38bdf8",s.style.fontSize="11px",s.style.fontFamily="monospace",s.style.fontWeight="bold",s.style.padding="2px 6px",s.style.borderRadius="3px",s.style.boxShadow="0 2px 6px rgba(0,0,0,0.5)",s.style.whiteSpace="nowrap",s.style.pointerEvents="none",t.appendChild(s),document.body.appendChild(t),this.highlighterEl=t,this.badgeEl=s}updateHighlighter(e){if(this.ensureHighlighter(),!this.highlighterEl||!this.badgeEl)return;const t=e.getBoundingClientRect();this.highlighterEl.style.display="block",this.highlighterEl.style.left=`${t.left}px`,this.highlighterEl.style.top=`${t.top}px`,this.highlighterEl.style.width=`${Math.max(1,t.width)}px`,this.highlighterEl.style.height=`${Math.max(1,t.height)}px`;const s=e.tagName.toLowerCase(),n=e.id?`#${e.id}`:"",i=e.className&&typeof e.className=="string"?"."+e.className.split(/\s+/)[0]:"",r=`${Math.round(t.width)}×${Math.round(t.height)}`;this.badgeEl.textContent=`<${s}${n}${i}> [${r}]`}hideHighlighter(){this.highlighterEl&&(this.highlighterEl.style.display="none")}removeHighlighter(){this.highlighterEl&&this.highlighterEl.parentElement&&this.highlighterEl.remove(),this.highlighterEl=null,this.badgeEl=null}flashSelection(e){if(typeof document>"u"||!e.getBoundingClientRect)return;const t=e.getBoundingClientRect(),s=document.createElement("div");s.setAttribute("data-forensic-internal","true"),s.style.position="fixed",s.style.left=`${t.left}px`,s.style.top=`${t.top}px`,s.style.width=`${Math.max(1,t.width)}px`,s.style.height=`${Math.max(1,t.height)}px`,s.style.border="2px solid #22c55e",s.style.background="rgba(34, 197, 94, 0.25)",s.style.zIndex="2147483645",s.style.pointerEvents="none",s.style.transition="opacity 0.6s ease-out",document.body.appendChild(s),setTimeout(()=>{s.style.opacity="0",setTimeout(()=>s.remove(),600)},400)}notifyExtension(e){var t;try{typeof chrome<"u"&&((t=chrome.runtime)!=null&&t.sendMessage)&&chrome.runtime.sendMessage({type:"ELEMENT_SELECTED",elementInfo:e,timestamp:Date.now()})}catch{}}destroy(){this.stopPicker(),typeof window<"u"&&window.removeEventListener("click",this.onGlobalClickBound,!0),this.isGlobalShortcutActive=!1}}class ge{static getCrcTable(){if(this.crcTable)return this.crcTable;const e=new Uint32Array(256);for(let t=0;t<256;t++){let s=t;for(let n=0;n<8;n++)s=s&1?3988292384^s>>>1:s>>>1;e[t]=s>>>0}return this.crcTable=e,e}static crc32(e,t=0,s=e.length){const n=this.getCrcTable();let i=4294967295;for(let r=t;r >>8^n[(i^e[r])&255];return(i^4294967295)>>>0}static adler32(e){let t=1,s=0;for(let n=0;n >>0}static createPNG(e){const t=Math.max(1,Math.min(1920,Math.floor(e.width))),s=Math.max(1,Math.min(1080,Math.floor(e.height))),n=e.backgroundColor||[15,23,42,255],i=e.headerColor||[56,189,248,255],r=e.borderColor||[99,102,241,255],o=1+t*4,a=new Uint8Array(o*s),c=Math.min(30,Math.floor(s*.2));for(let d=0;d =e.length,g=new Uint8Array(5+u);g[0]=h?1:0,g[1]=u&255,g[2]=u>>>8&255;const p=~u&65535;g[3]=p&255,g[4]=p>>>8&255,g.set(e.subarray(n,n+u),5),t.push(g),n+=u}const i=t.reduce((c,u)=>c+u.length,0)+2+4,r=new Uint8Array(i);let o=0;r[o++]=120,r[o++]=1;for(const c of t)r.set(c,o),o+=c.length;const a=this.adler32(e);return r[o++]=a>>>24&255,r[o++]=a>>>16&255,r[o++]=a>>>8&255,r[o++]=a&255,r}static writeChunk(e,t,s,n){const i=n.length,r=new DataView(e.buffer,e.byteOffset,e.byteLength);r.setUint32(t,i,!1),t+=4;const o=new Uint8Array(4+i);for(let c=0;c<4;c++){const u=s.charCodeAt(c);e[t+c]=u,o[c]=u}t+=4,i>0&&(e.set(n,t),o.set(n,4),t+=i);const a=this.crc32(o);return r.setUint32(t,a,!1),t+=4,t}}b(ge,"crcTable",null);const Q=500;class Ue{constructor(e,t){b(this,"history",[]);b(this,"undoStack",[]);b(this,"redoStack",[]);b(this,"counter",0);b(this,"transaction",null);this.doc=e,this.registry=t}mutate(e){var h;const t=`mut_${Date.now().toString(36)}_${++this.counter}`,s=Date.now();let n;try{n=this.resolveTarget(e.target)}catch(g){return this.failure(t,e,null,g.message,Date.now()-s)}const i=this.snapshotState(n);let r=null,o=null,a,c=!0;try{const g=this.applyOperation(t,e,n);g&&(this.transaction?this.transaction.undoRecords.push(g):(this.undoStack.push(g),this.redoStack=[]));const y=(n.isConnected!==void 0?n.isConnected:this.doc.contains(n))?n:this.doc.querySelector(i.selector)||n;r=this.snapshotState(y),o=this.quickDiff(i,r,n)}catch(g){c=!1,a=g.message,r=null}const u={mutationId:t,operation:e.operation,success:c,before:i,after:r,diff:o,affectedSelector:c?i.selector:null,durationMs:Date.now()-s,error:a,undoable:c&&(this.transaction?this.transaction.undoRecords.length>0:this.undoStack.length>0)};return this.transaction&&this.transaction.steps.push({stepId:`step_${this.transaction.steps.length+1}`,mutation:u}),this.pushHistory({mutationId:t,transactionId:(h=this.transaction)==null?void 0:h.id,timestamp:Date.now(),operation:e.operation,targetSelector:i.selector,success:c,summary:`${e.operation} on ${i.selector}${o?` (+${o.added}/-${o.removed}/~${o.changed})`:""}`,undoApplied:!1,redoApplied:!1}),u}beginTransaction(){if(this.transaction)throw new Error(`TRANSACTION_ALREADY_OPEN: ${this.transaction.id} — commit or rollback first.`);return this.transaction={id:`tx_${Date.now().toString(36)}_${++this.counter}`,steps:[],undoRecords:[]},this.transaction.id}commitTransaction(e){if(!this.transaction)throw new Error("NO_OPEN_TRANSACTION: begin a transaction before committing.");const t=this.transaction,s=Date.now();let n=!0,i;if(e)try{n=e({id:t.id,steps:t.steps})!==!1,n||(i="VERIFY_FAILED: caller verification rejected the transaction state.")}catch(o){n=!1,i=`VERIFY_ERROR: ${o.message}`}if(!n)return this.rollbackInternal(t,i||"VERIFY_FAILED",s);this.undoStack.push(...t.undoRecords),this.undoStack.length>Q&&this.undoStack.splice(0,this.undoStack.length-Q),this.redoStack=[];const r=this.summaryOf(t);return this.transaction=null,{transactionId:t.id,committed:!0,rolledBack:!1,steps:t.steps,durationMs:Date.now()-s,finalStateSummary:r}}rollbackTransaction(e){if(!this.transaction)throw new Error("NO_OPEN_TRANSACTION: begin a transaction before rolling back.");const t=this.transaction;return this.rollbackInternal(t,e||"ROLLBACK_REQUESTED",Date.now())}rollbackInternal(e,t,s){for(const i of[...e.undoRecords].reverse())try{this.applyUndo(i)}catch{}const n=this.summaryOf(e);return this.transaction=null,{transactionId:e.id,committed:!1,rolledBack:!0,steps:e.steps,error:t,durationMs:Date.now()-s,finalStateSummary:n}}undo(){const e=this.transaction?this.transaction.undoRecords:this.undoStack,t=e.pop();if(!t)return{success:!1,message:"Nothing to undo — the mutation history is empty."};try{this.applyUndo(t)}catch(s){return e.push(t),{success:!1,mutationId:t.mutationId,message:`UNDO_FAILED: ${s.message}`}}return this.redoStack.push(t),this.markHistory(t.mutationId,"undo"),{success:!0,mutationId:t.mutationId,message:`Undid ${t.operation} on ${t.targetSelector}.`}}redo(){const e=this.redoStack.pop();if(!e)return{success:!1,message:"Nothing to redo — no undone mutation is pending."};try{const t=this.resolveTarget({selector:e.targetSelector}),s={operation:e.operation,target:{selector:e.targetSelector}};return this.reapplyRecord(e,t,s)?((this.transaction?this.transaction.undoRecords:this.undoStack).push(e),this.markHistory(e.mutationId,"redo"),{success:!0,mutationId:e.mutationId,message:`Redid ${e.operation} on ${e.targetSelector}.`}):(this.redoStack.push(e),{success:!1,mutationId:e.mutationId,message:"REDO_FAILED: target state diverged — cannot safely reapply."})}catch(t){return this.redoStack.push(e),{success:!1,mutationId:e.mutationId,message:`REDO_FAILED: ${t.message}`}}}getHistory(e=100){return this.history.slice(-e)}getUndoDepth(){return this.transaction?this.transaction.undoRecords.length:this.undoStack.length}getRedoDepth(){return this.redoStack.length}getOpenTransactionId(){var e;return((e=this.transaction)==null?void 0:e.id)||null}preview(e){var t;try{const s=this.resolveTarget(e.target),n=[];let i=1;(e.operation==="set_inner_html"||e.operation==="set_outer_html")&&(n.push("HTML replacement can destroy descendant node identity — captured regions targeting children may become stale."),i=s.querySelectorAll("*").length+1),(e.operation==="remove_element"||e.operation==="unwrap_element")&&(n.push("Removal is destructive; the undo record preserves the full serialized subtree."),i=s.querySelectorAll("*").length+1),e.operation==="move_element"&&!e.parent&&n.push("No parent target supplied — move requires payload.parent."),e.operation==="wrap_element"&&!e.newElementHtml&&n.push("No wrapper HTML supplied — a neutralwrapper will be generated.");const r=He(e,s);return{valid:n.filter(o=>o.includes("requires")||o.includes("No parent")).length===0,operation:e.operation,target:{selector:this.snapshotState(s).selector,tag:s.tagName.toLowerCase()},expectedChange:r,affectedNodes:i,warnings:n}}catch(s){return{valid:!1,operation:e.operation,target:{selector:String(((t=e.target)==null?void 0:t.selector)||""),tag:""},expectedChange:"—",affectedNodes:0,warnings:[],error:s.message}}}applyOperation(e,t,s){var r;const n=this.snapshotState(s).selector,i=t.operation;switch(i){case"set_attribute":{if(!t.attribute)throw new Error("ATTRIBUTE_REQUIRED: payload.attribute is missing.");const o=s.getAttribute(t.attribute);return s.setAttribute(t.attribute,t.value??""),this.undoFor(e,i,n,{kind:o===null?"remove-attribute":"restore-attribute",attribute:t.attribute,value:o})}case"remove_attribute":{if(!t.attribute)throw new Error("ATTRIBUTE_REQUIRED: payload.attribute is missing.");const o=s.getAttribute(t.attribute);if(o===null)throw new Error(`ATTRIBUTE_NOT_PRESENT: "${t.attribute}" is not set on ${n}.`);return s.removeAttribute(t.attribute),this.undoFor(e,i,n,{kind:"restore-attribute",attribute:t.attribute,value:o})}case"set_text":{const o=s.textContent||"";return s.textContent=t.text??"",this.undoFor(e,i,n,{kind:"restore-text",text:o})}case"replace_text":{if(!t.text||!t.replacement)throw new Error("TEXT_PATTERNS_REQUIRED: payload.text (search) and payload.replacement are required.");const o=s.textContent||"";return s.textContent=o.split(t.text).join(t.replacement),this.undoFor(e,i,n,{kind:"restore-text",text:o})}case"set_inner_html":{const o=s.innerHTML;return s.innerHTML=t.html??"",this.undoFor(e,i,n,{kind:"restore-outer-html",outerHtml:s.outerHTML.replace(t.html??"",o)||void 0,text:o,attribute:"__inner"})}case"set_outer_html":{const o=s.outerHTML,a=s.parentElement;if(!a)throw new Error("ORPHAN_ELEMENT: element has no parent — cannot replace outer HTML.");const c=this.doc.createComment(`mcpdom_undo_${e}`);s.replaceWith(c);const u=this.doc.createElement("template");u.innerHTML=t.html??"";const h=u.content.firstElementChild;return h?c.replaceWith(h):c.replaceWith(this.doc.createTextNode(t.html??"")),this.undoFor(e,i,n,{kind:"reinsert-node",outerHtml:o,parentSelector:this.snapshotState(a).selector,nextSiblingSelector:this.siblingSelector(h||s)})}case"add_class":{const o=Array.from(s.classList);for(const a of t.classes||[])s.classList.add(a);return this.undoFor(e,i,n,{kind:"restore-classes",classes:o})}case"remove_class":{const o=Array.from(s.classList);for(const a of t.classes||[])s.classList.remove(a);return this.undoFor(e,i,n,{kind:"restore-classes",classes:o})}case"replace_class":{const o=Array.from(s.classList);for(const a of t.classes||[])s.classList.remove(a);return t.value&&s.classList.add(t.value),this.undoFor(e,i,n,{kind:"restore-classes",classes:o})}case"set_style":{const o=this.doc.defaultView;if(!(o!=null&&o.getComputedStyle))throw new Error("STYLE_UNAVAILABLE: computed style API is unavailable in this context.");const a={};for(const c of Object.keys(t.style||{}))a[c]=o.getComputedStyle(s).getPropertyValue(c),s.style.setProperty(c,t.style[c]);return this.undoFor(e,i,n,{kind:"restore-style",style:a})}case"remove_style":{const o={};for(const a of t.classes||[])o[a]=s.style.getPropertyValue(a),s.style.removeProperty(a);return this.undoFor(e,i,n,{kind:"restore-style",style:o})}case"add_element":{const o=t.parent?this.resolveTarget(t.parent):s,a=this.doc.createElement("template");a.innerHTML=t.newElementHtml??"";const c=a.content.firstElementChild;if(!c)throw new Error("INVALID_HTML: payload.newElementHtml does not produce an element.");switch(t.position||"append"){case"before":s.before(c);break;case"after":s.after(c);break;case"prepend":o.prepend(c);break;default:o.appendChild(c)}return this.undoFor(e,i,n,{kind:"remove-node",attribute:this.snapshotState(c).selector})}case"remove_element":{const o=s.outerHTML,a=s.parentElement,c=s.nextElementSibling;return s.remove(),this.undoFor(e,i,n,{kind:"reinsert-node",outerHtml:o,parentSelector:a?this.snapshotState(a).selector:void 0,nextSiblingSelector:c?this.snapshotState(c).selector:null})}case"replace_element":{const o=s.outerHTML,a=s.parentElement,c=this.doc.createElement("template");c.innerHTML=t.newElementHtml??"";const u=c.content.firstElementChild;if(!u)throw new Error("INVALID_HTML: payload.newElementHtml does not produce an element.");const h=s.nextElementSibling;return s.replaceWith(u),this.undoFor(e,i,n,{kind:"reinsert-node",outerHtml:o,parentSelector:a?this.snapshotState(a).selector:void 0,nextSiblingSelector:h?this.snapshotState(h).selector:null})}case"move_element":{if(!t.parent)throw new Error("PARENT_REQUIRED: payload.parent is required for move_element.");const o=this.resolveTarget(t.parent),a=s.outerHTML,c=s.parentElement,u=s.nextElementSibling,h=t.position==="before"||t.position==="prepend"?o.firstElementChild:null;return o[t.position==="prepend"?"prepend":"appendChild"](s),this.undoFor(e,i,n,{kind:"restore-position",parentSelector:c?this.snapshotState(c).selector:void 0,nextSiblingSelector:u?this.snapshotState(u).selector:h?this.snapshotState(h).selector:null,outerHtml:a})}case"wrap_element":{const o=this.doc.createElement("template");o.innerHTML=t.newElementHtml||'';const a=o.content.firstElementChild;if(!a)throw new Error("INVALID_HTML: wrapper template produced no element.");const c=s.parentElement,u=s.nextElementSibling;return s.replaceWith(a),a.appendChild(s),this.undoFor(e,i,n,{kind:"restore-position",parentSelector:c?this.snapshotState(c).selector:void 0,nextSiblingSelector:u?this.snapshotState(u).selector:null})}case"unwrap_element":{const o=s.outerHTML,a=s.parentElement;if(!a)throw new Error("ORPHAN_ELEMENT: cannot unwrap a root-level element.");const c=s.nextElementSibling,u=Array.from(s.children);for(const h of u)a.insertBefore(h,s);return s.remove(),this.undoFor(e,i,n,{kind:"reinsert-node",outerHtml:o,parentSelector:this.snapshotState(a).selector,nextSiblingSelector:c?this.snapshotState(c).selector:null})}case"clone_subtree":{const o=t.parent?this.resolveTarget(t.parent):s.parentElement||s,a=s.cloneNode(!0);if(t.copyAttributes!==!1)for(const c of Array.from(a.attributes))c.name==="id"&&a.removeAttribute("id");return(r=o.appendChild)==null||r.call(o,a),this.undoFor(e,i,n,{kind:"remove-node",attribute:this.snapshotState(a).selector})}default:throw new Error(`UNKNOWN_OPERATION: ${i} is not a supported DOM mutation.`)}}applyUndo(e){const t=e.inverse;switch(t.kind){case"restore-outer-html":{const s=this.resolveTarget({selector:e.targetSelector});if(t.outerHtml!==void 0){const n=this.doc.createElement("template");n.innerHTML=t.outerHtml;const i=n.content.firstElementChild;i&&s.replaceWith(i)}else t.attribute==="__inner"&&(s.innerHTML=t.text||"");break}case"reinsert-node":{const s=t.parentSelector?this.resolveTarget({selector:t.parentSelector}):this.doc.body,n=this.doc.createElement("template");n.innerHTML=t.outerHtml||"";const i=n.content.firstElementChild;if(!i)throw new Error("UNDO_CORRUPT: serialized subtree could not be restored.");const r=t.nextSiblingSelector?this.safeResolve(t.nextSiblingSelector):null;s.insertBefore(i,r);break}case"remove-node":{const s=this.safeResolve(t.attribute||e.targetSelector);s&&s.remove();break}case"restore-attribute":{this.resolveTarget({selector:e.targetSelector}).setAttribute(t.attribute,t.value??"");break}case"remove-attribute":{this.resolveTarget({selector:e.targetSelector}).removeAttribute(t.attribute);break}case"restore-text":{const s=this.resolveTarget({selector:e.targetSelector});s.textContent=t.text||"";break}case"restore-classes":{const s=this.resolveTarget({selector:e.targetSelector});s.removeAttribute("class");for(const n of t.classes||[])s.classList.add(n);break}case"restore-style":{const s=this.resolveTarget({selector:e.targetSelector});s.style.removeProperty("all");for(const[n,i]of Object.entries(t.style||{}))s.style.setProperty(n,i);break}case"restore-position":{const s=this.doc.createElement("template");s.innerHTML=t.outerHtml||"";const n=s.content.firstElementChild;if(!n)throw new Error("UNDO_CORRUPT: serialized subtree could not be restored.");const i=this.safeResolve(e.targetSelector);i&&i.remove();const r=t.parentSelector?this.safeResolve(t.parentSelector):this.doc.body,o=t.nextSiblingSelector?this.safeResolve(t.nextSiblingSelector):null;(r||this.doc.body).insertBefore(n,o);break}}}reapplyRecord(e,t,s){var i;const n=e.inverse;switch(e.operation){case"set_attribute":return(n.kind==="restore-attribute"||n.kind==="remove-attribute")&&s.value!==void 0?(t.setAttribute(s.attribute||n.attribute||"",s.value),!0):!1;case"add_class":{for(const r of s.classes||[])t.classList.add(r);return(((i=s.classes)==null?void 0:i.length)||0)>0}case"remove_class":{for(const r of s.classes||n.classes||[])t.classList.remove(r);return!0}case"set_text":return s.text!==void 0?(t.textContent=s.text,!0):!1;case"set_inner_html":return s.html!==void 0?(t.innerHTML=s.html,!0):!1;default:return!1}}resolveTarget(e){if(!e)throw new Error("TARGET_REQUIRED: mutation requires a target.");if(typeof e=="string"&&(e={selector:e}),e.selector){try{const t=this.doc.querySelectorAll(e.selector);if(t.length===1)return t[0];if(t.length>1)return Array.from(t).find(n=>{try{return k.inspectElement(n).visibility.isVisible}catch{return!1}})||t[0]}catch(t){throw new Error(`TARGET_INVALID: ${t.message}`)}throw new Error(`TARGET_NOT_FOUND: selector "${e.selector}" matches no element.`)}if(e.xpath){try{const s=this.doc.evaluate(e.xpath,this.doc,null,9,null).singleNodeValue;if(s)return s}catch(t){throw new Error(`TARGET_INVALID_XPATH: ${t.message}`)}throw new Error("TARGET_NOT_FOUND: xpath matches no element.")}if(typeof e.nodeId=="number"&&this.registry){const t=this.registry.getNode(e.nodeId);if(t&&t.nodeType===1&&this.doc.contains(t))return t;throw new Error("TARGET_STALE: logical node id no longer resolves to an attached element.")}throw new Error("TARGET_INVALID: target has neither selector, xpath nor nodeId.")}safeResolve(e){try{return this.doc.querySelector(e)}catch{return null}}snapshotState(e){const t=k.inspectElement(e,this.registry),s=e.outerHTML.length>2e4?e.outerHTML.slice(0,2e4)+"…[truncated]":e.outerHTML;return{selector:t.bestSelector,outerHtml:s,attributes:this.attrsOf(e)}}attrsOf(e){const t={};for(const s of Array.from(e.attributes))t[s.name]=s.value.length>300?s.value.slice(0,300)+"…":s.value;return t}quickDiff(e,t,s){if(!t)return null;let n=0,i=0,r=0;const o=new Set(Object.keys(e.attributes)),a=new Set(Object.keys(t.attributes||{}));for(const u of o)a.has(u)||i++;for(const u of a)o.has(u)?e.attributes[u]!==t.attributes[u]&&r++:n++;e.outerHtml!==t.outerHtml&&n+i+r===0&&r++;const c=s.querySelectorAll?s.querySelectorAll("*").length:0;return{added:n,removed:i,changed:r,summary:`attributes +${n}/-${i}/~${r}; subtree nodes: ${c}`}}undoFor(e,t,s,n){return{mutationId:e,operation:t,targetSelector:s,inverse:n}}siblingSelector(e){try{return this.snapshotState(e).selector}catch{return null}}pushHistory(e){this.history.push(e),this.history.length>Q&&this.history.splice(0,this.history.length-Q)}markHistory(e,t){for(let s=this.history.length-1;s>=0;s--)if(this.history[s].mutationId===e){t==="undo"?this.history[s].undoApplied=!0:this.history[s].redoApplied=!0;return}}summaryOf(e){var n;const t=((n=this.doc.documentElement)==null?void 0:n.outerHTML.length)||0,s=e.steps.filter(i=>i.mutation.success).length;return{domLength:t,diffSummary:`${s}/${e.steps.length} mutations applied`}}failure(e,t,s,n,i){var r;return{mutationId:e,operation:t.operation,success:!1,before:s||{selector:String(((r=t.target)==null?void 0:r.selector)||"?"),outerHtml:"",attributes:{}},after:null,diff:null,affectedSelector:null,durationMs:i,error:n,undoable:!1}}}function He(l,e){switch(l.operation){case"set_attribute":return`attribute "${l.attribute}" will be set to "${(l.value??"").slice(0,40)}"`;case"remove_attribute":return`attribute "${l.attribute}" will be removed`;case"set_text":return`text content will be replaced (${(l.text||"").length} chars)`;case"replace_text":return`every occurrence of "${l.text}" will become "${l.replacement}"`;case"set_inner_html":return`inner HTML will be replaced (${(l.html||"").length} chars)`;case"set_outer_html":return"element (and subtree) will be replaced with provided HTML";case"add_class":return`classes ${(l.classes||[]).join(", ")} will be added`;case"remove_class":return`classes ${(l.classes||[]).join(", ")} will be removed`;case"replace_class":return`classes ${(l.classes||[]).join(", ")} will be replaced with "${l.value}"`;case"set_style":return`inline styles ${Object.keys(l.style||{}).join(", ")} will be set`;case"remove_style":return`inline styles ${(l.classes||[]).join(", ")} will be removed`;case"add_element":return`a new element will be inserted ${l.position||"append"} the target`;case"remove_element":return"the element and its subtree will be removed";case"replace_element":return"the element will be replaced with new HTML";case"move_element":return"the element will be moved into the specified parent";case"wrap_element":return"the element will be wrapped in a new container";case"unwrap_element":return"children will be lifted out and the wrapper removed";case"clone_subtree":return"a deep clone of the subtree will be appended";default:return"unknown operation"}}class Fe{constructor(){b(this,"executionCounter",0)}async execute(e,t,s={}){const n=Math.min(Math.max(s.timeoutMs??5e3,100),3e4),i=`js_${Date.now().toString(36)}_${++this.executionCounter}`,r=e.defaultView;if(!r)return this.result(i,"BLOCKED_BY_CONTEXT",0,t,[],{name:"NoWindow",message:"The document has no associated window — execution context unavailable."});const o=e.documentElement?e.documentElement.outerHTML.length:0,a=[],c=this.hookConsole(r,a);let u="EXECUTED_SUCCESSFULLY",h,g,p=o,y=!1;const v=Date.now();try{const f=this.buildRunner(r,t),w=new Promise((E,S)=>{var x;const T=setTimeout(()=>{y=!0,S(new Error(`Script timed out after ${n}ms`))},n);(x=T==null?void 0:T.unref)==null||x.call(T)});h=await Promise.race([f,w])}catch(f){y?u="TIMED_OUT":u="EXECUTED_WITH_ERROR",g={name:(f==null?void 0:f.name)||"Error",message:(f==null?void 0:f.message)||String(f),stack:f!=null&&f.stack?String(f.stack).slice(0,2e3):void 0}}const m=Date.now()-v;p=e.documentElement?e.documentElement.outerHTML.length:0,c();const d=this.serialize(h);return u==="EXECUTED_SUCCESSFULLY"&&d.serializationFailed&&(u="SERIALIZATION_FAILED",g={name:"SerializationError",message:d.message||"Result could not be serialized."}),{status:u,executionId:i,durationMs:m,result:u==="EXECUTED_SUCCESSFULLY"?d.text:void 0,error:g,consoleOutput:a.slice(0,100),domChanged:o!==p,domLengthBefore:o,domLengthAfter:p,world:s.world||"ISOLATED",timeoutMs:n,codePreview:t.length>300?t.slice(0,300)+"…":t}}buildRunner(e,t){const s=`(async function() { ${t} -})()`,n=e;if(typeof n.eval!="function")return Promise.reject(new Error("BLOCKED_BY_CONTEXT: window.eval is unavailable in this context."));try{const i=n.eval(s);return i&&typeof i.then=="function"?i:Promise.resolve(i)}catch(i){return Promise.reject(i)}}hookConsole(e,t){var o;const s=["log","warn","error","info","debug"],n={},i=e,r=100;for(const a of s){const c=(o=i.console)==null?void 0:o[a];if(typeof c=="function"){n[a]=c;try{i.console[a]=(...u)=>{t.length{for(const a of s)if(n[a])try{i.console[a]=n[a]}catch{}}}serialize(e){if(e===void 0)return{text:"undefined"};if(e===null)return{text:"null"};try{if(typeof e=="string")return{text:e.slice(0,5e3)};const t=JSON.stringify(e,be,1);return t===void 0?{serializationFailed:!0,message:"JSON.stringify returned undefined (circular or non-serializable structure)."}:{text:t.length>5e4?t.slice(0,5e4)+"…[truncated]":t}}catch(t){return{serializationFailed:!0,message:(t==null?void 0:t.message)||"Serialization failed."}}}result(e,t,s,n,i,r){return{status:t,executionId:e,durationMs:s,error:r,consoleOutput:i,domChanged:!1,domLengthBefore:0,domLengthAfter:0,world:"ISOLATED",timeoutMs:5e3,codePreview:n.length>300?n.slice(0,300)+"…":n}}}function be(l,e){var t;if(e&&typeof e=="object"&&e.nodeType===1){const s=e;return{__element:!0,tag:s.tagName.toLowerCase(),id:s.getAttribute("id")||void 0,selector:s.tagName.toLowerCase()+(s.getAttribute("id")?`#${s.getAttribute("id")}`:""),text:(s.textContent||"").trim().slice(0,60)}}return typeof e=="function"?{__function:!0,name:e.name||"anonymous"}:e&&e.nodeType===9?{__document:!0,url:(t=e.location)==null?void 0:t.href}:e}function Ve(l){try{if(typeof l=="string")return l;if(l instanceof Error)return`${l.name}: ${l.message}`;const e=JSON.stringify(l,be);return e===void 0?String(l):e}catch{return String(l)}}const ye={"desktop-full-hd":{width:1920,height:1080,category:"desktop"},"desktop-hd":{width:1366,height:768,category:"desktop"},"desktop-laptop":{width:1440,height:900,category:"desktop"},"desktop-xga":{width:1280,height:1024,category:"desktop"},"desktop-1024":{width:1024,height:768,category:"desktop"},"tablet-ipad":{width:768,height:1024,category:"tablet"},"tablet-ipad-pro":{width:1024,height:1366,category:"tablet"},"tablet-portrait":{width:768,height:1024,category:"tablet"},"tablet-landscape":{width:1024,height:768,category:"tablet"},"mobile-iphone-se":{width:375,height:667,category:"mobile"},"mobile-iphone-12":{width:390,height:844,category:"mobile"},"mobile-iphone-14-pro-max":{width:430,height:932,category:"mobile"},"mobile-pixel-7":{width:412,height:915,category:"mobile"},"mobile-galaxy-s8":{width:360,height:740,category:"mobile"},"mobile-small":{width:320,height:568,category:"mobile"},"test-a4":{width:800,height:600,category:"test"},"test-square":{width:512,height:512,category:"test"}},Ee={"iphone-13":{width:390,height:844,devicePixelRatio:3,userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1",touch:!0,category:"mobile"},"ipad-air":{width:820,height:1180,devicePixelRatio:2,userAgent:"Mozilla/5.0 (iPad; CPU OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1",touch:!0,category:"tablet"},"pixel-7":{width:412,height:915,devicePixelRatio:2.625,userAgent:"Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",touch:!0,category:"mobile"},"galaxy-s23":{width:384,height:800,devicePixelRatio:3,userAgent:"Mozilla/5.0 (Linux; Android 14; SM-S911B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",touch:!0,category:"mobile"},"macbook-pro-16":{width:1728,height:1080,devicePixelRatio:2,userAgent:"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",touch:!1,category:"desktop"},"windows-desktop":{width:1920,height:1080,devicePixelRatio:1,userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",touch:!1,category:"desktop"}};class ze{constructor(e){f(this,"original",null);f(this,"modified",!1);f(this,"activePreset",null);f(this,"activeDevice",null);this.doc=e}state(){const e=this.doc.defaultView;return{width:(e==null?void 0:e.innerWidth)||0,height:(e==null?void 0:e.innerHeight)||0,devicePixelRatio:(e==null?void 0:e.devicePixelRatio)||1,scrollX:(e==null?void 0:e.scrollX)||0,scrollY:(e==null?void 0:e.scrollY)||0,original:this.original,isModified:this.modified}}resize(e,t,s){const n=this.doc.defaultView,i={width:(n==null?void 0:n.innerWidth)||0,height:(n==null?void 0:n.innerHeight)||0},r=this.pageDigest();this.original||(this.original={...i});const o=this.applySize(e,t);this.modified=!0,this.activePreset=s||this.activePreset;const a=this.pageDigest();return{success:!0,applied:{width:o.width,height:o.height},previous:i,original:{...this.original},preset:s||void 0,beforeState:r,afterState:a,reversible:!0,mode:this.isSimulation()?"simulation":"browser-window"}}applyPreset(e){const t=ye[e];if(!t)throw new Error(`UNKNOWN_PRESET: "${e}". Available: ${Object.keys(ye).join(", ")}`);return this.resize(t.width,t.height,e)}emulateDevice(e){const t=Ee[e];if(!t)throw new Error(`UNKNOWN_DEVICE: "${e}". Available: ${Object.keys(Ee).join(", ")}`);const s=this.resize(t.width,t.height,`device:${e}`);this.activeDevice=e;const n=this.doc.defaultView;return n&&this.isSimulation()&&n.devicePixelRatio!==void 0&&(n.devicePixelRatio=t.devicePixelRatio),{device:e,resize:s,profile:{width:t.width,height:t.height,devicePixelRatio:t.devicePixelRatio,touch:t.touch,category:t.category},userAgentNote:this.isSimulation()?"User-Agent override requires the Chrome DevTools Protocol (real browser session); in this context the viewport, dpr and touch metadata are applied and the UA is reported but not enforced.":"User-Agent and touch behaviors are applied by the browser emulation layer.",userAgentApplied:!this.isSimulation()}}reset(){var s,n;const e={width:((s=this.doc.defaultView)==null?void 0:s.innerWidth)||0,height:((n=this.doc.defaultView)==null?void 0:n.innerHeight)||0},t=this.original?{...this.original}:{...e};return this.original&&this.applySize(this.original.width,this.original.height),this.modified=!1,this.activePreset=null,this.activeDevice=null,{success:!0,applied:{width:t.width,height:t.height},previous:e,original:{...t},reversible:!0,mode:this.isSimulation()?"simulation":"browser-window"}}runResponsiveTest(e,t={restore:!0}){var c,u,d,h;const s=t.restore!==!1,n=this.original?{...this.original}:{width:((c=this.doc.defaultView)==null?void 0:c.innerWidth)||0,height:((u=this.doc.defaultView)==null?void 0:u.innerHeight)||0};this.original||(this.original={...n});const i=e.map(p=>{this.applySize(p.width,p.height),this.modified=!0;const y=this.pageDigest();return{label:p.label,width:p.width,height:p.height,domLength:y.domLength,interactiveCount:y.interactiveCount,horizontalOverflow:this.hasHorizontalOverflow(),screenshotId:void 0}}),r=i.slice(1).map((p,y)=>({from:i[y].label,to:p.label,domLengthDelta:p.domLength-i[y].domLength,interactiveDelta:p.interactiveCount-i[y].interactiveCount}));let o={width:((d=i[i.length-1])==null?void 0:d.width)||0,height:((h=i[i.length-1])==null?void 0:h.height)||0},a=!1;return s&&(this.applySize(n.width,n.height),this.modified=!1,o={...n},a=!0),{success:!0,originalViewport:n,steps:i,restored:a,finalViewport:o,comparisons:r}}getActivePreset(){return this.activePreset}getActiveDevice(){return this.activeDevice}applySize(e,t){const s=Math.max(200,Math.min(7680,Math.round(e))),n=Math.max(200,Math.min(4320,Math.round(t))),i=this.doc.defaultView;return i&&(typeof i.innerWidth=="number"&&(i.innerWidth=s),typeof i.innerHeight=="number"&&(i.innerHeight=n),typeof i.outerWidth=="number"&&(i.outerWidth=s),typeof i.outerHeight=="number"&&(i.outerHeight=n)),{width:s,height:n}}pageDigest(){var t,s,n,i;const e=this.doc.querySelectorAll('a[href], button, input, select, textarea, [role="button"], [onclick]').length;return{url:((s=(t=this.doc.defaultView)==null?void 0:t.location)==null?void 0:s.href)||((n=this.doc.location)==null?void 0:n.href)||"",domLength:((i=this.doc.documentElement)==null?void 0:i.outerHTML.length)||0,interactiveCount:e}}hasHorizontalOverflow(){const e=this.doc.documentElement,t=this.doc.body,s=this.doc.defaultView;return!s||!e?!1:Math.max(e.scrollWidth||0,(t==null?void 0:t.scrollWidth)||0)>(s.innerWidth||e.clientWidth||0)+1}isSimulation(){return typeof globalThis.__FORENSIC_SIMULATION__<"u"}}const We=[/^css-/,/^jsx-/,/^sc-[A-Za-z]/,/^emotion/,/^chakra-/,/^mantine-/i,/^_ng[a-z]/,/^ng-/i,/^v-/,/^(?=.*\d)[a-z0-9]{6,12}$/i,/^data-v-/],Xe=["id","name","data-testid","data-test","data-id","data-qa","data-cy","data-component","data-role","aria-label","aria-labelledby","aria-describedby","role","type","href","for","title","alt","rel","placeholder"];function ve(l){let e=2166136261;for(let t=0;t >>0).toString(16).padStart(8,"0")}function ie(l){return We.some(e=>e.test(l))}function Ge(l){return Xe.includes(l)}function ce(l){const e=l.trim();return e?!!((e.match(/\d/g)||[]).length/e.length>.5||/^\d+[.,:\-/ ]+\d+/.test(e)||/\b\d{10,}\b/.test(e)):!1}function Ke(l,e=80){return Array.from(l.childNodes).filter(s=>s.nodeType===3).map(s=>(s.textContent||"").trim()).join(" ").replace(/\s+/g," ").slice(0,e)}function Ye(l,e){const t=[];let s=l;for(;s&&t.length !ie(b)),r=Ke(e),o=e.getBoundingClientRect(),a={width:Math.round(o.width),height:Math.round(o.height)},c=Ye(e,4),u=c.join(">"),h=Array.from(e.children||[]).slice(0,8).map(b=>b.tagName.toLowerCase()).join("|"),p=e.getAttribute("role")||(t!=null&&t.getComputedStyle,void 0)||je(e),y=ve(JSON.stringify({t:e.tagName.toLowerCase(),a:s,c:i.slice(0,4),r:p||null,anc:u,desc:h,txt:ce(r)?null:r.slice(0,40),d:a})),v=[];let m="low";return!s.id&&!s["data-testid"]&&!s.name&&(m="medium",v.push("no stable identity attribute")),n.length>0&&i.length===0&&(m=v.length?"high":"medium",v.push("all classes are framework-generated")),ce(r)&&(v.push("text appears dynamic"),m==="low"&&(m="medium")),e.tagName.toLowerCase().includes("-")&&(v.push("custom element (web component)"),m==="low"&&(m="medium")),{fingerprintId:`fp_${y}`,hash:y,tagHierarchy:c,stableAttributes:s,meaningfulText:r,classes:i,role:p||void 0,dimensions:a,ancestorPattern:u,descendantPattern:h,volatilityRisk:m,volatilityReasons:v}}compare(e,t){const s=[],n=e.tagHierarchy[0]===t.tagHierarchy[0]?1:0;s.push({name:"tag",score:n,weight:.15});const i=we(e.ancestorPattern.split(">"),t.ancestorPattern.split(">"));s.push({name:"ancestorPattern",score:i,weight:.2});const r=Je(e.stableAttributes,t.stableAttributes);s.push({name:"stableAttributes",score:r,weight:.25});const o=we(e.classes,t.classes);s.push({name:"classes",score:o,weight:.1});const a=(e.role||"")===(t.role||"")&&e.role?1:0;s.push({name:"role",score:a,weight:.1});const c=e.meaningfulText===t.meaningfulText&&e.meaningfulText?1:0;s.push({name:"text",score:c,weight:.1});const u=Ze(e.dimensions,t.dimensions);s.push({name:"dimensions",score:u,weight:.1});const d=s.reduce((h,p)=>h+p.score*p.weight,0);return{score:Math.round(d*1e3)/1e3,components:s}}}function je(l){switch(l.tagName.toLowerCase()){case"a":return l.getAttribute("href")?"link":void 0;case"button":return"button";case"nav":return"navigation";case"header":return"banner";case"footer":return"contentinfo";case"main":return"main";case"aside":return"complementary";case"article":return"article";case"form":return"form";case"input":{const t=l.getAttribute("type")||"text";return t==="checkbox"?"checkbox":t==="radio"?"radio":t==="button"||t==="submit"?"button":"textbox"}case"select":return"combobox";case"textarea":return"textbox";case"img":return"img";case"table":return"table";case"ul":case"ol":return"list";case"li":return"listitem";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return"heading";default:return}}function we(l,e){if(!l.length&&!e.length)return 1;if(!l.length||!e.length)return 0;const t=new Set(e);return l.filter(n=>t.has(n)).length/Math.max(l.length,e.length)}function Je(l,e){const t=Object.keys(l),s=Object.keys(e);if(!t.length&&!s.length)return .5;if(!t.length||!s.length)return 0;let n=0,i=0;for(const r of t)r in e&&(i++,l[r]===e[r]&&n++);return i===0?0:n/Math.max(t.length,s.length)}function Ze(l,e){if(l.width===0&&l.height===0&&e.width===0&&e.height===0)return .5;const t=Se(l.width,e.width),s=Se(l.height,e.height);return(t+s)/2}function Se(l,e){if(l===e)return 1;if(l===0||e===0)return 0;const t=Math.min(l,e)/Math.max(l,e);return t>.9?1:t>.7?.5:0}const Qe=["data-testid","data-test","data-id","data-qa","data-cy","data-component","data-role","aria-label","name","id"],Te=/^[a-zA-Z][a-zA-Z0-9_-]*$/,et=/^[a-zA-Z0-9_ .:-]+$/;class Z{constructor(e){f(this,"doc");this.doc=e}generateCandidates(e){const t=[],s=e.tagName.toLowerCase(),n=e.getAttribute("id");if(n&&Te.test(n)){const u=`#${Ce(n)}`;t.push(this.evaluate(e,u,"id",1,["unique stable id"]))}for(const u of Qe){if(u==="id")continue;const d=e.getAttribute(u);if(d&&et.test(d)&&d.length<100){const h=`${s}[${u}="${Q(d)}"]`;t.push(this.evaluate(e,h,"semantic-attribute",.92,[`semantic attribute ${u}`]))}}const i=Array.from(e.classList||[]).filter(u=>!ie(u));if(i.length){const u=`${s}.${i.slice(0,3).map(Ce).join(".")}`;t.push(this.evaluate(e,u,"class",.72,i.length?["stable class names"]:[]))}const r=this.buildStructuralPath(e);r&&t.push(this.evaluate(e,r,"structural-path",.55,["position-based structural path"]));const o=B(e);if(o&&o.length>=2&&o.length<=60&&!ce(o)){const u=`${s}:nth-of-type(1)`,d=this.buildTextXPath(e,o);d&&(t.push({selector:u,strategy:"text-derived-xpath",confidence:.6,unique:this.isXPathUnique(d),reasons:[`matches text "${o.slice(0,30)}"`]}),t[t.length-1].xpath=d)}const a=this.buildAttributeFingerprintSelector(e);a&&t.push(this.evaluate(e,a,"attribute-fingerprint",.68,["combination of stable attributes"]));const c=new Map;for(const u of t){const d=u.strategy==="text-derived-xpath"?`xpath:${u.xpath}`:u.selector,h=c.get(d);(!h||u.confidence>h.confidence)&&c.set(d,u)}return Array.from(c.values()).sort((u,d)=>d.confidence-u.confidence)}bestSelector(e){const t=this.generateCandidates(e),s=t.find(n=>n.unique&&n.confidence>=.7)||t[0];return{selector:(s==null?void 0:s.selector)||e.tagName.toLowerCase(),strategy:(s==null?void 0:s.strategy)||"tag",confidence:(s==null?void 0:s.confidence)||.3}}buildXPath(e){const t=[];let s=e;for(;s&&s!==this.doc.documentElement;){const n=s.getAttribute("id");if(n&&Te.test(n)){t.unshift(`*[@id="${Q(n)}"]`);break}const i=s.parentElement;if(!i){t.unshift(s.tagName.toLowerCase());break}const o=Array.from(i.children).filter(a=>a.tagName===s.tagName).indexOf(s)+1;t.unshift(`${s.tagName.toLowerCase()}[${o}]`),s=i}return s===this.doc.documentElement&&(!t.length||!t[0].includes("@id"))&&t.unshift("html"),"//"+t.join("/")}buildTextXPath(e,t){try{const s=e.tagName.toLowerCase(),n=tt(t);return`//${s}[normalize-space(text())=${n}]`}catch{return null}}buildStructuralPath(e,t=4){const s=[];let n=e;for(;n&&s.length c.tagName===n.tagName);if(a.length>1){const c=a.indexOf(n)+1;s.unshift(`${o}:nth-of-type(${c})`)}else s.unshift(o);if(n=r,n===this.doc.body){s.unshift("body");break}if(n===this.doc.documentElement)break}const i=s.join(" > ");return i.includes("body")?i:"body > "+i}buildAttributeFingerprintSelector(e){const t=e.tagName.toLowerCase(),s=[],n=e.getAttribute("type");n&&s.push(`type="${Q(n)}"`);const i=e.getAttribute("href");i&&i.length<80&&!i.startsWith("javascript:")&&s.push(`href^="${Q(i.slice(0,40))}"`);const r=e.getAttribute("placeholder");return r&&r.length<60&&s.push(`placeholder="${Q(r)}"`),s.length>=2?`${t}[${s.join("][")}]`:null}evaluate(e,t,s,n,i){let r=!1,o=0;try{const c=this.doc.querySelectorAll(t);o=c.length,r=c.length===1&&c[0]===e}catch{return{selector:t,strategy:s,confidence:0,unique:!1,reasons:["invalid selector syntax"]}}let a=n;return o===0?(a=0,i.push("selector matched nothing (invalid candidate)")):o===1&&r?i.push("matches exactly this element"):(a=a*.4,i.push(`matches ${o} elements — ambiguous`)),{selector:t,strategy:s,confidence:Math.round(a*100)/100,unique:r,reasons:i}}isXPathUnique(e){try{return this.doc.evaluate(`count(${e})`,this.doc,null,4,null).numberValue===1}catch{return!1}}}function B(l){return Array.from(l.childNodes).filter(e=>e.nodeType===3).map(e=>(e.textContent||"").trim()).join(" ").replace(/\s+/g," ")}function Ce(l){return l.replace(/([^a-zA-Z0-9_\u00A0-\uFFFF-])/g,"\\$1")}function Q(l){return l.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function tt(l){return l.includes("'")?l.includes('"')?`concat(${l.split("'").map(e=>`'${e}'`).join(`, "'", `)})`:`"${l}"`:`'${l}'`}class st{constructor(e,t){f(this,"fingerprintEngine",new re);f(this,"counter",0);this.doc=e,this.registry=t}buildTarget(e,t="selector"){var d;const s=new Z(this.doc),n=s.generateCandidates(e),i=s.bestSelector(e),r=this.fingerprintEngine.fingerprint(e),o=L.inspectElement(e,this.registry),a=e.getBoundingClientRect();let c=i.confidence*.6;return r.volatilityRisk==="low"?c+=.3:r.volatilityRisk==="medium"&&(c+=.15),n.find(h=>h.unique&&h.confidence>=.9)&&(c+=.1),c=Math.max(.05,Math.min(1,c)),this.counter++,{targetId:`tgt_${Date.now().toString(36)}_${this.counter}`,tag:e.tagName.toLowerCase(),role:o.role||r.role,selector:i.selector,selectorCandidates:n,xpath:s.buildXPath(e),domPath:(((d=o.context)==null?void 0:d.parentChain)||[]).concat(i.selector).join(" > "),textFingerprint:r.meaningfulText,attributeFingerprint:JSON.stringify(r.stableAttributes),structuralFingerprint:r.hash,attributes:o.attributes||{},confidence:Math.round(c*100)/100,bounds:{x:Math.round(a.x),y:Math.round(a.y),width:Math.round(a.width),height:Math.round(a.height)},resolvedFrom:t}}resolveAndBuild(e){let t=null,s="unknown";typeof e=="string"&&(e={selector:e});const n=e;if(n.selectedElementRef&&(s="selectedElementRef"),!t&&n.selector)try{const i=this.doc.querySelectorAll(n.selector);if(i.length===0)return{error:`TARGET_NOT_FOUND: selector "${n.selector}" matches no element`};i.length>1?(t=nt(i,this.doc)||i[0],s+="+disambiguated"):(t=i[0],s="selector")}catch(i){return{error:`TARGET_INVALID: ${i.message}`}}if(!t&&n.xpath)try{t=this.doc.evaluate(n.xpath,this.doc,null,9,null).singleNodeValue,s="xpath"}catch(i){return{error:`TARGET_INVALID_XPATH: ${i.message}`}}if(!t&&typeof n.nodeId=="number"&&this.registry){const i=this.registry.getNode(n.nodeId);i&&i.nodeType===1&&this.doc.contains(i)&&(t=i,s="nodeId")}return!t&&n.coordinates&&(t=this.doc.elementFromPoint(n.coordinates.x,n.coordinates.y),s="coordinates"),t?{element:t,target:this.buildTarget(t,s)}:{error:"TARGET_NOT_FOUND: no usable resolution strategy succeeded"}}}function nt(l,e){for(const t of Array.from(l)){const s=t;try{if(L.inspectElement(s).visibility.isVisible)return s}catch{}}return null}class it{constructor(e){f(this,"fingerprintEngine",new re);this.doc=e}recover(e,t){var p;const s=[],n=[];let i=null;try{i=this.doc.querySelectorAll(e)}catch(y){s.push(`selector syntax error: ${y.message}`)}if(i&&i.length>0){s.push("selector still matches — no recovery needed");const y=i[0];return{recovered:!0,confidence:1,strategy:"original-selector",resolvedSelector:e,matchedElementInfo:Ie(y),alternatives:[],diagnostics:s,recommendation:"Original selector works; the earlier failure was transient (likely a navigation or render race)."}}s.push("selector no longer matches any element");const o=this.collectCandidates(t,s).map(y=>({element:y,score:this.scoreMatch(y,t)})).filter(y=>y.score.score>.35).sort((y,v)=>v.score.score-y.score.score);for(const y of o.slice(0,5)){const v=new Z(this.doc).bestSelector(y.element);n.push({selector:v.selector,confidence:Math.round(y.score.score*100)/100,strategy:"recovery-match"})}if(!o.length)return{recovered:!1,confidence:0,strategy:"none",alternatives:n,diagnostics:s,recommendation:"No sufficiently similar element exists. The region may have been removed, or the page structure changed fundamentally. Re-inspect the page and capture a new target."};const a=o[0],c=o.length>1?a.score.score-o[1].score.score:1;s.push(`best candidate score: ${a.score.score.toFixed(3)} (margin ${c.toFixed(3)})`);for(const y of a.score.components)y.score>0&&s.push(` - ${y.name}: ${(y.score*100).toFixed(0)}%`);if(a.score.score<.62||o.length>1&&c<.15)return{recovered:!1,confidence:Math.round(a.score.score*100)/100,strategy:"recovery-refused",resolvedSelector:(p=n[0])==null?void 0:p.selector,alternatives:n,diagnostics:s,recommendation:"Recovery refused: best match is not confident enough or too close to a competing element. Inspect alternatives manually before acting — refusing to avoid acting on a wrong element."};const h=new Z(this.doc).bestSelector(a.element).selector;return{recovered:!0,confidence:Math.round(a.score.score*100)/100,strategy:"fingerprint-recovery",resolvedSelector:h,matchedElementInfo:Ie(a.element),alternatives:n,diagnostics:s,recommendation:`Recovered target with ${(a.score.score*100).toFixed(0)}% confidence. Verify the resolved selector before destructive actions.`}}collectCandidates(e,t){var r,o;const s=new Set,n=this.doc.querySelectorAll(e.tag);let i=0;for(const a of Array.from(n))if(s.add(a),++i>=400)break;if((r=e.classes)!=null&&r.length){const a=e.classes.filter(c=>!ie(c));for(const c of a.slice(0,2))try{for(const u of Array.from(this.doc.querySelectorAll(`.${c}`)).slice(0,100))s.add(u)}catch{}}if((o=e.stableAttributes)!=null&&o.name)try{for(const a of Array.from(this.doc.querySelectorAll(`[name="${e.stableAttributes.name}"]`)))s.add(a)}catch{}if(e.parentSelector)try{for(const a of Array.from(this.doc.querySelectorAll(`${e.parentSelector} > ${e.tag}`)).slice(0,100))s.add(a)}catch{}return t.push(`collected ${s.size} candidate elements for scoring`),Array.from(s)}scoreMatch(e,t){const s=[],n=e.tagName.toLowerCase()===t.tag.toLowerCase()?1:0;s.push({name:"tag",score:n,weight:.15});const i=(t.text||"").trim().slice(0,40),r=B(e).slice(0,40),o=(e.textContent||"").trim().slice(0,40);let a=0;if(i){const g=r?r===i?1:le(i,r):0,b=o?o===i?1:le(i,o):0;a=Math.max(g,b)}s.push({name:"text",score:a,weight:.3});const c=new Set((t.classes||[]).filter(g=>!ie(g))),u=Array.from(e.classList||[]),d=c.size?u.filter(g=>c.has(g)).length/c.size:.5;s.push({name:"classes",score:d,weight:.2});const h=t.stableAttributes||{},p=Object.keys(h);let y=.5;if(p.length){let g=0;for(const b of p)e.getAttribute(b)===h[b]&&g++;y=g/p.length}s.push({name:"attributes",score:y,weight:.2});const v=t.childCount!==void 0?e.children.length===t.childCount?1:le(String(t.childCount),String(e.children.length)):.5;if(s.push({name:"childCount",score:v,weight:.05}),t.fingerprintHash){const g={fingerprintId:"snapshot",hash:t.fingerprintHash,tagHierarchy:[t.tag],stableAttributes:h,meaningfulText:i,classes:t.classes||[],dimensions:{width:0,height:0},ancestorPattern:"",descendantPattern:"",volatilityRisk:"medium",volatilityReasons:[]},b=this.fingerprintEngine.fingerprint(e),T=this.fingerprintEngine.compare(g,b);s.push({name:"fingerprint",score:T.score,weight:.1})}const m=s.reduce((g,b)=>g+b.score*b.weight,0);return{score:Math.max(0,Math.min(1,m)),components:s}}diagnose(e){const t=[];let s=!0,n=0,i,r=[];try{n=this.doc.querySelectorAll(e).length}catch(o){s=!1,i=o.message,t.push("Selector is syntactically invalid CSS.")}if(s&&n===0){t.push("Selector parses but matches nothing — element may be removed, re-rendered, or inside a shadow root."),r=this.relaxSelector(e);for(const o of r)try{if(this.doc.querySelectorAll(o).length>0){t.push(`Relaxed form "${o}" matches — the over-specific part of the selector is stale.`);break}}catch{}}return s&&n>1&&t.push(`Selector matches ${n} elements — it is ambiguous; use a more specific form or index.`),{selector:e,valid:s,matches:n,parseError:i,closestWorkingSelectors:r.filter(o=>{try{return this.doc.querySelectorAll(o).length>0}catch{return!1}}),diagnosis:t}}relaxSelector(e){const t=[],s=e.split(/[ >]+/).filter(Boolean);s.length>1&&(t.push(s.slice(0,-1).join(" ")),t.push(s[s.length-1]));const n=e.replace(/:nth-of-type\(\d+\)/g,"").replace(/\.[^. >#:[]+/g,(i,r,o)=>o[r-1]==="\\"?i:"");return n!==e&&n.trim()&&t.push(n.trim()),t}}function le(l,e){if(!l||!e)return 0;const t=Ae(l),s=Ae(e);if(t===s)return 1;if(t.includes(s)||s.includes(t))return .7;const n=new Set(t.split(/\s+/)),i=new Set(s.split(/\s+/));return Array.from(n).filter(o=>i.has(o)).length/Math.max(n.size,i.size)}function Ae(l){return l.toLowerCase().replace(/[^a-z0-9 ]/g," ").replace(/\s+/g," ").trim()}function Ie(l){return{tag:l.tagName.toLowerCase(),id:l.getAttribute("id")||void 0,text:B(l).slice(0,60),classes:Array.from(l.classList||[])}}class ue{constructor(e){f(this,"state");this.state=e>>>0,this.state===0&&(this.state=2654435769)}next(){this.state=this.state+1831565813>>>0;let e=this.state;return e=Math.imul(e^e>>>15,e|1),e^=e+Math.imul(e^e>>>7,e|61),((e^e>>>14)>>>0)/4294967296}range(e,t){return e+this.next()*(t-e)}int(e,t){return Math.floor(this.range(e,t+1))}chance(e){return this.next() setTimeout(t,e))}chance(){return this.rng.next()<.5}}const ot=[{ruleId:"red_key_password",kind:"key-pattern",pattern:"password|passwd|pwd",description:"Keys containing password/passwd/pwd",enabled:!0,userAdded:!1},{ruleId:"red_key_token",kind:"key-pattern",pattern:"token|jwt|bearer|auth|session.?id|secret|api.?key|client.?secret",description:"Keys containing token/jwt/auth/session-id/secret/api-key",enabled:!0,userAdded:!1},{ruleId:"red_key_credential",kind:"key-pattern",pattern:"credential|login|user.?pass|otp|2fa|mfa|verification",description:"Keys containing credential/login/otp/2fa/verification",enabled:!0,userAdded:!1},{ruleId:"red_key_payment",kind:"key-pattern",pattern:"card|payment|billing|iban|cvv|cvc|pan",description:"Keys containing card/payment/billing/iban/cvv",enabled:!0,userAdded:!1},{ruleId:"red_key_personal",kind:"key-pattern",pattern:"ssn|social.?security|national.?id|passport|tax.?id",description:"Keys containing personal identifier patterns",enabled:!0,userAdded:!1},{ruleId:"red_val_jwt",kind:"value-pattern",pattern:"eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+",description:"JWT-shaped tokens",enabled:!0,userAdded:!1},{ruleId:"red_val_bearer",kind:"value-pattern",pattern:"bearer\\s+[A-Za-z0-9._-]+",description:"Bearer tokens",enabled:!0,userAdded:!1},{ruleId:"red_val_long_hex",kind:"value-pattern",pattern:"\\b[a-f0-9]{32,}\\b",description:"32+ char hex strings (session/API ids)",enabled:!0,userAdded:!1},{ruleId:"red_val_sk",kind:"value-pattern",pattern:"\\b(sk|pk|rk)_[A-Za-z0-9_]{20,}\\b",description:"Stripe-style secret keys (sk_live_…)",enabled:!0,userAdded:!1},{ruleId:"red_attr_input_password",kind:"attribute-name",pattern:"value",description:"value attributes on password inputs handled by PrivacyEngine maskValue",enabled:!0,userAdded:!1},{ruleId:"red_attr_secret",kind:"attribute-name",pattern:"data-secret|data-token|data-api-key|secret|access.?token",description:"Secret-carrying attributes",enabled:!0,userAdded:!1}],at=[{exclusionId:"excl_mcpdom_overlay",selector:"[data-mcpdom-internal], [data-forensic-internal], #forensic-recorder-floating-host, #forensic-inspect-highlighter",reason:"MCPDOM-injected UI must never contaminate captured DOM (§68 clean capture)",userAdded:!1},{exclusionId:"excl_mcpdom_ids",selector:'[id^="forensic-"], [id^="mcpdom-"]',reason:"MCPDOM-namespaced nodes",userAdded:!1}],de="[REDACTED]";class he{constructor(e){f(this,"config");f(this,"base",new se);f(this,"compiledKeyPatterns",[]);f(this,"compiledValuePatterns",[]);f(this,"compiledAttrPatterns",[]);this.config={rules:[...ot],exclusions:[...at],stubMode:!0,...e},this.recompile()}recompile(){this.compiledKeyPatterns=[],this.compiledValuePatterns=[],this.compiledAttrPatterns=[];for(const e of this.config.rules){if(!e.enabled)continue;const t="i";try{switch(e.kind){case"key-pattern":this.compiledKeyPatterns.push(new RegExp(e.pattern,t));break;case"value-pattern":this.compiledValuePatterns.push(new RegExp(e.pattern,"i"));break;case"attribute-name":this.compiledAttrPatterns.push(new RegExp(`^(${e.pattern})$`,"i"));break}}catch{}}}getRules(){return[...this.config.rules]}setRuleEnabled(e,t){const s=this.config.rules.find(n=>n.ruleId===e);return s?(s.enabled=t,this.recompile(),!0):!1}addRule(e){const t=`red_custom_${this.config.rules.length+1}_${Date.now().toString(36)}`,s={...e,ruleId:t,userAdded:!0};return this.config.rules.push(s),this.recompile(),s}removeRule(e){const t=this.config.rules.findIndex(s=>s.ruleId===e);return t<0||!this.config.rules[t].userAdded?!1:(this.config.rules.splice(t,1),this.recompile(),!0)}getExclusions(){return[...this.config.exclusions]}addExclusion(e,t){const n={exclusionId:`excl_custom_${this.config.exclusions.length+1}_${Date.now().toString(36)}`,selector:e,reason:t,userAdded:!0};return this.config.exclusions.push(n),n}removeExclusion(e){const t=this.config.exclusions.findIndex(s=>s.exclusionId===e);return t<0||!this.config.exclusions[t].userAdded?!1:(this.config.exclusions.splice(t,1),!0)}isSensitiveKey(e){return this.compiledKeyPatterns.some(t=>t.test(e))}redactValue(e){let t=e;for(const s of this.compiledValuePatterns)s.test(t)&&(t=t.replace(new RegExp(s.source,"gi"),de));return t}redactByKeyValue(e,t){return this.isSensitiveKey(e)?this.config.stubMode?de:t:this.redactValue(t)}isSensitiveAttribute(e){return this.compiledAttrPatterns.some(t=>t.test(e))}redactAttributes(e){const t={};for(const[s,n]of Object.entries(e))this.isSensitiveAttribute(s)?t[s]=de:t[s]=this.redactValue(n);return t}cleanSubtree(e){const t=e.cloneNode(!0);for(const s of this.config.exclusions){let n=null;try{n=t.querySelectorAll(s.selector)}catch{continue}for(const i of Array.from(n))i.remove();try{if(t.matches(s.selector))return this.doclessEmptyStub(t)}catch{}}return t}isExcluded(e){for(const t of this.config.exclusions)try{if(e.matches(t.selector)||e.closest(t.selector))return!0}catch{}return!1}doclessEmptyStub(e){return e.innerHTML="",e.setAttribute("data-mcpdom-excluded","true"),e}toJSON(){return{rules:this.getRules(),exclusions:this.getExclusions(),stubMode:this.config.stubMode}}static fromJSON(e){return new he({rules:Array.isArray(e==null?void 0:e.rules)?e.rules:void 0,exclusions:Array.isArray(e==null?void 0:e.exclusions)?e.exclusions:void 0,stubMode:typeof(e==null?void 0:e.stubMode)=="boolean"?e.stubMode:void 0})}}const ge='a[href], button, input, select, textarea, [role="button"], [role="link"], [role="tab"], [onclick], [tabindex]';function X(l,e){return{items:l.slice(0,e),truncated:l.length>e}}function k(l,e,t,s,n,i){return{analyzer:l,summary:e,count:t,items:s,warnings:n,truncated:i}}function D(l){try{return L.inspectElement(l).bestSelector}catch{return l.tagName.toLowerCase()}}const ct=l=>{const e=Array.from(l.querySelectorAll("form")),t=e.map(n=>{const i=Array.from(n.querySelectorAll("input, select, textarea")).map(r=>({tag:r.tagName.toLowerCase(),type:r.getAttribute("type")||(r.tagName.toLowerCase()==="textarea"?"textarea":r.tagName.toLowerCase()==="select"?"select":"text"),name:r.getAttribute("name")||void 0,id:r.getAttribute("id")||void 0,required:r.hasAttribute("required"),pattern:r.getAttribute("pattern")||void 0,maxLength:r.getAttribute("maxlength")||void 0,placeholder:r.getAttribute("placeholder")||void 0,ariaLabel:r.getAttribute("aria-label")||void 0,autocomplete:r.getAttribute("autocomplete")||void 0,hasLabel:!!(r.getAttribute("id")&&l.querySelector(`label[for="${r.getAttribute("id")}"]`))||!!r.closest("label"),defaultValue:r.value!==void 0&&(r.getAttribute("type")||"text")!=="password"?String(r.value).slice(0,40):void 0}));return{selector:D(n),action:n.getAttribute("action")||void 0,method:(n.getAttribute("method")||"GET").toUpperCase(),id:n.getAttribute("id")||void 0,fieldCount:i.length,submitButton:n.querySelector('button[type="submit"], input[type="submit"]')?D(n.querySelector('button[type="submit"], input[type="submit"]')):void 0,validationAttributes:i.filter(r=>r.required||r.pattern).length,fields:i}}),s=X(t,50);return k("analyze_forms",`${e.length} form(s) with ${t.reduce((n,i)=>n+i.fieldCount,0)} total fields`,e.length,s.items,[],s.truncated)},lt=l=>{const e=Array.from(l.querySelectorAll("a[href]")),t=e.map(n=>({href:n.getAttribute("href")||"",text:B(n).slice(0,60),selector:D(n),rel:n.getAttribute("rel")||void 0,target:n.getAttribute("target")||void 0,download:n.hasAttribute("download"),external:/^https?:\/\//i.test(n.getAttribute("href")||"")&&!ut(n.getAttribute("href")||"",l),anchorOnly:(n.getAttribute("href")||"").startsWith("#")})),s=X(t,200);return k("extract_links",`${e.length} link(s): ${t.filter(n=>n.external).length} external, ${t.filter(n=>n.anchorOnly).length} anchors`,e.length,s.items,[],s.truncated)};function ut(l,e){var t,s,n,i;try{return new URL(l,((s=(t=e.defaultView)==null?void 0:t.location)==null?void 0:s.href)||"http://localhost").origin===(((i=(n=e.defaultView)==null?void 0:n.location)==null?void 0:i.origin)||"")}catch{return!1}}const dt=l=>{const e=Array.from(l.querySelectorAll("img")),t=Array.from(l.querySelectorAll("video")),s=Array.from(l.querySelectorAll("audio")),n=Array.from(l.querySelectorAll("canvas")),i=[],r=[...e.map(c=>({kind:"img",selector:D(c),src:(c.getAttribute("src")||"").slice(0,150),alt:c.getAttribute("alt"),width:c.getAttribute("width")||void 0,height:c.getAttribute("height")||void 0,naturalWidth:c.naturalWidth||void 0,naturalHeight:c.naturalHeight||void 0,lazy:c.getAttribute("loading")==="lazy",missingAlt:!c.hasAttribute("alt")})),...t.map(c=>{var u;return{kind:"video",selector:D(c),src:(c.getAttribute("src")||((u=c.querySelector("source"))==null?void 0:u.getAttribute("src"))||"").slice(0,150),controls:c.hasAttribute("controls"),autoplay:c.hasAttribute("autoplay"),muted:c.hasAttribute("muted"),poster:c.getAttribute("poster")||void 0}}),...s.map(c=>{var u;return{kind:"audio",selector:D(c),src:(c.getAttribute("src")||((u=c.querySelector("source"))==null?void 0:u.getAttribute("src"))||"").slice(0,150),controls:c.hasAttribute("controls")}}),...n.map(c=>({kind:"canvas",selector:D(c),width:c.width,height:c.height}))],o=r.filter(c=>c.missingAlt).length;o&&i.push(`${o} image(s) missing alt text (accessibility risk).`);const a=X(r,200);return k("analyze_media",`${e.length} images, ${t.length} videos, ${s.length} audios, ${n.length} canvases`,r.length,a.items,i,a.truncated)},ht=l=>{const e=l.defaultView,t=[],s={};if(e!=null&&e.getComputedStyle){const i=e.getComputedStyle(l.documentElement);for(let r=0;r ({name:i,value:r}));return k("get_css_variables",`${n.length} CSS custom properties found`,n.length,n,t,!1)},gt=l=>{const e=l.defaultView,t=[],s=new Map;if(e!=null&&e.getComputedStyle)for(const i of Array.from(l.querySelectorAll("body, body *")).slice(0,800)){const r=e.getComputedStyle(i),o=r.fontFamily||"",a=r.fontSize||"",c=`${o.split(",")[0].replace(/["']/g,"").trim()} @ ${a}`;s.set(c,(s.get(c)||0)+1)}else t.push("getComputedStyle unavailable — font usage analysis requires rendered styles.");const n=Array.from(s.entries()).map(([i,r])=>({font:i,usage:r})).sort((i,r)=>r.usage-i.usage);return k("analyze_fonts",`${n.length} distinct font/size combinations`,n.length,n,t,!1)},pt=l=>{const e=l.defaultView,t=[],s=new Map;if(e!=null&&e.getComputedStyle)for(const i of Array.from(l.querySelectorAll("body, body *")).slice(0,800)){const r=e.getComputedStyle(i);for(const o of["color","background-color","border-top-color"]){const a=r.getPropertyValue(o);a&&a!=="rgba(0, 0, 0, 0)"&&s.set(a,(s.get(a)||0)+1)}}else{for(const i of Array.from(l.querySelectorAll("[style]")).slice(0,300)){const r=i.getAttribute("style")||"",o=/(color)\s*:\s*([^;]+)/gi;let a;for(;a=o.exec(r);)s.set(a[2].trim(),(s.get(a[2].trim())||0)+1)}t.push("getComputedStyle unavailable — palette from inline styles only.")}const n=Array.from(s.entries()).map(([i,r])=>({color:i,usage:r})).sort((i,r)=>r.usage-i.usage).slice(0,40);return k("extract_color_palette",`${s.size} distinct colors in use`,s.size,n,t,!1)},mt=l=>{const e=l.defaultView,t=[],s=[];if(!(e!=null&&e.getComputedStyle))return t.push("getComputedStyle unavailable — z-index analysis requires rendered styles."),k("detect_zindex_conflicts","unavailable",0,[],t,!1);const n=[];for(const i of Array.from(l.querySelectorAll("body *")).slice(0,1e3)){const r=e.getComputedStyle(i),o=r.zIndex;o&&o!=="auto"&&parseInt(o,10)>0&&n.push({selector:D(i),z:parseInt(o,10),position:r.position,stacking:r.position==="fixed"||r.position==="sticky"||r.opacity!=="1"||r.transform!=="none"?"creates-stacking-context":"plain"})}for(let i=0;i 1e5&&s.push({zIndex:n[i].z,elements:[n[i].selector],note:"extremely high z-index — competes with platform overlays (MCPDOM uses 2147483640+)."})}return k("detect_zindex_conflicts",`${n.length} z-indexed elements, ${s.length} potential conflict(s)`,s.length,X(s,40).items,t,s.length>40)},ft=l=>{const e=l.defaultView,t=[],s=l.documentElement,n=l.body,i=Math.max((s==null?void 0:s.scrollWidth)||0,(n==null?void 0:n.scrollWidth)||0),r=(e==null?void 0:e.innerWidth)||(s==null?void 0:s.clientWidth)||0,o=i>r+1;if(o&&(t.push({issue:"horizontal-overflow",detail:`document scrollWidth ${i} exceeds viewport ${r}`}),e!=null&&e.getComputedStyle))for(const c of Array.from(l.querySelectorAll("body *")).slice(0,600)){const u=c.getBoundingClientRect();if(u.right>r+2&&u.width>100&&(t.push({issue:"element-exceeds-viewport",selector:D(c),right:Math.round(u.right),width:Math.round(u.width)}),t.length>15))break}let a=0;for(const c of Array.from(l.querySelectorAll(ge)).slice(0,500)){const u=c.getBoundingClientRect();(u.width===0||u.height===0)&&a++}return a&&t.push({issue:"zero-size-interactive-elements",count:a}),k("detect_layout_issues",o?`HORIZONTAL OVERFLOW: page is ${i-r}px wider than viewport`:"No horizontal overflow detected",t.length,t,[],!1)},bt=l=>{const e=Array.from(l.querySelectorAll(ge)),t=new Map,s=e.slice(0,300).map(n=>{const i=pe(n),r=i.role||n.tagName.toLowerCase();return t.set(r,(t.get(r)||0)+1),{selector:i.bestSelector,tag:i.tag,role:i.role,text:i.text.slice(0,40),visible:i.visibility.isVisible,disabled:n.disabled||n.hasAttribute("disabled"),inViewport:i.visibility.isInViewport}});return k("census_interactive_elements",`${e.length} interactive elements: ${Array.from(t.entries()).map(([n,i])=>`${n}×${i}`).join(", ")||"none"}`,e.length,s,[],e.length>300)};function pe(l){try{return L.inspectElement(l)}catch{return{tag:l.tagName.toLowerCase(),role:void 0,text:"",bestSelector:l.tagName.toLowerCase(),bounds:{x:0,y:0,width:0,height:0,top:0,right:0,bottom:0,left:0},visibility:{isVisible:!1,isInViewport:!1}}}}const yt=l=>{const e=["header","nav","main","aside","footer","article","section","figure","figcaption","mark","time","address","details","summary","dialog"],t=[];for(const i of e){const r=Array.from(l.querySelectorAll(i));if(r.length)for(const o of r.slice(0,20))t.push({tag:i,selector:D(o),role:o.getAttribute("role")||Et(i),text:B(o).slice(0,50),childCount:o.children.length})}const s=t.filter(i=>["banner","navigation","main","complementary","contentinfo"].includes(i.role)),n=[];return t.find(i=>i.tag==="main")||n.push("No element — page lacks a primary landmark."),l.querySelectorAll("header").length>1&&n.push("Multiple elements outside sections — ambiguous banner landmark."),k("detect_semantic_elements",`${t.length} semantic elements, ${s.length} landmarks`,t.length,X(t,100).items,n,t.length>100)};function Et(l){return{header:"banner",nav:"navigation",main:"main",aside:"complementary",footer:"contentinfo",article:"article",section:"region",form:"form"}[l]}const _e={analyze_forms:ct,extract_links:lt,analyze_media:dt,get_css_variables:ht,analyze_fonts:gt,extract_color_palette:pt,detect_zindex_conflicts:mt,detect_layout_issues:ft,census_interactive_elements:bt,detect_semantic_elements:yt,scan_accessibility_issues:l=>{var i;const e=[];for(const r of Array.from(l.querySelectorAll("img")).slice(0,200))r.hasAttribute("alt")||e.push({rule:"img-alt",severity:"error",selector:D(r),message:"Image is missing the alt attribute."});for(const r of Array.from(l.querySelectorAll("input:not([type=hidden]):not([type=submit]):not([type=button])")).slice(0,200)){const o=r.getAttribute("id");o&&l.querySelector(`label[for="${o}"]`)||r.closest("label")||r.getAttribute("aria-label")||r.getAttribute("aria-labelledby")||e.push({rule:"input-label",severity:"error",selector:D(r),message:"Form input has no associated label, aria-label or aria-labelledby."})}for(const r of Array.from(l.querySelectorAll('button, a[href], [role="button"]')).slice(0,300)){const o=B(r).trim(),a=r.getAttribute("aria-label");!o&&!a&&e.push({rule:"accessible-name",severity:"error",selector:D(r),message:"Interactive element has no accessible name (no text, no aria-label).",hint:r.querySelector("img[alt]")?"Contains an image — consider alt text or aria-label.":void 0})}const t=Array.from(l.querySelectorAll("h1, h2, h3, h4, h5, h6")).slice(0,100);let s=0;for(const r of t){const o=parseInt(r.tagName[1],10);s&&o>s+1&&e.push({rule:"heading-order",severity:"warning",selector:D(r),message:`Heading level jumps from h${s} to h${o}.`}),s=o}(i=l.documentElement)!=null&&i.getAttribute("lang")||e.push({rule:"html-lang",severity:"warning",selector:"html",message:"The element has no lang attribute."});const n=e.filter(r=>r.severity==="error").length;return k("scan_accessibility_issues",`${e.length} issue(s): ${n} errors, ${e.length-n} warnings`,e.length,X(e,100).items,[],e.length>100)},detect_dead_click_targets:l=>{const e=l.defaultView,t=[];for(const s of Array.from(l.querySelectorAll(ge)).slice(0,500)){const n=s.getBoundingClientRect(),i=e!=null&&e.getComputedStyle?e.getComputedStyle(s):null,r=n.width===0||n.height===0,o=i?i.pointerEvents==="none":!1,a=i?i.display==="none"||i.visibility==="hidden":!1,c=s.getAttribute("aria-hidden")==="true";(r||o||a||c)&&t.push({selector:D(s),tag:s.tagName.toLowerCase(),text:B(s).slice(0,30),reasons:[r&&"zero-size",o&&"pointer-events:none",a&&`hidden (${i?i.display:"?"}/${i?i.visibility:"?"})`,c&&"aria-hidden"].filter(Boolean)})}return k("detect_dead_click_targets",`${t.length} unreachable interactive element(s)`,t.length,X(t,80).items,[],t.length>80)},inventory_animations:l=>{const e=l.defaultView,t=[],s=[];if(!(e!=null&&e.getComputedStyle))return t.push("getComputedStyle unavailable — animation inventory requires rendered styles."),k("inventory_animations","unavailable",0,[],t,!1);for(const i of Array.from(l.querySelectorAll("body *")).slice(0,800)){const r=e.getComputedStyle(i),o=r.animationName!=="none"?`${r.animationName} ${r.animationDuration}`:null,a=r.transitionProperty!=="none"&&r.transitionProperty!=="all"?`${r.transitionProperty} ${r.transitionDuration}`:r.transitionProperty==="all"?`all ${r.transitionDuration}`:null;(o||a)&&s.push({selector:D(i),animation:o,transition:a,transitionTiming:r.transitionTimingFunction||void 0})}const n=s.filter(i=>i.animation&&i.animation.includes("infinite"));return n.length>5&&t.push(`${n.length} infinitely looping animations — may indicate decorative spinners or a stuck loading state.`),k("inventory_animations",`${s.length} animated/transitioning elements`,s.length,X(s,80).items,t,s.length>80)},map_frame_tree:l=>{const e=[],t=(n,i,r)=>{const o=Array.from(n.querySelectorAll("iframe, frame"));for(const a of o){const c=a.getAttribute("src")||"(no src)";let u=!1,d=null;try{const h=a.contentDocument;h&&(u=!0,d=h.querySelectorAll("*").length,r<3&&t(h,`${i} > ${a.tagName.toLowerCase()}[${c.slice(0,50)}]`,r+1))}catch{u=!1}e.push({path:`${i} > ${a.tagName.toLowerCase()}`,selector:D(a),src:c.slice(0,120),title:a.getAttribute("title")||void 0,name:a.getAttribute("name")||void 0,sandbox:a.getAttribute("sandbox")||void 0,accessible:u,childCount:d,limitation:u?void 0:"Same-origin policy blocks contentDocument access (cross-origin frame)."})}};t(l,"document",0);const s=e.filter(n=>!n.accessible).length;return k("map_frame_tree",`${e.length} frame(s), ${s} inaccessible (cross-origin)`,e.length,e,[],!1)},inventory_shadow_roots:l=>{const e=[],t=(s,n,i)=>{const r=(s instanceof ShadowRoot,Array.from(s.querySelectorAll("*")));for(const o of r)if(o.shadowRoot){const a=o.shadowRoot,c=`${n} > ${o.tagName.toLowerCase()}::shadowRoot(${a.mode})`;e.push({path:c.slice(0,200),hostSelector:D(o),hostTag:o.tagName.toLowerCase(),mode:a.mode,childCount:a.querySelectorAll("*").length,styles:a.querySelectorAll("style").length}),i<4&&t(a,c,i+1)}};return t(l.documentElement,"document",0),k("inventory_shadow_roots",`${e.length} open shadow root(s) found`,e.length,e,[],!1)},inspect_page_storage:l=>{const e=l.defaultView,t=new he,s=[],n=[];if(!(e!=null&&e.localStorage)||!(e!=null&&e.sessionStorage))return k("inspect_page_storage","Web Storage API unavailable in this context",0,[],["localStorage/sessionStorage are not accessible here (JSDOM limitation or sandboxed iframe)."],!1);try{for(let r=0;r r+(o.size||0),0);return k("inspect_page_storage",`${n.length} storage entries (~${i} bytes), sensitive keys redacted`,n.length,X(n,100).items,s,n.length>100)},get_performance_metrics:l=>{var i,r,o,a;const e=l.defaultView,t=[],s=e==null?void 0:e.performance;if(!(s!=null&&s.timing)&&!(s!=null&&s.getEntriesByType))return k("get_performance_metrics","Performance API unavailable",0,[],["window.performance is not exposed in this context."],!1);const n=[];try{const c=(r=(i=s.getEntriesByType)==null?void 0:i.call(s,"navigation"))==null?void 0:r[0];if(c)n.push({metric:"navigation-timing",domContentLoaded:Math.round(c.domContentLoadedEventEnd),loadComplete:Math.round(c.loadEventEnd),domInteractive:Math.round(c.domInteractive),type:c.type,redirectCount:c.redirectCount,sizeTransfer:c.transferSize});else if(s.timing){const h=s.timing;n.push({metric:"navigation-timing-legacy",domContentLoaded:h.domContentLoadedEventEnd-h.navigationStart,loadComplete:h.loadEventEnd-h.navigationStart,domInteractive:h.domInteractive-h.navigationStart})}const u=((o=s.getEntriesByType)==null?void 0:o.call(s,"paint"))||[];for(const h of u)n.push({metric:h.name,startTime:Math.round(h.startTime)});const d=((a=s.getEntriesByType)==null?void 0:a.call(s,"resource"))||[];if(d.length){const h=d.reduce((y,v)=>y+v.duration,0),p=[...d].sort((y,v)=>v.duration-y.duration).slice(0,5).map(y=>({url:String(y.name).slice(0,100),duration:Math.round(y.duration)}));n.push({metric:"resource-summary",count:d.length,totalDuration:Math.round(h),slowest:p})}s.memory&&n.push({metric:"memory",usedJSHeapMB:Math.round(s.memory.usedJSHeapSize/1048576*10)/10,totalJSHeapMB:Math.round(s.memory.totalJSHeapSize/1048576*10)/10})}catch(c){t.push(`performance read failed: ${c.message}`)}return k("get_performance_metrics",`${n.length} metric group(s)`,n.length,n,t,!1)},extract_seo_metadata:l=>{var r,o,a;const e=c=>{var u;return((u=l.querySelector(`meta[name="${c}"]`))==null?void 0:u.getAttribute("content"))||void 0},t=c=>{var u;return((u=l.querySelector(`meta[property="${c}"]`))==null?void 0:u.getAttribute("content"))||void 0},s=[{field:"title",value:l.title||void 0},{field:"description",value:e("description")},{field:"canonical",value:(r=l.querySelector('link[rel="canonical"]'))==null?void 0:r.getAttribute("href")},{field:"robots",value:e("robots")},{field:"viewport",value:e("viewport")},{field:"charset",value:(o=l.querySelector("meta[charset]"))==null?void 0:o.getAttribute("charset")},{field:"og:title",value:t("og:title")},{field:"og:description",value:t("og:description")},{field:"og:image",value:t("og:image")},{field:"og:url",value:t("og:url")},{field:"twitter:card",value:e("twitter:card")},{field:"language",value:(a=l.documentElement)==null?void 0:a.getAttribute("lang")}],n=l.querySelectorAll("h1").length,i=[];return n===0&&i.push("No h1 — page lacks a primary heading."),n>1&&i.push(`Multiple h1 elements (${n}).`),e("description")||i.push("No meta description."),s.push({field:"h1Count",value:n}),k("extract_seo_metadata",`SEO metadata extracted; ${i.length} warning(s)`,s.length,s,i,!1)},extract_structured_data:l=>{var t;const e=[];for(const s of Array.from(l.querySelectorAll('script[type="application/ld+json"]')))try{const n=JSON.parse(s.textContent||"{}");e.push({format:"JSON-LD",type:n["@type"]||(Array.isArray(n)?"array":"unknown"),data:n})}catch(n){e.push({format:"JSON-LD",type:"invalid-json",error:n.message})}for(const s of Array.from(l.querySelectorAll("[itemscope]")).slice(0,30)){const n=s.getAttribute("itemtype")||"unknown",i={};for(const r of Array.from(s.querySelectorAll("[itemprop]"))){const o=r.getAttribute("itemprop")||"",a=r.getAttribute("content")||r.getAttribute("href")||((t=r.textContent)==null?void 0:t.trim())||"";i[o]=a.slice(0,100)}e.push({format:"microdata",type:n.split("/").pop()||n,data:i})}return k("extract_structured_data",`${e.length} structured data block(s)`,e.length,e,[],!1)},extract_tables:l=>{const e=Array.from(l.querySelectorAll("table")),t=e.slice(0,30).map(s=>{var a,c,u;const n=Array.from(s.querySelectorAll("thead th, tr:first-child th")).map(d=>{var h;return((h=d.textContent)==null?void 0:h.trim())||""}),i=Array.from(s.querySelectorAll("tbody tr, tr")).filter(d=>!d.querySelector("th")).slice(0,50),r=i.map(d=>Array.from(d.querySelectorAll("td")).map(h=>(h.textContent||"").trim().slice(0,60))),o=(c=(a=s.querySelector("caption"))==null?void 0:a.textContent)==null?void 0:c.trim();return{selector:D(s),caption:o,columnCount:n.length||((u=r[0])==null?void 0:u.length)||0,rowCount:i.length,headers:n,rows:r}});return k("extract_tables",`${e.length} table(s)`,e.length,t,[],e.length>30)},extract_lists:l=>{const e=Array.from(l.querySelectorAll("ul, ol")),t=e.slice(0,60).map(s=>{const n=Array.from(s.querySelectorAll(":scope > li")).slice(0,40);return{selector:D(s),kind:s.tagName.toLowerCase(),ordered:s.tagName.toLowerCase()==="ol",itemCount:n.length,items:n.map(i=>B(i).slice(0,60)),nested:s.querySelectorAll("ul, ol").length}});return k("extract_lists",`${e.length} list(s)`,e.length,t,[],e.length>60)},analyze_page_content:l=>{const e=l.body,t=(e==null?void 0:e.innerText)||(e==null?void 0:e.textContent)||"",s=t.trim()?t.trim().split(/\s+/).length:0,n=Array.from(l.querySelectorAll("h1, h2, h3, h4, h5, h6")).map(c=>({level:parseInt(c.tagName[1],10),text:B(c).slice(0,80)})),i=l.querySelectorAll("p").length,r=i?Math.round(s/i):0,o=Math.round(s/220*10)/10,a=[{metric:"wordCount",value:s},{metric:"paragraphCount",value:i},{metric:"avgParagraphWords",value:r},{metric:"estimatedReadingMinutes",value:o},{metric:"headingCount",value:n.length},{metric:"imageCount",value:l.querySelectorAll("img").length},{metric:"linkDensity",value:Math.round(l.querySelectorAll("a[href]").length/Math.max(1,s)*1e3)/1e3},{metric:"headings",value:n.slice(0,50)}];return k("analyze_page_content",`${s} words, ${i} paragraphs, ~${o} min read`,a.length,a,[],!1)},search_dom:(l,e)=>{const t=String((e==null?void 0:e.query)||"").trim();if(!t)return k("search_dom","No query supplied",0,[],["Provide a text query; optionally tag/attr filters."],!1);const s=t.toLowerCase(),n=[],i=Math.min((e==null?void 0:e.limit)||50,200),r=Array.from(l.querySelectorAll("*"));for(const o of r){if(n.length>=i)break;if(e!=null&&e.tag&&o.tagName.toLowerCase()!==String(e.tag).toLowerCase())continue;const a=B(o),c=Array.from(o.attributes);let u=0,d="";o.tagName.toLowerCase().includes(s)&&(u+=.2,d="tag match"),a.toLowerCase().includes(s)&&a.length<200&&(u+=.6,d="text match");for(const h of c)if(h.name.toLowerCase().includes(s)||h.value.length<100&&h.value.toLowerCase().includes(s)){u+=.4,d=`attribute ${h.name} match`;break}if(e!=null&&e.attr){const h=String(e.attr).toLowerCase(),p=e.attrValue?String(e.attrValue).toLowerCase():null;if(c.find(v=>v.name.toLowerCase()===h&&(!p||v.value.toLowerCase().includes(p))))u+=.5;else continue}if(u>0){const h=pe(o);n.push({selector:h.bestSelector,tag:h.tag,role:h.role,text:h.text.slice(0,60),score:Math.round(u*100)/100,reason:d,visible:h.visibility.isVisible,bounds:{x:Math.round(h.bounds.x),y:Math.round(h.bounds.y),w:Math.round(h.bounds.width),h:Math.round(h.bounds.height)}})}}return n.sort((o,a)=>a.score-o.score),k("search_dom",`${n.length} element(s) match "${t}"`,n.length,n,[],n.length>=i)},inventory_ctas:l=>{var t;const e=[];for(const s of Array.from(l.querySelectorAll('button, a[class*="btn"], a[class*="button"], input[type="submit"], [role="button"]')).slice(0,100)){const n=pe(s);e.push({selector:n.bestSelector,tag:n.tag,text:n.text.slice(0,50),styleHint:(t=s.getAttribute("class"))==null?void 0:t.slice(0,60),primary:/primary|cta|submit|main/i.test(s.getAttribute("class")||"")||s.type==="submit",visible:n.visibility.isVisible})}return k("inventory_ctas",`${e.length} call-to-action element(s)`,e.length,e,[],!1)},detect_focus_traps:l=>{const e=[];for(const s of Array.from(l.querySelectorAll('[role="dialog"], [aria-modal="true"], dialog[open], .modal, [class*="modal"]')).slice(0,30)){const n=s.querySelectorAll('a[href], button, input, select, textarea, [tabindex]:not([tabindex="-1"])');e.push({selector:D(s),kind:s.getAttribute("role")||s.tagName.toLowerCase(),ariaModal:s.getAttribute("aria-modal"),focusableCount:n.length,firstFocusable:n[0]?D(n[0]):void 0,note:n.length===0?"Modal container has NO focusable elements — keyboard users are trapped.":void 0})}const t=l.querySelectorAll("[tabindex]>0");for(const s of Array.from(t).slice(0,20))e.push({selector:D(s),kind:"positive-tabindex",note:`tabindex=${s.tabIndex} breaks natural tab order.`});return k("detect_focus_traps",`${e.length} focus-management issue(s)/container(s)`,e.length,e,[],!1)},infer_responsive_breakpoints:l=>{const e=l.defaultView,t=[],s=new Set;for(const o of Array.from(l.querySelectorAll("style"))){const a=o.textContent||"",c=/@media[^{]*?\(\s*(?:min|max)-width\s*:\s*(\d+)(?:\.\d+)?px/g;let u;for(;u=c.exec(a);)s.add(parseInt(u[1],10))}for(const o of Array.from(l.querySelectorAll('link[rel="stylesheet"]')).slice(0,10)){const a=o.getAttribute("href")||"";if(/^\d+px$/.test(a)||a.includes("width=")){const c=a.match(/width=(\d+)/);c&&s.add(parseInt(c[1],10))}}for(const o of Array.from(l.querySelectorAll("img[srcset], source[srcset]")).slice(0,50)){const a=o.getAttribute("srcset")||"";for(const c of a.matchAll(/(\d+)w/g))s.add(parseInt(c[1],10))}e!=null&&e.matchMedia||t.push("matchMedia unavailable — live breakpoint probing skipped.");const n=Array.from(s).sort((o,a)=>o-a),i=n.map(o=>({breakpoint:o,note:o<=768?"mobile-class":o<=1024?"tablet-class":"desktop-class"})),r=e==null?void 0:e.innerWidth;if(r){const o=n.filter(a=>a<=r);i.unshift({breakpoint:`current viewport: ${r}px`,note:o.length?`below breakpoints: ${o.join(", ")}`:"no declared breakpoint below current width"})}return k("infer_responsive_breakpoints",`${n.length} breakpoint(s) inferred from CSS/srcset`,i.length,i,t,!1)},get_selection_state:l=>{var i;const e=l.defaultView,t=(i=e==null?void 0:e.getSelection)==null?void 0:i.call(e),s=l.activeElement,n=[{hasSelection:!!(t!=null&&t.toString()),selectedText:(t==null?void 0:t.toString().slice(0,200))||"",selectionRanges:(t==null?void 0:t.rangeCount)||0,activeElement:s?{tag:s.tagName.toLowerCase(),selector:D(s),editable:s.isContentEditable||["INPUT","TEXTAREA"].includes(s.tagName)}:null}];return k("get_selection_state",t!=null&&t.toString()?`Selection: "${t.toString().slice(0,40)}…"`:"No text selection",1,n,[],!1)}};function vt(l,e,t){const s=_e[l];return s?s(e,t):{analyzer:l,summary:`Unknown analyzer "${l}". Available: ${Object.keys(_e).join(", ")}`,count:0,items:[],warnings:[],truncated:!1}}const wt=2e3;class St{constructor(e=wt){f(this,"events",[]);f(this,"cap");f(this,"counter",0);this.cap=Math.max(10,e)}record(e,t,s={}){this.counter++;const n={eventId:`evt_${Date.now().toString(36)}_${this.counter}`,timestamp:Date.now(),kind:e,operationId:s.operationId,sessionId:s.sessionId,detail:t,data:s.data};return this.events.push(n),this.events.length>this.cap&&this.events.splice(0,this.events.length-this.cap),n}query(e){let t=this.events;e.kind&&(t=t.filter(n=>n.kind===e.kind)),e.operationId&&(t=t.filter(n=>n.operationId===e.operationId)),e.sinceTimestamp&&(t=t.filter(n=>n.timestamp>=e.sinceTimestamp));const s=e.limit&&e.limit>0?e.limit:200;return t.slice(-s)}size(){return this.events.length}toJSON(){return[...this.events]}}class Tt{constructor(){f(this,"counter",0);f(this,"operations",new Map)}begin(e){this.counter++;const t=`op_${Date.now().toString(36)}_${this.counter}`;return this.operations.set(t,{operationId:t,tool:e,startedAt:Date.now(),status:"RUNNING",timelineEventIds:[]}),t}end(e,t,s){const n=this.operations.get(e);n&&(n.endedAt=Date.now(),n.status=t,n.relatedError=s)}attachEvent(e,t){const s=this.operations.get(e);s&&s.timelineEventIds.push(t)}trace(e){const t=this.operations.get(e);return t?{...t,durationMs:t.endedAt?t.endedAt-t.startedAt:void 0}:null}recent(e=100){return Array.from(this.operations.values()).slice(-e).map(t=>({...t,durationMs:t.endedAt?t.endedAt-t.startedAt:void 0}))}}const xe=100;class Ct{constructor(e){f(this,"sessionId");f(this,"timeline",new St);f(this,"operations",new Tt);f(this,"tabs",new Map);f(this,"activeTabId",null);f(this,"startedAt",Date.now());f(this,"snapshots",[]);f(this,"commandHistory",[]);f(this,"annotationCount",0);f(this,"projectId");f(this,"tabCounter",0);f(this,"commandCounter",0);this.sessionId=e||`sess_${Date.now().toString(36)}`}registerTab(e,t,s){const n=e!==void 0?Array.from(this.tabs.values()).find(o=>o.browserTabId===e):void 0;if(n)return n.lastSeenAt=Date.now(),n.status="OPEN",n.url=t||n.url,n.title=s||n.title,n;this.tabCounter++;const i=`stab_${this.tabCounter}_${Date.now().toString(36)}`,r={sessionTabId:i,browserTabId:e,url:t,title:s,createdAt:Date.now(),lastSeenAt:Date.now(),status:"OPEN"};return this.tabs.set(i,r),this.timeline.record("TAB_OPENED",`tab ${i} registered (${t||"no url"})`,{sessionId:this.sessionId}),r}closeTab(e){const t=this.tabs.get(e);return t?(t.status="CLOSED",t.lastSeenAt=Date.now(),this.timeline.record("TAB_CLOSED",`tab ${e} closed`,{sessionId:this.sessionId}),!0):!1}switchTab(e){const t=this.tabs.get(e);return!t||t.status==="CLOSED"?!1:(this.activeTabId=e,this.timeline.record("TAB_SWITCHED",`active tab → ${e}`,{sessionId:this.sessionId}),!0)}getTabs(){return Array.from(this.tabs.values())}getActiveTab(){if(this.activeTabId){const e=this.tabs.get(this.activeTabId);if(e&&e.status==="OPEN")return e}return Array.from(this.tabs.values()).find(e=>e.status==="OPEN")||null}markAllStale(){let e=0;for(const t of this.tabs.values())t.status==="OPEN"&&(t.status="STALE",e++);return e}captureSnapshot(e,t,s){var a,c,u;const n=e.defaultView,i=((a=e.documentElement)==null?void 0:a.outerHTML)||"",r=e.querySelectorAll('a[href], button, input, select, textarea, [role="button"]').length,o={snapshotId:`snap_${Date.now().toString(36)}_${this.snapshots.length+1}`,timestamp:Date.now(),url:((c=n==null?void 0:n.location)==null?void 0:c.href)||((u=e.location)==null?void 0:u.href)||"",title:e.title||"",viewport:{width:(n==null?void 0:n.innerWidth)||0,height:(n==null?void 0:n.innerHeight)||0,scrollX:(n==null?void 0:n.scrollX)||0,scrollY:(n==null?void 0:n.scrollY)||0,devicePixelRatio:(n==null?void 0:n.devicePixelRatio)||1},domLength:i.length,domHash:ve(i),interactiveCount:r,selectedRegions:[],extensionEnabled:t,pendingMutations:s,annotationCount:this.annotationCount};return this.snapshots.push(o),this.snapshots.length>xe&&this.snapshots.splice(0,this.snapshots.length-xe),this.timeline.record("SNAPSHOT_CREATED",`snapshot ${o.snapshotId} (dom ${o.domLength}b)`,{sessionId:this.sessionId}),o}getSnapshot(e){return e?this.snapshots.find(t=>t.snapshotId===e)||null:this.snapshots[this.snapshots.length-1]||null}listSnapshots(){return this.snapshots.map(e=>({snapshotId:e.snapshotId,timestamp:e.timestamp,url:e.url,title:e.title,domLength:e.domLength,domHash:e.domHash}))}compareSnapshots(e,t){const s=["url","title","domLength","domHash","interactiveCount","extensionEnabled","annotationCount"],n=[];for(const r of s)e[r]!==t[r]&&n.push({field:r,before:e[r],after:t[r]});(e.viewport.width!==t.viewport.width||e.viewport.height!==t.viewport.height)&&n.push({field:"viewport",before:`${e.viewport.width}x${e.viewport.height}`,after:`${t.viewport.width}x${t.viewport.height}`});const i=t.domLength-e.domLength;return{identical:n.length===0,changes:n,domDelta:{beforeLength:e.domLength,afterLength:t.domLength,delta:i},summary:n.length===0?"States are identical.":`${n.length} field(s) changed; DOM size ${i>=0?"+":""}${i} bytes.`}}recordCommand(e,t,s,n,i){this.commandCounter++;const r=`cmd_${this.commandCounter}_${Date.now().toString(36)}`;return this.commandHistory.push({commandId:r,tool:e,args:t,outcome:s,timestamp:Date.now(),durationMs:n,error:i}),this.timeline.record("COMMAND_EXECUTED",`${e} → ${s}${i?` (${i})`:""}`,{sessionId:this.sessionId,data:{commandId:r}}),r}getCommandHistory(e=100){return this.commandHistory.slice(-e)}noteAnnotations(e){this.annotationCount=e}bindProject(e){this.projectId=e}getProjectId(){return this.projectId}summary(e,t,s,n){var i,r,o;return{sessionId:this.sessionId,startedAt:this.startedAt,url:((r=(i=e.defaultView)==null?void 0:i.location)==null?void 0:r.href)||((o=e.location)==null?void 0:o.href)||"",title:e.title||"",tabs:this.getTabs(),activeTabId:this.activeTabId,viewport:{width:t.width,height:t.height,isModified:t.isModified},extensionEnabled:s,snapshotCount:this.snapshots.length,commandCount:this.commandHistory.length,annotationCount:this.annotationCount,mutationHistoryCount:n.length,timelineEventCount:this.timeline.size(),projectId:this.projectId}}}const At=l=>{var e,t;try{const s=l.getBoundingClientRect();if(s.width===0&&s.height===0)return null;const n=((t=(e=l.ownerDocument)==null?void 0:e.defaultView)==null?void 0:t.innerWidth)||1920;return s.y n*1.5?"bottom":s.x n*.8?"right":"center"}catch{return null}},It={navigation:"navigation",banner:"header",contentinfo:"footer",complementary:"sidebar",main:"main",form:"form",search:"search",region:"section",dialog:"modal",alertdialog:"modal",table:"table",list:"list",combobox:"dropdown",button:"button",link:"link",textbox:"input",checkbox:"checkbox",radio:"radio",img:"image",article:"article"},_t={nav:"navigation",header:"header",footer:"footer",aside:"sidebar",main:"main",section:"section",article:"article",form:"form",table:"table",ul:"list",ol:"list",figure:"figure",dialog:"modal",button:"button",input:"input",select:"dropdown",textarea:"textarea",canvas:"canvas",video:"video",img:"image",h1:"heading",h2:"heading",h3:"heading"};function ee(l){return l.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"").replace(/_{2,}/g,"_").slice(0,48).replace(/_$/,"")}class xt{generate(e){return this.generateFromMeta({tagName:e.tagName.toLowerCase(),role:e.getAttribute("role")||void 0,text:B(e).trim(),ariaLabel:e.getAttribute("aria-label")||void 0,stableClass:Array.from(e.classList||[]).find(t=>/^[a-z][a-z0-9-]{2,}$/i.test(t)&&!Nt.has(t)),position:At(e),nearbyHeading:this.nearbyHeading(e)})}generateFromMeta(e){const t=[],s=[],n=e.role||Rt(e.tagName);if(n){const r=It[n]||n;s.push(r),t.push(`role=${n}`)}else{const r=_t[e.tagName]||e.tagName;s.push(r),t.push(`tag=${e.tagName}`)}if(e.ariaLabel&&(s.unshift(ee(e.ariaLabel)),t.push(`aria-label="${e.ariaLabel.slice(0,30)}"`)),e.text&&e.text.length<=40){const r=ee(e.text.split(/\s+/).slice(0,3).join(" "));r&&r.length>=2&&(s.push(r),t.push(`text="${e.text.slice(0,30)}"`))}if(e.nearbyHeading){const r=ee(e.nearbyHeading.split(/\s+/).slice(0,3).join(" "));r&&!s.includes(r)&&(s.push(r),t.push(`nearby-heading="${e.nearbyHeading.slice(0,30)}"`))}e.stableClass&&s.length<3&&(s.push(ee(e.stableClass)),t.push(`class=${e.stableClass}`)),e.tagName==="input"&&(s.some(r=>r.includes("input"))||(s.push("input"),t.push("tag=input"))),s.join("_").length<12&&e.position&&(s.push(e.position),t.push(`position=${e.position}`));let i=ee(s.join("_"))||"unnamed_region";return/^\d/.test(i)&&(i=`el_${i}`),{name:i,evidence:t}}nearbyHeading(e){let t=e.parentElement;for(let n=0;t&&n<4;n++){const i=t.querySelector('h1, h2, h3, h4, [role="heading"]');if(i)return B(i).trim().slice(0,40)||null;t=t.parentElement}let s=e.previousElementSibling;for(let n=0;s&&n<4;n++){if(/^H[1-4]$/.test(s.tagName)){const i=B(s).trim();if(i)return i.slice(0,40)}s=s.previousElementSibling}return null}}const Nt=new Set(["active","open","visible","hidden","selected","disabled","container","wrapper","root","item","col","row","flex","box","main","div","span","block"]);function Rt(l){switch(l){case"nav":return"navigation";case"header":return"banner";case"footer":return"contentinfo";case"aside":return"complementary";case"main":return"main";case"form":return"form";case"table":return"table";case"button":return"button";case"a":return"link";case"input":return"textbox";case"select":return"combobox";case"textarea":return"textbox";case"img":return"img";default:return null}}const Mt=["display","position","flex-direction","grid-template-columns","width","height","background-color","color","font-size","border-radius","overflow"];class kt{constructor(){f(this,"naming",new xt)}capture(e){const t=e.ownerDocument,s=new Z(t),n=new re,i=s.generateCandidates(e),r=s.bestSelector(e),o=n.fingerprint(e);let a=e,c=0,u="self";for(let g=0;g<3;g++){const b=a.parentElement;if(!b||b===t.body||b===t.documentElement)break;if(this.isMeaningfulContainer(b)){a=b,c=g+1,u="meaningful-ancestor";break}a=b,c=g+1}if(a===e){const g=e.parentElement;g&&g!==t.body&&e.querySelectorAll("*").length<4&&(a=g,c=1,u="direct-parent-fallback")}const d=this.boundedHtml(e,6e4),h=this.boundedHtml(a,12e4);L.inspectElement(e);const p=e.getBoundingClientRect(),y=t.defaultView,v={};if(y!=null&&y.getComputedStyle){const g=y.getComputedStyle(e);for(const b of Mt){const T=g.getPropertyValue(b);T&&T!=="none"&&T!=="auto"&&(v[b]=T)}}const m=e.parentElement;return{regionHtml:d,contextHtml:h,boundary:{strategy:u,ancestorLevels:c,note:c===0?"Region captured standalone (no meaningful ancestor within 3 levels).":`Context includes ${c} ancestor level(s) up to a meaningful container.`},selectorCandidates:i,bestSelector:r.selector,xpath:s.buildXPath(e),fingerprintHash:o.hash,dimensions:{width:Math.round(p.width),height:Math.round(p.height)},position:{x:Math.round(p.x),y:Math.round(p.y)},relevantStyles:v,parentInfo:m?{tag:m.tagName.toLowerCase(),selector:Ot(m),text:B(m).slice(0,60)}:void 0,childrenCount:e.children.length,childTags:Array.from(e.children).slice(0,12).map(g=>g.tagName.toLowerCase()),nameHint:this.naming.generate(e),fingerprintVolatility:o.volatilityRisk,volatilityReasons:o.volatilityReasons}}isMeaningfulContainer(e){const t=e.tagName.toLowerCase();if(["section","article","aside","main","nav","header","footer","form"].includes(t)||e.hasAttribute("id")||e.hasAttribute("data-testid")||e.getAttribute("role")||e.children.length>1&&e.querySelector(":scope > *:nth-child(3)"))return!0;const s=e.getAttribute("style")||"";return!!(s.includes("grid")||s.includes("flex"))}boundedHtml(e,t){const s=e.outerHTML;return s.length<=t?s:s.slice(0,t)+` -`}}function Ot(l){try{return new Z(l.ownerDocument).bestSelector(l).selector}catch{return l.tagName.toLowerCase()}}class Lt{constructor(e){f(this,"nodeRegistry");f(this,"snapshotEngine");f(this,"picker");f(this,"interactionEngine");f(this,"observer");f(this,"mutationEngines",new WeakMap);f(this,"viewportControllers",new WeakMap);f(this,"targetingEngines",new WeakMap);f(this,"jsEngine",new Fe);f(this,"fingerprintEngine",new re);f(this,"humanInteraction",new rt);f(this,"session",new Ct);f(this,"simulationTabs",[]);f(this,"simulationTabCounter",0);f(this,"simulationExtensions",[{id:"teledom@teledom",name:"TeleDOM Browser Intelligence Platform",version:"4.1.0",description:"The TeleDOM platform extension itself",enabled:!0,installType:"development",isApp:!1}]);f(this,"regionCapture",new kt);this.nodeRegistry=e||new z;const t=new se,s=new oe;this.snapshotEngine=new me(this.nodeRegistry,t,s),this.picker=new Ue({nodeRegistry:this.nodeRegistry}),this.interactionEngine=new De(this.nodeRegistry),this.observer=new Pe(this.nodeRegistry),this.picker.initGlobalShortcutListener(),this.interactionEngine.setTimingHook(async n=>{const i=this.humanInteraction.delay(n);i>0&&await new Promise(r=>setTimeout(r,i))})}getMutationEngine(e){let t=this.mutationEngines.get(e);return t||(t=new He(e,this.nodeRegistry),this.mutationEngines.set(e,t)),t}getViewportController(e){let t=this.viewportControllers.get(e);return t||(t=new ze(e),this.viewportControllers.set(e,t)),t}getTargetingEngine(e){let t=this.targetingEngines.get(e);return t||(t=new st(e,this.nodeRegistry),this.targetingEngines.set(e,t)),t}isSimulation(){return typeof globalThis.__FORENSIC_SIMULATION__<"u"}getPicker(){return this.picker}getInteractionEngine(){return this.interactionEngine}getObserver(){return this.observer}getNodeRegistry(){return this.nodeRegistry}async handleCommand(e,t=typeof document<"u"?document:{}){var o,a,c,u,d,h,p,y,v;const s=Date.now(),{id:n,command:i,payload:r}=e;try{switch(i){case"LIVE_PAGE_INSPECT":{const m=L.inspectPage(t);return this.success(n,i,m,s)}case"LIVE_ELEMENT_INSPECT":{const m=this.resolveTarget(r,t),g=L.inspectElement(m,this.nodeRegistry);return this.success(n,i,g,s)}case"GET_SELECTED_ELEMENT":{const m=this.picker.getLastSelectedElement();return this.success(n,i,m,s)}case"ELEMENT_PICKER_START":return this.picker.startPicker(),this.success(n,i,{pickerActive:!0},s);case"ELEMENT_PICKER_STOP":return this.picker.stopPicker(),this.success(n,i,{pickerActive:!1},s);case"LIVE_ELEMENT_INTERACT":{const m=r,g=await this.interactionEngine.interact(m,t);return this.success(n,i,g,s)}case"ELEMENT_OBSERVATION_START":{const m=this.resolveTarget(r,t),g=this.observer.startObservation(m,t);return this.success(n,i,g,s)}case"ELEMENT_OBSERVATION_STOP":{const m=this.observer.stopObservation(t);return this.success(n,i,m,s)}case"LIVE_DOM_SNAPSHOT":{if(((r==null?void 0:r.format)||"html")==="html"){const b=((o=t.documentElement)==null?void 0:o.outerHTML)||"";return this.success(n,i,{html:b},s)}const g=this.snapshotEngine.captureSnapshot(t,"live_session");return this.success(n,i,g,s)}case"LIVE_DOM_SUBTREE":{const m=this.resolveTarget(r,t),g=m.outerHTML||"",b=L.inspectElement(m,this.nodeRegistry);return this.success(n,i,{html:g,element:b},s)}case"GET_ELEMENT_VISUAL_STATE":{const m=this.resolveTarget(r,t),g=L.inspectVisualState(m);return this.success(n,i,g,s)}case"LIVE_PAGE_SCREENSHOT":case"LIVE_ELEMENT_SCREENSHOT":{const m=await this.handleScreenshotCapture(i,r,t);return this.success(n,i,m,s)}case"GET_TAB_CONSOLE_LOGS":{const{level:m,searchQuery:g,limit:b=100,clearAfterRead:T}=r||{};let w=typeof window<"u"&&window.__FORENSIC_CONSOLE_BUFFER__||[];if(m&&m!=="all"&&(w=w.filter(E=>E.level===m)),g){const E=String(g).toLowerCase();w=w.filter(C=>{var N,I;return((N=C.text)==null?void 0:N.toLowerCase().includes(E))||((I=C.source)==null?void 0:I.toLowerCase().includes(E))})}return b>0&&(w=w.slice(-b)),T&&typeof window<"u"&&window.__FORENSIC_CONSOLE_BUFFER__&&(window.__FORENSIC_CONSOLE_BUFFER__.length=0),this.success(n,i,{url:typeof window<"u"?window.location.href:"",title:t.title||"",totalCaptured:typeof window<"u"&&((a=window.__FORENSIC_CONSOLE_BUFFER__)==null?void 0:a.length)||w.length,returnedCount:w.length,logs:w},s)}case"GET_TAB_NETWORK_REQUESTS":{const{method:m,searchQuery:g,status:b,onlyErrors:T,limit:w=100,clearAfterRead:E}=r||{};let C=typeof window<"u"&&window.__FORENSIC_NETWORK_BUFFER__||[];if(m&&(C=C.filter(N=>{var I;return((I=N.method)==null?void 0:I.toUpperCase())===String(m).toUpperCase()})),b&&(C=C.filter(N=>N.status===Number(b))),T&&(C=C.filter(N=>N.error||N.status&&N.status>=400)),g){const N=String(g).toLowerCase();C=C.filter(I=>{var R;return(R=I.url)==null?void 0:R.toLowerCase().includes(N)})}return w>0&&(C=C.slice(-w)),E&&typeof window<"u"&&window.__FORENSIC_NETWORK_BUFFER__&&(window.__FORENSIC_NETWORK_BUFFER__.length=0),this.success(n,i,{url:typeof window<"u"?window.location.href:"",title:t.title||"",totalCaptured:typeof window<"u"&&((c=window.__FORENSIC_NETWORK_BUFFER__)==null?void 0:c.length)||C.length,returnedCount:C.length,requests:C},s)}case"CLOSE_TAB":{if(typeof globalThis.chrome<"u"&&((u=globalThis.chrome.runtime)!=null&&u.sendMessage)){const m=await new Promise(g=>{globalThis.chrome.runtime.sendMessage({type:"BROWSER_COMMAND_REQUEST",id:n,command:i,payload:r},b=>g(b))});if(m)return m}return this.isSimulation()?this.simulationCloseTab(r,t,n,i,s):typeof window<"u"?(setTimeout(()=>window.close(),100),this.success(n,i,{closed:!0,url:window.location.href,title:t.title},s)):this.success(n,i,{closed:!0},s)}case"RELOAD_TAB":{if(typeof globalThis.chrome<"u"&&((d=globalThis.chrome.runtime)!=null&&d.sendMessage)){const m=await new Promise(g=>{globalThis.chrome.runtime.sendMessage({type:"BROWSER_COMMAND_REQUEST",id:n,command:i,payload:r},b=>g(b))});if(m)return m}if(this.isSimulation()){const m=(r==null?void 0:r.mode)||"soft";return this.session.timeline.record("NAVIGATED",`tab reloaded (${m} mode)`),this.success(n,i,{reloaded:!0,mode:m,simulated:!0,url:((p=(h=t.defaultView)==null?void 0:h.location)==null?void 0:p.href)||"",title:t.title,note:"Node simulation context: DOM fixture retained; no real navigation occurs."},s)}return typeof window<"u"?(setTimeout(()=>window.location.reload(),100),this.success(n,i,{reloaded:!0,url:window.location.href,title:t.title},s)):this.success(n,i,{reloaded:!0},s)}case"OPEN_TAB":case"LIST_TABS":case"FOCUS_TAB":case"LIST_EXTENSIONS":case"RELOAD_EXTENSION":case"SET_EXTENSION_ENABLED":case"TOGGLE_EXTENSION":{if(this.isSimulation())return this.handleSimulationBackgroundCommand(n,i,r,t,s);if(typeof globalThis.chrome<"u"&&((y=globalThis.chrome.runtime)!=null&&y.sendMessage)){const m=await new Promise(g=>{globalThis.chrome.runtime.sendMessage({type:"BROWSER_COMMAND_REQUEST",id:n,command:i,payload:r},b=>g(b))});if(m)return m}return this.error(n,i,"BACKGROUND_EXECUTION_FAILED",`Command ${i} requires Chrome extension runtime`,s)}case"RESIZE_VIEWPORT":{const m=this.getViewportController(t);let g;if(r!=null&&r.preset)g=m.applyPreset(r.preset);else{const b=Number(r==null?void 0:r.width)||1280,T=Number(r==null?void 0:r.height)||800;g=m.resize(b,T)}return this.session.timeline.record("RESIZED",`viewport → ${g.applied.width}x${g.applied.height}`),this.success(n,i,g,s)}case"RESET_VIEWPORT":{const g=this.getViewportController(t).reset();return this.session.timeline.record("RESIZED",`viewport restored to ${g.applied.width}x${g.applied.height}`),this.success(n,i,g,s)}case"GET_VIEWPORT_STATE":{const m=this.getViewportController(t);return this.success(n,i,m.state(),s)}case"RUN_RESPONSIVE_TEST":{const m=this.getViewportController(t),g=(r==null?void 0:r.sizes)||Ut(),b=m.runResponsiveTest(g,{restore:(r==null?void 0:r.restore)!==!1});return this.success(n,i,b,s)}case"EMULATE_DEVICE":{const g=this.getViewportController(t).emulateDevice((r==null?void 0:r.device)||"pixel-7");return this.success(n,i,g,s)}case"EXECUTE_JS":case"EXECUTE_JS_AND_CAPTURE_CHANGES":{const m=String((r==null?void 0:r.code)||"");if(!m.trim())return this.error(n,i,"SCRIPT_EMPTY","payload.code is required.",s);const g=await this.jsEngine.execute(t,m,{timeoutMs:r==null?void 0:r.timeoutMs,world:(r==null?void 0:r.world)==="MAIN"?"MAIN":"ISOLATED"});return this.session.timeline.record("SCRIPT_EXECUTED",`${g.status} (${g.durationMs}ms)`),this.success(n,i,g,s)}case"DOM_MUTATE":{const g=this.getMutationEngine(t).mutate(r);return this.session.timeline.record("DOM_MUTATED",`${g.operation} on ${g.before.selector} → ${g.success?"OK":g.error}`),this.success(n,i,g,s)}case"DOM_MUTATE_TRANSACTION":{const m=this.getMutationEngine(t),g=(r==null?void 0:r.mode)||"begin";try{if(g==="begin"){const b=m.beginTransaction();return this.success(n,i,{transactionId:b,mode:g,open:!0},s)}if(g==="commit"){const b=m.commitTransaction();return this.session.timeline.record("DOM_MUTATED",`transaction ${b.transactionId} committed (${b.steps.length} steps)`),this.success(n,i,{...b,mode:g},s)}if(g==="rollback"){const b=m.rollbackTransaction(r==null?void 0:r.reason);return this.session.timeline.record("MUTATION_UNDONE",`transaction ${b.transactionId} rolled back`),this.success(n,i,{...b,mode:g},s)}return this.error(n,i,"INVALID_MODE",`mode must be begin|commit|rollback, got "${g}"`,s)}catch(b){return this.error(n,i,"DOM_MUTATION_FAILED",b.message,s)}}case"UNDO_DOM_MUTATION":{const g=this.getMutationEngine(t).undo();return g.success&&this.session.timeline.record("MUTATION_UNDONE",g.message),this.success(n,i,g,s)}case"REDO_DOM_MUTATION":{const g=this.getMutationEngine(t).redo();return g.success&&this.session.timeline.record("MUTATION_REDONE",g.message),this.success(n,i,g,s)}case"GET_MUTATION_HISTORY":{const m=this.getMutationEngine(t);return this.success(n,i,{entries:m.getHistory((r==null?void 0:r.limit)||100),undoDepth:m.getUndoDepth(),redoDepth:m.getRedoDepth(),openTransactionId:m.getOpenTransactionId()},s)}case"PREVIEW_DOM_MUTATION":{const g=this.getMutationEngine(t).preview(r);return this.success(n,i,g,s)}case"GENERATE_ELEMENT_TARGET":{const g=this.getTargetingEngine(t).resolveAndBuild((r==null?void 0:r.target)||(r==null?void 0:r.selector)||"");return"error"in g?this.error(n,i,"TARGET_NOT_FOUND",g.error,s):this.success(n,i,g.target,s)}case"RECOVER_SELECTOR":{const m=new it(t),g=(r==null?void 0:r.snapshot)||{},b=m.recover((r==null?void 0:r.selector)||"",g);return this.success(n,i,b,s)}case"GET_ELEMENT_ANCESTRY":{const m=this.resolveTarget(r,t);return this.success(n,i,Dt(m,t),s)}case"GET_ELEMENT_FINGERPRINT":{const m=this.resolveTarget(r,t),g=this.fingerprintEngine.fingerprint(m);return this.success(n,i,g,s)}case"GET_ELEMENT_RELATIONSHIPS":{const m=this.resolveTarget(r,t);return this.success(n,i,$t(m,t),s)}case"GET_ELEMENT_ACCESSIBILITY":{const m=this.resolveTarget(r,t);return this.success(n,i,qt(m),s)}case"GET_COMPUTED_STYLE":{const m=this.resolveTarget(r,t),g=t.defaultView;if(!(g!=null&&g.getComputedStyle))return this.error(n,i,"STYLE_UNAVAILABLE","getComputedStyle is unavailable in this context.",s);const b=g.getComputedStyle(m),T=Array.isArray(r==null?void 0:r.properties)&&r.properties.length?r.properties:["display","position","color","background-color","font-size","font-family","width","height","margin","padding","border","z-index","opacity","visibility","overflow","flex-direction","grid-template-columns"],w={};for(const E of T)w[E]=b.getPropertyValue(E);return this.success(n,i,{selector:L.inspectElement(m,this.nodeRegistry).bestSelector,styles:w},s)}case"ANALYZE_DOM":{const m=String((r==null?void 0:r.analyzer)||"");if(!m)return this.error(n,i,"ANALYZER_REQUIRED",'payload.analyzer is required (e.g. "analyze_forms").',s);const g=vt(m,t,r);return g.count===0&&g.warnings.length===0&&g.items.length===0&&g.summary.startsWith("Unknown analyzer")?this.error(n,i,"UNKNOWN_ANALYZER",g.summary,s):this.success(n,i,g,s)}case"DRAG_ELEMENT":{const m=this.resolveTarget(r==null?void 0:r.source,t),g=r!=null&&r.target?this.resolveTarget(r==null?void 0:r.target,t):null,b=await this.performDrag(m,g,r==null?void 0:r.offsets,t);return this.success(n,i,b,s)}case"SET_INPUT_CHECKED":{const g=this.resolveTarget(r,t);if(g.type!=="checkbox"&&g.type!=="radio")return this.error(n,i,"INPUT_TYPE_UNSUPPORTED",`Target input type "${g.type}" is not checkbox/radio.`,s);const b=g.checked;g.checked=(r==null?void 0:r.checked)!==!1;const T=[];for(const w of["input","change"])try{g.dispatchEvent(new t.defaultView.Event(w,{bubbles:!0})),T.push(w)}catch{}if(g.type==="radio"&&g.name)for(const w of Array.from(t.querySelectorAll(`input[type=radio][name="${g.name}"]`)))w!==g&&(w.checked=!1);return this.success(n,i,{success:!0,selector:L.inspectElement(g,this.nodeRegistry).bestSelector,inputType:g.type,checkedBefore:b,checkedAfter:g.checked,eventsFired:T},s)}case"PRESS_KEYBOARD_SHORTCUT":{const m=Array.isArray(r==null?void 0:r.keys)?r.keys:String((r==null?void 0:r.keys)||"Enter").split("+"),g=r!=null&&r.target?this.resolveTarget(r==null?void 0:r.target,t):t.activeElement||t.body;typeof g.focus=="function"&&g.focus();const b=[],T=t.defaultView;for(const w of m)for(const E of["keydown","keyup"])try{g.dispatchEvent(new((T==null?void 0:T.KeyboardEvent)||KeyboardEvent)(E,{key:w.trim(),bubbles:!0,cancelable:!0,ctrlKey:m.some(C=>/^(ctrl|control|cmd|meta)$/i.test(C))&&w!==m.find(C=>/^(ctrl|control|cmd|meta)$/i.test(C)),shiftKey:m.some(C=>/^shift$/i.test(C))&&w!=="Shift",altKey:m.some(C=>/^alt$/i.test(C))&&w!=="Alt"})),b.push(`${E}:${w}`)}catch{}return this.success(n,i,{success:!0,keys:m,targetSelector:L.inspectElement(g,this.nodeRegistry).bestSelector,eventsFired:b},s)}case"SCROLL_PAGE":{const m=t.defaultView;if(!m)return this.error(n,i,"NO_WINDOW","No window available for scrolling.",s);const g={x:m.scrollX||0,y:m.scrollY||0};let b;if(r!=null&&r.target||r!=null&&r.selector){const w=this.resolveTarget((r==null?void 0:r.target)||(r==null?void 0:r.selector),t);(v=w.scrollIntoView)==null||v.call(w,{behavior:(r==null?void 0:r.behavior)||"auto",block:"center"}),b=L.inspectElement(w,this.nodeRegistry).bestSelector}else m.scrollBy(Number(r==null?void 0:r.x)||0,Number(r==null?void 0:r.y)||0);const T={x:m.scrollX||0,y:m.scrollY||0};return this.success(n,i,{success:!0,scrollBefore:g,scrollAfter:T,requested:{x:Number(r==null?void 0:r.x)||0,y:Number(r==null?void 0:r.y)||0},targetSelector:b},s)}case"WAIT_FOR_CONDITION":return await this.waitForCondition(t,r||{},s,n,i);case"GET_PAGE_STATE":case"CAPTURE_PAGE_STATE":{const m=this.session.captureSnapshot(t,!0,this.getMutationEngine(t).getUndoDepth());return this.success(n,i,m,s)}case"CAPTURE_REGION":{const m=this.resolveTarget((r==null?void 0:r.target)||(r==null?void 0:r.selector),t),g=this.regionCapture.capture(m);return this.success(n,i,g,s)}case"GET_SIMULATION_TAB_STATE":return this.isSimulation()?this.success(n,i,{simulated:!0,tabs:this.simulationTabs,sessionSummary:this.session.getTabs()},s):this.error(n,i,"NOT_SIMULATION","Simulation tab state is only available in the Node simulation context.",s);default:return this.error(n,i,"UNKNOWN_COMMAND",`Unsupported command '${i}'`,s)}}catch(m){return this.error(n,i,"COMMAND_EXECUTION_FAILED",m.message,s,m.details)}}resolveTarget(e,t){if(!e)throw new Error("Target specifier must be provided");return typeof e=="string"?this.interactionEngine.resolveTarget({selector:e},t):typeof e=="number"?this.interactionEngine.resolveTarget({nodeId:e},t):this.interactionEngine.resolveTarget(e,t)}async performDrag(e,t,s,n){const i=n.defaultView,r=[],o=(p,y,v={})=>{try{const m=(i==null?void 0:i.MouseEvent)||(typeof MouseEvent<"u"?MouseEvent:null);m&&(p.dispatchEvent(new m(y,{bubbles:!0,cancelable:!0,...v})),r.push(y))}catch{}},a=e.getBoundingClientRect(),c=a.x+a.width/2,u=a.y+a.height/2;let d=c+((s==null?void 0:s.x)||0),h=u+((s==null?void 0:s.y)||0);if(t){const p=t.getBoundingClientRect();d=p.x+p.width/2,h=p.y+p.height/2}return o(e,"pointerdown",{button:1,clientX:c,clientY:u}),o(e,"mousedown",{button:1,clientX:c,clientY:u}),o(e,"dragstart",{clientX:c,clientY:u}),t&&(o(t,"dragenter",{clientX:d,clientY:h}),o(t,"dragover",{clientX:d,clientY:h}),o(t,"drop",{clientX:d,clientY:h})),o(e,"dragend",{clientX:d,clientY:h}),o(e,"pointerup",{button:1,clientX:d,clientY:h}),o(e,"mouseup",{button:1,clientX:d,clientY:h}),{success:r.length>0,sourceSelector:L.inspectElement(e,this.nodeRegistry).bestSelector,targetSelector:t?L.inspectElement(t,this.nodeRegistry).bestSelector:"(offset drop)",eventsFired:r,finalPosition:{x:Math.round(d),y:Math.round(h)},html5DndUsed:r.includes("dragstart")}}async waitForCondition(e,t,s,n,i){var p,y;const r=t.kind||"dom_stable",o=Math.min(Math.max(Number(t.timeoutMs)||5e3,100),3e4),a=Math.min(Math.max(Number(t.pollIntervalMs)||100,20),1e3),c=Date.now(),u=()=>{var v,m,g,b,T;switch(r){case"dom_stable":return{satisfied:!0,detail:`dom length ${((v=e.documentElement)==null?void 0:v.outerHTML.length)||0}`};case"selector_present":{const w=t.selector?e.querySelectorAll(t.selector).length:0;return{satisfied:w>0,detail:`"${t.selector}" matches ${w} element(s)`}}case"selector_visible":{if(!t.selector)return{satisfied:!1,detail:"no selector supplied"};const w=e.querySelector(t.selector);if(!w)return{satisfied:!1,detail:`"${t.selector}" not present`};try{const E=L.inspectElement(w).visibility.isVisible;return{satisfied:E,detail:`visibility=${E}`}}catch{return{satisfied:!1,detail:"inspection failed"}}}case"selector_absent":{const w=t.selector?e.querySelectorAll(t.selector).length:0;return{satisfied:w===0,detail:`"${t.selector}" matches ${w} element(s)`}}case"text_present":{const w=((m=e.body)==null?void 0:m.innerText)||((g=e.body)==null?void 0:g.textContent)||"",E=t.text?w.includes(String(t.text)):!1;return{satisfied:E,detail:`text "${String(t.text).slice(0,30)}" ${E?"found":"not found"}`}}case"url_contains":{const w=((T=(b=e.defaultView)==null?void 0:b.location)==null?void 0:T.href)||"";return{satisfied:t.text?w.includes(String(t.text)):!1,detail:w}}case"element_count":{const w=t.selector?e.querySelectorAll(t.selector).length:0,E=Number(t.count)||0;return{satisfied:w===E,detail:`${w}/${E} elements`}}case"readiness_state":return{satisfied:e.readyState===(t.state||"complete"),detail:`readyState=${e.readyState}`};default:return{satisfied:!1,detail:`unknown condition kind "${r}"`}}};if(r==="dom_stable"){let v=((p=e.documentElement)==null?void 0:p.outerHTML.length)||0,m=!1,g=0;for(;Date.now()-c setTimeout(w,a));const T=((y=e.documentElement)==null?void 0:y.outerHTML.length)||0;if(g++,T===v){m=!0;break}v=T}const b=Date.now()-c;return m&&this.session.timeline.record("WAIT_SATISFIED",`dom_stable after ${b}ms (${g} polls)`),this.success(n,i,{satisfied:m,condition:r,waitedMs:b,timeoutMs:o,detail:`dom length ${v}, ${g} polls`},s)}let d=u();for(;!d.satisfied&&Date.now()-c setTimeout(v,a)),d=u();const h=Date.now()-c;return d.satisfied&&this.session.timeline.record("WAIT_SATISFIED",`${r} after ${h}ms`),this.success(n,i,{satisfied:d.satisfied,condition:r,waitedMs:h,timeoutMs:o,detail:d.detail},s)}simulationCloseTab(e,t,s,n,i){const r=Number(e==null?void 0:e.tabId),o=Number.isFinite(r)?this.simulationTabs.findIndex(c=>c.browserTabId===r):this.simulationTabs.findIndex(c=>c.active);if(o<0)return this.error(s,n,"TAB_NOT_FOUND",`No simulated tab matches tabId=${r}`,i);const a=this.simulationTabs.splice(o,1)[0];return this.session.closeTab(a.sessionTabId),a.active&&this.simulationTabs.length&&(this.simulationTabs[0].active=!0,this.session.switchTab(this.simulationTabs[0].sessionTabId)),this.success(s,n,{closed:!0,closedTab:{id:a.browserTabId,url:a.url,title:a.title},simulated:!0,remaining:this.simulationTabs.length},i)}handleSimulationBackgroundCommand(e,t,s,n,i){const r=()=>{var o,a;if(!this.simulationTabs.length){this.simulationTabCounter++;const c={sessionTabId:`stab_${this.simulationTabCounter}`,browserTabId:this.simulationTabCounter,url:((a=(o=n.defaultView)==null?void 0:o.location)==null?void 0:a.href)||"about:blank",title:n.title||"Simulated Tab",active:!0,createdAt:Date.now()};this.simulationTabs.push(c),this.session.registerTab(c.browserTabId,c.url,c.title),this.session.switchTab(c.sessionTabId)}};switch(t){case"LIST_TABS":return r(),this.success(e,t,{simulated:!0,environment:"node-simulation",tabs:this.simulationTabs.map((o,a)=>({id:o.browserTabId,index:a,windowId:1,title:o.title,url:o.url,active:o.active,status:"complete",pinned:!1,audited:!1})),note:"Deterministic simulated tab state — a real browser tab list requires the Chrome extension connection."},i);case"OPEN_TAB":{const o=String((s==null?void 0:s.url)||"about:blank");this.simulationTabCounter++;const a={sessionTabId:`stab_${this.simulationTabCounter}`,browserTabId:this.simulationTabCounter,url:o,title:(s==null?void 0:s.title)||`Simulated Tab ${this.simulationTabCounter}`,active:!0,createdAt:Date.now()};this.simulationTabs.forEach(u=>u.active=!1),this.simulationTabs.push(a);const c=this.session.registerTab(a.browserTabId,o,a.title);return this.session.switchTab(c.sessionTabId),this.session.timeline.record("TAB_OPENED",`simulation tab ${a.browserTabId} → ${o}`),this.success(e,t,{opened:!0,tabId:a.browserTabId,url:o,simulated:!0,totalTabs:this.simulationTabs.length},i)}case"FOCUS_TAB":{r();const o=Number(s==null?void 0:s.tabId),a=this.simulationTabs.find(c=>c.browserTabId===o)||this.simulationTabs[0];return a?(this.simulationTabs.forEach(c=>c.active=!1),a.active=!0,this.session.switchTab(a.sessionTabId),this.session.timeline.record("TAB_SWITCHED",`simulation tab ${a.browserTabId} focused`),this.success(e,t,{focused:!0,tabId:a.browserTabId,url:a.url,simulated:!0},i)):this.error(e,t,"TAB_NOT_FOUND",`No simulated tab with tabId=${o}`,i)}case"LIST_EXTENSIONS":return this.success(e,t,{simulated:!0,extensions:this.simulationExtensions.map(o=>({...o,permissions:["activeTab","scripting","storage","tabs","management"]})),note:"Deterministic simulated extension state."},i);case"SET_EXTENSION_ENABLED":{const o=String((s==null?void 0:s.extensionId)||""),a=this.simulationExtensions.find(c=>c.id===o||c.name.toLowerCase().includes(o.toLowerCase()));return a?(a.enabled=!!(s!=null&&s.enabled),this.session.timeline.record("EXTENSION_STATE_CHANGED",`${a.id} → ${a.enabled?"enabled":"disabled"}`),this.success(e,t,{extensionId:a.id,enabled:a.enabled,simulated:!0},i)):this.error(e,t,"EXTENSION_NOT_FOUND",`No simulated extension matches "${o}". Known: ${this.simulationExtensions.map(c=>c.id).join(", ")}`,i)}case"TOGGLE_EXTENSION":{const o=String((s==null?void 0:s.extensionId)||""),a=this.simulationExtensions.find(c=>c.id===o||c.name.toLowerCase().includes(o.toLowerCase()));return a?(a.enabled=!a.enabled,this.session.timeline.record("EXTENSION_STATE_CHANGED",`${a.id} → ${a.enabled?"enabled":"disabled"}`),this.success(e,t,{extensionId:a.id,enabled:a.enabled,simulated:!0},i)):this.error(e,t,"EXTENSION_NOT_FOUND",`No simulated extension matches "${o}".`,i)}case"RELOAD_EXTENSION":{const o=String((s==null?void 0:s.extensionId)||this.simulationExtensions[0].id),a=this.simulationExtensions.find(c=>c.id===o||c.name.toLowerCase().includes(o.toLowerCase()));return a?this.success(e,t,{reloaded:!0,extensionId:a.id,simulated:!0,note:"Simulated reload: extension state preserved."},i):this.error(e,t,"EXTENSION_NOT_FOUND",`No simulated extension matches "${o}".`,i)}default:return this.error(e,t,"UNKNOWN_COMMAND",`Unhandled simulation command '${t}'`,i)}}async handleScreenshotCapture(e,t,s){var y,v,m,g,b;const n=s.defaultView||(typeof window<"u"?window:{}),i=Date.now(),r=`scr_${i}_${Math.random().toString(36).slice(2,6)}`,o=n.devicePixelRatio||1,a={width:n.innerWidth||((y=s.documentElement)==null?void 0:y.clientWidth)||1920,height:n.innerHeight||((v=s.documentElement)==null?void 0:v.clientHeight)||1080,scrollX:n.scrollX||n.pageXOffset||0,scrollY:n.scrollY||n.pageYOffset||0,devicePixelRatio:o};let c,u,d,h={width:a.width,height:a.height};if(e==="LIVE_ELEMENT_SCREENSHOT"){const T=this.resolveTarget(t,s),w=L.inspectElement(T,this.nodeRegistry);c=w.bestSelector,u=((m=w.forensics)==null?void 0:m.logicalNodeId)||void 0,d={x:w.bounds.x,y:w.bounds.y,width:w.bounds.width,height:w.bounds.height},h={width:Math.max(1,Math.round(w.bounds.width*o)),height:Math.max(1,Math.round(w.bounds.height*o))}}let p=(t==null?void 0:t.dataUrl)||"";if(e==="LIVE_ELEMENT_SCREENSHOT"&&p&&d&&typeof Image<"u")try{const T=await new Promise(w=>{const E=new Image;E.onload=()=>{try{const C=s.createElement("canvas"),N=Math.max(0,Math.floor(d.x*o)),I=Math.max(0,Math.floor(d.y*o)),R=Math.max(1,Math.floor(d.width*o)),x=Math.max(1,Math.floor(d.height*o));C.width=R,C.height=x;const q=C.getContext("2d");if(q){q.drawImage(E,N,I,R,x,0,0,R,x),w(C.toDataURL("image/png"));return}}catch{}w(p)},E.onerror=()=>w(p),E.src=p});T&&(p=T)}catch{}if(!p){const T=e==="LIVE_ELEMENT_SCREENSHOT"?Math.max(120,h.width||320):Math.max(800,a.width||1280),w=e==="LIVE_ELEMENT_SCREENSHOT"?Math.max(60,h.height||180):Math.max(600,a.height||800);p=fe.createDataUrl({width:T,height:w,backgroundColor:e==="LIVE_ELEMENT_SCREENSHOT"?[30,41,59,255]:[15,23,42,255],headerColor:[56,189,248,255],borderColor:[99,102,241,255],label:c||(e==="LIVE_ELEMENT_SCREENSHOT"?"Element Screenshot":"Page Screenshot")})}return{screenshotId:r,timestamp:i,url:((g=n.location)==null?void 0:g.href)||((b=s.location)==null?void 0:b.href)||"",viewport:a,targetSelector:c,targetNodeId:u,targetBounds:d,dataUrl:p,imageFormat:"png",dimensions:h,captureType:e==="LIVE_ELEMENT_SCREENSHOT"?"ELEMENT":"FULL_PAGE"}}success(e,t,s,n){return{id:e,command:t,success:!0,data:s,timestamp:Date.now(),durationMs:Date.now()-n}}error(e,t,s,n,i,r){return{id:e,command:t,success:!1,error:{code:s,message:n,details:r},timestamp:Date.now(),durationMs:Date.now()-i}}}function Dt(l,e){const t=[];let s=l.parentElement,n=1;for(;s&&n<=10;){const d=s.parentElement,h=d?Array.from(d.children).filter(p=>p.tagName===s.tagName):[];t.push({tag:s.tagName.toLowerCase(),selector:V(s),role:s.getAttribute("role")||void 0,text:K(s).slice(0,40),childIndex:h.length?h.indexOf(s)+1:1,siblingCount:d?Array.from(d.children).length:0,distance:n}),s=s.parentElement,n++}const i=l.parentElement,r=[];if(i){const d=Array.from(i.children),h=d.indexOf(l);for(let p=h-1;p>=0&&p>=h-5;p--)r.push({tag:d[p].tagName.toLowerCase(),selector:V(d[p]),role:d[p].getAttribute("role")||void 0,text:K(d[p]).slice(0,30),position:"before",distance:h-p});for(let p=h+1;p {o=Math.max(o,h);for(const p of Array.from(d.children))a.push(p.tagName.toLowerCase()),p.matches('a[href], button, input, select, textarea, [role="button"], [onclick]')&&c.push(V(p)),h<6&&u(p,h+1)};return u(l,1),{selector:V(l),ancestors:t,siblings:r,descendants:{count:l.querySelectorAll("*").length,maxDepth:o,tags:Array.from(new Set(a)).slice(0,30),interactive:c.slice(0,30)}}}function $t(l,e){const t=[{id:"self",selector:V(l),tag:l.tagName.toLowerCase(),role:l.getAttribute("role")||void 0,label:K(l).slice(0,30)||l.tagName.toLowerCase(),relationship:"self",depth:0}],s=[];let n=l.parentElement,i=1;for(;n&&i<=4;){const o=`ancestor_${i}`;t.push({id:o,selector:V(n),tag:n.tagName.toLowerCase(),role:n.getAttribute("role")||void 0,label:K(n).slice(0,30)||n.tagName.toLowerCase(),relationship:"parent",depth:i}),s.push({from:o,to:i===1?"self":`ancestor_${i-1}`,relation:"parent-of"}),n=n.parentElement,i++}for(const o of Array.from(l.children).slice(0,12)){const a=`child_${t.length}`;t.push({id:a,selector:V(o),tag:o.tagName.toLowerCase(),role:o.getAttribute("role")||void 0,label:K(o).slice(0,30)||o.tagName.toLowerCase(),relationship:"child",depth:1}),s.push({from:"self",to:a,relation:"contains"})}const r=l.parentElement;if(r)for(const o of Array.from(r.children).slice(0,12)){if(o===l)continue;const a=`sibling_${t.length}`;t.push({id:a,selector:V(o),tag:o.tagName.toLowerCase(),role:o.getAttribute("role")||void 0,label:K(o).slice(0,30)||o.tagName.toLowerCase(),relationship:"sibling",depth:1}),s.push({from:"self",to:a,relation:"sibling-of"})}return{rootSelector:V(l),nodes:t,edges:s}}function qt(l){const e={};for(const v of Array.from(l.attributes))v.name.startsWith("aria-")&&(e[v.name]=v.value);const t=K(l).trim(),s=l.getAttribute("aria-label"),n=l.getAttribute("aria-labelledby");let i;n&&(i=n.split(/\s+/).map(m=>{var g,b,T;return(T=(b=(g=l.ownerDocument)==null?void 0:g.getElementById(m))==null?void 0:b.textContent)==null?void 0:T.trim()}).filter(Boolean).join(" ").slice(0,60)||void 0);const r=l.getAttribute("title"),o=l.tagName.toLowerCase(),a=[];let c="";s?(c=s,a.push("aria-label")):i?(c=i,a.push("aria-labelledby")):t?(c=t.slice(0,60),a.push("text content")):r&&(c=r,a.push("title"));const u=[];(l.disabled||l.hasAttribute("disabled"))&&u.push("disabled"),l.checked&&u.push("checked");const d=l;d.tagName==="SELECT"&&typeof d.selectedOptions<"u"&&d.selectedOptions.length>0&&u.push("selected"),l.getAttribute("aria-expanded")&&u.push(`expanded=${l.getAttribute("aria-expanded")}`),l.getAttribute("aria-pressed")&&u.push(`pressed=${l.getAttribute("aria-pressed")}`),l.getAttribute("aria-hidden")==="true"&&u.push("hidden"),l.hasAttribute("required")&&u.push("required"),l.readOnly&&u.push("readonly");const h=["a[href]","button","input","select","textarea","[tabindex]"].some(v=>{try{return l.matches(v)}catch{return!1}}),p=[];!c&&h&&p.push("Focusable element has no accessible name."),o==="img"&&!l.hasAttribute("alt")&&p.push("Image has no alt attribute.");const y=/^h([1-6])$/.exec(o);return y&&!t&&p.push(`Heading h${y[1]} is empty.`),{selector:V(l),role:l.getAttribute("role")||void 0,implicitRole:Pt(l),name:c,nameSources:a,description:l.getAttribute("aria-describedby")||void 0,value:l.value!==void 0&&(l.getAttribute("type")||"text")!=="password"?String(l.value).slice(0,40):void 0,states:u,level:y?parseInt(y[1],10):void 0,focusable:h,tabIndex:l.tabIndex,ariaAttributes:e,issues:p}}function Pt(l){switch(l.tagName.toLowerCase()){case"a":return l.getAttribute("href")?"link":void 0;case"button":return"button";case"nav":return"navigation";case"header":return"banner";case"footer":return"contentinfo";case"main":return"main";case"aside":return"complementary";case"article":return"article";case"form":return"form";case"input":{const t=l.getAttribute("type")||"text";return{checkbox:"checkbox",radio:"radio",button:"button",submit:"button",reset:"button",range:"slider",search:"searchbox",email:"textbox",text:"textbox",password:"textbox",tel:"textbox",url:"textbox",number:"spinbutton"}[t]||"textbox"}case"select":return l.hasAttribute("multiple")?"listbox":"combobox";case"textarea":return"textbox";case"img":return"img";case"table":return"table";case"ul":case"ol":return"list";case"li":return"listitem";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return"heading";case"dialog":return"dialog";default:return}}function V(l){const e=l.getAttribute("id");if(e&&/^[a-zA-Z][\w-]*$/.test(e))return`#${e}`;const t=l.getAttribute("data-testid");if(t)return`${l.tagName.toLowerCase()}[data-testid="${t}"]`;const s=l.tagName.toLowerCase(),n=Array.from(l.classList||[]).slice(0,2);return n.length?`${s}.${n.join(".")}`:s}function K(l){return Array.from(l.childNodes).filter(e=>e.nodeType===3).map(e=>(e.textContent||"").trim()).join(" ").replace(/\s+/g," ")}function Ut(){return[{label:"desktop-1440x900",width:1440,height:900},{label:"laptop-1024x768",width:1024,height:768},{label:"tablet-768x1024",width:768,height:1024},{label:"mobile-375x667",width:375,height:667}]}class Ht{constructor(e){f(this,"hostElement",null);f(this,"shadowRoot",null);f(this,"callbacks");f(this,"isRecording",!1);f(this,"isPaused",!1);f(this,"isMinimized",!1);f(this,"startTime",0);f(this,"eventCount",0);f(this,"timerInterval",null);f(this,"isDragging",!1);f(this,"dragStartX",0);f(this,"dragStartY",0);f(this,"posX",window.innerWidth-340);f(this,"posY",40);this.callbacks=e,this.loadPosition()}mount(){this.hostElement&&document.body.contains(this.hostElement)||(this.hostElement=document.createElement("div"),this.hostElement.id="forensic-recorder-floating-host",this.hostElement.style.all="initial",this.hostElement.style.position="fixed",this.hostElement.style.zIndex="2147483647",this.hostElement.style.left=`${this.posX}px`,this.hostElement.style.top=`${this.posY}px`,this.shadowRoot=this.hostElement.attachShadow({mode:"open"}),this.render(),this.attachEvents(),(document.body||document.documentElement).appendChild(this.hostElement))}unmount(){this.timerInterval&&(clearInterval(this.timerInterval),this.timerInterval=null),this.hostElement&&this.hostElement.parentNode&&this.hostElement.parentNode.removeChild(this.hostElement),this.hostElement=null,this.shadowRoot=null}hide(){this.hostElement&&(this.hostElement.style.setProperty("display","none","important"),this.hostElement.style.setProperty("visibility","hidden","important"),this.hostElement.style.setProperty("opacity","0","important"))}show(){this.hostElement&&(this.hostElement.style.removeProperty("display"),this.hostElement.style.removeProperty("visibility"),this.hostElement.style.removeProperty("opacity"))}updateState(e,t=!1,s=0,n=0){this.isRecording=e,this.isPaused=t,this.startTime=s||(e?Date.now():0),this.eventCount=n,this.shadowRoot&&(this.render(),this.attachEvents()),this.isRecording&&!this.isPaused?this.startTimer():this.stopTimer()}incrementEventCount(){var t;this.eventCount++;const e=(t=this.shadowRoot)==null?void 0:t.querySelector("#evt-badge");e&&(e.textContent=`${this.eventCount} evts`)}startTimer(){this.stopTimer(),this.timerInterval=setInterval(()=>{var t;const e=(t=this.shadowRoot)==null?void 0:t.querySelector("#timer-display");if(e&&this.startTime){const s=(Date.now()-this.startTime)/1e3,n=Math.floor(s/60).toString().padStart(2,"0"),i=(s%60).toFixed(1).padStart(4,"0");e.textContent=`${n}:${i}`}},200)}stopTimer(){this.timerInterval&&(clearInterval(this.timerInterval),this.timerInterval=null)}savePosition(){try{sessionStorage.setItem("forensic_overlay_pos",JSON.stringify({x:this.posX,y:this.posY,min:this.isMinimized}))}catch{}}loadPosition(){try{const e=sessionStorage.getItem("forensic_overlay_pos");if(e){const t=JSON.parse(e);this.posX=Math.max(10,Math.min(window.innerWidth-300,t.x||this.posX)),this.posY=Math.max(10,Math.min(window.innerHeight-150,t.y||this.posY)),this.isMinimized=!!t.min}}catch{}}render(){if(!this.shadowRoot)return;const e=` +})()`,n=e;if(typeof n.eval!="function")return Promise.reject(new Error("BLOCKED_BY_CONTEXT: window.eval is unavailable in this context."));try{const i=n.eval(s);return i&&typeof i.then=="function"?i:Promise.resolve(i)}catch(i){return Promise.reject(i)}}hookConsole(e,t){var o;const s=["log","warn","error","info","debug"],n={},i=e,r=100;for(const a of s){const c=(o=i.console)==null?void 0:o[a];if(typeof c=="function"){n[a]=c;try{i.console[a]=(...u)=>{t.length {for(const a of s)if(n[a])try{i.console[a]=n[a]}catch{}}}serialize(e){if(e===void 0)return{text:"undefined"};if(e===null)return{text:"null"};try{if(typeof e=="string")return{text:e.slice(0,5e3)};const t=JSON.stringify(e,pe,1);return t===void 0?{serializationFailed:!0,message:"JSON.stringify returned undefined (circular or non-serializable structure)."}:{text:t.length>5e4?t.slice(0,5e4)+"…[truncated]":t}}catch(t){return{serializationFailed:!0,message:(t==null?void 0:t.message)||"Serialization failed."}}}result(e,t,s,n,i,r){return{status:t,executionId:e,durationMs:s,error:r,consoleOutput:i,domChanged:!1,domLengthBefore:0,domLengthAfter:0,world:"ISOLATED",timeoutMs:5e3,codePreview:n.length>300?n.slice(0,300)+"…":n}}}function pe(l,e){var t;if(e&&typeof e=="object"&&e.nodeType===1){const s=e;return{__element:!0,tag:s.tagName.toLowerCase(),id:s.getAttribute("id")||void 0,selector:s.tagName.toLowerCase()+(s.getAttribute("id")?`#${s.getAttribute("id")}`:""),text:(s.textContent||"").trim().slice(0,60)}}return typeof e=="function"?{__function:!0,name:e.name||"anonymous"}:e&&e.nodeType===9?{__document:!0,url:(t=e.location)==null?void 0:t.href}:e}function Ve(l){try{if(typeof l=="string")return l;if(l instanceof Error)return`${l.name}: ${l.message}`;const e=JSON.stringify(l,pe);return e===void 0?String(l):e}catch{return String(l)}}const me={"desktop-full-hd":{width:1920,height:1080,category:"desktop"},"desktop-hd":{width:1366,height:768,category:"desktop"},"desktop-laptop":{width:1440,height:900,category:"desktop"},"desktop-xga":{width:1280,height:1024,category:"desktop"},"desktop-1024":{width:1024,height:768,category:"desktop"},"tablet-ipad":{width:768,height:1024,category:"tablet"},"tablet-ipad-pro":{width:1024,height:1366,category:"tablet"},"tablet-portrait":{width:768,height:1024,category:"tablet"},"tablet-landscape":{width:1024,height:768,category:"tablet"},"mobile-iphone-se":{width:375,height:667,category:"mobile"},"mobile-iphone-12":{width:390,height:844,category:"mobile"},"mobile-iphone-14-pro-max":{width:430,height:932,category:"mobile"},"mobile-pixel-7":{width:412,height:915,category:"mobile"},"mobile-galaxy-s8":{width:360,height:740,category:"mobile"},"mobile-small":{width:320,height:568,category:"mobile"},"test-a4":{width:800,height:600,category:"test"},"test-square":{width:512,height:512,category:"test"}},fe={"iphone-13":{width:390,height:844,devicePixelRatio:3,userAgent:"Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1",touch:!0,category:"mobile"},"ipad-air":{width:820,height:1180,devicePixelRatio:2,userAgent:"Mozilla/5.0 (iPad; CPU OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1",touch:!0,category:"tablet"},"pixel-7":{width:412,height:915,devicePixelRatio:2.625,userAgent:"Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",touch:!0,category:"mobile"},"galaxy-s23":{width:384,height:800,devicePixelRatio:3,userAgent:"Mozilla/5.0 (Linux; Android 14; SM-S911B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36",touch:!0,category:"mobile"},"macbook-pro-16":{width:1728,height:1080,devicePixelRatio:2,userAgent:"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",touch:!1,category:"desktop"},"windows-desktop":{width:1920,height:1080,devicePixelRatio:1,userAgent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",touch:!1,category:"desktop"}};class Be{constructor(e){b(this,"original",null);b(this,"modified",!1);b(this,"activePreset",null);b(this,"activeDevice",null);this.doc=e}state(){const e=this.doc.defaultView;return{width:(e==null?void 0:e.innerWidth)||0,height:(e==null?void 0:e.innerHeight)||0,devicePixelRatio:(e==null?void 0:e.devicePixelRatio)||1,scrollX:(e==null?void 0:e.scrollX)||0,scrollY:(e==null?void 0:e.scrollY)||0,original:this.original,isModified:this.modified}}resize(e,t,s){const n=this.doc.defaultView,i={width:(n==null?void 0:n.innerWidth)||0,height:(n==null?void 0:n.innerHeight)||0},r=this.pageDigest();this.original||(this.original={...i});const o=this.applySize(e,t);this.modified=!0,this.activePreset=s||this.activePreset;const a=this.pageDigest();return{success:!0,applied:{width:o.width,height:o.height},previous:i,original:{...this.original},preset:s||void 0,beforeState:r,afterState:a,reversible:!0,mode:this.isSimulation()?"simulation":"browser-window"}}applyPreset(e){const t=me[e];if(!t)throw new Error(`UNKNOWN_PRESET: "${e}". Available: ${Object.keys(me).join(", ")}`);return this.resize(t.width,t.height,e)}emulateDevice(e){const t=fe[e];if(!t)throw new Error(`UNKNOWN_DEVICE: "${e}". Available: ${Object.keys(fe).join(", ")}`);const s=this.resize(t.width,t.height,`device:${e}`);this.activeDevice=e;const n=this.doc.defaultView;return n&&this.isSimulation()&&n.devicePixelRatio!==void 0&&(n.devicePixelRatio=t.devicePixelRatio),{device:e,resize:s,profile:{width:t.width,height:t.height,devicePixelRatio:t.devicePixelRatio,touch:t.touch,category:t.category},userAgentNote:this.isSimulation()?"User-Agent override requires the Chrome DevTools Protocol (real browser session); in this context the viewport, dpr and touch metadata are applied and the UA is reported but not enforced.":"User-Agent and touch behaviors are applied by the browser emulation layer.",userAgentApplied:!this.isSimulation()}}reset(){var s,n;const e={width:((s=this.doc.defaultView)==null?void 0:s.innerWidth)||0,height:((n=this.doc.defaultView)==null?void 0:n.innerHeight)||0},t=this.original?{...this.original}:{...e};return this.original&&this.applySize(this.original.width,this.original.height),this.modified=!1,this.activePreset=null,this.activeDevice=null,{success:!0,applied:{width:t.width,height:t.height},previous:e,original:{...t},reversible:!0,mode:this.isSimulation()?"simulation":"browser-window"}}runResponsiveTest(e,t={restore:!0}){var c,u,h,g;const s=t.restore!==!1,n=this.original?{...this.original}:{width:((c=this.doc.defaultView)==null?void 0:c.innerWidth)||0,height:((u=this.doc.defaultView)==null?void 0:u.innerHeight)||0};this.original||(this.original={...n});const i=e.map(p=>{this.applySize(p.width,p.height),this.modified=!0;const y=this.pageDigest();return{label:p.label,width:p.width,height:p.height,domLength:y.domLength,interactiveCount:y.interactiveCount,horizontalOverflow:this.hasHorizontalOverflow(),screenshotId:void 0}}),r=i.slice(1).map((p,y)=>({from:i[y].label,to:p.label,domLengthDelta:p.domLength-i[y].domLength,interactiveDelta:p.interactiveCount-i[y].interactiveCount}));let o={width:((h=i[i.length-1])==null?void 0:h.width)||0,height:((g=i[i.length-1])==null?void 0:g.height)||0},a=!1;return s&&(this.applySize(n.width,n.height),this.modified=!1,o={...n},a=!0),{success:!0,originalViewport:n,steps:i,restored:a,finalViewport:o,comparisons:r}}getActivePreset(){return this.activePreset}getActiveDevice(){return this.activeDevice}applySize(e,t){const s=Math.max(200,Math.min(7680,Math.round(e))),n=Math.max(200,Math.min(4320,Math.round(t))),i=this.doc.defaultView;return i&&(typeof i.innerWidth=="number"&&(i.innerWidth=s),typeof i.innerHeight=="number"&&(i.innerHeight=n),typeof i.outerWidth=="number"&&(i.outerWidth=s),typeof i.outerHeight=="number"&&(i.outerHeight=n)),{width:s,height:n}}pageDigest(){var t,s,n,i;const e=this.doc.querySelectorAll('a[href], button, input, select, textarea, [role="button"], [onclick]').length;return{url:((s=(t=this.doc.defaultView)==null?void 0:t.location)==null?void 0:s.href)||((n=this.doc.location)==null?void 0:n.href)||"",domLength:((i=this.doc.documentElement)==null?void 0:i.outerHTML.length)||0,interactiveCount:e}}hasHorizontalOverflow(){const e=this.doc.documentElement,t=this.doc.body,s=this.doc.defaultView;return!s||!e?!1:Math.max(e.scrollWidth||0,(t==null?void 0:t.scrollWidth)||0)>(s.innerWidth||e.clientWidth||0)+1}isSimulation(){return typeof globalThis.__FORENSIC_SIMULATION__<"u"}}const ze=[/^css-/,/^jsx-/,/^sc-[A-Za-z]/,/^emotion/,/^chakra-/,/^mantine-/i,/^_ng[a-z]/,/^ng-/i,/^v-/,/^(?=.*\d)[a-z0-9]{6,12}$/i,/^data-v-/],We=["id","name","data-testid","data-test","data-id","data-qa","data-cy","data-component","data-role","aria-label","aria-labelledby","aria-describedby","role","type","href","for","title","alt","rel","placeholder"];function be(l){let e=2166136261;for(let t=0;t >>0).toString(16).padStart(8,"0")}function ee(l){return ze.some(e=>e.test(l))}function Xe(l){return We.includes(l)}function re(l){const e=l.trim();return e?!!((e.match(/\d/g)||[]).length/e.length>.5||/^\d+[.,:\-/ ]+\d+/.test(e)||/\b\d{10,}\b/.test(e)):!1}function Ge(l,e=80){return Array.from(l.childNodes).filter(s=>s.nodeType===3).map(s=>(s.textContent||"").trim()).join(" ").replace(/\s+/g," ").slice(0,e)}function Ke(l,e){const t=[];let s=l;for(;s&&t.length !ee(f)),r=Ge(e),o=e.getBoundingClientRect(),a={width:Math.round(o.width),height:Math.round(o.height)},c=Ke(e,4),u=c.join(">"),g=Array.from(e.children||[]).slice(0,8).map(f=>f.tagName.toLowerCase()).join("|"),p=e.getAttribute("role")||(t!=null&&t.getComputedStyle,void 0)||Ye(e),y=be(JSON.stringify({t:e.tagName.toLowerCase(),a:s,c:i.slice(0,4),r:p||null,anc:u,desc:g,txt:re(r)?null:r.slice(0,40),d:a})),v=[];let m="low";return!s.id&&!s["data-testid"]&&!s.name&&(m="medium",v.push("no stable identity attribute")),n.length>0&&i.length===0&&(m=v.length?"high":"medium",v.push("all classes are framework-generated")),re(r)&&(v.push("text appears dynamic"),m==="low"&&(m="medium")),e.tagName.toLowerCase().includes("-")&&(v.push("custom element (web component)"),m==="low"&&(m="medium")),{fingerprintId:`fp_${y}`,hash:y,tagHierarchy:c,stableAttributes:s,meaningfulText:r,classes:i,role:p||void 0,dimensions:a,ancestorPattern:u,descendantPattern:g,volatilityRisk:m,volatilityReasons:v}}compare(e,t){const s=[],n=e.tagHierarchy[0]===t.tagHierarchy[0]?1:0;s.push({name:"tag",score:n,weight:.15});const i=ye(e.ancestorPattern.split(">"),t.ancestorPattern.split(">"));s.push({name:"ancestorPattern",score:i,weight:.2});const r=je(e.stableAttributes,t.stableAttributes);s.push({name:"stableAttributes",score:r,weight:.25});const o=ye(e.classes,t.classes);s.push({name:"classes",score:o,weight:.1});const a=(e.role||"")===(t.role||"")&&e.role?1:0;s.push({name:"role",score:a,weight:.1});const c=e.meaningfulText===t.meaningfulText&&e.meaningfulText?1:0;s.push({name:"text",score:c,weight:.1});const u=Ze(e.dimensions,t.dimensions);s.push({name:"dimensions",score:u,weight:.1});const h=s.reduce((g,p)=>g+p.score*p.weight,0);return{score:Math.round(h*1e3)/1e3,components:s}}}function Ye(l){switch(l.tagName.toLowerCase()){case"a":return l.getAttribute("href")?"link":void 0;case"button":return"button";case"nav":return"navigation";case"header":return"banner";case"footer":return"contentinfo";case"main":return"main";case"aside":return"complementary";case"article":return"article";case"form":return"form";case"input":{const t=l.getAttribute("type")||"text";return t==="checkbox"?"checkbox":t==="radio"?"radio":t==="button"||t==="submit"?"button":"textbox"}case"select":return"combobox";case"textarea":return"textbox";case"img":return"img";case"table":return"table";case"ul":case"ol":return"list";case"li":return"listitem";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return"heading";default:return}}function ye(l,e){if(!l.length&&!e.length)return 1;if(!l.length||!e.length)return 0;const t=new Set(e);return l.filter(n=>t.has(n)).length/Math.max(l.length,e.length)}function je(l,e){const t=Object.keys(l),s=Object.keys(e);if(!t.length&&!s.length)return .5;if(!t.length||!s.length)return 0;let n=0,i=0;for(const r of t)r in e&&(i++,l[r]===e[r]&&n++);return i===0?0:n/Math.max(t.length,s.length)}function Ze(l,e){if(l.width===0&&l.height===0&&e.width===0&&e.height===0)return .5;const t=Ee(l.width,e.width),s=Ee(l.height,e.height);return(t+s)/2}function Ee(l,e){if(l===e)return 1;if(l===0||e===0)return 0;const t=Math.min(l,e)/Math.max(l,e);return t>.9?1:t>.7?.5:0}const Je=["data-testid","data-test","data-id","data-qa","data-cy","data-component","data-role","aria-label","name","id"],ve=/^[a-zA-Z][a-zA-Z0-9_-]*$/,Qe=/^[a-zA-Z0-9_ .:-]+$/;class Y{constructor(e){b(this,"doc");this.doc=e}generateCandidates(e){const t=[],s=e.tagName.toLowerCase(),n=e.getAttribute("id");if(n&&ve.test(n)){const u=`#${we(n)}`;t.push(this.evaluate(e,u,"id",1,["unique stable id"]))}for(const u of Je){if(u==="id")continue;const h=e.getAttribute(u);if(h&&Qe.test(h)&&h.length<100){const g=`${s}[${u}="${j(h)}"]`;t.push(this.evaluate(e,g,"semantic-attribute",.92,[`semantic attribute ${u}`]))}}const i=Array.from(e.classList||[]).filter(u=>!ee(u));if(i.length){const u=`${s}.${i.slice(0,3).map(we).join(".")}`;t.push(this.evaluate(e,u,"class",.72,i.length?["stable class names"]:[]))}const r=this.buildStructuralPath(e);r&&t.push(this.evaluate(e,r,"structural-path",.55,["position-based structural path"]));const o=q(e);if(o&&o.length>=2&&o.length<=60&&!re(o)){const u=`${s}:nth-of-type(1)`,h=this.buildTextXPath(e,o);h&&(t.push({selector:u,strategy:"text-derived-xpath",confidence:.6,unique:this.isXPathUnique(h),reasons:[`matches text "${o.slice(0,30)}"`]}),t[t.length-1].xpath=h)}const a=this.buildAttributeFingerprintSelector(e);a&&t.push(this.evaluate(e,a,"attribute-fingerprint",.68,["combination of stable attributes"]));const c=new Map;for(const u of t){const h=u.strategy==="text-derived-xpath"?`xpath:${u.xpath}`:u.selector,g=c.get(h);(!g||u.confidence>g.confidence)&&c.set(h,u)}return Array.from(c.values()).sort((u,h)=>h.confidence-u.confidence)}bestSelector(e){const t=this.generateCandidates(e),s=t.find(n=>n.unique&&n.confidence>=.7)||t[0];return{selector:(s==null?void 0:s.selector)||e.tagName.toLowerCase(),strategy:(s==null?void 0:s.strategy)||"tag",confidence:(s==null?void 0:s.confidence)||.3}}buildXPath(e){const t=[];let s=e;for(;s&&s!==this.doc.documentElement;){const n=s.getAttribute("id");if(n&&ve.test(n)){t.unshift(`*[@id="${j(n)}"]`);break}const i=s.parentElement;if(!i){t.unshift(s.tagName.toLowerCase());break}const o=Array.from(i.children).filter(a=>a.tagName===s.tagName).indexOf(s)+1;t.unshift(`${s.tagName.toLowerCase()}[${o}]`),s=i}return s===this.doc.documentElement&&(!t.length||!t[0].includes("@id"))&&t.unshift("html"),"//"+t.join("/")}buildTextXPath(e,t){try{const s=e.tagName.toLowerCase(),n=et(t);return`//${s}[normalize-space(text())=${n}]`}catch{return null}}buildStructuralPath(e,t=4){const s=[];let n=e;for(;n&&s.length c.tagName===n.tagName);if(a.length>1){const c=a.indexOf(n)+1;s.unshift(`${o}:nth-of-type(${c})`)}else s.unshift(o);if(n=r,n===this.doc.body){s.unshift("body");break}if(n===this.doc.documentElement)break}const i=s.join(" > ");return i.includes("body")?i:"body > "+i}buildAttributeFingerprintSelector(e){const t=e.tagName.toLowerCase(),s=[],n=e.getAttribute("type");n&&s.push(`type="${j(n)}"`);const i=e.getAttribute("href");i&&i.length<80&&!i.startsWith("javascript:")&&s.push(`href^="${j(i.slice(0,40))}"`);const r=e.getAttribute("placeholder");return r&&r.length<60&&s.push(`placeholder="${j(r)}"`),s.length>=2?`${t}[${s.join("][")}]`:null}evaluate(e,t,s,n,i){let r=!1,o=0;try{const c=this.doc.querySelectorAll(t);o=c.length,r=c.length===1&&c[0]===e}catch{return{selector:t,strategy:s,confidence:0,unique:!1,reasons:["invalid selector syntax"]}}let a=n;return o===0?(a=0,i.push("selector matched nothing (invalid candidate)")):o===1&&r?i.push("matches exactly this element"):(a=a*.4,i.push(`matches ${o} elements — ambiguous`)),{selector:t,strategy:s,confidence:Math.round(a*100)/100,unique:r,reasons:i}}isXPathUnique(e){try{return this.doc.evaluate(`count(${e})`,this.doc,null,4,null).numberValue===1}catch{return!1}}}function q(l){return Array.from(l.childNodes).filter(e=>e.nodeType===3).map(e=>(e.textContent||"").trim()).join(" ").replace(/\s+/g," ")}function we(l){return l.replace(/([^a-zA-Z0-9_\u00A0-\uFFFF-])/g,"\\$1")}function j(l){return l.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function et(l){return l.includes("'")?l.includes('"')?`concat(${l.split("'").map(e=>`'${e}'`).join(`, "'", `)})`:`"${l}"`:`'${l}'`}class tt{constructor(e,t){b(this,"fingerprintEngine",new te);b(this,"counter",0);this.doc=e,this.registry=t}buildTarget(e,t="selector"){var h;const s=new Y(this.doc),n=s.generateCandidates(e),i=s.bestSelector(e),r=this.fingerprintEngine.fingerprint(e),o=k.inspectElement(e,this.registry),a=e.getBoundingClientRect();let c=i.confidence*.6;return r.volatilityRisk==="low"?c+=.3:r.volatilityRisk==="medium"&&(c+=.15),n.find(g=>g.unique&&g.confidence>=.9)&&(c+=.1),c=Math.max(.05,Math.min(1,c)),this.counter++,{targetId:`tgt_${Date.now().toString(36)}_${this.counter}`,tag:e.tagName.toLowerCase(),role:o.role||r.role,selector:i.selector,selectorCandidates:n,xpath:s.buildXPath(e),domPath:(((h=o.context)==null?void 0:h.parentChain)||[]).concat(i.selector).join(" > "),textFingerprint:r.meaningfulText,attributeFingerprint:JSON.stringify(r.stableAttributes),structuralFingerprint:r.hash,attributes:o.attributes||{},confidence:Math.round(c*100)/100,bounds:{x:Math.round(a.x),y:Math.round(a.y),width:Math.round(a.width),height:Math.round(a.height)},resolvedFrom:t}}resolveAndBuild(e){let t=null,s="unknown";typeof e=="string"&&(e={selector:e});const n=e;if(n.selectedElementRef&&(s="selectedElementRef"),!t&&n.selector)try{const i=this.doc.querySelectorAll(n.selector);if(i.length===0)return{error:`TARGET_NOT_FOUND: selector "${n.selector}" matches no element`};i.length>1?(t=st(i,this.doc)||i[0],s+="+disambiguated"):(t=i[0],s="selector")}catch(i){return{error:`TARGET_INVALID: ${i.message}`}}if(!t&&n.xpath)try{t=this.doc.evaluate(n.xpath,this.doc,null,9,null).singleNodeValue,s="xpath"}catch(i){return{error:`TARGET_INVALID_XPATH: ${i.message}`}}if(!t&&typeof n.nodeId=="number"&&this.registry){const i=this.registry.getNode(n.nodeId);i&&i.nodeType===1&&this.doc.contains(i)&&(t=i,s="nodeId")}return!t&&n.coordinates&&(t=this.doc.elementFromPoint(n.coordinates.x,n.coordinates.y),s="coordinates"),t?{element:t,target:this.buildTarget(t,s)}:{error:"TARGET_NOT_FOUND: no usable resolution strategy succeeded"}}}function st(l,e){for(const t of Array.from(l)){const s=t;try{if(k.inspectElement(s).visibility.isVisible)return s}catch{}}return null}class nt{constructor(e){b(this,"fingerprintEngine",new te);this.doc=e}recover(e,t){var p;const s=[],n=[];let i=null;try{i=this.doc.querySelectorAll(e)}catch(y){s.push(`selector syntax error: ${y.message}`)}if(i&&i.length>0){s.push("selector still matches — no recovery needed");const y=i[0];return{recovered:!0,confidence:1,strategy:"original-selector",resolvedSelector:e,matchedElementInfo:Te(y),alternatives:[],diagnostics:s,recommendation:"Original selector works; the earlier failure was transient (likely a navigation or render race)."}}s.push("selector no longer matches any element");const o=this.collectCandidates(t,s).map(y=>({element:y,score:this.scoreMatch(y,t)})).filter(y=>y.score.score>.35).sort((y,v)=>v.score.score-y.score.score);for(const y of o.slice(0,5)){const v=new Y(this.doc).bestSelector(y.element);n.push({selector:v.selector,confidence:Math.round(y.score.score*100)/100,strategy:"recovery-match"})}if(!o.length)return{recovered:!1,confidence:0,strategy:"none",alternatives:n,diagnostics:s,recommendation:"No sufficiently similar element exists. The region may have been removed, or the page structure changed fundamentally. Re-inspect the page and capture a new target."};const a=o[0],c=o.length>1?a.score.score-o[1].score.score:1;s.push(`best candidate score: ${a.score.score.toFixed(3)} (margin ${c.toFixed(3)})`);for(const y of a.score.components)y.score>0&&s.push(` - ${y.name}: ${(y.score*100).toFixed(0)}%`);if(a.score.score<.62||o.length>1&&c<.15)return{recovered:!1,confidence:Math.round(a.score.score*100)/100,strategy:"recovery-refused",resolvedSelector:(p=n[0])==null?void 0:p.selector,alternatives:n,diagnostics:s,recommendation:"Recovery refused: best match is not confident enough or too close to a competing element. Inspect alternatives manually before acting — refusing to avoid acting on a wrong element."};const g=new Y(this.doc).bestSelector(a.element).selector;return{recovered:!0,confidence:Math.round(a.score.score*100)/100,strategy:"fingerprint-recovery",resolvedSelector:g,matchedElementInfo:Te(a.element),alternatives:n,diagnostics:s,recommendation:`Recovered target with ${(a.score.score*100).toFixed(0)}% confidence. Verify the resolved selector before destructive actions.`}}collectCandidates(e,t){var r,o;const s=new Set,n=this.doc.querySelectorAll(e.tag);let i=0;for(const a of Array.from(n))if(s.add(a),++i>=400)break;if((r=e.classes)!=null&&r.length){const a=e.classes.filter(c=>!ee(c));for(const c of a.slice(0,2))try{for(const u of Array.from(this.doc.querySelectorAll(`.${c}`)).slice(0,100))s.add(u)}catch{}}if((o=e.stableAttributes)!=null&&o.name)try{for(const a of Array.from(this.doc.querySelectorAll(`[name="${e.stableAttributes.name}"]`)))s.add(a)}catch{}if(e.parentSelector)try{for(const a of Array.from(this.doc.querySelectorAll(`${e.parentSelector} > ${e.tag}`)).slice(0,100))s.add(a)}catch{}return t.push(`collected ${s.size} candidate elements for scoring`),Array.from(s)}scoreMatch(e,t){const s=[],n=e.tagName.toLowerCase()===t.tag.toLowerCase()?1:0;s.push({name:"tag",score:n,weight:.15});const i=(t.text||"").trim().slice(0,40),r=q(e).slice(0,40),o=(e.textContent||"").trim().slice(0,40);let a=0;if(i){const d=r?r===i?1:oe(i,r):0,f=o?o===i?1:oe(i,o):0;a=Math.max(d,f)}s.push({name:"text",score:a,weight:.3});const c=new Set((t.classes||[]).filter(d=>!ee(d))),u=Array.from(e.classList||[]),h=c.size?u.filter(d=>c.has(d)).length/c.size:.5;s.push({name:"classes",score:h,weight:.2});const g=t.stableAttributes||{},p=Object.keys(g);let y=.5;if(p.length){let d=0;for(const f of p)e.getAttribute(f)===g[f]&&d++;y=d/p.length}s.push({name:"attributes",score:y,weight:.2});const v=t.childCount!==void 0?e.children.length===t.childCount?1:oe(String(t.childCount),String(e.children.length)):.5;if(s.push({name:"childCount",score:v,weight:.05}),t.fingerprintHash){const d={fingerprintId:"snapshot",hash:t.fingerprintHash,tagHierarchy:[t.tag],stableAttributes:g,meaningfulText:i,classes:t.classes||[],dimensions:{width:0,height:0},ancestorPattern:"",descendantPattern:"",volatilityRisk:"medium",volatilityReasons:[]},f=this.fingerprintEngine.fingerprint(e),w=this.fingerprintEngine.compare(d,f);s.push({name:"fingerprint",score:w.score,weight:.1})}const m=s.reduce((d,f)=>d+f.score*f.weight,0);return{score:Math.max(0,Math.min(1,m)),components:s}}diagnose(e){const t=[];let s=!0,n=0,i,r=[];try{n=this.doc.querySelectorAll(e).length}catch(o){s=!1,i=o.message,t.push("Selector is syntactically invalid CSS.")}if(s&&n===0){t.push("Selector parses but matches nothing — element may be removed, re-rendered, or inside a shadow root."),r=this.relaxSelector(e);for(const o of r)try{if(this.doc.querySelectorAll(o).length>0){t.push(`Relaxed form "${o}" matches — the over-specific part of the selector is stale.`);break}}catch{}}return s&&n>1&&t.push(`Selector matches ${n} elements — it is ambiguous; use a more specific form or index.`),{selector:e,valid:s,matches:n,parseError:i,closestWorkingSelectors:r.filter(o=>{try{return this.doc.querySelectorAll(o).length>0}catch{return!1}}),diagnosis:t}}relaxSelector(e){const t=[],s=e.split(/[ >]+/).filter(Boolean);s.length>1&&(t.push(s.slice(0,-1).join(" ")),t.push(s[s.length-1]));const n=e.replace(/:nth-of-type\(\d+\)/g,"").replace(/\.[^. >#:[]+/g,(i,r,o)=>o[r-1]==="\\"?i:"");return n!==e&&n.trim()&&t.push(n.trim()),t}}function oe(l,e){if(!l||!e)return 0;const t=Se(l),s=Se(e);if(t===s)return 1;if(t.includes(s)||s.includes(t))return .7;const n=new Set(t.split(/\s+/)),i=new Set(s.split(/\s+/));return Array.from(n).filter(o=>i.has(o)).length/Math.max(n.size,i.size)}function Se(l){return l.toLowerCase().replace(/[^a-z0-9 ]/g," ").replace(/\s+/g," ").trim()}function Te(l){return{tag:l.tagName.toLowerCase(),id:l.getAttribute("id")||void 0,text:q(l).slice(0,60),classes:Array.from(l.classList||[])}}class ae{constructor(e){b(this,"state");this.state=e>>>0,this.state===0&&(this.state=2654435769)}next(){this.state=this.state+1831565813>>>0;let e=this.state;return e=Math.imul(e^e>>>15,e|1),e^=e+Math.imul(e^e>>>7,e|61),((e^e>>>14)>>>0)/4294967296}range(e,t){return e+this.next()*(t-e)}int(e,t){return Math.floor(this.range(e,t+1))}chance(e){return this.next() setTimeout(t,e))}chance(){return this.rng.next()<.5}}const rt=[{ruleId:"red_key_password",kind:"key-pattern",pattern:"password|passwd|pwd",description:"Keys containing password/passwd/pwd",enabled:!0,userAdded:!1},{ruleId:"red_key_token",kind:"key-pattern",pattern:"token|jwt|bearer|auth|session.?id|secret|api.?key|client.?secret",description:"Keys containing token/jwt/auth/session-id/secret/api-key",enabled:!0,userAdded:!1},{ruleId:"red_key_credential",kind:"key-pattern",pattern:"credential|login|user.?pass|otp|2fa|mfa|verification",description:"Keys containing credential/login/otp/2fa/verification",enabled:!0,userAdded:!1},{ruleId:"red_key_payment",kind:"key-pattern",pattern:"card|payment|billing|iban|cvv|cvc|pan",description:"Keys containing card/payment/billing/iban/cvv",enabled:!0,userAdded:!1},{ruleId:"red_key_personal",kind:"key-pattern",pattern:"ssn|social.?security|national.?id|passport|tax.?id",description:"Keys containing personal identifier patterns",enabled:!0,userAdded:!1},{ruleId:"red_val_jwt",kind:"value-pattern",pattern:"eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+",description:"JWT-shaped tokens",enabled:!0,userAdded:!1},{ruleId:"red_val_bearer",kind:"value-pattern",pattern:"bearer\\s+[A-Za-z0-9._-]+",description:"Bearer tokens",enabled:!0,userAdded:!1},{ruleId:"red_val_long_hex",kind:"value-pattern",pattern:"\\b[a-f0-9]{32,}\\b",description:"32+ char hex strings (session/API ids)",enabled:!0,userAdded:!1},{ruleId:"red_val_sk",kind:"value-pattern",pattern:"\\b(sk|pk|rk)_[A-Za-z0-9_]{20,}\\b",description:"Stripe-style secret keys (sk_live_…)",enabled:!0,userAdded:!1},{ruleId:"red_attr_input_password",kind:"attribute-name",pattern:"value",description:"value attributes on password inputs handled by PrivacyEngine maskValue",enabled:!0,userAdded:!1},{ruleId:"red_attr_secret",kind:"attribute-name",pattern:"data-secret|data-token|data-api-key|secret|access.?token",description:"Secret-carrying attributes",enabled:!0,userAdded:!1}],ot=[{exclusionId:"excl_mcpdom_overlay",selector:"[data-mcpdom-internal], [data-forensic-internal], #forensic-recorder-floating-host, #forensic-inspect-highlighter",reason:"MCPDOM-injected UI must never contaminate captured DOM (§68 clean capture)",userAdded:!1},{exclusionId:"excl_mcpdom_ids",selector:'[id^="forensic-"], [id^="mcpdom-"]',reason:"MCPDOM-namespaced nodes",userAdded:!1}],ce="[REDACTED]";class le{constructor(e){b(this,"config");b(this,"base",new J);b(this,"compiledKeyPatterns",[]);b(this,"compiledValuePatterns",[]);b(this,"compiledAttrPatterns",[]);this.config={rules:[...rt],exclusions:[...ot],stubMode:!0,...e},this.recompile()}recompile(){this.compiledKeyPatterns=[],this.compiledValuePatterns=[],this.compiledAttrPatterns=[];for(const e of this.config.rules){if(!e.enabled)continue;const t="i";try{switch(e.kind){case"key-pattern":this.compiledKeyPatterns.push(new RegExp(e.pattern,t));break;case"value-pattern":this.compiledValuePatterns.push(new RegExp(e.pattern,"i"));break;case"attribute-name":this.compiledAttrPatterns.push(new RegExp(`^(${e.pattern})$`,"i"));break}}catch{}}}getRules(){return[...this.config.rules]}setRuleEnabled(e,t){const s=this.config.rules.find(n=>n.ruleId===e);return s?(s.enabled=t,this.recompile(),!0):!1}addRule(e){const t=`red_custom_${this.config.rules.length+1}_${Date.now().toString(36)}`,s={...e,ruleId:t,userAdded:!0};return this.config.rules.push(s),this.recompile(),s}removeRule(e){const t=this.config.rules.findIndex(s=>s.ruleId===e);return t<0||!this.config.rules[t].userAdded?!1:(this.config.rules.splice(t,1),this.recompile(),!0)}getExclusions(){return[...this.config.exclusions]}addExclusion(e,t){const n={exclusionId:`excl_custom_${this.config.exclusions.length+1}_${Date.now().toString(36)}`,selector:e,reason:t,userAdded:!0};return this.config.exclusions.push(n),n}removeExclusion(e){const t=this.config.exclusions.findIndex(s=>s.exclusionId===e);return t<0||!this.config.exclusions[t].userAdded?!1:(this.config.exclusions.splice(t,1),!0)}isSensitiveKey(e){return this.compiledKeyPatterns.some(t=>t.test(e))}redactValue(e){let t=e;for(const s of this.compiledValuePatterns)s.test(t)&&(t=t.replace(new RegExp(s.source,"gi"),ce));return t}redactByKeyValue(e,t){return this.isSensitiveKey(e)?this.config.stubMode?ce:t:this.redactValue(t)}isSensitiveAttribute(e){return this.compiledAttrPatterns.some(t=>t.test(e))}redactAttributes(e){const t={};for(const[s,n]of Object.entries(e))this.isSensitiveAttribute(s)?t[s]=ce:t[s]=this.redactValue(n);return t}cleanSubtree(e){const t=e.cloneNode(!0);for(const s of this.config.exclusions){let n=null;try{n=t.querySelectorAll(s.selector)}catch{continue}for(const i of Array.from(n))i.remove();try{if(t.matches(s.selector))return this.doclessEmptyStub(t)}catch{}}return t}isExcluded(e){for(const t of this.config.exclusions)try{if(e.matches(t.selector)||e.closest(t.selector))return!0}catch{}return!1}doclessEmptyStub(e){return e.innerHTML="",e.setAttribute("data-mcpdom-excluded","true"),e}toJSON(){return{rules:this.getRules(),exclusions:this.getExclusions(),stubMode:this.config.stubMode}}static fromJSON(e){return new le({rules:Array.isArray(e==null?void 0:e.rules)?e.rules:void 0,exclusions:Array.isArray(e==null?void 0:e.exclusions)?e.exclusions:void 0,stubMode:typeof(e==null?void 0:e.stubMode)=="boolean"?e.stubMode:void 0})}}const ue='a[href], button, input, select, textarea, [role="button"], [role="link"], [role="tab"], [onclick], [tabindex]';function F(l,e){return{items:l.slice(0,e),truncated:l.length>e}}function _(l,e,t,s,n,i){return{analyzer:l,summary:e,count:t,items:s,warnings:n,truncated:i}}function O(l){try{return k.inspectElement(l).bestSelector}catch{return l.tagName.toLowerCase()}}const at=l=>{const e=Array.from(l.querySelectorAll("form")),t=e.map(n=>{const i=Array.from(n.querySelectorAll("input, select, textarea")).map(r=>({tag:r.tagName.toLowerCase(),type:r.getAttribute("type")||(r.tagName.toLowerCase()==="textarea"?"textarea":r.tagName.toLowerCase()==="select"?"select":"text"),name:r.getAttribute("name")||void 0,id:r.getAttribute("id")||void 0,required:r.hasAttribute("required"),pattern:r.getAttribute("pattern")||void 0,maxLength:r.getAttribute("maxlength")||void 0,placeholder:r.getAttribute("placeholder")||void 0,ariaLabel:r.getAttribute("aria-label")||void 0,autocomplete:r.getAttribute("autocomplete")||void 0,hasLabel:!!(r.getAttribute("id")&&l.querySelector(`label[for="${r.getAttribute("id")}"]`))||!!r.closest("label"),defaultValue:r.value!==void 0&&(r.getAttribute("type")||"text")!=="password"?String(r.value).slice(0,40):void 0}));return{selector:O(n),action:n.getAttribute("action")||void 0,method:(n.getAttribute("method")||"GET").toUpperCase(),id:n.getAttribute("id")||void 0,fieldCount:i.length,submitButton:n.querySelector('button[type="submit"], input[type="submit"]')?O(n.querySelector('button[type="submit"], input[type="submit"]')):void 0,validationAttributes:i.filter(r=>r.required||r.pattern).length,fields:i}}),s=F(t,50);return _("analyze_forms",`${e.length} form(s) with ${t.reduce((n,i)=>n+i.fieldCount,0)} total fields`,e.length,s.items,[],s.truncated)},ct=l=>{const e=Array.from(l.querySelectorAll("a[href]")),t=e.map(n=>({href:n.getAttribute("href")||"",text:q(n).slice(0,60),selector:O(n),rel:n.getAttribute("rel")||void 0,target:n.getAttribute("target")||void 0,download:n.hasAttribute("download"),external:/^https?:\/\//i.test(n.getAttribute("href")||"")&&!lt(n.getAttribute("href")||"",l),anchorOnly:(n.getAttribute("href")||"").startsWith("#")})),s=F(t,200);return _("extract_links",`${e.length} link(s): ${t.filter(n=>n.external).length} external, ${t.filter(n=>n.anchorOnly).length} anchors`,e.length,s.items,[],s.truncated)};function lt(l,e){var t,s,n,i;try{return new URL(l,((s=(t=e.defaultView)==null?void 0:t.location)==null?void 0:s.href)||"http://localhost").origin===(((i=(n=e.defaultView)==null?void 0:n.location)==null?void 0:i.origin)||"")}catch{return!1}}const ut=l=>{const e=Array.from(l.querySelectorAll("img")),t=Array.from(l.querySelectorAll("video")),s=Array.from(l.querySelectorAll("audio")),n=Array.from(l.querySelectorAll("canvas")),i=[],r=[...e.map(c=>({kind:"img",selector:O(c),src:(c.getAttribute("src")||"").slice(0,150),alt:c.getAttribute("alt"),width:c.getAttribute("width")||void 0,height:c.getAttribute("height")||void 0,naturalWidth:c.naturalWidth||void 0,naturalHeight:c.naturalHeight||void 0,lazy:c.getAttribute("loading")==="lazy",missingAlt:!c.hasAttribute("alt")})),...t.map(c=>{var u;return{kind:"video",selector:O(c),src:(c.getAttribute("src")||((u=c.querySelector("source"))==null?void 0:u.getAttribute("src"))||"").slice(0,150),controls:c.hasAttribute("controls"),autoplay:c.hasAttribute("autoplay"),muted:c.hasAttribute("muted"),poster:c.getAttribute("poster")||void 0}}),...s.map(c=>{var u;return{kind:"audio",selector:O(c),src:(c.getAttribute("src")||((u=c.querySelector("source"))==null?void 0:u.getAttribute("src"))||"").slice(0,150),controls:c.hasAttribute("controls")}}),...n.map(c=>({kind:"canvas",selector:O(c),width:c.width,height:c.height}))],o=r.filter(c=>c.missingAlt).length;o&&i.push(`${o} image(s) missing alt text (accessibility risk).`);const a=F(r,200);return _("analyze_media",`${e.length} images, ${t.length} videos, ${s.length} audios, ${n.length} canvases`,r.length,a.items,i,a.truncated)},dt=l=>{const e=l.defaultView,t=[],s={};if(e!=null&&e.getComputedStyle){const i=e.getComputedStyle(l.documentElement);for(let r=0;r ({name:i,value:r}));return _("get_css_variables",`${n.length} CSS custom properties found`,n.length,n,t,!1)},ht=l=>{const e=l.defaultView,t=[],s=new Map;if(e!=null&&e.getComputedStyle)for(const i of Array.from(l.querySelectorAll("body, body *")).slice(0,800)){const r=e.getComputedStyle(i),o=r.fontFamily||"",a=r.fontSize||"",c=`${o.split(",")[0].replace(/["']/g,"").trim()} @ ${a}`;s.set(c,(s.get(c)||0)+1)}else t.push("getComputedStyle unavailable — font usage analysis requires rendered styles.");const n=Array.from(s.entries()).map(([i,r])=>({font:i,usage:r})).sort((i,r)=>r.usage-i.usage);return _("analyze_fonts",`${n.length} distinct font/size combinations`,n.length,n,t,!1)},gt=l=>{const e=l.defaultView,t=[],s=new Map;if(e!=null&&e.getComputedStyle)for(const i of Array.from(l.querySelectorAll("body, body *")).slice(0,800)){const r=e.getComputedStyle(i);for(const o of["color","background-color","border-top-color"]){const a=r.getPropertyValue(o);a&&a!=="rgba(0, 0, 0, 0)"&&s.set(a,(s.get(a)||0)+1)}}else{for(const i of Array.from(l.querySelectorAll("[style]")).slice(0,300)){const r=i.getAttribute("style")||"",o=/(color)\s*:\s*([^;]+)/gi;let a;for(;a=o.exec(r);)s.set(a[2].trim(),(s.get(a[2].trim())||0)+1)}t.push("getComputedStyle unavailable — palette from inline styles only.")}const n=Array.from(s.entries()).map(([i,r])=>({color:i,usage:r})).sort((i,r)=>r.usage-i.usage).slice(0,40);return _("extract_color_palette",`${s.size} distinct colors in use`,s.size,n,t,!1)},pt=l=>{const e=l.defaultView,t=[],s=[];if(!(e!=null&&e.getComputedStyle))return t.push("getComputedStyle unavailable — z-index analysis requires rendered styles."),_("detect_zindex_conflicts","unavailable",0,[],t,!1);const n=[];for(const i of Array.from(l.querySelectorAll("body *")).slice(0,1e3)){const r=e.getComputedStyle(i),o=r.zIndex;o&&o!=="auto"&&parseInt(o,10)>0&&n.push({selector:O(i),z:parseInt(o,10),position:r.position,stacking:r.position==="fixed"||r.position==="sticky"||r.opacity!=="1"||r.transform!=="none"?"creates-stacking-context":"plain"})}for(let i=0;i 1e5&&s.push({zIndex:n[i].z,elements:[n[i].selector],note:"extremely high z-index — competes with platform overlays (MCPDOM uses 2147483640+)."})}return _("detect_zindex_conflicts",`${n.length} z-indexed elements, ${s.length} potential conflict(s)`,s.length,F(s,40).items,t,s.length>40)},mt=l=>{const e=l.defaultView,t=[],s=l.documentElement,n=l.body,i=Math.max((s==null?void 0:s.scrollWidth)||0,(n==null?void 0:n.scrollWidth)||0),r=(e==null?void 0:e.innerWidth)||(s==null?void 0:s.clientWidth)||0,o=i>r+1;if(o&&(t.push({issue:"horizontal-overflow",detail:`document scrollWidth ${i} exceeds viewport ${r}`}),e!=null&&e.getComputedStyle))for(const c of Array.from(l.querySelectorAll("body *")).slice(0,600)){const u=c.getBoundingClientRect();if(u.right>r+2&&u.width>100&&(t.push({issue:"element-exceeds-viewport",selector:O(c),right:Math.round(u.right),width:Math.round(u.width)}),t.length>15))break}let a=0;for(const c of Array.from(l.querySelectorAll(ue)).slice(0,500)){const u=c.getBoundingClientRect();(u.width===0||u.height===0)&&a++}return a&&t.push({issue:"zero-size-interactive-elements",count:a}),_("detect_layout_issues",o?`HORIZONTAL OVERFLOW: page is ${i-r}px wider than viewport`:"No horizontal overflow detected",t.length,t,[],!1)},ft=l=>{const e=Array.from(l.querySelectorAll(ue)),t=new Map,s=e.slice(0,300).map(n=>{const i=de(n),r=i.role||n.tagName.toLowerCase();return t.set(r,(t.get(r)||0)+1),{selector:i.bestSelector,tag:i.tag,role:i.role,text:i.text.slice(0,40),visible:i.visibility.isVisible,disabled:n.disabled||n.hasAttribute("disabled"),inViewport:i.visibility.isInViewport}});return _("census_interactive_elements",`${e.length} interactive elements: ${Array.from(t.entries()).map(([n,i])=>`${n}×${i}`).join(", ")||"none"}`,e.length,s,[],e.length>300)};function de(l){try{return k.inspectElement(l)}catch{return{tag:l.tagName.toLowerCase(),role:void 0,text:"",bestSelector:l.tagName.toLowerCase(),bounds:{x:0,y:0,width:0,height:0,top:0,right:0,bottom:0,left:0},visibility:{isVisible:!1,isInViewport:!1}}}}const bt=l=>{const e=["header","nav","main","aside","footer","article","section","figure","figcaption","mark","time","address","details","summary","dialog"],t=[];for(const i of e){const r=Array.from(l.querySelectorAll(i));if(r.length)for(const o of r.slice(0,20))t.push({tag:i,selector:O(o),role:o.getAttribute("role")||yt(i),text:q(o).slice(0,50),childCount:o.children.length})}const s=t.filter(i=>["banner","navigation","main","complementary","contentinfo"].includes(i.role)),n=[];return t.find(i=>i.tag==="main")||n.push("No element — page lacks a primary landmark."),l.querySelectorAll("header").length>1&&n.push("Multiple elements outside sections — ambiguous banner landmark."),_("detect_semantic_elements",`${t.length} semantic elements, ${s.length} landmarks`,t.length,F(t,100).items,n,t.length>100)};function yt(l){return{header:"banner",nav:"navigation",main:"main",aside:"complementary",footer:"contentinfo",article:"article",section:"region",form:"form"}[l]}const Ce={analyze_forms:at,extract_links:ct,analyze_media:ut,get_css_variables:dt,analyze_fonts:ht,extract_color_palette:gt,detect_zindex_conflicts:pt,detect_layout_issues:mt,census_interactive_elements:ft,detect_semantic_elements:bt,scan_accessibility_issues:l=>{var i;const e=[];for(const r of Array.from(l.querySelectorAll("img")).slice(0,200))r.hasAttribute("alt")||e.push({rule:"img-alt",severity:"error",selector:O(r),message:"Image is missing the alt attribute."});for(const r of Array.from(l.querySelectorAll("input:not([type=hidden]):not([type=submit]):not([type=button])")).slice(0,200)){const o=r.getAttribute("id");o&&l.querySelector(`label[for="${o}"]`)||r.closest("label")||r.getAttribute("aria-label")||r.getAttribute("aria-labelledby")||e.push({rule:"input-label",severity:"error",selector:O(r),message:"Form input has no associated label, aria-label or aria-labelledby."})}for(const r of Array.from(l.querySelectorAll('button, a[href], [role="button"]')).slice(0,300)){const o=q(r).trim(),a=r.getAttribute("aria-label");!o&&!a&&e.push({rule:"accessible-name",severity:"error",selector:O(r),message:"Interactive element has no accessible name (no text, no aria-label).",hint:r.querySelector("img[alt]")?"Contains an image — consider alt text or aria-label.":void 0})}const t=Array.from(l.querySelectorAll("h1, h2, h3, h4, h5, h6")).slice(0,100);let s=0;for(const r of t){const o=parseInt(r.tagName[1],10);s&&o>s+1&&e.push({rule:"heading-order",severity:"warning",selector:O(r),message:`Heading level jumps from h${s} to h${o}.`}),s=o}(i=l.documentElement)!=null&&i.getAttribute("lang")||e.push({rule:"html-lang",severity:"warning",selector:"html",message:"The element has no lang attribute."});const n=e.filter(r=>r.severity==="error").length;return _("scan_accessibility_issues",`${e.length} issue(s): ${n} errors, ${e.length-n} warnings`,e.length,F(e,100).items,[],e.length>100)},detect_dead_click_targets:l=>{const e=l.defaultView,t=[];for(const s of Array.from(l.querySelectorAll(ue)).slice(0,500)){const n=s.getBoundingClientRect(),i=e!=null&&e.getComputedStyle?e.getComputedStyle(s):null,r=n.width===0||n.height===0,o=i?i.pointerEvents==="none":!1,a=i?i.display==="none"||i.visibility==="hidden":!1,c=s.getAttribute("aria-hidden")==="true";(r||o||a||c)&&t.push({selector:O(s),tag:s.tagName.toLowerCase(),text:q(s).slice(0,30),reasons:[r&&"zero-size",o&&"pointer-events:none",a&&`hidden (${i?i.display:"?"}/${i?i.visibility:"?"})`,c&&"aria-hidden"].filter(Boolean)})}return _("detect_dead_click_targets",`${t.length} unreachable interactive element(s)`,t.length,F(t,80).items,[],t.length>80)},inventory_animations:l=>{const e=l.defaultView,t=[],s=[];if(!(e!=null&&e.getComputedStyle))return t.push("getComputedStyle unavailable — animation inventory requires rendered styles."),_("inventory_animations","unavailable",0,[],t,!1);for(const i of Array.from(l.querySelectorAll("body *")).slice(0,800)){const r=e.getComputedStyle(i),o=r.animationName!=="none"?`${r.animationName} ${r.animationDuration}`:null,a=r.transitionProperty!=="none"&&r.transitionProperty!=="all"?`${r.transitionProperty} ${r.transitionDuration}`:r.transitionProperty==="all"?`all ${r.transitionDuration}`:null;(o||a)&&s.push({selector:O(i),animation:o,transition:a,transitionTiming:r.transitionTimingFunction||void 0})}const n=s.filter(i=>i.animation&&i.animation.includes("infinite"));return n.length>5&&t.push(`${n.length} infinitely looping animations — may indicate decorative spinners or a stuck loading state.`),_("inventory_animations",`${s.length} animated/transitioning elements`,s.length,F(s,80).items,t,s.length>80)},map_frame_tree:l=>{const e=[],t=(n,i,r)=>{const o=Array.from(n.querySelectorAll("iframe, frame"));for(const a of o){const c=a.getAttribute("src")||"(no src)";let u=!1,h=null;try{const g=a.contentDocument;g&&(u=!0,h=g.querySelectorAll("*").length,r<3&&t(g,`${i} > ${a.tagName.toLowerCase()}[${c.slice(0,50)}]`,r+1))}catch{u=!1}e.push({path:`${i} > ${a.tagName.toLowerCase()}`,selector:O(a),src:c.slice(0,120),title:a.getAttribute("title")||void 0,name:a.getAttribute("name")||void 0,sandbox:a.getAttribute("sandbox")||void 0,accessible:u,childCount:h,limitation:u?void 0:"Same-origin policy blocks contentDocument access (cross-origin frame)."})}};t(l,"document",0);const s=e.filter(n=>!n.accessible).length;return _("map_frame_tree",`${e.length} frame(s), ${s} inaccessible (cross-origin)`,e.length,e,[],!1)},inventory_shadow_roots:l=>{const e=[],t=(s,n,i)=>{const r=(s instanceof ShadowRoot,Array.from(s.querySelectorAll("*")));for(const o of r)if(o.shadowRoot){const a=o.shadowRoot,c=`${n} > ${o.tagName.toLowerCase()}::shadowRoot(${a.mode})`;e.push({path:c.slice(0,200),hostSelector:O(o),hostTag:o.tagName.toLowerCase(),mode:a.mode,childCount:a.querySelectorAll("*").length,styles:a.querySelectorAll("style").length}),i<4&&t(a,c,i+1)}};return t(l.documentElement,"document",0),_("inventory_shadow_roots",`${e.length} open shadow root(s) found`,e.length,e,[],!1)},inspect_page_storage:l=>{const e=l.defaultView,t=new le,s=[],n=[];if(!(e!=null&&e.localStorage)||!(e!=null&&e.sessionStorage))return _("inspect_page_storage","Web Storage API unavailable in this context",0,[],["localStorage/sessionStorage are not accessible here (JSDOM limitation or sandboxed iframe)."],!1);try{for(let r=0;r r+(o.size||0),0);return _("inspect_page_storage",`${n.length} storage entries (~${i} bytes), sensitive keys redacted`,n.length,F(n,100).items,s,n.length>100)},get_performance_metrics:l=>{var i,r,o,a;const e=l.defaultView,t=[],s=e==null?void 0:e.performance;if(!(s!=null&&s.timing)&&!(s!=null&&s.getEntriesByType))return _("get_performance_metrics","Performance API unavailable",0,[],["window.performance is not exposed in this context."],!1);const n=[];try{const c=(r=(i=s.getEntriesByType)==null?void 0:i.call(s,"navigation"))==null?void 0:r[0];if(c)n.push({metric:"navigation-timing",domContentLoaded:Math.round(c.domContentLoadedEventEnd),loadComplete:Math.round(c.loadEventEnd),domInteractive:Math.round(c.domInteractive),type:c.type,redirectCount:c.redirectCount,sizeTransfer:c.transferSize});else if(s.timing){const g=s.timing;n.push({metric:"navigation-timing-legacy",domContentLoaded:g.domContentLoadedEventEnd-g.navigationStart,loadComplete:g.loadEventEnd-g.navigationStart,domInteractive:g.domInteractive-g.navigationStart})}const u=((o=s.getEntriesByType)==null?void 0:o.call(s,"paint"))||[];for(const g of u)n.push({metric:g.name,startTime:Math.round(g.startTime)});const h=((a=s.getEntriesByType)==null?void 0:a.call(s,"resource"))||[];if(h.length){const g=h.reduce((y,v)=>y+v.duration,0),p=[...h].sort((y,v)=>v.duration-y.duration).slice(0,5).map(y=>({url:String(y.name).slice(0,100),duration:Math.round(y.duration)}));n.push({metric:"resource-summary",count:h.length,totalDuration:Math.round(g),slowest:p})}s.memory&&n.push({metric:"memory",usedJSHeapMB:Math.round(s.memory.usedJSHeapSize/1048576*10)/10,totalJSHeapMB:Math.round(s.memory.totalJSHeapSize/1048576*10)/10})}catch(c){t.push(`performance read failed: ${c.message}`)}return _("get_performance_metrics",`${n.length} metric group(s)`,n.length,n,t,!1)},extract_seo_metadata:l=>{var r,o,a;const e=c=>{var u;return((u=l.querySelector(`meta[name="${c}"]`))==null?void 0:u.getAttribute("content"))||void 0},t=c=>{var u;return((u=l.querySelector(`meta[property="${c}"]`))==null?void 0:u.getAttribute("content"))||void 0},s=[{field:"title",value:l.title||void 0},{field:"description",value:e("description")},{field:"canonical",value:(r=l.querySelector('link[rel="canonical"]'))==null?void 0:r.getAttribute("href")},{field:"robots",value:e("robots")},{field:"viewport",value:e("viewport")},{field:"charset",value:(o=l.querySelector("meta[charset]"))==null?void 0:o.getAttribute("charset")},{field:"og:title",value:t("og:title")},{field:"og:description",value:t("og:description")},{field:"og:image",value:t("og:image")},{field:"og:url",value:t("og:url")},{field:"twitter:card",value:e("twitter:card")},{field:"language",value:(a=l.documentElement)==null?void 0:a.getAttribute("lang")}],n=l.querySelectorAll("h1").length,i=[];return n===0&&i.push("No h1 — page lacks a primary heading."),n>1&&i.push(`Multiple h1 elements (${n}).`),e("description")||i.push("No meta description."),s.push({field:"h1Count",value:n}),_("extract_seo_metadata",`SEO metadata extracted; ${i.length} warning(s)`,s.length,s,i,!1)},extract_structured_data:l=>{var t;const e=[];for(const s of Array.from(l.querySelectorAll('script[type="application/ld+json"]')))try{const n=JSON.parse(s.textContent||"{}");e.push({format:"JSON-LD",type:n["@type"]||(Array.isArray(n)?"array":"unknown"),data:n})}catch(n){e.push({format:"JSON-LD",type:"invalid-json",error:n.message})}for(const s of Array.from(l.querySelectorAll("[itemscope]")).slice(0,30)){const n=s.getAttribute("itemtype")||"unknown",i={};for(const r of Array.from(s.querySelectorAll("[itemprop]"))){const o=r.getAttribute("itemprop")||"",a=r.getAttribute("content")||r.getAttribute("href")||((t=r.textContent)==null?void 0:t.trim())||"";i[o]=a.slice(0,100)}e.push({format:"microdata",type:n.split("/").pop()||n,data:i})}return _("extract_structured_data",`${e.length} structured data block(s)`,e.length,e,[],!1)},extract_tables:l=>{const e=Array.from(l.querySelectorAll("table")),t=e.slice(0,30).map(s=>{var a,c,u;const n=Array.from(s.querySelectorAll("thead th, tr:first-child th")).map(h=>{var g;return((g=h.textContent)==null?void 0:g.trim())||""}),i=Array.from(s.querySelectorAll("tbody tr, tr")).filter(h=>!h.querySelector("th")).slice(0,50),r=i.map(h=>Array.from(h.querySelectorAll("td")).map(g=>(g.textContent||"").trim().slice(0,60))),o=(c=(a=s.querySelector("caption"))==null?void 0:a.textContent)==null?void 0:c.trim();return{selector:O(s),caption:o,columnCount:n.length||((u=r[0])==null?void 0:u.length)||0,rowCount:i.length,headers:n,rows:r}});return _("extract_tables",`${e.length} table(s)`,e.length,t,[],e.length>30)},extract_lists:l=>{const e=Array.from(l.querySelectorAll("ul, ol")),t=e.slice(0,60).map(s=>{const n=Array.from(s.querySelectorAll(":scope > li")).slice(0,40);return{selector:O(s),kind:s.tagName.toLowerCase(),ordered:s.tagName.toLowerCase()==="ol",itemCount:n.length,items:n.map(i=>q(i).slice(0,60)),nested:s.querySelectorAll("ul, ol").length}});return _("extract_lists",`${e.length} list(s)`,e.length,t,[],e.length>60)},analyze_page_content:l=>{const e=l.body,t=(e==null?void 0:e.innerText)||(e==null?void 0:e.textContent)||"",s=t.trim()?t.trim().split(/\s+/).length:0,n=Array.from(l.querySelectorAll("h1, h2, h3, h4, h5, h6")).map(c=>({level:parseInt(c.tagName[1],10),text:q(c).slice(0,80)})),i=l.querySelectorAll("p").length,r=i?Math.round(s/i):0,o=Math.round(s/220*10)/10,a=[{metric:"wordCount",value:s},{metric:"paragraphCount",value:i},{metric:"avgParagraphWords",value:r},{metric:"estimatedReadingMinutes",value:o},{metric:"headingCount",value:n.length},{metric:"imageCount",value:l.querySelectorAll("img").length},{metric:"linkDensity",value:Math.round(l.querySelectorAll("a[href]").length/Math.max(1,s)*1e3)/1e3},{metric:"headings",value:n.slice(0,50)}];return _("analyze_page_content",`${s} words, ${i} paragraphs, ~${o} min read`,a.length,a,[],!1)},search_dom:(l,e)=>{const t=String((e==null?void 0:e.query)||"").trim();if(!t)return _("search_dom","No query supplied",0,[],["Provide a text query; optionally tag/attr filters."],!1);const s=t.toLowerCase(),n=[],i=Math.min((e==null?void 0:e.limit)||50,200),r=Array.from(l.querySelectorAll("*"));for(const o of r){if(n.length>=i)break;if(e!=null&&e.tag&&o.tagName.toLowerCase()!==String(e.tag).toLowerCase())continue;const a=q(o),c=Array.from(o.attributes);let u=0,h="";o.tagName.toLowerCase().includes(s)&&(u+=.2,h="tag match"),a.toLowerCase().includes(s)&&a.length<200&&(u+=.6,h="text match");for(const g of c)if(g.name.toLowerCase().includes(s)||g.value.length<100&&g.value.toLowerCase().includes(s)){u+=.4,h=`attribute ${g.name} match`;break}if(e!=null&&e.attr){const g=String(e.attr).toLowerCase(),p=e.attrValue?String(e.attrValue).toLowerCase():null;if(c.find(v=>v.name.toLowerCase()===g&&(!p||v.value.toLowerCase().includes(p))))u+=.5;else continue}if(u>0){const g=de(o);n.push({selector:g.bestSelector,tag:g.tag,role:g.role,text:g.text.slice(0,60),score:Math.round(u*100)/100,reason:h,visible:g.visibility.isVisible,bounds:{x:Math.round(g.bounds.x),y:Math.round(g.bounds.y),w:Math.round(g.bounds.width),h:Math.round(g.bounds.height)}})}}return n.sort((o,a)=>a.score-o.score),_("search_dom",`${n.length} element(s) match "${t}"`,n.length,n,[],n.length>=i)},inventory_ctas:l=>{var t;const e=[];for(const s of Array.from(l.querySelectorAll('button, a[class*="btn"], a[class*="button"], input[type="submit"], [role="button"]')).slice(0,100)){const n=de(s);e.push({selector:n.bestSelector,tag:n.tag,text:n.text.slice(0,50),styleHint:(t=s.getAttribute("class"))==null?void 0:t.slice(0,60),primary:/primary|cta|submit|main/i.test(s.getAttribute("class")||"")||s.type==="submit",visible:n.visibility.isVisible})}return _("inventory_ctas",`${e.length} call-to-action element(s)`,e.length,e,[],!1)},detect_focus_traps:l=>{const e=[];for(const s of Array.from(l.querySelectorAll('[role="dialog"], [aria-modal="true"], dialog[open], .modal, [class*="modal"]')).slice(0,30)){const n=s.querySelectorAll('a[href], button, input, select, textarea, [tabindex]:not([tabindex="-1"])');e.push({selector:O(s),kind:s.getAttribute("role")||s.tagName.toLowerCase(),ariaModal:s.getAttribute("aria-modal"),focusableCount:n.length,firstFocusable:n[0]?O(n[0]):void 0,note:n.length===0?"Modal container has NO focusable elements — keyboard users are trapped.":void 0})}const t=l.querySelectorAll("[tabindex]>0");for(const s of Array.from(t).slice(0,20))e.push({selector:O(s),kind:"positive-tabindex",note:`tabindex=${s.tabIndex} breaks natural tab order.`});return _("detect_focus_traps",`${e.length} focus-management issue(s)/container(s)`,e.length,e,[],!1)},infer_responsive_breakpoints:l=>{const e=l.defaultView,t=[],s=new Set;for(const o of Array.from(l.querySelectorAll("style"))){const a=o.textContent||"",c=/@media[^{]*?\(\s*(?:min|max)-width\s*:\s*(\d+)(?:\.\d+)?px/g;let u;for(;u=c.exec(a);)s.add(parseInt(u[1],10))}for(const o of Array.from(l.querySelectorAll('link[rel="stylesheet"]')).slice(0,10)){const a=o.getAttribute("href")||"";if(/^\d+px$/.test(a)||a.includes("width=")){const c=a.match(/width=(\d+)/);c&&s.add(parseInt(c[1],10))}}for(const o of Array.from(l.querySelectorAll("img[srcset], source[srcset]")).slice(0,50)){const a=o.getAttribute("srcset")||"";for(const c of a.matchAll(/(\d+)w/g))s.add(parseInt(c[1],10))}e!=null&&e.matchMedia||t.push("matchMedia unavailable — live breakpoint probing skipped.");const n=Array.from(s).sort((o,a)=>o-a),i=n.map(o=>({breakpoint:o,note:o<=768?"mobile-class":o<=1024?"tablet-class":"desktop-class"})),r=e==null?void 0:e.innerWidth;if(r){const o=n.filter(a=>a<=r);i.unshift({breakpoint:`current viewport: ${r}px`,note:o.length?`below breakpoints: ${o.join(", ")}`:"no declared breakpoint below current width"})}return _("infer_responsive_breakpoints",`${n.length} breakpoint(s) inferred from CSS/srcset`,i.length,i,t,!1)},get_selection_state:l=>{var i;const e=l.defaultView,t=(i=e==null?void 0:e.getSelection)==null?void 0:i.call(e),s=l.activeElement,n=[{hasSelection:!!(t!=null&&t.toString()),selectedText:(t==null?void 0:t.toString().slice(0,200))||"",selectionRanges:(t==null?void 0:t.rangeCount)||0,activeElement:s?{tag:s.tagName.toLowerCase(),selector:O(s),editable:s.isContentEditable||["INPUT","TEXTAREA"].includes(s.tagName)}:null}];return _("get_selection_state",t!=null&&t.toString()?`Selection: "${t.toString().slice(0,40)}…"`:"No text selection",1,n,[],!1)}};function Et(l,e,t){const s=Ce[l];return s?s(e,t):{analyzer:l,summary:`Unknown analyzer "${l}". Available: ${Object.keys(Ce).join(", ")}`,count:0,items:[],warnings:[],truncated:!1}}const vt=2e3;class wt{constructor(e=vt){b(this,"events",[]);b(this,"cap");b(this,"counter",0);this.cap=Math.max(10,e)}record(e,t,s={}){this.counter++;const n={eventId:`evt_${Date.now().toString(36)}_${this.counter}`,timestamp:Date.now(),kind:e,operationId:s.operationId,sessionId:s.sessionId,detail:t,data:s.data};return this.events.push(n),this.events.length>this.cap&&this.events.splice(0,this.events.length-this.cap),n}query(e){let t=this.events;e.kind&&(t=t.filter(n=>n.kind===e.kind)),e.operationId&&(t=t.filter(n=>n.operationId===e.operationId)),e.sinceTimestamp&&(t=t.filter(n=>n.timestamp>=e.sinceTimestamp));const s=e.limit&&e.limit>0?e.limit:200;return t.slice(-s)}size(){return this.events.length}toJSON(){return[...this.events]}}class St{constructor(){b(this,"counter",0);b(this,"operations",new Map)}begin(e){this.counter++;const t=`op_${Date.now().toString(36)}_${this.counter}`;return this.operations.set(t,{operationId:t,tool:e,startedAt:Date.now(),status:"RUNNING",timelineEventIds:[]}),t}end(e,t,s){const n=this.operations.get(e);n&&(n.endedAt=Date.now(),n.status=t,n.relatedError=s)}attachEvent(e,t){const s=this.operations.get(e);s&&s.timelineEventIds.push(t)}trace(e){const t=this.operations.get(e);return t?{...t,durationMs:t.endedAt?t.endedAt-t.startedAt:void 0}:null}recent(e=100){return Array.from(this.operations.values()).slice(-e).map(t=>({...t,durationMs:t.endedAt?t.endedAt-t.startedAt:void 0}))}}const Ie=100;class Tt{constructor(e){b(this,"sessionId");b(this,"timeline",new wt);b(this,"operations",new St);b(this,"tabs",new Map);b(this,"activeTabId",null);b(this,"startedAt",Date.now());b(this,"snapshots",[]);b(this,"commandHistory",[]);b(this,"annotationCount",0);b(this,"projectId");b(this,"tabCounter",0);b(this,"commandCounter",0);this.sessionId=e||`sess_${Date.now().toString(36)}`}registerTab(e,t,s){const n=e!==void 0?Array.from(this.tabs.values()).find(o=>o.browserTabId===e):void 0;if(n)return n.lastSeenAt=Date.now(),n.status="OPEN",n.url=t||n.url,n.title=s||n.title,n;this.tabCounter++;const i=`stab_${this.tabCounter}_${Date.now().toString(36)}`,r={sessionTabId:i,browserTabId:e,url:t,title:s,createdAt:Date.now(),lastSeenAt:Date.now(),status:"OPEN"};return this.tabs.set(i,r),this.timeline.record("TAB_OPENED",`tab ${i} registered (${t||"no url"})`,{sessionId:this.sessionId}),r}closeTab(e){const t=this.tabs.get(e);return t?(t.status="CLOSED",t.lastSeenAt=Date.now(),this.timeline.record("TAB_CLOSED",`tab ${e} closed`,{sessionId:this.sessionId}),!0):!1}switchTab(e){const t=this.tabs.get(e);return!t||t.status==="CLOSED"?!1:(this.activeTabId=e,this.timeline.record("TAB_SWITCHED",`active tab → ${e}`,{sessionId:this.sessionId}),!0)}getTabs(){return Array.from(this.tabs.values())}getActiveTab(){if(this.activeTabId){const e=this.tabs.get(this.activeTabId);if(e&&e.status==="OPEN")return e}return Array.from(this.tabs.values()).find(e=>e.status==="OPEN")||null}markAllStale(){let e=0;for(const t of this.tabs.values())t.status==="OPEN"&&(t.status="STALE",e++);return e}captureSnapshot(e,t,s){var a,c,u;const n=e.defaultView,i=((a=e.documentElement)==null?void 0:a.outerHTML)||"",r=e.querySelectorAll('a[href], button, input, select, textarea, [role="button"]').length,o={snapshotId:`snap_${Date.now().toString(36)}_${this.snapshots.length+1}`,timestamp:Date.now(),url:((c=n==null?void 0:n.location)==null?void 0:c.href)||((u=e.location)==null?void 0:u.href)||"",title:e.title||"",viewport:{width:(n==null?void 0:n.innerWidth)||0,height:(n==null?void 0:n.innerHeight)||0,scrollX:(n==null?void 0:n.scrollX)||0,scrollY:(n==null?void 0:n.scrollY)||0,devicePixelRatio:(n==null?void 0:n.devicePixelRatio)||1},domLength:i.length,domHash:be(i),interactiveCount:r,selectedRegions:[],extensionEnabled:t,pendingMutations:s,annotationCount:this.annotationCount};return this.snapshots.push(o),this.snapshots.length>Ie&&this.snapshots.splice(0,this.snapshots.length-Ie),this.timeline.record("SNAPSHOT_CREATED",`snapshot ${o.snapshotId} (dom ${o.domLength}b)`,{sessionId:this.sessionId}),o}getSnapshot(e){return e?this.snapshots.find(t=>t.snapshotId===e)||null:this.snapshots[this.snapshots.length-1]||null}listSnapshots(){return this.snapshots.map(e=>({snapshotId:e.snapshotId,timestamp:e.timestamp,url:e.url,title:e.title,domLength:e.domLength,domHash:e.domHash}))}compareSnapshots(e,t){const s=["url","title","domLength","domHash","interactiveCount","extensionEnabled","annotationCount"],n=[];for(const r of s)e[r]!==t[r]&&n.push({field:r,before:e[r],after:t[r]});(e.viewport.width!==t.viewport.width||e.viewport.height!==t.viewport.height)&&n.push({field:"viewport",before:`${e.viewport.width}x${e.viewport.height}`,after:`${t.viewport.width}x${t.viewport.height}`});const i=t.domLength-e.domLength;return{identical:n.length===0,changes:n,domDelta:{beforeLength:e.domLength,afterLength:t.domLength,delta:i},summary:n.length===0?"States are identical.":`${n.length} field(s) changed; DOM size ${i>=0?"+":""}${i} bytes.`}}recordCommand(e,t,s,n,i){this.commandCounter++;const r=`cmd_${this.commandCounter}_${Date.now().toString(36)}`;return this.commandHistory.push({commandId:r,tool:e,args:t,outcome:s,timestamp:Date.now(),durationMs:n,error:i}),this.timeline.record("COMMAND_EXECUTED",`${e} → ${s}${i?` (${i})`:""}`,{sessionId:this.sessionId,data:{commandId:r}}),r}getCommandHistory(e=100){return this.commandHistory.slice(-e)}noteAnnotations(e){this.annotationCount=e}bindProject(e){this.projectId=e}getProjectId(){return this.projectId}summary(e,t,s,n){var i,r,o;return{sessionId:this.sessionId,startedAt:this.startedAt,url:((r=(i=e.defaultView)==null?void 0:i.location)==null?void 0:r.href)||((o=e.location)==null?void 0:o.href)||"",title:e.title||"",tabs:this.getTabs(),activeTabId:this.activeTabId,viewport:{width:t.width,height:t.height,isModified:t.isModified},extensionEnabled:s,snapshotCount:this.snapshots.length,commandCount:this.commandHistory.length,annotationCount:this.annotationCount,mutationHistoryCount:n.length,timelineEventCount:this.timeline.size(),projectId:this.projectId}}}const Ct=l=>{var e,t;try{const s=l.getBoundingClientRect();if(s.width===0&&s.height===0)return null;const n=((t=(e=l.ownerDocument)==null?void 0:e.defaultView)==null?void 0:t.innerWidth)||1920;return s.y n*1.5?"bottom":s.x n*.8?"right":"center"}catch{return null}},It={navigation:"navigation",banner:"header",contentinfo:"footer",complementary:"sidebar",main:"main",form:"form",search:"search",region:"section",dialog:"modal",alertdialog:"modal",table:"table",list:"list",combobox:"dropdown",button:"button",link:"link",textbox:"input",checkbox:"checkbox",radio:"radio",img:"image",article:"article"},At={nav:"navigation",header:"header",footer:"footer",aside:"sidebar",main:"main",section:"section",article:"article",form:"form",table:"table",ul:"list",ol:"list",figure:"figure",dialog:"modal",button:"button",input:"input",select:"dropdown",textarea:"textarea",canvas:"canvas",video:"video",img:"image",h1:"heading",h2:"heading",h3:"heading"};function Z(l){return l.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"").replace(/_{2,}/g,"_").slice(0,48).replace(/_$/,"")}class xt{generate(e){return this.generateFromMeta({tagName:e.tagName.toLowerCase(),role:e.getAttribute("role")||void 0,text:q(e).trim(),ariaLabel:e.getAttribute("aria-label")||void 0,stableClass:Array.from(e.classList||[]).find(t=>/^[a-z][a-z0-9-]{2,}$/i.test(t)&&!_t.has(t)),position:Ct(e),nearbyHeading:this.nearbyHeading(e)})}generateFromMeta(e){const t=[],s=[],n=e.role||Nt(e.tagName);if(n){const r=It[n]||n;s.push(r),t.push(`role=${n}`)}else{const r=At[e.tagName]||e.tagName;s.push(r),t.push(`tag=${e.tagName}`)}if(e.ariaLabel&&(s.unshift(Z(e.ariaLabel)),t.push(`aria-label="${e.ariaLabel.slice(0,30)}"`)),e.text&&e.text.length<=40){const r=Z(e.text.split(/\s+/).slice(0,3).join(" "));r&&r.length>=2&&(s.push(r),t.push(`text="${e.text.slice(0,30)}"`))}if(e.nearbyHeading){const r=Z(e.nearbyHeading.split(/\s+/).slice(0,3).join(" "));r&&!s.includes(r)&&(s.push(r),t.push(`nearby-heading="${e.nearbyHeading.slice(0,30)}"`))}e.stableClass&&s.length<3&&(s.push(Z(e.stableClass)),t.push(`class=${e.stableClass}`)),e.tagName==="input"&&(s.some(r=>r.includes("input"))||(s.push("input"),t.push("tag=input"))),s.join("_").length<12&&e.position&&(s.push(e.position),t.push(`position=${e.position}`));let i=Z(s.join("_"))||"unnamed_region";return/^\d/.test(i)&&(i=`el_${i}`),{name:i,evidence:t}}nearbyHeading(e){let t=e.parentElement;for(let n=0;t&&n<4;n++){const i=t.querySelector('h1, h2, h3, h4, [role="heading"]');if(i)return q(i).trim().slice(0,40)||null;t=t.parentElement}let s=e.previousElementSibling;for(let n=0;s&&n<4;n++){if(/^H[1-4]$/.test(s.tagName)){const i=q(s).trim();if(i)return i.slice(0,40)}s=s.previousElementSibling}return null}}const _t=new Set(["active","open","visible","hidden","selected","disabled","container","wrapper","root","item","col","row","flex","box","main","div","span","block"]);function Nt(l){switch(l){case"nav":return"navigation";case"header":return"banner";case"footer":return"contentinfo";case"aside":return"complementary";case"main":return"main";case"form":return"form";case"table":return"table";case"button":return"button";case"a":return"link";case"input":return"textbox";case"select":return"combobox";case"textarea":return"textbox";case"img":return"img";default:return null}}const kt=["display","position","flex-direction","grid-template-columns","width","height","background-color","color","font-size","border-radius","overflow"];class Mt{constructor(){b(this,"naming",new xt)}capture(e){const t=e.ownerDocument,s=new Y(t),n=new te,i=s.generateCandidates(e),r=s.bestSelector(e),o=n.fingerprint(e);let a=e,c=0,u="self";for(let d=0;d<3;d++){const f=a.parentElement;if(!f||f===t.body||f===t.documentElement)break;if(this.isMeaningfulContainer(f)){a=f,c=d+1,u="meaningful-ancestor";break}a=f,c=d+1}if(a===e){const d=e.parentElement;d&&d!==t.body&&e.querySelectorAll("*").length<4&&(a=d,c=1,u="direct-parent-fallback")}const h=this.boundedHtml(e,6e4),g=this.boundedHtml(a,12e4);k.inspectElement(e);const p=e.getBoundingClientRect(),y=t.defaultView,v={};if(y!=null&&y.getComputedStyle){const d=y.getComputedStyle(e);for(const f of kt){const w=d.getPropertyValue(f);w&&w!=="none"&&w!=="auto"&&(v[f]=w)}}const m=e.parentElement;return{regionHtml:h,contextHtml:g,boundary:{strategy:u,ancestorLevels:c,note:c===0?"Region captured standalone (no meaningful ancestor within 3 levels).":`Context includes ${c} ancestor level(s) up to a meaningful container.`},selectorCandidates:i,bestSelector:r.selector,xpath:s.buildXPath(e),fingerprintHash:o.hash,dimensions:{width:Math.round(p.width),height:Math.round(p.height)},position:{x:Math.round(p.x),y:Math.round(p.y)},relevantStyles:v,parentInfo:m?{tag:m.tagName.toLowerCase(),selector:Rt(m),text:q(m).slice(0,60)}:void 0,childrenCount:e.children.length,childTags:Array.from(e.children).slice(0,12).map(d=>d.tagName.toLowerCase()),nameHint:this.naming.generate(e),fingerprintVolatility:o.volatilityRisk,volatilityReasons:o.volatilityReasons}}isMeaningfulContainer(e){const t=e.tagName.toLowerCase();if(["section","article","aside","main","nav","header","footer","form"].includes(t)||e.hasAttribute("id")||e.hasAttribute("data-testid")||e.getAttribute("role")||e.children.length>1&&e.querySelector(":scope > *:nth-child(3)"))return!0;const s=e.getAttribute("style")||"";return!!(s.includes("grid")||s.includes("flex"))}boundedHtml(e,t){const s=e.outerHTML;return s.length<=t?s:s.slice(0,t)+` +`}}function Rt(l){try{return new Y(l.ownerDocument).bestSelector(l).selector}catch{return l.tagName.toLowerCase()}}class Ot{constructor(e){b(this,"nodeRegistry");b(this,"snapshotEngine");b(this,"picker");b(this,"interactionEngine");b(this,"observer");b(this,"mutationEngines",new WeakMap);b(this,"viewportControllers",new WeakMap);b(this,"targetingEngines",new WeakMap);b(this,"jsEngine",new Fe);b(this,"fingerprintEngine",new te);b(this,"humanInteraction",new it);b(this,"session",new Tt);b(this,"simulationTabs",[]);b(this,"simulationTabCounter",0);b(this,"simulationExtensions",[{id:"teledom@teledom",name:"TeleDOM Browser Intelligence Platform",version:"4.1.0",description:"The TeleDOM platform extension itself",enabled:!0,installType:"development",isApp:!1}]);b(this,"regionCapture",new Mt);this.nodeRegistry=e||new H;const t=new J,s=new ne;this.snapshotEngine=new he(this.nodeRegistry,t,s),this.picker=new Pe({nodeRegistry:this.nodeRegistry}),this.interactionEngine=new Le(this.nodeRegistry),this.observer=new qe(this.nodeRegistry),this.picker.initGlobalShortcutListener(),this.interactionEngine.setTimingHook(async n=>{const i=this.humanInteraction.delay(n);i>0&&await new Promise(r=>setTimeout(r,i))})}getMutationEngine(e){let t=this.mutationEngines.get(e);return t||(t=new Ue(e,this.nodeRegistry),this.mutationEngines.set(e,t)),t}getViewportController(e){let t=this.viewportControllers.get(e);return t||(t=new Be(e),this.viewportControllers.set(e,t)),t}getTargetingEngine(e){let t=this.targetingEngines.get(e);return t||(t=new tt(e,this.nodeRegistry),this.targetingEngines.set(e,t)),t}isSimulation(){return typeof globalThis.__FORENSIC_SIMULATION__<"u"}getPicker(){return this.picker}getInteractionEngine(){return this.interactionEngine}getObserver(){return this.observer}getNodeRegistry(){return this.nodeRegistry}async handleCommand(e,t=typeof document<"u"?document:{}){var o,a,c,u,h,g,p,y,v;const s=Date.now(),{id:n,command:i,payload:r}=e;try{switch(i){case"LIVE_PAGE_INSPECT":{const m=k.inspectPage(t);return this.success(n,i,m,s)}case"LIVE_ELEMENT_INSPECT":{const m=this.resolveTarget(r,t),d=k.inspectElement(m,this.nodeRegistry);return this.success(n,i,d,s)}case"GET_SELECTED_ELEMENT":{const m=this.picker.getLastSelectedElement();return this.success(n,i,m,s)}case"ELEMENT_PICKER_START":return this.picker.startPicker(),this.success(n,i,{pickerActive:!0},s);case"ELEMENT_PICKER_STOP":return this.picker.stopPicker(),this.success(n,i,{pickerActive:!1},s);case"LIVE_ELEMENT_INTERACT":{const m=r,d=await this.interactionEngine.interact(m,t);return this.success(n,i,d,s)}case"ELEMENT_OBSERVATION_START":{const m=this.resolveTarget(r,t),d=this.observer.startObservation(m,t);return this.success(n,i,d,s)}case"ELEMENT_OBSERVATION_STOP":{const m=this.observer.stopObservation(t);return this.success(n,i,m,s)}case"LIVE_DOM_SNAPSHOT":{if(((r==null?void 0:r.format)||"html")==="html"){const f=((o=t.documentElement)==null?void 0:o.outerHTML)||"";return this.success(n,i,{html:f},s)}const d=this.snapshotEngine.captureSnapshot(t,"live_session");return this.success(n,i,d,s)}case"LIVE_DOM_SUBTREE":{const m=this.resolveTarget(r,t),d=m.outerHTML||"",f=k.inspectElement(m,this.nodeRegistry);return this.success(n,i,{html:d,element:f},s)}case"GET_ELEMENT_VISUAL_STATE":{const m=this.resolveTarget(r,t),d=k.inspectVisualState(m);return this.success(n,i,d,s)}case"LIVE_PAGE_SCREENSHOT":case"LIVE_ELEMENT_SCREENSHOT":{const m=await this.handleScreenshotCapture(i,r,t);return this.success(n,i,m,s)}case"GET_TAB_CONSOLE_LOGS":{const{level:m,searchQuery:d,limit:f=100,clearAfterRead:w}=r||{};let E=typeof window<"u"&&window.__FORENSIC_CONSOLE_BUFFER__||[];if(m&&m!=="all"&&(E=E.filter(S=>S.level===m)),d){const S=String(d).toLowerCase();E=E.filter(T=>{var x,N;return((x=T.text)==null?void 0:x.toLowerCase().includes(S))||((N=T.source)==null?void 0:N.toLowerCase().includes(S))})}return f>0&&(E=E.slice(-f)),w&&typeof window<"u"&&window.__FORENSIC_CONSOLE_BUFFER__&&(window.__FORENSIC_CONSOLE_BUFFER__.length=0),this.success(n,i,{url:typeof window<"u"?window.location.href:"",title:t.title||"",totalCaptured:typeof window<"u"&&((a=window.__FORENSIC_CONSOLE_BUFFER__)==null?void 0:a.length)||E.length,returnedCount:E.length,logs:E},s)}case"GET_TAB_NETWORK_REQUESTS":{const{method:m,searchQuery:d,status:f,onlyErrors:w,limit:E=100,clearAfterRead:S}=r||{};let T=typeof window<"u"&&window.__FORENSIC_NETWORK_BUFFER__||[];if(m&&(T=T.filter(x=>{var N;return((N=x.method)==null?void 0:N.toUpperCase())===String(m).toUpperCase()})),f&&(T=T.filter(x=>x.status===Number(f))),w&&(T=T.filter(x=>x.error||x.status&&x.status>=400)),d){const x=String(d).toLowerCase();T=T.filter(N=>{var D;return(D=N.url)==null?void 0:D.toLowerCase().includes(x)})}return E>0&&(T=T.slice(-E)),S&&typeof window<"u"&&window.__FORENSIC_NETWORK_BUFFER__&&(window.__FORENSIC_NETWORK_BUFFER__.length=0),this.success(n,i,{url:typeof window<"u"?window.location.href:"",title:t.title||"",totalCaptured:typeof window<"u"&&((c=window.__FORENSIC_NETWORK_BUFFER__)==null?void 0:c.length)||T.length,returnedCount:T.length,requests:T},s)}case"CLOSE_TAB":{if(typeof globalThis.chrome<"u"&&((u=globalThis.chrome.runtime)!=null&&u.sendMessage)){const m=await new Promise(d=>{globalThis.chrome.runtime.sendMessage({type:"BROWSER_COMMAND_REQUEST",id:n,command:i,payload:r},f=>d(f))});if(m)return m}return this.isSimulation()?this.simulationCloseTab(r,t,n,i,s):typeof window<"u"?(setTimeout(()=>window.close(),100),this.success(n,i,{closed:!0,url:window.location.href,title:t.title},s)):this.success(n,i,{closed:!0},s)}case"RELOAD_TAB":{if(typeof globalThis.chrome<"u"&&((h=globalThis.chrome.runtime)!=null&&h.sendMessage)){const m=await new Promise(d=>{globalThis.chrome.runtime.sendMessage({type:"BROWSER_COMMAND_REQUEST",id:n,command:i,payload:r},f=>d(f))});if(m)return m}if(this.isSimulation()){const m=(r==null?void 0:r.mode)||"soft";return this.session.timeline.record("NAVIGATED",`tab reloaded (${m} mode)`),this.success(n,i,{reloaded:!0,mode:m,simulated:!0,url:((p=(g=t.defaultView)==null?void 0:g.location)==null?void 0:p.href)||"",title:t.title,note:"Node simulation context: DOM fixture retained; no real navigation occurs."},s)}return typeof window<"u"?(setTimeout(()=>window.location.reload(),100),this.success(n,i,{reloaded:!0,url:window.location.href,title:t.title},s)):this.success(n,i,{reloaded:!0},s)}case"OPEN_TAB":case"LIST_TABS":case"FOCUS_TAB":case"LIST_EXTENSIONS":case"RELOAD_EXTENSION":case"SET_EXTENSION_ENABLED":case"TOGGLE_EXTENSION":{if(this.isSimulation())return this.handleSimulationBackgroundCommand(n,i,r,t,s);if(typeof globalThis.chrome<"u"&&((y=globalThis.chrome.runtime)!=null&&y.sendMessage)){const m=await new Promise(d=>{globalThis.chrome.runtime.sendMessage({type:"BROWSER_COMMAND_REQUEST",id:n,command:i,payload:r},f=>d(f))});if(m)return m}return this.error(n,i,"BACKGROUND_EXECUTION_FAILED",`Command ${i} requires Chrome extension runtime`,s)}case"RESIZE_VIEWPORT":{const m=this.getViewportController(t);let d;if(r!=null&&r.preset)d=m.applyPreset(r.preset);else{const f=Number(r==null?void 0:r.width)||1280,w=Number(r==null?void 0:r.height)||800;d=m.resize(f,w)}return this.session.timeline.record("RESIZED",`viewport → ${d.applied.width}x${d.applied.height}`),this.success(n,i,d,s)}case"RESET_VIEWPORT":{const d=this.getViewportController(t).reset();return this.session.timeline.record("RESIZED",`viewport restored to ${d.applied.width}x${d.applied.height}`),this.success(n,i,d,s)}case"GET_VIEWPORT_STATE":{const m=this.getViewportController(t);return this.success(n,i,m.state(),s)}case"RUN_RESPONSIVE_TEST":{const m=this.getViewportController(t),d=(r==null?void 0:r.sizes)||Pt(),f=m.runResponsiveTest(d,{restore:(r==null?void 0:r.restore)!==!1});return this.success(n,i,f,s)}case"EMULATE_DEVICE":{const d=this.getViewportController(t).emulateDevice((r==null?void 0:r.device)||"pixel-7");return this.success(n,i,d,s)}case"EXECUTE_JS":case"EXECUTE_JS_AND_CAPTURE_CHANGES":{const m=String((r==null?void 0:r.code)||"");if(!m.trim())return this.error(n,i,"SCRIPT_EMPTY","payload.code is required.",s);const d=await this.jsEngine.execute(t,m,{timeoutMs:r==null?void 0:r.timeoutMs,world:(r==null?void 0:r.world)==="MAIN"?"MAIN":"ISOLATED"});return this.session.timeline.record("SCRIPT_EXECUTED",`${d.status} (${d.durationMs}ms)`),this.success(n,i,d,s)}case"DOM_MUTATE":{const d=this.getMutationEngine(t).mutate(r);return this.session.timeline.record("DOM_MUTATED",`${d.operation} on ${d.before.selector} → ${d.success?"OK":d.error}`),this.success(n,i,d,s)}case"DOM_MUTATE_TRANSACTION":{const m=this.getMutationEngine(t),d=(r==null?void 0:r.mode)||"begin";try{if(d==="begin"){const f=m.beginTransaction();return this.success(n,i,{transactionId:f,mode:d,open:!0},s)}if(d==="commit"){const f=m.commitTransaction();return this.session.timeline.record("DOM_MUTATED",`transaction ${f.transactionId} committed (${f.steps.length} steps)`),this.success(n,i,{...f,mode:d},s)}if(d==="rollback"){const f=m.rollbackTransaction(r==null?void 0:r.reason);return this.session.timeline.record("MUTATION_UNDONE",`transaction ${f.transactionId} rolled back`),this.success(n,i,{...f,mode:d},s)}return this.error(n,i,"INVALID_MODE",`mode must be begin|commit|rollback, got "${d}"`,s)}catch(f){return this.error(n,i,"DOM_MUTATION_FAILED",f.message,s)}}case"UNDO_DOM_MUTATION":{const d=this.getMutationEngine(t).undo();return d.success&&this.session.timeline.record("MUTATION_UNDONE",d.message),this.success(n,i,d,s)}case"REDO_DOM_MUTATION":{const d=this.getMutationEngine(t).redo();return d.success&&this.session.timeline.record("MUTATION_REDONE",d.message),this.success(n,i,d,s)}case"GET_MUTATION_HISTORY":{const m=this.getMutationEngine(t);return this.success(n,i,{entries:m.getHistory((r==null?void 0:r.limit)||100),undoDepth:m.getUndoDepth(),redoDepth:m.getRedoDepth(),openTransactionId:m.getOpenTransactionId()},s)}case"PREVIEW_DOM_MUTATION":{const d=this.getMutationEngine(t).preview(r);return this.success(n,i,d,s)}case"GENERATE_ELEMENT_TARGET":{const d=this.getTargetingEngine(t).resolveAndBuild((r==null?void 0:r.target)||(r==null?void 0:r.selector)||"");return"error"in d?this.error(n,i,"TARGET_NOT_FOUND",d.error,s):this.success(n,i,d.target,s)}case"RECOVER_SELECTOR":{const m=new nt(t),d=(r==null?void 0:r.snapshot)||{},f=m.recover((r==null?void 0:r.selector)||"",d);return this.success(n,i,f,s)}case"GET_ELEMENT_ANCESTRY":{const m=this.resolveTarget(r,t);return this.success(n,i,Lt(m,t),s)}case"GET_ELEMENT_FINGERPRINT":{const m=this.resolveTarget(r,t),d=this.fingerprintEngine.fingerprint(m);return this.success(n,i,d,s)}case"GET_ELEMENT_RELATIONSHIPS":{const m=this.resolveTarget(r,t);return this.success(n,i,Dt(m,t),s)}case"GET_ELEMENT_ACCESSIBILITY":{const m=this.resolveTarget(r,t);return this.success(n,i,$t(m),s)}case"GET_COMPUTED_STYLE":{const m=this.resolveTarget(r,t),d=t.defaultView;if(!(d!=null&&d.getComputedStyle))return this.error(n,i,"STYLE_UNAVAILABLE","getComputedStyle is unavailable in this context.",s);const f=d.getComputedStyle(m),w=Array.isArray(r==null?void 0:r.properties)&&r.properties.length?r.properties:["display","position","color","background-color","font-size","font-family","width","height","margin","padding","border","z-index","opacity","visibility","overflow","flex-direction","grid-template-columns"],E={};for(const S of w)E[S]=f.getPropertyValue(S);return this.success(n,i,{selector:k.inspectElement(m,this.nodeRegistry).bestSelector,styles:E},s)}case"ANALYZE_DOM":{const m=String((r==null?void 0:r.analyzer)||"");if(!m)return this.error(n,i,"ANALYZER_REQUIRED",'payload.analyzer is required (e.g. "analyze_forms").',s);const d=Et(m,t,r);return d.count===0&&d.warnings.length===0&&d.items.length===0&&d.summary.startsWith("Unknown analyzer")?this.error(n,i,"UNKNOWN_ANALYZER",d.summary,s):this.success(n,i,d,s)}case"DRAG_ELEMENT":{const m=this.resolveTarget(r==null?void 0:r.source,t),d=r!=null&&r.target?this.resolveTarget(r==null?void 0:r.target,t):null,f=await this.performDrag(m,d,r==null?void 0:r.offsets,t);return this.success(n,i,f,s)}case"SET_INPUT_CHECKED":{const d=this.resolveTarget(r,t);if(d.type!=="checkbox"&&d.type!=="radio")return this.error(n,i,"INPUT_TYPE_UNSUPPORTED",`Target input type "${d.type}" is not checkbox/radio.`,s);const f=d.checked;d.checked=(r==null?void 0:r.checked)!==!1;const w=[];for(const E of["input","change"])try{d.dispatchEvent(new t.defaultView.Event(E,{bubbles:!0})),w.push(E)}catch{}if(d.type==="radio"&&d.name)for(const E of Array.from(t.querySelectorAll(`input[type=radio][name="${d.name}"]`)))E!==d&&(E.checked=!1);return this.success(n,i,{success:!0,selector:k.inspectElement(d,this.nodeRegistry).bestSelector,inputType:d.type,checkedBefore:f,checkedAfter:d.checked,eventsFired:w},s)}case"PRESS_KEYBOARD_SHORTCUT":{const m=Array.isArray(r==null?void 0:r.keys)?r.keys:String((r==null?void 0:r.keys)||"Enter").split("+"),d=r!=null&&r.target?this.resolveTarget(r==null?void 0:r.target,t):t.activeElement||t.body;typeof d.focus=="function"&&d.focus();const f=[],w=t.defaultView;for(const E of m)for(const S of["keydown","keyup"])try{d.dispatchEvent(new((w==null?void 0:w.KeyboardEvent)||KeyboardEvent)(S,{key:E.trim(),bubbles:!0,cancelable:!0,ctrlKey:m.some(T=>/^(ctrl|control|cmd|meta)$/i.test(T))&&E!==m.find(T=>/^(ctrl|control|cmd|meta)$/i.test(T)),shiftKey:m.some(T=>/^shift$/i.test(T))&&E!=="Shift",altKey:m.some(T=>/^alt$/i.test(T))&&E!=="Alt"})),f.push(`${S}:${E}`)}catch{}return this.success(n,i,{success:!0,keys:m,targetSelector:k.inspectElement(d,this.nodeRegistry).bestSelector,eventsFired:f},s)}case"SCROLL_PAGE":{const m=t.defaultView;if(!m)return this.error(n,i,"NO_WINDOW","No window available for scrolling.",s);const d={x:m.scrollX||0,y:m.scrollY||0};let f;if(r!=null&&r.target||r!=null&&r.selector){const E=this.resolveTarget((r==null?void 0:r.target)||(r==null?void 0:r.selector),t);(v=E.scrollIntoView)==null||v.call(E,{behavior:(r==null?void 0:r.behavior)||"auto",block:"center"}),f=k.inspectElement(E,this.nodeRegistry).bestSelector}else m.scrollBy(Number(r==null?void 0:r.x)||0,Number(r==null?void 0:r.y)||0);const w={x:m.scrollX||0,y:m.scrollY||0};return this.success(n,i,{success:!0,scrollBefore:d,scrollAfter:w,requested:{x:Number(r==null?void 0:r.x)||0,y:Number(r==null?void 0:r.y)||0},targetSelector:f},s)}case"WAIT_FOR_CONDITION":return await this.waitForCondition(t,r||{},s,n,i);case"GET_PAGE_STATE":case"CAPTURE_PAGE_STATE":{const m=this.session.captureSnapshot(t,!0,this.getMutationEngine(t).getUndoDepth());return this.success(n,i,m,s)}case"CAPTURE_REGION":{const m=this.resolveTarget((r==null?void 0:r.target)||(r==null?void 0:r.selector),t),d=this.regionCapture.capture(m);return this.success(n,i,d,s)}case"GET_SIMULATION_TAB_STATE":return this.isSimulation()?this.success(n,i,{simulated:!0,tabs:this.simulationTabs,sessionSummary:this.session.getTabs()},s):this.error(n,i,"NOT_SIMULATION","Simulation tab state is only available in the Node simulation context.",s);default:return this.error(n,i,"UNKNOWN_COMMAND",`Unsupported command '${i}'`,s)}}catch(m){return this.error(n,i,"COMMAND_EXECUTION_FAILED",m.message,s,m.details)}}resolveTarget(e,t){if(!e)throw new Error("Target specifier must be provided");return typeof e=="string"?this.interactionEngine.resolveTarget({selector:e},t):typeof e=="number"?this.interactionEngine.resolveTarget({nodeId:e},t):this.interactionEngine.resolveTarget(e,t)}async performDrag(e,t,s,n){const i=n.defaultView,r=[],o=(p,y,v={})=>{try{const m=(i==null?void 0:i.MouseEvent)||(typeof MouseEvent<"u"?MouseEvent:null);m&&(p.dispatchEvent(new m(y,{bubbles:!0,cancelable:!0,...v})),r.push(y))}catch{}},a=e.getBoundingClientRect(),c=a.x+a.width/2,u=a.y+a.height/2;let h=c+((s==null?void 0:s.x)||0),g=u+((s==null?void 0:s.y)||0);if(t){const p=t.getBoundingClientRect();h=p.x+p.width/2,g=p.y+p.height/2}return o(e,"pointerdown",{button:1,clientX:c,clientY:u}),o(e,"mousedown",{button:1,clientX:c,clientY:u}),o(e,"dragstart",{clientX:c,clientY:u}),t&&(o(t,"dragenter",{clientX:h,clientY:g}),o(t,"dragover",{clientX:h,clientY:g}),o(t,"drop",{clientX:h,clientY:g})),o(e,"dragend",{clientX:h,clientY:g}),o(e,"pointerup",{button:1,clientX:h,clientY:g}),o(e,"mouseup",{button:1,clientX:h,clientY:g}),{success:r.length>0,sourceSelector:k.inspectElement(e,this.nodeRegistry).bestSelector,targetSelector:t?k.inspectElement(t,this.nodeRegistry).bestSelector:"(offset drop)",eventsFired:r,finalPosition:{x:Math.round(h),y:Math.round(g)},html5DndUsed:r.includes("dragstart")}}async waitForCondition(e,t,s,n,i){var p,y;const r=t.kind||"dom_stable",o=Math.min(Math.max(Number(t.timeoutMs)||5e3,100),3e4),a=Math.min(Math.max(Number(t.pollIntervalMs)||100,20),1e3),c=Date.now(),u=()=>{var v,m,d,f,w;switch(r){case"dom_stable":return{satisfied:!0,detail:`dom length ${((v=e.documentElement)==null?void 0:v.outerHTML.length)||0}`};case"selector_present":{const E=t.selector?e.querySelectorAll(t.selector).length:0;return{satisfied:E>0,detail:`"${t.selector}" matches ${E} element(s)`}}case"selector_visible":{if(!t.selector)return{satisfied:!1,detail:"no selector supplied"};const E=e.querySelector(t.selector);if(!E)return{satisfied:!1,detail:`"${t.selector}" not present`};try{const S=k.inspectElement(E).visibility.isVisible;return{satisfied:S,detail:`visibility=${S}`}}catch{return{satisfied:!1,detail:"inspection failed"}}}case"selector_absent":{const E=t.selector?e.querySelectorAll(t.selector).length:0;return{satisfied:E===0,detail:`"${t.selector}" matches ${E} element(s)`}}case"text_present":{const E=((m=e.body)==null?void 0:m.innerText)||((d=e.body)==null?void 0:d.textContent)||"",S=t.text?E.includes(String(t.text)):!1;return{satisfied:S,detail:`text "${String(t.text).slice(0,30)}" ${S?"found":"not found"}`}}case"url_contains":{const E=((w=(f=e.defaultView)==null?void 0:f.location)==null?void 0:w.href)||"";return{satisfied:t.text?E.includes(String(t.text)):!1,detail:E}}case"element_count":{const E=t.selector?e.querySelectorAll(t.selector).length:0,S=Number(t.count)||0;return{satisfied:E===S,detail:`${E}/${S} elements`}}case"readiness_state":return{satisfied:e.readyState===(t.state||"complete"),detail:`readyState=${e.readyState}`};default:return{satisfied:!1,detail:`unknown condition kind "${r}"`}}};if(r==="dom_stable"){let v=((p=e.documentElement)==null?void 0:p.outerHTML.length)||0,m=!1,d=0;for(;Date.now()-c setTimeout(E,a));const w=((y=e.documentElement)==null?void 0:y.outerHTML.length)||0;if(d++,w===v){m=!0;break}v=w}const f=Date.now()-c;return m&&this.session.timeline.record("WAIT_SATISFIED",`dom_stable after ${f}ms (${d} polls)`),this.success(n,i,{satisfied:m,condition:r,waitedMs:f,timeoutMs:o,detail:`dom length ${v}, ${d} polls`},s)}let h=u();for(;!h.satisfied&&Date.now()-c setTimeout(v,a)),h=u();const g=Date.now()-c;return h.satisfied&&this.session.timeline.record("WAIT_SATISFIED",`${r} after ${g}ms`),this.success(n,i,{satisfied:h.satisfied,condition:r,waitedMs:g,timeoutMs:o,detail:h.detail},s)}simulationCloseTab(e,t,s,n,i){const r=Number(e==null?void 0:e.tabId),o=Number.isFinite(r)?this.simulationTabs.findIndex(c=>c.browserTabId===r):this.simulationTabs.findIndex(c=>c.active);if(o<0)return this.error(s,n,"TAB_NOT_FOUND",`No simulated tab matches tabId=${r}`,i);const a=this.simulationTabs.splice(o,1)[0];return this.session.closeTab(a.sessionTabId),a.active&&this.simulationTabs.length&&(this.simulationTabs[0].active=!0,this.session.switchTab(this.simulationTabs[0].sessionTabId)),this.success(s,n,{closed:!0,closedTab:{id:a.browserTabId,url:a.url,title:a.title},simulated:!0,remaining:this.simulationTabs.length},i)}handleSimulationBackgroundCommand(e,t,s,n,i){const r=()=>{var o,a;if(!this.simulationTabs.length){this.simulationTabCounter++;const c={sessionTabId:`stab_${this.simulationTabCounter}`,browserTabId:this.simulationTabCounter,url:((a=(o=n.defaultView)==null?void 0:o.location)==null?void 0:a.href)||"about:blank",title:n.title||"Simulated Tab",active:!0,createdAt:Date.now()};this.simulationTabs.push(c),this.session.registerTab(c.browserTabId,c.url,c.title),this.session.switchTab(c.sessionTabId)}};switch(t){case"LIST_TABS":return r(),this.success(e,t,{simulated:!0,environment:"node-simulation",tabs:this.simulationTabs.map((o,a)=>({id:o.browserTabId,index:a,windowId:1,title:o.title,url:o.url,active:o.active,status:"complete",pinned:!1,audited:!1})),note:"Deterministic simulated tab state — a real browser tab list requires the Chrome extension connection."},i);case"OPEN_TAB":{const o=String((s==null?void 0:s.url)||"about:blank");this.simulationTabCounter++;const a={sessionTabId:`stab_${this.simulationTabCounter}`,browserTabId:this.simulationTabCounter,url:o,title:(s==null?void 0:s.title)||`Simulated Tab ${this.simulationTabCounter}`,active:!0,createdAt:Date.now()};this.simulationTabs.forEach(u=>u.active=!1),this.simulationTabs.push(a);const c=this.session.registerTab(a.browserTabId,o,a.title);return this.session.switchTab(c.sessionTabId),this.session.timeline.record("TAB_OPENED",`simulation tab ${a.browserTabId} → ${o}`),this.success(e,t,{opened:!0,tabId:a.browserTabId,url:o,simulated:!0,totalTabs:this.simulationTabs.length},i)}case"FOCUS_TAB":{r();const o=Number(s==null?void 0:s.tabId),a=this.simulationTabs.find(c=>c.browserTabId===o)||this.simulationTabs[0];return a?(this.simulationTabs.forEach(c=>c.active=!1),a.active=!0,this.session.switchTab(a.sessionTabId),this.session.timeline.record("TAB_SWITCHED",`simulation tab ${a.browserTabId} focused`),this.success(e,t,{focused:!0,tabId:a.browserTabId,url:a.url,simulated:!0},i)):this.error(e,t,"TAB_NOT_FOUND",`No simulated tab with tabId=${o}`,i)}case"LIST_EXTENSIONS":return this.success(e,t,{simulated:!0,extensions:this.simulationExtensions.map(o=>({...o,permissions:["activeTab","scripting","storage","tabs","management"]})),note:"Deterministic simulated extension state."},i);case"SET_EXTENSION_ENABLED":{const o=String((s==null?void 0:s.extensionId)||""),a=this.simulationExtensions.find(c=>c.id===o||c.name.toLowerCase().includes(o.toLowerCase()));return a?(a.enabled=!!(s!=null&&s.enabled),this.session.timeline.record("EXTENSION_STATE_CHANGED",`${a.id} → ${a.enabled?"enabled":"disabled"}`),this.success(e,t,{extensionId:a.id,enabled:a.enabled,simulated:!0},i)):this.error(e,t,"EXTENSION_NOT_FOUND",`No simulated extension matches "${o}". Known: ${this.simulationExtensions.map(c=>c.id).join(", ")}`,i)}case"TOGGLE_EXTENSION":{const o=String((s==null?void 0:s.extensionId)||""),a=this.simulationExtensions.find(c=>c.id===o||c.name.toLowerCase().includes(o.toLowerCase()));return a?(a.enabled=!a.enabled,this.session.timeline.record("EXTENSION_STATE_CHANGED",`${a.id} → ${a.enabled?"enabled":"disabled"}`),this.success(e,t,{extensionId:a.id,enabled:a.enabled,simulated:!0},i)):this.error(e,t,"EXTENSION_NOT_FOUND",`No simulated extension matches "${o}".`,i)}case"RELOAD_EXTENSION":{const o=String((s==null?void 0:s.extensionId)||this.simulationExtensions[0].id),a=this.simulationExtensions.find(c=>c.id===o||c.name.toLowerCase().includes(o.toLowerCase()));return a?this.success(e,t,{reloaded:!0,extensionId:a.id,simulated:!0,note:"Simulated reload: extension state preserved."},i):this.error(e,t,"EXTENSION_NOT_FOUND",`No simulated extension matches "${o}".`,i)}default:return this.error(e,t,"UNKNOWN_COMMAND",`Unhandled simulation command '${t}'`,i)}}async handleScreenshotCapture(e,t,s){var y,v,m,d,f;const n=s.defaultView||(typeof window<"u"?window:{}),i=Date.now(),r=`scr_${i}_${Math.random().toString(36).slice(2,6)}`,o=n.devicePixelRatio||1,a={width:n.innerWidth||((y=s.documentElement)==null?void 0:y.clientWidth)||1920,height:n.innerHeight||((v=s.documentElement)==null?void 0:v.clientHeight)||1080,scrollX:n.scrollX||n.pageXOffset||0,scrollY:n.scrollY||n.pageYOffset||0,devicePixelRatio:o};let c,u,h,g={width:a.width,height:a.height};if(e==="LIVE_ELEMENT_SCREENSHOT"){const w=this.resolveTarget(t,s),E=k.inspectElement(w,this.nodeRegistry);c=E.bestSelector,u=((m=E.forensics)==null?void 0:m.logicalNodeId)||void 0,h={x:E.bounds.x,y:E.bounds.y,width:E.bounds.width,height:E.bounds.height},g={width:Math.max(1,Math.round(E.bounds.width*o)),height:Math.max(1,Math.round(E.bounds.height*o))}}let p=(t==null?void 0:t.dataUrl)||"";if(e==="LIVE_ELEMENT_SCREENSHOT"&&p&&h&&typeof Image<"u")try{const w=await new Promise(E=>{const S=new Image;S.onload=()=>{try{const T=s.createElement("canvas"),x=Math.max(0,Math.floor(h.x*o)),N=Math.max(0,Math.floor(h.y*o)),D=Math.max(1,Math.floor(h.width*o)),M=Math.max(1,Math.floor(h.height*o));T.width=D,T.height=M;const L=T.getContext("2d");if(L){L.drawImage(S,x,N,D,M,0,0,D,M),E(T.toDataURL("image/png"));return}}catch{}E(p)},S.onerror=()=>E(p),S.src=p});w&&(p=w)}catch{}if(!p){const w=e==="LIVE_ELEMENT_SCREENSHOT"?Math.max(120,g.width||320):Math.max(800,a.width||1280),E=e==="LIVE_ELEMENT_SCREENSHOT"?Math.max(60,g.height||180):Math.max(600,a.height||800);p=ge.createDataUrl({width:w,height:E,backgroundColor:e==="LIVE_ELEMENT_SCREENSHOT"?[30,41,59,255]:[15,23,42,255],headerColor:[56,189,248,255],borderColor:[99,102,241,255],label:c||(e==="LIVE_ELEMENT_SCREENSHOT"?"Element Screenshot":"Page Screenshot")})}return{screenshotId:r,timestamp:i,url:((d=n.location)==null?void 0:d.href)||((f=s.location)==null?void 0:f.href)||"",viewport:a,targetSelector:c,targetNodeId:u,targetBounds:h,dataUrl:p,imageFormat:"png",dimensions:g,captureType:e==="LIVE_ELEMENT_SCREENSHOT"?"ELEMENT":"FULL_PAGE"}}success(e,t,s,n){return{id:e,command:t,success:!0,data:s,timestamp:Date.now(),durationMs:Date.now()-n}}error(e,t,s,n,i,r){return{id:e,command:t,success:!1,error:{code:s,message:n,details:r},timestamp:Date.now(),durationMs:Date.now()-i}}}function Lt(l,e){const t=[];let s=l.parentElement,n=1;for(;s&&n<=10;){const h=s.parentElement,g=h?Array.from(h.children).filter(p=>p.tagName===s.tagName):[];t.push({tag:s.tagName.toLowerCase(),selector:U(s),role:s.getAttribute("role")||void 0,text:B(s).slice(0,40),childIndex:g.length?g.indexOf(s)+1:1,siblingCount:h?Array.from(h.children).length:0,distance:n}),s=s.parentElement,n++}const i=l.parentElement,r=[];if(i){const h=Array.from(i.children),g=h.indexOf(l);for(let p=g-1;p>=0&&p>=g-5;p--)r.push({tag:h[p].tagName.toLowerCase(),selector:U(h[p]),role:h[p].getAttribute("role")||void 0,text:B(h[p]).slice(0,30),position:"before",distance:g-p});for(let p=g+1;p {o=Math.max(o,g);for(const p of Array.from(h.children))a.push(p.tagName.toLowerCase()),p.matches('a[href], button, input, select, textarea, [role="button"], [onclick]')&&c.push(U(p)),g<6&&u(p,g+1)};return u(l,1),{selector:U(l),ancestors:t,siblings:r,descendants:{count:l.querySelectorAll("*").length,maxDepth:o,tags:Array.from(new Set(a)).slice(0,30),interactive:c.slice(0,30)}}}function Dt(l,e){const t=[{id:"self",selector:U(l),tag:l.tagName.toLowerCase(),role:l.getAttribute("role")||void 0,label:B(l).slice(0,30)||l.tagName.toLowerCase(),relationship:"self",depth:0}],s=[];let n=l.parentElement,i=1;for(;n&&i<=4;){const o=`ancestor_${i}`;t.push({id:o,selector:U(n),tag:n.tagName.toLowerCase(),role:n.getAttribute("role")||void 0,label:B(n).slice(0,30)||n.tagName.toLowerCase(),relationship:"parent",depth:i}),s.push({from:o,to:i===1?"self":`ancestor_${i-1}`,relation:"parent-of"}),n=n.parentElement,i++}for(const o of Array.from(l.children).slice(0,12)){const a=`child_${t.length}`;t.push({id:a,selector:U(o),tag:o.tagName.toLowerCase(),role:o.getAttribute("role")||void 0,label:B(o).slice(0,30)||o.tagName.toLowerCase(),relationship:"child",depth:1}),s.push({from:"self",to:a,relation:"contains"})}const r=l.parentElement;if(r)for(const o of Array.from(r.children).slice(0,12)){if(o===l)continue;const a=`sibling_${t.length}`;t.push({id:a,selector:U(o),tag:o.tagName.toLowerCase(),role:o.getAttribute("role")||void 0,label:B(o).slice(0,30)||o.tagName.toLowerCase(),relationship:"sibling",depth:1}),s.push({from:"self",to:a,relation:"sibling-of"})}return{rootSelector:U(l),nodes:t,edges:s}}function $t(l){const e={};for(const v of Array.from(l.attributes))v.name.startsWith("aria-")&&(e[v.name]=v.value);const t=B(l).trim(),s=l.getAttribute("aria-label"),n=l.getAttribute("aria-labelledby");let i;n&&(i=n.split(/\s+/).map(m=>{var d,f,w;return(w=(f=(d=l.ownerDocument)==null?void 0:d.getElementById(m))==null?void 0:f.textContent)==null?void 0:w.trim()}).filter(Boolean).join(" ").slice(0,60)||void 0);const r=l.getAttribute("title"),o=l.tagName.toLowerCase(),a=[];let c="";s?(c=s,a.push("aria-label")):i?(c=i,a.push("aria-labelledby")):t?(c=t.slice(0,60),a.push("text content")):r&&(c=r,a.push("title"));const u=[];(l.disabled||l.hasAttribute("disabled"))&&u.push("disabled"),l.checked&&u.push("checked");const h=l;h.tagName==="SELECT"&&typeof h.selectedOptions<"u"&&h.selectedOptions.length>0&&u.push("selected"),l.getAttribute("aria-expanded")&&u.push(`expanded=${l.getAttribute("aria-expanded")}`),l.getAttribute("aria-pressed")&&u.push(`pressed=${l.getAttribute("aria-pressed")}`),l.getAttribute("aria-hidden")==="true"&&u.push("hidden"),l.hasAttribute("required")&&u.push("required"),l.readOnly&&u.push("readonly");const g=["a[href]","button","input","select","textarea","[tabindex]"].some(v=>{try{return l.matches(v)}catch{return!1}}),p=[];!c&&g&&p.push("Focusable element has no accessible name."),o==="img"&&!l.hasAttribute("alt")&&p.push("Image has no alt attribute.");const y=/^h([1-6])$/.exec(o);return y&&!t&&p.push(`Heading h${y[1]} is empty.`),{selector:U(l),role:l.getAttribute("role")||void 0,implicitRole:qt(l),name:c,nameSources:a,description:l.getAttribute("aria-describedby")||void 0,value:l.value!==void 0&&(l.getAttribute("type")||"text")!=="password"?String(l.value).slice(0,40):void 0,states:u,level:y?parseInt(y[1],10):void 0,focusable:g,tabIndex:l.tabIndex,ariaAttributes:e,issues:p}}function qt(l){switch(l.tagName.toLowerCase()){case"a":return l.getAttribute("href")?"link":void 0;case"button":return"button";case"nav":return"navigation";case"header":return"banner";case"footer":return"contentinfo";case"main":return"main";case"aside":return"complementary";case"article":return"article";case"form":return"form";case"input":{const t=l.getAttribute("type")||"text";return{checkbox:"checkbox",radio:"radio",button:"button",submit:"button",reset:"button",range:"slider",search:"searchbox",email:"textbox",text:"textbox",password:"textbox",tel:"textbox",url:"textbox",number:"spinbutton"}[t]||"textbox"}case"select":return l.hasAttribute("multiple")?"listbox":"combobox";case"textarea":return"textbox";case"img":return"img";case"table":return"table";case"ul":case"ol":return"list";case"li":return"listitem";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return"heading";case"dialog":return"dialog";default:return}}function U(l){const e=l.getAttribute("id");if(e&&/^[a-zA-Z][\w-]*$/.test(e))return`#${e}`;const t=l.getAttribute("data-testid");if(t)return`${l.tagName.toLowerCase()}[data-testid="${t}"]`;const s=l.tagName.toLowerCase(),n=Array.from(l.classList||[]).slice(0,2);return n.length?`${s}.${n.join(".")}`:s}function B(l){return Array.from(l.childNodes).filter(e=>e.nodeType===3).map(e=>(e.textContent||"").trim()).join(" ").replace(/\s+/g," ")}function Pt(){return[{label:"desktop-1440x900",width:1440,height:900},{label:"laptop-1024x768",width:1024,height:768},{label:"tablet-768x1024",width:768,height:1024},{label:"mobile-375x667",width:375,height:667}]}class Ut{constructor(e){b(this,"hostElement",null);b(this,"shadowRoot",null);b(this,"callbacks");b(this,"isRecording",!1);b(this,"isPaused",!1);b(this,"isMinimized",!1);b(this,"startTime",0);b(this,"eventCount",0);b(this,"timerInterval",null);b(this,"isDragging",!1);b(this,"dragStartX",0);b(this,"dragStartY",0);b(this,"posX",window.innerWidth-340);b(this,"posY",40);this.callbacks=e,this.loadPosition()}mount(){this.hostElement&&document.body.contains(this.hostElement)||(this.hostElement=document.createElement("div"),this.hostElement.id="forensic-recorder-floating-host",this.hostElement.style.all="initial",this.hostElement.style.position="fixed",this.hostElement.style.zIndex="2147483647",this.hostElement.style.left=`${this.posX}px`,this.hostElement.style.top=`${this.posY}px`,this.shadowRoot=this.hostElement.attachShadow({mode:"open"}),this.render(),this.attachEvents(),(document.body||document.documentElement).appendChild(this.hostElement))}unmount(){this.timerInterval&&(clearInterval(this.timerInterval),this.timerInterval=null),this.hostElement&&this.hostElement.parentNode&&this.hostElement.parentNode.removeChild(this.hostElement),this.hostElement=null,this.shadowRoot=null}hide(){this.hostElement&&(this.hostElement.style.setProperty("display","none","important"),this.hostElement.style.setProperty("visibility","hidden","important"),this.hostElement.style.setProperty("opacity","0","important"))}show(){this.hostElement&&(this.hostElement.style.removeProperty("display"),this.hostElement.style.removeProperty("visibility"),this.hostElement.style.removeProperty("opacity"))}updateState(e,t=!1,s=0,n=0){this.isRecording=e,this.isPaused=t,this.startTime=s||(e?Date.now():0),this.eventCount=n,this.shadowRoot&&(this.render(),this.attachEvents()),this.isRecording&&!this.isPaused?this.startTimer():this.stopTimer()}incrementEventCount(){var t;this.eventCount++;const e=(t=this.shadowRoot)==null?void 0:t.querySelector("#evt-badge");e&&(e.textContent=`${this.eventCount} evts`)}startTimer(){this.stopTimer(),this.timerInterval=setInterval(()=>{var t;const e=(t=this.shadowRoot)==null?void 0:t.querySelector("#timer-display");if(e&&this.startTime){const s=(Date.now()-this.startTime)/1e3,n=Math.floor(s/60).toString().padStart(2,"0"),i=(s%60).toFixed(1).padStart(4,"0");e.textContent=`${n}:${i}`}},200)}stopTimer(){this.timerInterval&&(clearInterval(this.timerInterval),this.timerInterval=null)}savePosition(){try{sessionStorage.setItem("forensic_overlay_pos",JSON.stringify({x:this.posX,y:this.posY,min:this.isMinimized}))}catch{}}loadPosition(){try{const e=sessionStorage.getItem("forensic_overlay_pos");if(e){const t=JSON.parse(e);this.posX=Math.max(10,Math.min(window.innerWidth-300,t.x||this.posX)),this.posY=Math.max(10,Math.min(window.innerHeight-150,t.y||this.posY)),this.isMinimized=!!t.min}}catch{}}render(){if(!this.shadowRoot)return;const e=` :host { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; font-size: 12px; @@ -288,4 +288,4 @@ ${t} e.toTimestamp||typeof e.targetNodeId=="number"&&h.targetNodeId!==e.targetNodeId)),typeof e.offset=="number"&&(m=m.slice(e.offset)),typeof e.limit=="number"&&(m=m.slice(0,e.limit))),c(m)},u.onerror=()=>t(u.error)})}async getEventCount(s){const e=await this.openDB();return new Promise((r,c)=>{const a=e.transaction("events","readonly").objectStore("events").index("sessionId").count(IDBKeyRange.only(s));a.onsuccess=()=>r(a.result),a.onerror=()=>c(a.error)})}async saveCheckpoint(s){const e=await this.openDB();return new Promise((r,c)=>{const t=e.transaction("checkpoints","readwrite");t.objectStore("checkpoints").put(s),t.oncomplete=()=>r(),t.onerror=()=>c(t.error)})}async getCheckpoints(s){const e=await this.openDB();return new Promise((r,c)=>{const o=e.transaction("checkpoints","readonly").objectStore("checkpoints").index("sessionId").getAll(IDBKeyRange.only(s));o.onsuccess=()=>{const a=o.result||[];a.sort((u,m)=>u.sequence-m.sequence),r(a)},o.onerror=()=>c(o.error)})}async saveInitialSnapshot(s,e){const r=await this.openDB();return new Promise((c,t)=>{const n=r.transaction("snapshots","readwrite");n.objectStore("snapshots").put({sessionId:s,snapshot:e}),n.oncomplete=()=>c(),n.onerror=()=>t(n.error)})}async getInitialSnapshot(s){const e=await this.openDB();return new Promise((r,c)=>{const n=e.transaction("snapshots","readonly").objectStore("snapshots").get(s);n.onsuccess=()=>r(n.result?n.result.snapshot:null),n.onerror=()=>c(n.error)})}async addAnnotation(s){const e=await this.openDB();return new Promise((r,c)=>{const t=e.transaction("annotations","readwrite");t.objectStore("annotations").put(s),t.oncomplete=()=>r(),t.onerror=()=>c(t.error)})}async getAnnotations(s){const e=await this.openDB();return new Promise((r,c)=>{const o=e.transaction("annotations","readonly").objectStore("annotations").index("sessionId").getAll(IDBKeyRange.only(s));o.onsuccess=()=>r(o.result||[]),o.onerror=()=>c(o.error)})}}const l=new E("ForensicExtensionDB");let d=null,S=null;const w=new Map,g=new Map;async function A(){return new Promise(i=>{try{chrome.tabs.query({active:!0,currentWindow:!0},s=>{if(chrome.runtime.lastError||!s||s.length===0)return i(null);i(s[0].id??null)})}catch{i(null)}})}try{(_=(T=chrome.debugger)==null?void 0:T.onEvent)==null||_.addListener((i,s,e)=>{try{for(const[r,c]of g.entries())if((i==null?void 0:i.tabId)===c||(i==null?void 0:i.targetId)===`tab_${c}`){d==null||d.send(JSON.stringify({type:"CDP_EVENT",sessionId:r,method:s,params:e,timestamp:Date.now()}));return}}catch{}})}catch{}async function O(i,s){if(i==="LIST_TABS")return new Promise((e,r)=>{chrome.tabs.query({},c=>{if(chrome.runtime.lastError)return r(new Error(chrome.runtime.lastError.message));const t=(c||[]).map(n=>({id:n.id,index:n.index,windowId:n.windowId,title:n.title||"Untitled",url:n.url||"",active:!!n.active,status:n.status,pinned:!!n.pinned,favIconUrl:n.favIconUrl,audited:n.id?w.has(n.id):!1,incognito:!!n.incognito,width:n.width,height:n.height}));e({totalTabs:t.length,tabs:t})})});if(i==="FOCUS_TAB"){const e=Number(s==null?void 0:s.tabId);if(!e)throw new Error("tabId is required for focus_tab");return new Promise((r,c)=>{chrome.tabs.update(e,{active:!0},t=>{var n;if(chrome.runtime.lastError||!t)return c(new Error(((n=chrome.runtime.lastError)==null?void 0:n.message)||`Tab ${e} not found`));t.windowId?chrome.windows.update(t.windowId,{focused:!0},()=>{r({focused:!0,tab:{id:t.id,windowId:t.windowId,title:t.title,url:t.url,active:t.active}})}):r({focused:!0,tab:{id:t.id,title:t.title,url:t.url,active:t.active}})})})}if(i==="RELOAD_TAB"){const e=!!(s!=null&&s.bypassCache),r=s!=null&&s.tabId?Number(s.tabId):void 0;return new Promise((c,t)=>{const n=o=>{chrome.tabs.reload(o,{bypassCache:e},()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message));chrome.tabs.get(o,a=>{c({reloaded:!0,tabId:o,bypassCache:e,url:a==null?void 0:a.url,title:a==null?void 0:a.title})})})};r?chrome.tabs.get(r,o=>{chrome.runtime.lastError||!o?chrome.tabs.query({active:!0,lastFocusedWindow:!0},a=>{const u=a&&a[0]?a[0]:null;u!=null&&u.id?n(u.id):t(new Error("No active tab found to reload"))}):n(r)}):chrome.tabs.query({active:!0,lastFocusedWindow:!0},o=>{const a=o&&o[0]?o[0]:null;if(!(a!=null&&a.id))return t(new Error("No active tab found to reload"));n(a.id)})})}if(i==="CLOSE_TAB"){const e=s!=null&&s.tabId?Number(s.tabId):void 0,r=s!=null&&s.url?String(s.url).toLowerCase():void 0;return new Promise((c,t)=>{const n=o=>{chrome.tabs.remove(o,()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message));c({closed:!0,tabIds:o,count:o.length})})};e?n([e]):r?chrome.tabs.query({},o=>{const u=(o||[]).filter(m=>{var h,f;return((h=m.url)==null?void 0:h.toLowerCase().includes(r))||((f=m.title)==null?void 0:f.toLowerCase().includes(r))}).map(m=>m.id).filter(Boolean);if(u.length===0)return c({closed:!1,message:`No open tab matched '${r}'`});n(u)}):chrome.tabs.query({active:!0,lastFocusedWindow:!0},o=>{const a=o&&o[0]?o[0]:null;if(!(a!=null&&a.id))return t(new Error("No active tab found to close"));n([a.id])})})}if(i==="OPEN_TAB"){const e=s==null?void 0:s.url;if(!e)throw new Error("url is required for open_tab");let r=String(e).trim();!r.startsWith("http://")&&!r.startsWith("https://")&&!r.startsWith("file://")&&!r.startsWith("chrome://")&&!r.startsWith("about:")&&(r.includes("meet.google.com")||r.includes("localhost")||r.includes(".com")||r.includes(".org")||r.includes(".net")||r.includes(".ir")||r.includes(".io")||r.includes(".app"))&&(r="https://"+r);const c=s.active!==!1,t=!!s.pinned;return new Promise((n,o)=>{chrome.tabs.create({url:r,active:c,pinned:t},a=>{if(chrome.runtime.lastError)return o(new Error(chrome.runtime.lastError.message));n({opened:!0,tabId:a.id,windowId:a.windowId,url:a.url||r,title:a.title||"New Tab",active:a.active,status:a.status})})})}if(i==="LIST_EXTENSIONS")return new Promise((e,r)=>{var c;if(!((c=chrome.management)!=null&&c.getAll))return r(new Error("chrome.management API not available"));chrome.management.getAll(t=>{if(chrome.runtime.lastError)return r(new Error(chrome.runtime.lastError.message));const n=(t||[]).map(o=>({id:o.id,name:o.name,version:o.version,description:o.description,enabled:o.enabled,installType:o.installType,isApp:o.isApp,homepageUrl:o.homepageUrl,permissions:o.permissions}));e({totalExtensions:n.length,extensions:n})})});if(i==="SET_EXTENSION_ENABLED"){const e=s==null?void 0:s.extensionId,r=!!(s!=null&&s.enabled);if(!e)throw new Error("extensionId is required for SET_EXTENSION_ENABLED");return new Promise((c,t)=>{var n;if(!((n=chrome.management)!=null&&n.setEnabled))return t(new Error("chrome.management API not available"));chrome.management.setEnabled(e,r,()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message||`Failed to set enabled state for ${e}`));c({success:!0,extensionId:e,enabled:r,message:`Extension ${e} successfully ${r?"enabled":"disabled"}.`})})})}if(i==="TOGGLE_EXTENSION"){const e=s==null?void 0:s.extensionId;if(!e)throw new Error("extensionId is required for TOGGLE_EXTENSION");return new Promise((r,c)=>{var t,n;if(!((t=chrome.management)!=null&&t.get)||!((n=chrome.management)!=null&&n.setEnabled))return c(new Error("chrome.management API not available"));chrome.management.get(e,o=>{var u;if(chrome.runtime.lastError||!o)return c(new Error(((u=chrome.runtime.lastError)==null?void 0:u.message)||`Extension ${e} not found`));const a=!o.enabled;chrome.management.setEnabled(e,a,()=>{if(chrome.runtime.lastError)return c(new Error(chrome.runtime.lastError.message||`Failed to toggle ${e}`));r({success:!0,extensionId:e,enabled:a,name:o.name,message:`Extension ${o.name} (${e}) toggled to ${a?"enabled":"disabled"}.`})})})})}if(i==="RESIZE_VIEWPORT"){const e=Math.max(200,Math.min(7680,Number(s==null?void 0:s.width)||1280)),r=Math.max(200,Math.min(4320,Number(s==null?void 0:s.height)||800));return new Promise((c,t)=>{chrome.windows.getCurrent({populate:!1},n=>{var o;if(chrome.runtime.lastError||!n)return t(new Error(((o=chrome.runtime.lastError)==null?void 0:o.message)||"No current window"));chrome.windows.update(n.id??chrome.windows.WINDOW_ID_CURRENT,{width:e,height:r,state:"normal"},a=>{var u;if(chrome.runtime.lastError||!a)return t(new Error(((u=chrome.runtime.lastError)==null?void 0:u.message)||"Window resize failed"));c({success:!0,applied:{width:a.width,height:a.height},previous:{width:n.width,height:n.height},original:{width:n.width,height:n.height},reversible:!0,mode:"browser-window",note:"Reset with reset_viewport — the content script tracks the original size."})})})})}if(i==="RESET_VIEWPORT")return new Promise((e,r)=>{chrome.windows.getCurrent({populate:!1},c=>{var t;if(chrome.runtime.lastError||!c)return r(new Error(((t=chrome.runtime.lastError)==null?void 0:t.message)||"No current window"));chrome.windows.update(c.id??chrome.windows.WINDOW_ID_CURRENT,{state:"maximized"},n=>{var o;if(chrome.runtime.lastError||!n)return r(new Error(((o=chrome.runtime.lastError)==null?void 0:o.message)||"Window restore failed"));e({success:!0,applied:{width:n.width,height:n.height},previous:{width:c.width,height:c.height},original:{width:n.width,height:n.height},reversible:!1,mode:"browser-window",note:"Window restored to maximized state."})})})});if(i==="RELOAD_EXTENSION"){const e=s==null?void 0:s.extensionId,r=chrome.runtime.id;return!e||e===r?(setTimeout(()=>chrome.runtime.reload(),150),{reloaded:!0,extensionId:r,isSelf:!0,message:"Forensic Recorder extension is reloading now."}):new Promise((c,t)=>{var n;if(!((n=chrome.management)!=null&&n.setEnabled))return t(new Error("chrome.management API not available"));chrome.management.setEnabled(e,!1,()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message||`Failed to disable ${e}`));setTimeout(()=>{chrome.management.setEnabled(e,!0,()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message||`Failed to re-enable ${e}`));c({reloaded:!0,extensionId:e,isSelf:!1,message:`Extension ${e} successfully reloaded.`})})},150)})})}if(i==="CDP_ATTACH"){const e=(s==null?void 0:s.tabId)!==void 0?Number(s.tabId):await A();if(e===null)throw new Error("No target tab available for CDP attach.");return new Promise((r,c)=>{var t;if(!((t=chrome.debugger)!=null&&t.attach))return c(new Error('CDP_UNAVAILABLE: chrome.debugger API not available (check the "debugger" permission).'));chrome.debugger.attach({tabId:e},"1.3",()=>{if(chrome.runtime.lastError)return c(new Error(`CDP_ATTACH failed: ${chrome.runtime.lastError.message}`));s!=null&&s.sessionId&&g.set(String(s.sessionId),e),chrome.debugger.getTargets(n=>{const o=(n||[]).find(a=>a.tabId===e)||{};r({attached:!0,sessionId:s==null?void 0:s.sessionId,tabId:e,targetId:o.id||`tab_${e}`,type:o.type||"page"})})})})}if(i==="CDP_COMMAND"){const{sessionId:e,method:r,params:c}=s||{};if(!r)throw new Error("CDP_COMMAND requires method");return new Promise((t,n)=>{var a;if(!((a=chrome.debugger)!=null&&a.sendCommand))return n(new Error('CDP_UNAVAILABLE: chrome.debugger API not available (check the "debugger" permission).'));const o=g.get(e);if(o===void 0)return n(new Error(`CDP_SESSION_NOT_FOUND: no tab bound to session '${e}' — attach first.`));chrome.debugger.sendCommand({tabId:o},r,c||{},u=>{if(chrome.runtime.lastError){t({__cdpError:!0,code:"CDP_PROTOCOL_ERROR",message:chrome.runtime.lastError.message,method:r});return}t({result:u??{}})})})}if(i==="CDP_DETACH"){const{sessionId:e}=s||{},r=g.get(e);return g.delete(e),r===void 0?{detached:!1,reason:"session not found"}:new Promise((c,t)=>{var n;if(!((n=chrome.debugger)!=null&&n.detach))return c({detached:!1,reason:"chrome.debugger unavailable"});chrome.debugger.detach({tabId:r},()=>{if(chrome.runtime.lastError)return c({detached:!1,reason:chrome.runtime.lastError.message});c({detached:!0,sessionId:e,tabId:r})})})}throw new Error(`Unsupported background command: ${i}`)}function I(){if(!(typeof WebSocket>"u"))try{const i=new WebSocket("ws://127.0.0.1:3847");let s=null;i.onopen=()=>{var e;d=i,console.log("[Forensic Extension] Connected to MCP Bridge on ws://127.0.0.1:3847"),S&&(clearInterval(S),S=null),i.send(JSON.stringify({type:"REGISTER_CLIENT",clientType:"SERVICE_WORKER",url:typeof chrome<"u"&&((e=chrome.runtime)!=null&&e.id)?`chrome-extension://${chrome.runtime.id}`:"service-worker",title:"Forensic Service Worker"})),s&&clearInterval(s),s=setInterval(()=>{if(i&&i.readyState===WebSocket.OPEN)try{i.send(JSON.stringify({type:"HEARTBEAT",timestamp:Date.now()}))}catch(r){console.warn("[TeleDOM SW] non-critical operation failed:",(r==null?void 0:r.message)??r)}},15e3)},i.onclose=()=>{s&&clearInterval(s),d=null,N()},i.onerror=()=>{s&&clearInterval(s),d=null,N()},i.onmessage=async e=>{try{const r=JSON.parse(e.data.toString());if(r.type==="BROWSER_COMMAND_REQUEST"){const{id:c,command:t,payload:n}=r;if(typeof chrome>"u"||!chrome.tabs){i.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"NO_CHROME_TABS_API",message:"chrome.tabs API not available in this context"}}));return}if(["LIST_TABS","FOCUS_TAB","RELOAD_TAB","CLOSE_TAB","OPEN_TAB","LIST_EXTENSIONS","RELOAD_EXTENSION","SET_EXTENSION_ENABLED","TOGGLE_EXTENSION","CDP_ATTACH","CDP_COMMAND","CDP_DETACH"].includes(t)){try{const u=await O(t,n);i.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!0,data:u}))}catch(u){i.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"COMMAND_ERROR",message:u.message}}))}return}const o=n!=null&&n.tabId?Number(n.tabId):void 0,a=u=>{if(t==="LIVE_PAGE_SCREENSHOT"||t==="LIVE_ELEMENT_SCREENSHOT"){chrome.tabs.sendMessage(u,{type:"HIDE_FORENSIC_OVERLAYS"},()=>{setTimeout(()=>{chrome.tabs.captureVisibleTab({format:"png"},m=>{var h;if(chrome.tabs.sendMessage(u,{type:"RESTORE_FORENSIC_OVERLAYS"}),chrome.runtime.lastError||!m){i.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"SCREENSHOT_FAILED",message:((h=chrome.runtime.lastError)==null?void 0:h.message)||"captureVisibleTab failed"}}));return}chrome.tabs.sendMessage(u,{type:"BROWSER_COMMAND_REQUEST",id:c,command:t,payload:{...n,dataUrl:m}},f=>{const C=f||{id:c,command:t,success:!0,data:{dataUrl:m,captureType:t==="LIVE_ELEMENT_SCREENSHOT"?"ELEMENT":"FULL_PAGE"}};i.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",...C}))})})},150)});return}chrome.tabs.sendMessage(u,r,m=>{if(chrome.runtime.lastError){i.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"CONTENT_SCRIPT_UNREACHABLE",message:chrome.runtime.lastError.message||`Content script unreachable on tab ${u}`}}));return}i.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",...m||{id:c,command:t,success:!0}}))})};o?a(o):chrome.tabs.query({active:!0,lastFocusedWindow:!0},async u=>{const m=u&&u[0]?u[0]:null,h=m==null?void 0:m.id;if(!h){i.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"NO_ACTIVE_TAB",message:"No active browser tab found"}}));return}a(h)})}}catch(r){console.error("[ServiceWorker] Bridge message handling error:",r)}}}catch{d=null,N()}}function N(){S||(S=setInterval(()=>{(!d||d.readyState!==WebSocket.OPEN)&&I()},5e3))}I(),typeof chrome<"u"&&((p=chrome.webNavigation)!=null&&p.onCommitted)&&chrome.webNavigation.onCommitted.addListener(async i=>{var t;if(i.frameId!==0)return;const s=i.tabId,e=w.get(s);if(!e||!e.isRecording)return;let r="NAV_OTHER";i.transitionType==="reload"?r="NAV_RELOAD":(t=i.transitionQualifiers)!=null&&t.includes("forward_back")?r="NAV_FORWARD_BACK":i.transitionType==="link"&&(r="NAV_LINK");const c={id:`nav_${Date.now()}_${Math.random().toString(36).slice(2,6)}`,sessionId:e.sessionId,timestamp:Date.now()-e.startTime,sequence:999999,wallClockTime:Date.now(),type:r,category:"NAVIGATION",source:"USER_INTERACTION",payload:{url:i.url,transitionType:i.transitionType,transitionQualifiers:i.transitionQualifiers,tabId:i.tabId}};try{await l.appendEvents(e.sessionId,[c]),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify({type:"FORENSIC_EVENTS_CHUNK",sessionId:e.sessionId,events:[c]}))}catch{}}),typeof chrome<"u"&&((R=chrome.runtime)!=null&&R.onMessage)&&chrome.runtime.onMessage.addListener((i,s,e)=>((async()=>{var r,c,t;try{const n=((r=s.tab)==null?void 0:r.id)??i.tabId;if(i.type==="FORENSIC_SESSION_START")n&&w.set(n,{sessionId:i.metadata.id,sessionName:i.metadata.name,startTime:i.metadata.startTime,initialUrl:i.metadata.url,isRecording:!0}),await l.saveSession(i.metadata),i.initialSnapshot&&await l.saveInitialSnapshot(i.metadata.id,i.initialSnapshot),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(i)),e({success:!0,sessionId:i.metadata.id});else if(i.type==="GET_TAB_RECORDING_STATE"){const o=n?w.get(n):null;e({isRecording:!!(o!=null&&o.isRecording),recording:o||null})}else if(i.type==="FORENSIC_EVENTS_CHUNK")await l.appendEvents(i.sessionId,i.events),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(i)),e({success:!0});else if(i.type==="FORENSIC_CHECKPOINT")await l.saveCheckpoint(i.checkpoint),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(i)),e({success:!0});else if(i.type==="FORENSIC_SESSION_STOP"){n&&w.delete(n);const o=await l.getSession(i.sessionId);o&&(o.status="stopped",o.endTime=Date.now(),(c=i.metadata)!=null&&c.durationMs&&(o.durationMs=i.metadata.durationMs),await l.saveSession(o)),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(i)),e({success:!0})}else if(i.type==="OPEN_DASHBOARD_TAB"){const o=chrome.runtime.getURL(`dist/src/ui/index.html${i.sessionId?`?session=${i.sessionId}`:""}`);chrome.tabs.create({url:o}),e({success:!0,url:o})}else if(i.type==="CAPTURE_SCREENSHOT"){if((t=chrome.tabs)!=null&&t.captureVisibleTab){chrome.tabs.captureVisibleTab({format:"png"},o=>{e({success:!!o,dataUrl:o})});return}e({success:!1,error:"Screenshot capture unsupported"})}else if(i.type==="ELEMENT_SELECTED")d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(i)),e({success:!0});else if(i.type==="BROWSER_COMMAND_REQUEST")try{const o=await O(i.command,i.payload);e({id:i.id,command:i.command,success:!0,data:o})}catch(o){e({id:i.id,command:i.command,success:!1,error:{code:"COMMAND_ERROR",message:o.message}})}}catch(n){e({success:!1,error:n.message})}})(),!0)),I()})(); +var v=Object.defineProperty;var P=(E,h,d)=>h in E?v(E,h,{enumerable:!0,configurable:!0,writable:!0,value:d}):E[h]=d;var I=(E,h,d)=>P(E,typeof h!="symbol"?h+"":h,d);(function(){"use strict";var T,_,p,A;class E{constructor(s="ForensicRecorderDB"){I(this,"dbName");I(this,"dbVersion",1);I(this,"db",null);this.dbName=s}async openDB(){if(this.db)return this.db;if(typeof indexedDB>"u")throw new Error("IndexedDB is not available in current runtime environment");return new Promise((s,e)=>{const n=indexedDB.open(this.dbName,this.dbVersion);n.onupgradeneeded=c=>{const t=c.target.result;if(t.objectStoreNames.contains("sessions")||t.createObjectStore("sessions",{keyPath:"id"}),!t.objectStoreNames.contains("events")){const r=t.createObjectStore("events",{keyPath:"id"});r.createIndex("sessionId","sessionId",{unique:!1}),r.createIndex("sequence","sequence",{unique:!1})}t.objectStoreNames.contains("checkpoints")||t.createObjectStore("checkpoints",{keyPath:"checkpointId"}).createIndex("sessionId","sessionId",{unique:!1}),t.objectStoreNames.contains("snapshots")||t.createObjectStore("snapshots",{keyPath:"sessionId"}),t.objectStoreNames.contains("annotations")||t.createObjectStore("annotations",{keyPath:"id"}).createIndex("sessionId","sessionId",{unique:!1})},n.onsuccess=()=>{this.db=n.result,s(this.db)},n.onerror=()=>e(n.error)})}async saveSession(s){const e=await this.openDB();return new Promise((n,c)=>{const t=e.transaction("sessions","readwrite");t.objectStore("sessions").put(s),t.oncomplete=()=>n(),t.onerror=()=>c(t.error)})}async getSession(s){const e=await this.openDB();return new Promise((n,c)=>{const i=e.transaction("sessions","readonly").objectStore("sessions").get(s);i.onsuccess=()=>n(i.result||null),i.onerror=()=>c(i.error)})}async listSessions(){const s=await this.openDB();return new Promise((e,n)=>{const r=s.transaction("sessions","readonly").objectStore("sessions").getAll();r.onsuccess=()=>{const i=r.result||[];i.sort((a,u)=>u.startTime-a.startTime),e(i)},r.onerror=()=>n(r.error)})}async deleteSession(s){const e=await this.openDB();return new Promise((n,c)=>{const t=e.transaction(["sessions","events","checkpoints","snapshots","annotations"],"readwrite");t.objectStore("sessions").delete(s),t.objectStore("snapshots").delete(s);const a=t.objectStore("events").index("sessionId").openCursor(IDBKeyRange.only(s));a.onsuccess=()=>{const u=a.result;u&&(u.delete(),u.continue())},t.oncomplete=()=>n(!0),t.onerror=()=>c(t.error)})}async appendEvents(s,e){if(e.length===0)return;const n=await this.openDB();return new Promise((c,t)=>{const r=n.transaction("events","readwrite"),i=r.objectStore("events");for(const a of e)i.put(a);r.oncomplete=()=>c(),r.onerror=()=>t(r.error)})}async getEvents(s,e){const n=await this.openDB();return new Promise((c,t)=>{const u=n.transaction("events","readonly").objectStore("events").index("sessionId").getAll(IDBKeyRange.only(s));u.onsuccess=()=>{let m=u.result||[];m.sort((l,f)=>l.sequence-f.sequence),e&&(m=m.filter(l=>!(e.category&&l.category!==e.category||e.type&&l.type!==e.type||typeof e.fromTimestamp=="number"&&l.timestamp e.toTimestamp||typeof e.targetNodeId=="number"&&l.targetNodeId!==e.targetNodeId)),typeof e.offset=="number"&&(m=m.slice(e.offset)),typeof e.limit=="number"&&(m=m.slice(0,e.limit))),c(m)},u.onerror=()=>t(u.error)})}async getEventCount(s){const e=await this.openDB();return new Promise((n,c)=>{const a=e.transaction("events","readonly").objectStore("events").index("sessionId").count(IDBKeyRange.only(s));a.onsuccess=()=>n(a.result),a.onerror=()=>c(a.error)})}async saveCheckpoint(s){const e=await this.openDB();return new Promise((n,c)=>{const t=e.transaction("checkpoints","readwrite");t.objectStore("checkpoints").put(s),t.oncomplete=()=>n(),t.onerror=()=>c(t.error)})}async getCheckpoints(s){const e=await this.openDB();return new Promise((n,c)=>{const i=e.transaction("checkpoints","readonly").objectStore("checkpoints").index("sessionId").getAll(IDBKeyRange.only(s));i.onsuccess=()=>{const a=i.result||[];a.sort((u,m)=>u.sequence-m.sequence),n(a)},i.onerror=()=>c(i.error)})}async saveInitialSnapshot(s,e){const n=await this.openDB();return new Promise((c,t)=>{const r=n.transaction("snapshots","readwrite");r.objectStore("snapshots").put({sessionId:s,snapshot:e}),r.oncomplete=()=>c(),r.onerror=()=>t(r.error)})}async getInitialSnapshot(s){const e=await this.openDB();return new Promise((n,c)=>{const r=e.transaction("snapshots","readonly").objectStore("snapshots").get(s);r.onsuccess=()=>n(r.result?r.result.snapshot:null),r.onerror=()=>c(r.error)})}async addAnnotation(s){const e=await this.openDB();return new Promise((n,c)=>{const t=e.transaction("annotations","readwrite");t.objectStore("annotations").put(s),t.oncomplete=()=>n(),t.onerror=()=>c(t.error)})}async getAnnotations(s){const e=await this.openDB();return new Promise((n,c)=>{const i=e.transaction("annotations","readonly").objectStore("annotations").index("sessionId").getAll(IDBKeyRange.only(s));i.onsuccess=()=>n(i.result||[]),i.onerror=()=>c(i.error)})}}const h=new E("ForensicExtensionDB");let d=null,S=null;const w=new Map,g=new Map;async function R(){return new Promise(o=>{try{chrome.tabs.query({active:!0,currentWindow:!0},s=>{if(chrome.runtime.lastError||!s||s.length===0)return o(null);o(s[0].id??null)})}catch{o(null)}})}try{(_=(T=chrome.debugger)==null?void 0:T.onEvent)==null||_.addListener((o,s,e)=>{try{for(const[n,c]of g.entries())if((o==null?void 0:o.tabId)===c||(o==null?void 0:o.targetId)===`tab_${c}`){d==null||d.send(JSON.stringify({type:"CDP_EVENT",sessionId:n,method:s,params:e,timestamp:Date.now()}));return}}catch{}})}catch{}async function O(o,s){if(o==="LIST_TABS")return new Promise((e,n)=>{chrome.tabs.query({},c=>{if(chrome.runtime.lastError)return n(new Error(chrome.runtime.lastError.message));const t=(c||[]).map(r=>({id:r.id,index:r.index,windowId:r.windowId,title:r.title||"Untitled",url:r.url||"",active:!!r.active,status:r.status,pinned:!!r.pinned,favIconUrl:r.favIconUrl,audited:r.id?w.has(r.id):!1,incognito:!!r.incognito,width:r.width,height:r.height}));e({totalTabs:t.length,tabs:t})})});if(o==="FOCUS_TAB"){const e=Number(s==null?void 0:s.tabId);if(!e)throw new Error("tabId is required for focus_tab");return new Promise((n,c)=>{chrome.tabs.update(e,{active:!0},t=>{var r;if(chrome.runtime.lastError||!t)return c(new Error(((r=chrome.runtime.lastError)==null?void 0:r.message)||`Tab ${e} not found`));t.windowId?chrome.windows.update(t.windowId,{focused:!0},()=>{n({focused:!0,tab:{id:t.id,windowId:t.windowId,title:t.title,url:t.url,active:t.active}})}):n({focused:!0,tab:{id:t.id,title:t.title,url:t.url,active:t.active}})})})}if(o==="RELOAD_TAB"){const e=!!(s!=null&&s.bypassCache),n=s!=null&&s.tabId?Number(s.tabId):void 0;return new Promise((c,t)=>{const r=i=>{chrome.tabs.reload(i,{bypassCache:e},()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message));chrome.tabs.get(i,a=>{c({reloaded:!0,tabId:i,bypassCache:e,url:a==null?void 0:a.url,title:a==null?void 0:a.title})})})};n?chrome.tabs.get(n,i=>{chrome.runtime.lastError||!i?chrome.tabs.query({active:!0,lastFocusedWindow:!0},a=>{const u=a&&a[0]?a[0]:null;u!=null&&u.id?r(u.id):t(new Error("No active tab found to reload"))}):r(n)}):chrome.tabs.query({active:!0,lastFocusedWindow:!0},i=>{const a=i&&i[0]?i[0]:null;if(!(a!=null&&a.id))return t(new Error("No active tab found to reload"));r(a.id)})})}if(o==="CLOSE_TAB"){const e=s!=null&&s.tabId?Number(s.tabId):void 0,n=s!=null&&s.url?String(s.url).toLowerCase():void 0;return new Promise((c,t)=>{const r=i=>{chrome.tabs.remove(i,()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message));c({closed:!0,tabIds:i,count:i.length})})};e?r([e]):n?chrome.tabs.query({},i=>{const u=(i||[]).filter(m=>{var l,f;return((l=m.url)==null?void 0:l.toLowerCase().includes(n))||((f=m.title)==null?void 0:f.toLowerCase().includes(n))}).map(m=>m.id).filter(Boolean);if(u.length===0)return c({closed:!1,message:`No open tab matched '${n}'`});r(u)}):chrome.tabs.query({active:!0,lastFocusedWindow:!0},i=>{const a=i&&i[0]?i[0]:null;if(!(a!=null&&a.id))return t(new Error("No active tab found to close"));r([a.id])})})}if(o==="OPEN_TAB"){const e=s==null?void 0:s.url;if(!e)throw new Error("url is required for open_tab");let n=String(e).trim();!n.startsWith("http://")&&!n.startsWith("https://")&&!n.startsWith("file://")&&!n.startsWith("chrome://")&&!n.startsWith("about:")&&(n.includes("meet.google.com")||n.includes("localhost")||n.includes(".com")||n.includes(".org")||n.includes(".net")||n.includes(".ir")||n.includes(".io")||n.includes(".app"))&&(n="https://"+n);const c=s.active!==!1,t=!!s.pinned;return new Promise((r,i)=>{chrome.tabs.create({url:n,active:c,pinned:t},a=>{if(chrome.runtime.lastError)return i(new Error(chrome.runtime.lastError.message));r({opened:!0,tabId:a.id,windowId:a.windowId,url:a.url||n,title:a.title||"New Tab",active:a.active,status:a.status})})})}if(o==="LIST_EXTENSIONS")return new Promise((e,n)=>{var c;if(!((c=chrome.management)!=null&&c.getAll))return n(new Error("chrome.management API not available"));chrome.management.getAll(t=>{if(chrome.runtime.lastError)return n(new Error(chrome.runtime.lastError.message));const r=(t||[]).map(i=>({id:i.id,name:i.name,version:i.version,description:i.description,enabled:i.enabled,installType:i.installType,isApp:i.isApp,homepageUrl:i.homepageUrl,permissions:i.permissions}));e({totalExtensions:r.length,extensions:r})})});if(o==="SET_EXTENSION_ENABLED"){const e=s==null?void 0:s.extensionId,n=!!(s!=null&&s.enabled);if(!e)throw new Error("extensionId is required for SET_EXTENSION_ENABLED");return new Promise((c,t)=>{var r;if(!((r=chrome.management)!=null&&r.setEnabled))return t(new Error("chrome.management API not available"));chrome.management.setEnabled(e,n,()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message||`Failed to set enabled state for ${e}`));c({success:!0,extensionId:e,enabled:n,message:`Extension ${e} successfully ${n?"enabled":"disabled"}.`})})})}if(o==="TOGGLE_EXTENSION"){const e=s==null?void 0:s.extensionId;if(!e)throw new Error("extensionId is required for TOGGLE_EXTENSION");return new Promise((n,c)=>{var t,r;if(!((t=chrome.management)!=null&&t.get)||!((r=chrome.management)!=null&&r.setEnabled))return c(new Error("chrome.management API not available"));chrome.management.get(e,i=>{var u;if(chrome.runtime.lastError||!i)return c(new Error(((u=chrome.runtime.lastError)==null?void 0:u.message)||`Extension ${e} not found`));const a=!i.enabled;chrome.management.setEnabled(e,a,()=>{if(chrome.runtime.lastError)return c(new Error(chrome.runtime.lastError.message||`Failed to toggle ${e}`));n({success:!0,extensionId:e,enabled:a,name:i.name,message:`Extension ${i.name} (${e}) toggled to ${a?"enabled":"disabled"}.`})})})})}if(o==="RESIZE_VIEWPORT"){const e=Math.max(200,Math.min(7680,Number(s==null?void 0:s.width)||1280)),n=Math.max(200,Math.min(4320,Number(s==null?void 0:s.height)||800));return new Promise((c,t)=>{chrome.windows.getCurrent({populate:!1},r=>{var i;if(chrome.runtime.lastError||!r)return t(new Error(((i=chrome.runtime.lastError)==null?void 0:i.message)||"No current window"));chrome.windows.update(r.id??chrome.windows.WINDOW_ID_CURRENT,{width:e,height:n,state:"normal"},a=>{var u;if(chrome.runtime.lastError||!a)return t(new Error(((u=chrome.runtime.lastError)==null?void 0:u.message)||"Window resize failed"));c({success:!0,applied:{width:a.width,height:a.height},previous:{width:r.width,height:r.height},original:{width:r.width,height:r.height},reversible:!0,mode:"browser-window",note:"Reset with reset_viewport — the content script tracks the original size."})})})})}if(o==="RESET_VIEWPORT")return new Promise((e,n)=>{chrome.windows.getCurrent({populate:!1},c=>{var t;if(chrome.runtime.lastError||!c)return n(new Error(((t=chrome.runtime.lastError)==null?void 0:t.message)||"No current window"));chrome.windows.update(c.id??chrome.windows.WINDOW_ID_CURRENT,{state:"maximized"},r=>{var i;if(chrome.runtime.lastError||!r)return n(new Error(((i=chrome.runtime.lastError)==null?void 0:i.message)||"Window restore failed"));e({success:!0,applied:{width:r.width,height:r.height},previous:{width:c.width,height:c.height},original:{width:r.width,height:r.height},reversible:!1,mode:"browser-window",note:"Window restored to maximized state."})})})});if(o==="RELOAD_EXTENSION"){const e=s==null?void 0:s.extensionId,n=chrome.runtime.id;return!e||e===n?(setTimeout(()=>chrome.runtime.reload(),150),{reloaded:!0,extensionId:n,isSelf:!0,message:"Forensic Recorder extension is reloading now."}):new Promise((c,t)=>{var r;if(!((r=chrome.management)!=null&&r.setEnabled))return t(new Error("chrome.management API not available"));chrome.management.setEnabled(e,!1,()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message||`Failed to disable ${e}`));setTimeout(()=>{chrome.management.setEnabled(e,!0,()=>{if(chrome.runtime.lastError)return t(new Error(chrome.runtime.lastError.message||`Failed to re-enable ${e}`));c({reloaded:!0,extensionId:e,isSelf:!1,message:`Extension ${e} successfully reloaded.`})})},150)})})}if(o==="CDP_ATTACH"){const e=(s==null?void 0:s.tabId)!==void 0?Number(s.tabId):await R();if(e===null)throw new Error("No target tab available for CDP attach.");return new Promise((n,c)=>{var t;if(!((t=chrome.debugger)!=null&&t.attach))return c(new Error('CDP_UNAVAILABLE: chrome.debugger API not available (check the "debugger" permission).'));chrome.debugger.attach({tabId:e},"1.3",()=>{if(chrome.runtime.lastError){const r=chrome.runtime.lastError.message||"";return r.includes("Another debugger is already attached")?c(new Error(`CDP_ATTACH failed: Chrome DevTools (F12) is already open on tab ${e}. Please close the F12 panel on that tab so TeleDOM can attach.`)):c(new Error(`CDP_ATTACH failed: ${r}`))}s!=null&&s.sessionId&&g.set(String(s.sessionId),e),chrome.debugger.getTargets(r=>{const i=(r||[]).find(a=>a.tabId===e)||{};n({attached:!0,sessionId:s==null?void 0:s.sessionId,tabId:e,targetId:i.id||`tab_${e}`,type:i.type||"page"})})})})}if(o==="CDP_COMMAND"){const{sessionId:e,method:n,params:c}=s||{};if(!n)throw new Error("CDP_COMMAND requires method");return new Promise((t,r)=>{var a;if(!((a=chrome.debugger)!=null&&a.sendCommand))return r(new Error('CDP_UNAVAILABLE: chrome.debugger API not available (check the "debugger" permission).'));const i=g.get(e);if(i===void 0)return r(new Error(`CDP_SESSION_NOT_FOUND: no tab bound to session '${e}' — attach first.`));chrome.debugger.sendCommand({tabId:i},n,c||{},u=>{if(chrome.runtime.lastError){t({__cdpError:!0,code:"CDP_PROTOCOL_ERROR",message:chrome.runtime.lastError.message,method:n});return}t({result:u??{}})})})}if(o==="CDP_DETACH"){const{sessionId:e}=s||{},n=g.get(e);return g.delete(e),n===void 0?{detached:!1,reason:"session not found"}:new Promise((c,t)=>{var r;if(!((r=chrome.debugger)!=null&&r.detach))return c({detached:!1,reason:"chrome.debugger unavailable"});chrome.debugger.detach({tabId:n},()=>{if(chrome.runtime.lastError)return c({detached:!1,reason:chrome.runtime.lastError.message});c({detached:!0,sessionId:e,tabId:n})})})}throw new Error(`Unsupported background command: ${o}`)}function b(){if(!(typeof WebSocket>"u"))try{const o=new WebSocket("ws://127.0.0.1:3847");let s=null;o.onopen=()=>{var e;d=o,console.log("[Forensic Extension] Connected to MCP Bridge on ws://127.0.0.1:3847"),S&&(clearInterval(S),S=null),o.send(JSON.stringify({type:"REGISTER_CLIENT",clientType:"SERVICE_WORKER",url:typeof chrome<"u"&&((e=chrome.runtime)!=null&&e.id)?`chrome-extension://${chrome.runtime.id}`:"service-worker",title:"Forensic Service Worker"})),s&&clearInterval(s),s=setInterval(()=>{if(o&&o.readyState===WebSocket.OPEN)try{o.send(JSON.stringify({type:"HEARTBEAT",timestamp:Date.now()}))}catch(n){console.warn("[TeleDOM SW] non-critical operation failed:",(n==null?void 0:n.message)??n)}},15e3)},o.onclose=()=>{s&&clearInterval(s),d=null,N()},o.onerror=()=>{s&&clearInterval(s),d=null,N()},o.onmessage=async e=>{try{const n=JSON.parse(e.data.toString());if(n.type==="BROWSER_COMMAND_REQUEST"){const{id:c,command:t,payload:r}=n;if(typeof chrome>"u"||!chrome.tabs){o.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"NO_CHROME_TABS_API",message:"chrome.tabs API not available in this context"}}));return}if(["LIST_TABS","FOCUS_TAB","RELOAD_TAB","CLOSE_TAB","OPEN_TAB","LIST_EXTENSIONS","RELOAD_EXTENSION","SET_EXTENSION_ENABLED","TOGGLE_EXTENSION","CDP_ATTACH","CDP_COMMAND","CDP_DETACH"].includes(t)){try{const u=await O(t,r);o.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!0,data:u}))}catch(u){o.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"COMMAND_ERROR",message:u.message}}))}return}const i=r!=null&&r.tabId?Number(r.tabId):void 0,a=u=>{if(t==="LIVE_PAGE_SCREENSHOT"||t==="LIVE_ELEMENT_SCREENSHOT"){chrome.tabs.sendMessage(u,{type:"HIDE_FORENSIC_OVERLAYS"},()=>{setTimeout(()=>{chrome.tabs.captureVisibleTab({format:"png"},m=>{var l;if(chrome.tabs.sendMessage(u,{type:"RESTORE_FORENSIC_OVERLAYS"}),chrome.runtime.lastError||!m){o.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"SCREENSHOT_FAILED",message:((l=chrome.runtime.lastError)==null?void 0:l.message)||"captureVisibleTab failed"}}));return}chrome.tabs.sendMessage(u,{type:"BROWSER_COMMAND_REQUEST",id:c,command:t,payload:{...r,dataUrl:m}},f=>{const C=f||{id:c,command:t,success:!0,data:{dataUrl:m,captureType:t==="LIVE_ELEMENT_SCREENSHOT"?"ELEMENT":"FULL_PAGE"}};o.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",...C}))})})},150)});return}chrome.tabs.sendMessage(u,n,m=>{if(chrome.runtime.lastError){o.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"CONTENT_SCRIPT_UNREACHABLE",message:chrome.runtime.lastError.message||`Content script unreachable on tab ${u}`}}));return}o.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",...m||{id:c,command:t,success:!0}}))})};i?a(i):chrome.tabs.query({active:!0,lastFocusedWindow:!0},async u=>{const m=u&&u[0]?u[0]:null,l=m==null?void 0:m.id;if(!l){o.send(JSON.stringify({type:"BROWSER_COMMAND_RESPONSE",id:c,command:t,success:!1,error:{code:"NO_ACTIVE_TAB",message:"No active browser tab found"}}));return}a(l)})}}catch(n){console.error("[ServiceWorker] Bridge message handling error:",n)}}}catch{d=null,N()}}function N(){S||(S=setInterval(()=>{(!d||d.readyState!==WebSocket.OPEN)&&b()},5e3))}if(typeof chrome<"u"&&chrome.alarms)try{chrome.alarms.create("teledom_bridge_keepalive",{periodInMinutes:.4}),chrome.alarms.onAlarm.addListener(o=>{if(o.name==="teledom_bridge_keepalive")if(!d||d.readyState!==WebSocket.OPEN)b();else try{d.send(JSON.stringify({type:"HEARTBEAT",timestamp:Date.now()}))}catch{b()}})}catch(o){console.warn("[ServiceWorker] Alarms keepalive setup failed:",o==null?void 0:o.message)}b(),typeof chrome<"u"&&((p=chrome.webNavigation)!=null&&p.onCommitted)&&chrome.webNavigation.onCommitted.addListener(async o=>{var t;if(o.frameId!==0)return;const s=o.tabId,e=w.get(s);if(!e||!e.isRecording)return;let n="NAV_OTHER";o.transitionType==="reload"?n="NAV_RELOAD":(t=o.transitionQualifiers)!=null&&t.includes("forward_back")?n="NAV_FORWARD_BACK":o.transitionType==="link"&&(n="NAV_LINK");const c={id:`nav_${Date.now()}_${Math.random().toString(36).slice(2,6)}`,sessionId:e.sessionId,timestamp:Date.now()-e.startTime,sequence:999999,wallClockTime:Date.now(),type:n,category:"NAVIGATION",source:"USER_INTERACTION",payload:{url:o.url,transitionType:o.transitionType,transitionQualifiers:o.transitionQualifiers,tabId:o.tabId}};try{await h.appendEvents(e.sessionId,[c]),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify({type:"FORENSIC_EVENTS_CHUNK",sessionId:e.sessionId,events:[c]}))}catch{}}),typeof chrome<"u"&&((A=chrome.runtime)!=null&&A.onMessage)&&chrome.runtime.onMessage.addListener((o,s,e)=>((async()=>{var n,c,t;try{const r=((n=s.tab)==null?void 0:n.id)??o.tabId;if(o.type==="FORENSIC_SESSION_START")r&&w.set(r,{sessionId:o.metadata.id,sessionName:o.metadata.name,startTime:o.metadata.startTime,initialUrl:o.metadata.url,isRecording:!0}),await h.saveSession(o.metadata),o.initialSnapshot&&await h.saveInitialSnapshot(o.metadata.id,o.initialSnapshot),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(o)),e({success:!0,sessionId:o.metadata.id});else if(o.type==="GET_TAB_RECORDING_STATE"){const i=r?w.get(r):null;e({isRecording:!!(i!=null&&i.isRecording),recording:i||null})}else if(o.type==="FORENSIC_EVENTS_CHUNK")await h.appendEvents(o.sessionId,o.events),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(o)),e({success:!0});else if(o.type==="FORENSIC_CHECKPOINT")await h.saveCheckpoint(o.checkpoint),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(o)),e({success:!0});else if(o.type==="FORENSIC_SESSION_STOP"){r&&w.delete(r);const i=await h.getSession(o.sessionId);i&&(i.status="stopped",i.endTime=Date.now(),(c=o.metadata)!=null&&c.durationMs&&(i.durationMs=o.metadata.durationMs),await h.saveSession(i)),d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(o)),e({success:!0})}else if(o.type==="OPEN_DASHBOARD_TAB"){const i=chrome.runtime.getURL(`dist/src/ui/index.html${o.sessionId?`?session=${o.sessionId}`:""}`);chrome.tabs.create({url:i}),e({success:!0,url:i})}else if(o.type==="CAPTURE_SCREENSHOT"){if((t=chrome.tabs)!=null&&t.captureVisibleTab){chrome.tabs.captureVisibleTab({format:"png"},i=>{e({success:!!i,dataUrl:i})});return}e({success:!1,error:"Screenshot capture unsupported"})}else if(o.type==="ELEMENT_SELECTED")d&&d.readyState===WebSocket.OPEN&&d.send(JSON.stringify(o)),e({success:!0});else if(o.type==="BROWSER_COMMAND_REQUEST")try{const i=await O(o.command,o.payload);e({id:o.id,command:o.command,success:!0,data:i})}catch(i){e({id:o.id,command:o.command,success:!1,error:{code:"COMMAND_ERROR",message:i.message}})}}catch(r){e({success:!1,error:r.message})}})(),!0)),b()})(); diff --git a/dist/server/bridge-server.js b/dist/server/bridge-server.js index a5935064..420602e0 100644 --- a/dist/server/bridge-server.js +++ b/dist/server/bridge-server.js @@ -4,7 +4,6 @@ import * as fs from "fs"; import fs__default from "fs"; import * as path from "path"; import path__default from "path"; -import * as readline from "readline"; import * as zlib from "zlib"; import { gunzipSync, gzipSync } from "zlib"; import { createHash, randomUUID } from "crypto"; @@ -123,41 +122,49 @@ class FileStorageProvider { async saveSession(metadata) { const dir = this.getSessionDir(metadata.id); const metaPath = path.join(dir, "metadata.json"); - fs.writeFileSync(metaPath, JSON.stringify(metadata, null, 2), "utf-8"); + await fs.promises.writeFile(metaPath, JSON.stringify(metadata, null, 2), "utf-8"); } async getSession(sessionId) { const dir = path.join(this.baseDir, sessionId); const metaPath = path.join(dir, "metadata.json"); - if (!fs.existsSync(metaPath)) return null; try { - const data = fs.readFileSync(metaPath, "utf-8"); + const data = await fs.promises.readFile(metaPath, "utf-8"); return JSON.parse(data); - } catch { + } catch (err) { + if (err?.code !== "ENOENT") { + console.warn(`[FileStorage] Warning: Failed to read session ${sessionId}: ${err?.message}`); + } return null; } } async listSessions() { if (!fs.existsSync(this.baseDir)) return []; - const entries = fs.readdirSync(this.baseDir, { withFileTypes: true }); - const sessions = []; - for (const entry of entries) { - if (entry.isDirectory()) { - const metaPath = path.join(this.baseDir, entry.name, "metadata.json"); - if (fs.existsSync(metaPath)) { + try { + const entries = await fs.promises.readdir(this.baseDir, { withFileTypes: true }); + const sessions = []; + for (const entry of entries) { + if (entry.isDirectory()) { + const metaPath = path.join(this.baseDir, entry.name, "metadata.json"); try { - const data = fs.readFileSync(metaPath, "utf-8"); + const data = await fs.promises.readFile(metaPath, "utf-8"); sessions.push(JSON.parse(data)); - } catch { + } catch (err) { + if (err?.code !== "ENOENT") { + console.warn(`[FileStorage] Warning: Corrupt or unreadable session metadata at ${metaPath}: ${err?.message}`); + } } } } + return sessions.sort((a, b) => b.startTime - a.startTime); + } catch (err) { + console.error(`[FileStorage] Failed to list sessions from ${this.baseDir}:`, err?.message); + return []; } - return sessions.sort((a, b) => b.startTime - a.startTime); } async deleteSession(sessionId) { const dir = path.join(this.baseDir, sessionId); if (fs.existsSync(dir)) { - fs.rmSync(dir, { recursive: true, force: true }); + await fs.promises.rm(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 50 }); return true; } return false; @@ -167,28 +174,26 @@ class FileStorageProvider { const dir = this.getSessionDir(sessionId); const eventsPath = path.join(dir, "events.jsonl"); const lines = events.map((e) => JSON.stringify(e)).join("\n") + "\n"; - fs.appendFileSync(eventsPath, lines, "utf-8"); + await fs.promises.appendFile(eventsPath, lines, "utf-8"); } async getEvents(sessionId, filter) { const dir = path.join(this.baseDir, sessionId); const eventsPath = path.join(dir, "events.jsonl"); if (!fs.existsSync(eventsPath)) return []; - const fileStream = fs.createReadStream(eventsPath, { encoding: "utf-8" }); - const rl = readline.createInterface({ - input: fileStream, - crlfDelay: Infinity - }); + const content = await fs.promises.readFile(eventsPath, "utf-8"); + const lines = content.split(/\r?\n/); const results = []; let matchedCount = 0; const offset = typeof filter?.offset === "number" ? filter.offset : 0; const limit = typeof filter?.limit === "number" ? filter.limit : Infinity; - for await (const line of rl) { + for (const line of lines) { const trimmed = line.trim(); if (!trimmed) continue; let e; try { e = JSON.parse(trimmed); - } catch { + } catch (parseErr) { + console.warn(`[FileStorage] Skipping malformed event line in session ${sessionId}:`, parseErr); continue; } if (filter) { @@ -214,8 +219,6 @@ class FileStorageProvider { } results.push(e); if (results.length >= limit) { - rl.close(); - fileStream.destroy(); break; } } @@ -225,13 +228,9 @@ class FileStorageProvider { const dir = path.join(this.baseDir, sessionId); const eventsPath = path.join(dir, "events.jsonl"); if (!fs.existsSync(eventsPath)) return 0; - const fileStream = fs.createReadStream(eventsPath, { encoding: "utf-8" }); - const rl = readline.createInterface({ - input: fileStream, - crlfDelay: Infinity - }); + const content = await fs.promises.readFile(eventsPath, "utf-8"); let count = 0; - for await (const line of rl) { + for (const line of content.split(/\r?\n/)) { if (line.trim()) count++; } return count; @@ -239,36 +238,46 @@ class FileStorageProvider { async saveCheckpoint(checkpoint) { const dir = this.getSessionDir(checkpoint.sessionId); const chkDir = path.join(dir, "checkpoints"); - if (!fs.existsSync(chkDir)) fs.mkdirSync(chkDir, { recursive: true }); + await fs.promises.mkdir(chkDir, { recursive: true }); const file = path.join(chkDir, `${checkpoint.checkpointId}.json`); - fs.writeFileSync(file, JSON.stringify(checkpoint, null, 2), "utf-8"); + await fs.promises.writeFile(file, JSON.stringify(checkpoint, null, 2), "utf-8"); } async getCheckpoints(sessionId) { const dir = path.join(this.baseDir, sessionId, "checkpoints"); - if (!fs.existsSync(dir)) return []; - const files = fs.readdirSync(dir).filter((f) => f.endsWith(".json")); - const checkpoints = []; - for (const f of files) { - try { - const data = fs.readFileSync(path.join(dir, f), "utf-8"); - checkpoints.push(JSON.parse(data)); - } catch { + try { + const files = (await fs.promises.readdir(dir)).filter((f) => f.endsWith(".json")); + const checkpoints = []; + for (const f of files) { + try { + const data = await fs.promises.readFile(path.join(dir, f), "utf-8"); + checkpoints.push(JSON.parse(data)); + } catch (err) { + console.warn(`[FileStorage] Failed to read/parse checkpoint file ${f} in session ${sessionId}:`, err); + } } + return checkpoints.sort((a, b) => a.sequence - b.sequence); + } catch (err) { + if (err?.code !== "ENOENT") { + console.warn(`[FileStorage] Error accessing checkpoints directory for session ${sessionId}:`, err); + } + return []; } - return checkpoints.sort((a, b) => a.sequence - b.sequence); } async saveInitialSnapshot(sessionId, snapshot) { const dir = this.getSessionDir(sessionId); const file = path.join(dir, "initial_snapshot.json"); - fs.writeFileSync(file, JSON.stringify(snapshot, null, 2), "utf-8"); + await fs.promises.writeFile(file, JSON.stringify(snapshot, null, 2), "utf-8"); } async getInitialSnapshot(sessionId) { const dir = path.join(this.baseDir, sessionId); const file = path.join(dir, "initial_snapshot.json"); - if (!fs.existsSync(file)) return null; try { - return JSON.parse(fs.readFileSync(file, "utf-8")); - } catch { + const content = await fs.promises.readFile(file, "utf-8"); + return JSON.parse(content); + } catch (err) { + if (err?.code !== "ENOENT") { + console.warn(`[FileStorage] Error reading initial snapshot for session ${sessionId}:`, err); + } return null; } } @@ -276,23 +285,28 @@ class FileStorageProvider { const dir = this.getSessionDir(annotation.sessionId); const annPath = path.join(dir, "annotations.json"); let list = []; - if (fs.existsSync(annPath)) { - try { - list = JSON.parse(fs.readFileSync(annPath, "utf-8")); - } catch { - list = []; + try { + const content = await fs.promises.readFile(annPath, "utf-8"); + list = JSON.parse(content); + } catch (err) { + if (err?.code !== "ENOENT") { + console.warn(`[FileStorage] Corrupted annotations file for session ${annotation.sessionId}, starting fresh:`, err); } + list = []; } list.push(annotation); - fs.writeFileSync(annPath, JSON.stringify(list, null, 2), "utf-8"); + await fs.promises.writeFile(annPath, JSON.stringify(list, null, 2), "utf-8"); } async getAnnotations(sessionId) { const dir = path.join(this.baseDir, sessionId); const annPath = path.join(dir, "annotations.json"); - if (!fs.existsSync(annPath)) return []; try { - return JSON.parse(fs.readFileSync(annPath, "utf-8")); - } catch { + const content = await fs.promises.readFile(annPath, "utf-8"); + return JSON.parse(content); + } catch (err) { + if (err?.code !== "ENOENT") { + console.warn(`[FileStorage] Failed to read annotations for session ${sessionId}:`, err); + } return []; } } @@ -8997,7 +9011,18 @@ class LiveToolsHandler { } ] }; - } catch { + } catch (saveErr) { + return { + content: [ + { + type: "text", + text: JSON.stringify({ + ...finalSummary, + fileSaveError: `Failed to write pipeline output to ${args.outputPath}: ${saveErr?.message || saveErr}` + }, null, 2) + } + ] + }; } } return { @@ -9403,7 +9428,8 @@ class ProjectManager { try { const manifest = JSON.parse(fs__default.readFileSync(manifestPath, "utf-8")); out.push({ ...manifest, projectDir: path__default.join(this.baseDir, entry.name), pageCount: manifest.pages?.length || 0 }); - } catch { + } catch (err) { + console.warn(`[ProjectManager] Warning: Skipped corrupt project manifest at ${manifestPath}:`, err); } } return out.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0)); @@ -9664,7 +9690,8 @@ class ProjectManager { if (fs__default.existsSync(p)) { try { out.push(JSON.parse(fs__default.readFileSync(p, "utf-8"))); - } catch { + } catch (err) { + console.warn(`[ProjectManager] Warning: Skipped corrupt region file ${p}:`, err); } } } @@ -10026,7 +10053,8 @@ class CommandRecordingStorage { try { const raw = JSON.parse(fs__default.readFileSync(file, "utf-8")); return raw.recording || raw; - } catch { + } catch (err) { + console.warn(`[RecordingStorage] Warning: Failed to parse recording file ${file}:`, err); return null; } } @@ -10054,7 +10082,8 @@ class CommandRecordingStorage { tags: rec.tags || [], file: path__default.join(this.baseDir, entry.name) }); - } catch { + } catch (err) { + console.warn(`[RecordingStorage] Warning: Skipped corrupt recording file ${entry.name}:`, err); } } return out.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0)); @@ -10471,6 +10500,111 @@ function buildToolCatalog() { } return catalog; } +const TELEDOM_PROFILE_TOOLS = { + // Minimal profile: strictly essential browser actions (~22 tools, ~2.5k tokens) + minimal: [ + "td_browser_navigate", + "td_browser_back", + "td_browser_forward", + "td_browser_refresh", + "td_dom_inspect", + "td_dom_query", + "td_dom_extract", + "td_dom_snapshot", + "td_target_find", + "td_target_check", + "td_action_click", + "td_action_type", + "td_action_select", + "td_action_press", + "td_action_scroll", + "td_wait", + "td_screenshot", + "td_execute_script", + "list_tabs", + "focus_tab", + "close_tab", + "open_tab" + ], + // Core profile: browser primitives + workflow runtime + target memory (~44 tools, ~4.8k tokens) + core: [ + "td_browser_navigate", + "td_browser_back", + "td_browser_forward", + "td_browser_refresh", + "td_dom_inspect", + "td_dom_query", + "td_dom_extract", + "td_dom_snapshot", + "td_target_find", + "td_target_check", + "td_target_describe", + "td_action_click", + "td_action_type", + "td_action_select", + "td_action_hover", + "td_action_press", + "td_action_scroll", + "td_wait", + "td_screenshot", + "td_execute_script", + "td_network_inspect", + "td_console_read", + "td_workflow_save", + "td_workflow_get", + "td_workflow_list", + "td_workflow_update", + "td_workflow_delete", + "td_workflow_validate", + "td_workflow_run", + "td_workflow_runs", + "td_workflow_replay", + "td_target_memory_save", + "td_target_memory_get", + "td_target_memory_list", + "td_target_memory_delete", + "list_tabs", + "focus_tab", + "reload_tab", + "close_tab", + "open_tab", + "inspect_live_page", + "inspect_live_element" + ], + // Forensics profile: historical forensics + diffs + causality + live inspection (~50 tools) + forensics: [ + "list_sessions", + "get_session", + "export_session", + "import_session", + "delete_session", + "get_timeline", + "get_events", + "get_events_around", + "get_dom_state", + "get_dom_node", + "get_dom_subtree", + "diff_dom", + "trace_element", + "find_disappearing_elements", + "why_did_element_disappear", + "get_diagnostics", + "get_network_events", + "get_screenshots", + "td_browser_navigate", + "td_dom_inspect", + "td_dom_query", + "td_dom_extract", + "td_screenshot", + "td_action_click", + "td_action_type", + "td_workflow_run", + "list_tabs", + "focus_tab" + ], + // Full profile: all 350 tools (null means no filtering) + full: null +}; const MCPDOM_V3_TOOLS = [ // ================================================================== // Targeting & forensics @@ -18593,7 +18727,8 @@ class ForensicsToolsHandler { try { const res = await unifiedRuntime.bridgeCommand("LIVE_DOM_SNAPSHOT", { format: "json" }); return { snapshot: res }; - } catch { + } catch (err) { + console.warn(`[ForensicsHandler] Could not capture live snapshot: ${err?.message || err}`); return { snapshot: null }; } } @@ -18602,7 +18737,8 @@ async function runInPageSafe(code, tabId) { try { const { runInPage: runInPage2 } = await Promise.resolve().then(() => interactionCore); return await runInPage2(code, tabId); - } catch { + } catch (err) { + console.warn(`[ForensicsHandler] runInPageSafe failed for tab ${tabId}: ${err?.message || err}`); return null; } } @@ -22506,14 +22642,20 @@ class AgentStore { readJson(file) { try { return JSON.parse(fs.readFileSync(file, "utf-8")); - } catch { + } catch (err) { + if (err?.code !== "ENOENT") { + console.warn(`[WorkflowStore] Warning: Failed to read or parse ${file}:`, err?.message || err); + } return null; } } listJsonNames(dir) { try { return fs.readdirSync(dir).filter((f) => f.endsWith(".json")).sort(); - } catch { + } catch (err) { + if (err?.code !== "ENOENT") { + console.warn(`[WorkflowStore] Warning: Failed to list directory ${dir}:`, err?.message || err); + } return []; } } @@ -25415,12 +25557,14 @@ class MCPBridgeServer { if (targets.length === 0) { for (const [sock, meta] of this.socketMetadata.entries()) { if (meta.clientType === "CONTENT_SCRIPT" && sock.readyState === WebSocket.OPEN) { - targets.push(sock); + targets = [sock]; + break; } } } - if (targets.length === 0) { - targets = Array.from(this.activeSockets); + if (targets.length === 0 && this.activeSockets.size > 0) { + const first = Array.from(this.activeSockets).find((s) => s.readyState === WebSocket.OPEN); + if (first) targets = [first]; } let sentCount = 0; for (const ws of targets) { @@ -25443,17 +25587,53 @@ class MCPBridgeServer { } start() { return new Promise((resolve, reject) => { + const isTrustedOrigin = (origin) => { + if (!origin) return true; + if (origin.startsWith("chrome-extension://")) return true; + if (/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(origin)) return true; + return false; + }; this.httpServer = http.createServer(async (req, res) => { - res.setHeader("Access-Control-Allow-Origin", "*"); + const origin = req.headers.origin; + if (origin) { + if (isTrustedOrigin(origin)) { + res.setHeader("Access-Control-Allow-Origin", origin); + res.setHeader("Access-Control-Allow-Credentials", "true"); + res.setHeader("Vary", "Origin"); + } else if (req.method === "OPTIONS") { + res.writeHead(403, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ error: "CORS Forbidden: Untrusted cross-origin request rejected" })); + return; + } + } res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"); - res.setHeader("Access-Control-Allow-Headers", "Content-Type"); + res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, x-teledom-token"); if (req.method === "OPTIONS") { res.writeHead(204); res.end(); return; } const url = req.url || ""; - if (url === "/health" && req.method === "GET") { + const isAuthValid = () => { + if (!isTrustedOrigin(origin)) return false; + const expectedToken = process.env.TELEDOM_BRIDGE_TOKEN; + if (!expectedToken) return true; + const authHeader = req.headers.authorization; + const tokenHeader = req.headers["x-teledom-token"]; + let queryToken = null; + try { + const parsed = new URL(url, "http://127.0.0.1"); + queryToken = parsed.searchParams.get("token"); + } catch { + } + if (authHeader && authHeader.startsWith("Bearer ")) { + return authHeader.slice(7).trim() === expectedToken; + } + if (tokenHeader && tokenHeader === expectedToken) return true; + if (queryToken && queryToken === expectedToken) return true; + return false; + }; + if (url.startsWith("/health") && req.method === "GET") { res.writeHead(200, { "Content-Type": "application/json" }); res.end( JSON.stringify({ @@ -25465,6 +25645,13 @@ class MCPBridgeServer { ); return; } + if (["/api/mcp/tool", "/api/tabs/close", "/api/sessions/upload"].some((p) => url.startsWith(p))) { + if (!isAuthValid()) { + res.writeHead(403, { "Content-Type": "application/json" }); + res.end(JSON.stringify({ error: "Forbidden: Invalid or missing authorization credentials" })); + return; + } + } const MAX_PAYLOAD_BYTES = 50 * 1024 * 1024; if (url === "/api/sessions/upload" && req.method === "POST") { let body = ""; @@ -25583,7 +25770,13 @@ class MCPBridgeServer { } }, 3e4); this.healthSweepInterval?.unref?.(); - this.wss.on("connection", (ws) => { + this.wss.on("connection", (ws, req) => { + const origin = req?.headers?.origin; + if (origin && !isTrustedOrigin(origin)) { + console.error(`[MCP Bridge] WebSocket connection rejected from untrusted origin: ${origin}`); + ws.close(4403, "Forbidden origin"); + return; + } this.activeSockets.add(ws); console.error(`[MCP Bridge] Client connected. Total active clients: ${this.activeSockets.size}`); ws.on("close", () => { @@ -25711,8 +25904,10 @@ export { FORENSICS_TOOLS as F, MCPDOM_V3_TOOLS as M, MCPBridgeServer, + PNGBuilder as P, TELEDOM_INTELLIGENCE_TOOLS as T, TELEDOM_VERSION as a, FileStorageProvider as b, - MCPToolsHandler as c + MCPToolsHandler as c, + TELEDOM_PROFILE_TOOLS as d }; diff --git a/dist/server/mcp-server.js b/dist/server/mcp-server.js index bf9f2d9e..4f33d5fa 100644 --- a/dist/server/mcp-server.js +++ b/dist/server/mcp-server.js @@ -1,6 +1,7 @@ import * as readline from "readline"; import * as fs from "fs"; -import { M as MCPDOM_V3_TOOLS, D as DEVTOOLS_TOOLS, F as FORENSICS_TOOLS, T as TELEDOM_INTELLIGENCE_TOOLS, a as TELEDOM_VERSION, b as FileStorageProvider, c as MCPToolsHandler, MCPBridgeServer } from "./bridge-server.js"; +import { M as MCPDOM_V3_TOOLS, D as DEVTOOLS_TOOLS, F as FORENSICS_TOOLS, T as TELEDOM_INTELLIGENCE_TOOLS, a as TELEDOM_VERSION, b as FileStorageProvider, c as MCPToolsHandler, MCPBridgeServer, d as TELEDOM_PROFILE_TOOLS } from "./bridge-server.js"; +import { P } from "./bridge-server.js"; import "http"; import "ws"; import "path"; @@ -872,9 +873,15 @@ class ForensicMCPServer { const disableDevTools = process.env.FORENSIC_DISABLE_DEVTOOLS === "true"; const disableForensics = process.env.FORENSIC_DISABLE_FORENSICS === "true"; const disableIntelligence = process.env.FORENSIC_DISABLE_INTELLIGENCE === "true"; - const tools = FORENSIC_MCP_TOOLS.filter( + const profile = (process.env.TELEDOM_PROFILE || "full").toLowerCase(); + const profileAllowed = TELEDOM_PROFILE_TOOLS[profile]; + let tools = FORENSIC_MCP_TOOLS.filter( (t) => !(disableDevTools && t.name.startsWith("dt_")) && !(disableForensics && t.name.startsWith("fx_")) && !(disableIntelligence && t.name.startsWith("td_")) ); + if (profileAllowed && Array.isArray(profileAllowed)) { + const allowedSet = new Set(profileAllowed); + tools = tools.filter((t) => allowedSet.has(t.name)); + } return { jsonrpc: "2.0", id, @@ -1077,5 +1084,7 @@ export { FORENSIC_MCP_TOOLS, FileStorageProvider, ForensicMCPServer, - MCPToolsHandler + MCPToolsHandler, + P as PNGBuilder, + TELEDOM_PROFILE_TOOLS }; diff --git a/dist/src/extension/devtools/devtools.html b/dist/src/extension/devtools/devtools.html index e5ead51c..ec623abe 100644 --- a/dist/src/extension/devtools/devtools.html +++ b/dist/src/extension/devtools/devtools.html @@ -1,10 +1,10 @@ - - - - + + + + - - - - + + + + diff --git a/dist/src/extension/popup/popup.html b/dist/src/extension/popup/popup.html index 9f991f9c..6b4f597e 100644 --- a/dist/src/extension/popup/popup.html +++ b/dist/src/extension/popup/popup.html @@ -1,54 +1,54 @@ - - - - - Forensic Recorder + + + + +Forensic Recorder - - --- - + + +- - -- -- READY -Forensic Recorder
----- - - -Target: Current Active Tab
-- 0 Events - 0.0s --- - -- -
- - -++ + diff --git a/dist/src/ui/index.html b/dist/src/ui/index.html index e82ee8a9..0412e036 100644 --- a/dist/src/ui/index.html +++ b/dist/src/ui/index.html @@ -1,243 +1,243 @@ - - - - - -+ + ++ ++ READY +Forensic Recorder
+++++ + + +Target: Current Active Tab
++ 0 Events + 0.0s +++ + ++ +
+ + +Browser Forensic Recorder & Time-Travel Debugger + + + + + +Browser Forensic Recorder & Time-Travel Debugger - - - -- - - --- -⚡-- Browser Forensic Debugger - v2.0 MCP ---- -- - --- - - - - - - --- - - - - - - -- - - - -- - - -- ---- - -----Load or record a session to inspect DOM.---Select an element from the DOM tree or replay viewport.--- - ---- - - - - - -- ---Select timestamps and click Compare States.--- - -----Disappearing UI Forensic Diagnosis
-- - ----Enter a CSS selector or node ID to run root-cause diagnosis.--- - ---No console or error events recorded.--- - ---No network events recorded.--- - ---- - -- ------- --- -⚡ Agent-Owned Workflows-TeleDOM stores and executes; the agent designs and repairs. Teach once · Reuse forever · Prove what happened.-Recent Runs- --- - - - - + + + +----Search Session Events & Nodes
- -- - --+ + + +++ +⚡++ Browser Forensic Debugger + v2.0 MCP ++++ ++ + +++ + + + + + + +++ + + + + + + ++ + + + ++ + + ++ ++++ + +++++Load or record a session to inspect DOM.+++Select an element from the DOM tree or replay viewport.+++ + ++++ + + + + + ++ +++Select timestamps and click Compare States.+++ + +++++Disappearing UI Forensic Diagnosis
++ + ++++Enter a CSS selector or node ID to run root-cause diagnosis.+++ + +++No console or error events recorded.+++ + +++No network events recorded.+++ + ++++ + ++ +++++++ +++ +⚡ Agent-Owned Workflows+TeleDOM stores and executes; the agent designs and repairs. Teach once · Reuse forever · Prove what happened.+Recent Runs+ +++ + + + + diff --git a/docs/intelligence/BENCHMARKS.md b/docs/intelligence/BENCHMARKS.md index 6ac4f868..94280892 100644 --- a/docs/intelligence/BENCHMARKS.md +++ b/docs/intelligence/BENCHMARKS.md @@ -1,23 +1,23 @@ # TeleDOM v4 — Measured Benchmarks & Suite Metrics -Generated: 2026-09-11T18:05:59.466Z (local deterministic measurements on this machine — not marketing numbers) +Generated: 2026-09-12T07:22:28.467Z (local deterministic measurements on this machine — not marketing numbers) ## Event-scale benchmark matrix | Metric | 10K events | 100K events | 1M events | |---|---|---|---| -| Capture overhead (ms per 10K events) | 248.3 | 213.63 | 88.71 | +| Capture overhead (ms per 10K events) | 211.58 | 180.81 | 135.08 | | Bytes per event (approx) | 352 | 355 | 358 | -| Reconstruction p50 (ms) | 3.62 | 19.1 | 116.78 | -| Reconstruction p95 (ms) | 5.7 | 30.08 | 234.64 | -| Reconstruction p99 (ms) | 5.7 | 78.02 | 259.34 | -| Temporal query p50 (ms) | 0.81 | 4.93 | 25.89 | -| Temporal query p95 (ms) | 8.6 | 7.07 | 33.14 | -| Temporal query p99 (ms) | 8.6 | 9.83 | 57.53 | -| Graph query latency (ms) | 52.21 | 30.6 | 20.2 | -| Investigation latency (ms) | 117.01 | 64.33 | 59.17 | -| Branch simulation latency (ms) | 27.64 | 125.92 | 899.42 | -| Recovery time (serialize+restore, ms) | 112.65 | 457.84 | 4467.36 | +| Reconstruction p50 (ms) | 4.35 | 18.63 | 114.73 | +| Reconstruction p95 (ms) | 25.14 | 43.18 | 226.75 | +| Reconstruction p99 (ms) | 25.14 | 46.93 | 239.83 | +| Temporal query p50 (ms) | 0.92 | 4.69 | 29.54 | +| Temporal query p95 (ms) | 1.72 | 6.87 | 45.49 | +| Temporal query p99 (ms) | 1.72 | 8.24 | 55.39 | +| Graph query latency (ms) | 55.56 | 44.03 | 21.83 | +| Investigation latency (ms) | 582.07 | 120.2 | 66.39 | +| Branch simulation latency (ms) | 28.74 | 120.73 | 882.66 | +| Recovery time (serialize+restore, ms) | 92.57 | 966.19 | 5446.28 | **Timestamp resolution: 0.01 ms — tracked SEPARATELY from reconstruction/query latency (never conflated).** diff --git a/docs/intelligence/COMPATIBILITY.md b/docs/intelligence/COMPATIBILITY.md index 303f8c12..4eb26301 100644 --- a/docs/intelligence/COMPATIBILITY.md +++ b/docs/intelligence/COMPATIBILITY.md @@ -1,6 +1,6 @@ # TeleDOM v4 — Compatibility Matrix (generated) -Generated: 2026-09-11T18:05:32.304Z · TeleDOM version: 4.1.0 +Generated: 2026-09-12T07:22:00.113Z · TeleDOM version: 4.1.0 **Surfaces**: td_=144 · dt_=54 · fx_=31 · base=47 · v3=74 · **total=350** diff --git a/manifest.json b/manifest.json index 63066493..5c230ce8 100644 --- a/manifest.json +++ b/manifest.json @@ -16,7 +16,8 @@ "tabs", "webNavigation", "management", - "debugger" + "debugger", + "alarms" ], "host_permissions": [ "++++Search Session Events & Nodes
+ ++ + ++" diff --git a/package.json b/package.json index 0b174041..d8aae37e 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,10 @@ "bench": "vitest run tests/intelligence/suite-reports.test.ts", "golden": "vitest run tests/intelligence/suite-reports.test.ts", "chaos": "vitest run tests/intelligence/suite-reports.test.ts", - "test:sdk": "python sdk/python/test_sdk.py" + "test:sdk": "python sdk/python/test_sdk.py", + "lint:python": "python -m ruff check sdk/python && python -m mypy sdk/python", + "format:python": "python -m isort sdk/python && python -m black sdk/python", + "qa:all": "npm run build && npm run test:unit && npm run test:sdk && npm run lint:python" }, "keywords": [ "browser", diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 00000000..bf842cbb --- /dev/null +++ b/ruff.toml @@ -0,0 +1,15 @@ +line-length = 100 +target-version = "py39" + +[lint] +select = ["E", "F", "W", "I", "RUF022"] +ignore = [ + "EXE001", # shebang executable check + "UP045", # requires Python 3.10+ PEP 604; project supports Python 3.9+ + "BLE001", # blind exception catch during process teardown + "S110", # try-except-pass in process termination + "PYI034", # __enter__ return self + "UP037", # quotes in type annotations + "E402", # module level import not at top of file + "E501", # line length handled by formatter +] diff --git a/scripts/run-operational-suite.js b/scripts/run-operational-suite.js index fcc1961c..a198da2b 100644 --- a/scripts/run-operational-suite.js +++ b/scripts/run-operational-suite.js @@ -4,8 +4,7 @@ import { fileURLToPath } from 'url'; import { spawn } from 'child_process'; import readline from 'readline'; import { JSDOM } from 'jsdom'; -import { FORENSIC_MCP_TOOLS, FileStorageProvider } from '../dist/server/mcp-server.js'; -import { PNGBuilder } from '../src/core/png-builder.ts'; +import { FORENSIC_MCP_TOOLS, FileStorageProvider, PNGBuilder } from '../dist/server/mcp-server.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); diff --git a/sdk/python/examples/extension_smoke_test.py b/sdk/python/examples/extension_smoke_test.py index b24222c6..4640b086 100644 --- a/sdk/python/examples/extension_smoke_test.py +++ b/sdk/python/examples/extension_smoke_test.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python3 """Extension smoke test — the golden v4.1 use case, as a reusable robot. The scenario the TeleDOM owner asked for: "I develop an extension; I want @@ -24,12 +23,13 @@ HERE = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, os.path.join(HERE, "..")) -from teledom import Browser, Workflow, TargetMemory # noqa: E402 +from teledom import Browser, TargetMemory, Workflow FIXTURE = os.path.abspath( os.path.join(HERE, "..", "..", "..", "operational-tests", "_fixtures", "dom-fixture.html") ) + def main() -> int: store = tempfile.mkdtemp(prefix="teledom-sdk-demo-") env = { @@ -54,8 +54,10 @@ def main() -> int: # ── LEARN — persist knowledge (agent-owned; TeleDOM just stores) ── mem = TargetMemory(client=browser.client) mem.save( - "example.test", "primary_action_button", - css="#primary-action-btn", aria="Run Analysis", + "example.test", + "primary_action_button", + css="#primary-action-btn", + aria="Run Analysis", identity={"role": "button", "accessibleName": "Run Analysis"}, confidence=0.95, notes="verify with browser.verify(); repair with find()+describe() when the UI changes", @@ -73,13 +75,28 @@ def main() -> int: wf.input("cta_selector", "Primary CTA selector", default="#primary-action-btn") wf.input("counter_selector", "Counter selector", default="#click-counter") wf.step("inspect", "td_dom_inspect", description="observe the page") - wf.step("verify_cta", "td_target_check", args={"selector": "{{inputs.cta_selector}}"}, - description="cheap target check — no DOM re-analysis") + wf.step( + "verify_cta", + "td_target_check", + args={"selector": "{{inputs.cta_selector}}"}, + description="cheap target check — no DOM re-analysis", + ) wf.step("click_cta", "td_action_click", args={"selector": "{{inputs.cta_selector}}"}) - wf.step("extract_counter", "td_dom_extract", - args={"selector": "{{inputs.counter_selector}}", "fields": {"text": "el.textContent.trim()"}}) - wf.step("assert_state", "td_execute_script", - args={"code": 'return document.querySelector("{{inputs.counter_selector}}").textContent.trim();'}) + wf.step( + "extract_counter", + "td_dom_extract", + args={ + "selector": "{{inputs.counter_selector}}", + "fields": {"text": "el.textContent.trim()"}, + }, + ) + wf.step( + "assert_state", + "td_execute_script", + args={ + "code": 'return document.querySelector("{{inputs.counter_selector}}").textContent.trim();' + }, + ) wf.save(version="1.0.0") print("[LEARN] workflow saved (5 steps, 2 templated inputs, policy caps)") @@ -92,9 +109,13 @@ def main() -> int: metrics = body.get("metrics", {}) print(f" runId : {run.get('runId')}") print(f" status : {body.get('status')}") - print(f" steps : {[(s.get('stepId'), s.get('status')) for s in body.get('steps', [])]}") - print(f" metrics : toolCalls={metrics.get('toolCalls')} domScans={metrics.get('domScans')} " - f"duration={metrics.get('durationMs')}ms") + print( + f" steps : {[(s.get('stepId'), s.get('status')) for s in body.get('steps', [])]}" + ) + print( + f" metrics : toolCalls={metrics.get('toolCalls')} domScans={metrics.get('domScans')} " + f"duration={metrics.get('durationMs')}ms" + ) # ── REPLAY — deterministic re-execution of the recorded run ───── replay = wf.replay(run["runId"]) @@ -108,16 +129,20 @@ def main() -> int: check = browser.verify(css) if not check.get("resolvable", False): failures.append(f"recovery check not resolvable: {check}") - print(f"[RECOVERY] : learned locator '{css}' resolvable={check.get('resolvable')} " - f"confidence={check.get('confidence')}") + print( + f"[RECOVERY] : learned locator '{css}' resolvable={check.get('resolvable')} " + f"confidence={check.get('confidence')}" + ) # ── KPI summary (the v4.1 golden demo) ────────────────────────────── print("\n=== KPIs ===") print("first run : 5 tool calls · 2 DOM scans · 5 MCP round trips") - print(f"reuse run : {metrics.get('toolCalls')} tool calls · {metrics.get('domScans')} DOM scans · 1 MCP round trip") - print(f"MCP round-trip reduction: 80% DOM-scan reduction: 50%") + print( + f"reuse run : {metrics.get('toolCalls')} tool calls · {metrics.get('domScans')} DOM scans · 1 MCP round trip" + ) + print("MCP round-trip reduction: 80% DOM-scan reduction: 50%") print(f"tokensSavedEstimate : {metrics.get('tokensSavedEstimate')}") - print(f"unsafe action bypass : 0 (approval gates BLOCK, never auto-approve)") + print("unsafe action bypass : 0 (approval gates BLOCK, never auto-approve)") if failures: print("\nFAILURES:", failures) diff --git a/sdk/python/pyproject.toml b/sdk/python/pyproject.toml index 3f985556..598a8906 100644 --- a/sdk/python/pyproject.toml +++ b/sdk/python/pyproject.toml @@ -25,3 +25,35 @@ Homepage = "https://github.com/IrMaho/TeleDOM" [tool.setuptools.packages.find] include = ["teledom*"] + +[tool.black] +line-length = 100 +target-version = ["py39", "py310", "py311", "py312"] + +[tool.isort] +profile = "black" +line_length = 100 + +[tool.ruff] +line-length = 100 +target-version = "py39" + +[tool.ruff.lint] +select = ["E", "F", "W", "I", "RUF022"] +ignore = [ + "EXE001", + "UP045", + "BLE001", + "S110", + "PYI034", + "UP037", + "E402", + "E501", +] + +[tool.mypy] +python_version = "3.9" +warn_return_any = true +warn_unused_configs = true +disallow_untyped_defs = false +ignore_missing_imports = true diff --git a/sdk/python/teledom/__init__.py b/sdk/python/teledom/__init__.py index 0461d174..68b7284e 100644 --- a/sdk/python/teledom/__init__.py +++ b/sdk/python/teledom/__init__.py @@ -24,19 +24,19 @@ internal tools, sites with no public API at all. """ -from .client import TeleDOMClient, TeleDOMError from .browser import Browser -from .workflow import Workflow, workflows +from .client import TeleDOMClient, TeleDOMError from .targets import TargetMemory +from .workflow import Workflow, workflows __version__ = "4.1.0" __all__ = [ + "Browser", + "TargetMemory", "TeleDOMClient", "TeleDOMError", - "Browser", "Workflow", - "workflows", - "TargetMemory", "__version__", + "workflows", ] diff --git a/sdk/python/teledom/browser.py b/sdk/python/teledom/browser.py index 28738243..a1be53d9 100644 --- a/sdk/python/teledom/browser.py +++ b/sdk/python/teledom/browser.py @@ -1,13 +1,13 @@ """Semantic Browser programming — the TeleDOM Level-2 primitive surface. - browser = Browser() # spawns + connects TeleDOM - browser.navigate("https://any.site") # any website — API never required - page = browser.inspect() # observe (the agent's eyes) - hits = browser.query("Comments") # find elements without selectors - target = browser.find(selector="#reply-box") - browser.click(target) - browser.type(target, "hello") - browser.verify(selector="#sent") +browser = Browser() # spawns + connects TeleDOM +browser.navigate("https://any.site") # any website — API never required +page = browser.inspect() # observe (the agent's eyes) +hits = browser.query("Comments") # find elements without selectors +target = browser.find(selector="#reply-box") +browser.click(target) +browser.type(target, "hello") +browser.verify(selector="#sent") """ from __future__ import annotations @@ -94,7 +94,12 @@ def snapshot(self, fmt: str = "html") -> Any: # ── targeting ────────────────────────────────────────────────────── - def find(self, selector: Optional[str] = None, xpath: Optional[str] = None, text: Optional[str] = None) -> Any: + def find( + self, + selector: Optional[str] = None, + xpath: Optional[str] = None, + text: Optional[str] = None, + ) -> Any: """Find an element by selector / xpath / text → canonical TARGET with confidence.""" args: dict = {} if selector: @@ -109,7 +114,9 @@ def find(self, selector: Optional[str] = None, xpath: Optional[str] = None, text def verify(self, selector: str, min_confidence: float = 0.0) -> Any: """Cheap target verification — replaces full DOM re-analysis.""" - return self._client.call("td_target_check", {"selector": selector, "minConfidence": min_confidence}) + return self._client.call( + "td_target_check", {"selector": selector, "minConfidence": min_confidence} + ) def describe(self, selector: str) -> Any: return self._client.call("td_target_describe", {"selector": selector}) @@ -155,7 +162,9 @@ def execute_script(self, code: str, timeout_ms: Optional[int] = None) -> Any: return self._client.call("td_execute_script", args) def network(self, url_contains: Optional[str] = None, limit: int = 50) -> Any: - return self._client.call("td_network_inspect", {"urlContains": url_contains, "limit": limit}) + return self._client.call( + "td_network_inspect", {"urlContains": url_contains, "limit": limit} + ) def console(self, level: str = "all") -> Any: return self._client.call("td_console_read", {"level": level}) diff --git a/sdk/python/teledom/client.py b/sdk/python/teledom/client.py index 77916c64..7c1675c9 100644 --- a/sdk/python/teledom/client.py +++ b/sdk/python/teledom/client.py @@ -8,9 +8,9 @@ import json import os +import queue import subprocess import threading -import queue from typing import Any, Optional @@ -32,7 +32,9 @@ def __init__( env: Optional[dict] = None, node_binary: str = "node", ): - self.server_path = server_path or os.environ.get("TELEDOM_SERVER_PATH") or self._default_server_path() + self.server_path = ( + server_path or os.environ.get("TELEDOM_SERVER_PATH") or self._default_server_path() + ) self.cwd = cwd self._proc: Optional[subprocess.Popen] = None self._env = env @@ -95,7 +97,13 @@ def _read_stdout(self) -> None: continue if "id" in msg: self._responses.put(msg) - self._responses.put({"jsonrpc": "2.0", "id": -1, "error": {"message": "server closed the stream"}}) + self._responses.put( + { + "jsonrpc": "2.0", + "id": -1, + "error": {"message": "server closed the stream"}, + } + ) def _next_id(self) -> int: with self._lock: @@ -106,7 +114,12 @@ def _next_id(self) -> int: def request(self, method: str, params: Optional[dict] = None, timeout: float = 60.0) -> dict: rid = self._next_id() - payload = {"jsonrpc": "2.0", "id": rid, "method": method, "params": params or {}} + payload = { + "jsonrpc": "2.0", + "id": rid, + "method": method, + "params": params or {}, + } assert self._proc and self._proc.stdin self._proc.stdin.write((json.dumps(payload) + "\n").encode("utf-8")) self._proc.stdin.flush() diff --git a/sdk/python/teledom/targets.py b/sdk/python/teledom/targets.py index 64daa0b2..7ed9497a 100644 --- a/sdk/python/teledom/targets.py +++ b/sdk/python/teledom/targets.py @@ -73,7 +73,9 @@ def list(self, site: Optional[str] = None, semantic_id: Optional[str] = None) -> return self._client.call("td_target_memory_list", args) def delete(self, site: str, semantic_id: str) -> Any: - return self._client.call("td_target_memory_delete", {"site": site, "semanticId": semantic_id}) + return self._client.call( + "td_target_memory_delete", {"site": site, "semanticId": semantic_id} + ) def close(self) -> None: if self._owns_client: diff --git a/sdk/python/teledom/workflow.py b/sdk/python/teledom/workflow.py index 8fc6894c..a97e1afb 100644 --- a/sdk/python/teledom/workflow.py +++ b/sdk/python/teledom/workflow.py @@ -48,8 +48,18 @@ def __init__( # ── authoring ────────────────────────────────────────────────────── - def input(self, name: str, description: str = "", required: bool = False, default: Any = None) -> "Workflow": - self.inputs[name] = {"description": description, "required": required, "default": default} + def input( + self, + name: str, + description: str = "", + required: bool = False, + default: Any = None, + ) -> "Workflow": + self.inputs[name] = { + "description": description, + "required": required, + "default": default, + } return self def step( @@ -63,7 +73,12 @@ def step( timeout_ms: Optional[int] = None, description: str = "", ) -> "Workflow": - s: dict = {"id": step_id, "tool": tool, "onError": on_error, "description": description} + s: dict = { + "id": step_id, + "tool": tool, + "onError": on_error, + "description": description, + } if args: s["args"] = args if retry_count: @@ -114,7 +129,12 @@ def export(self) -> Any: # ── dumb execution + records ─────────────────────────────────────── - def run(self, inputs: Optional[dict] = None, approved_steps: Optional[list] = None, dry_run: bool = False) -> Any: + def run( + self, + inputs: Optional[dict] = None, + approved_steps: Optional[list] = None, + dry_run: bool = False, + ) -> Any: args: dict = {"name": self.name, "inputs": inputs or {}} if approved_steps: args["approvedSteps"] = approved_steps diff --git a/sdk/python/test_sdk.py b/sdk/python/test_sdk.py index 3667378c..6118bcdf 100644 --- a/sdk/python/test_sdk.py +++ b/sdk/python/test_sdk.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python3 """Self-test for the TeleDOM Python SDK (no pytest required). Runs the full Level-2 surface against the deterministic DOM fixture: @@ -13,9 +12,11 @@ HERE = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, HERE) -from teledom import Browser, TeleDOMError, Workflow, TargetMemory # noqa: E402 +from teledom import Browser, TargetMemory, Workflow -FIXTURE = os.path.abspath(os.path.join(HERE, "..", "..", "operational-tests", "_fixtures", "dom-fixture.html")) +FIXTURE = os.path.abspath( + os.path.join(HERE, "..", "..", "operational-tests", "_fixtures", "dom-fixture.html") +) passed, failed = 0, 0 @@ -40,8 +41,14 @@ def main() -> int: with Browser(env=env) as browser: print("client:") - check("server handshake reports teledom", browser.server_info.get("name") == "teledom") - check("server version is 4.1.x", browser.server_info.get("version", "").startswith("4.1")) + check( + "server handshake reports teledom", + browser.server_info.get("name") == "teledom", + ) + check( + "server version is 4.1.x", + browser.server_info.get("version", "").startswith("4.1"), + ) tools = browser.client.list_tools() check("350 tools exposed over MCP", len(tools) == 350, f"got {len(tools)}") @@ -60,9 +67,17 @@ def main() -> int: print("target memory:") mem = TargetMemory(client=browser.client) - mem.save("example.test", "primary_action_button", css="#primary-action-btn", confidence=0.95) + mem.save( + "example.test", + "primary_action_button", + css="#primary-action-btn", + confidence=0.95, + ) target = mem.get("example.test", "primary_action_button").get("target", {}) - check("learned target persisted", (target.get("locators") or {}).get("css") == "#primary-action-btn") + check( + "learned target persisted", + (target.get("locators") or {}).get("css") == "#primary-action-btn", + ) listing = mem.list(site="example.test") check("target memory list works", listing.get("count", 0) >= 1) @@ -70,15 +85,26 @@ def main() -> int: wf = Workflow("sdk_self_test", client=browser.client, description="SDK self-test workflow") wf.input("selector", "CTA selector", default="#primary-action-btn") wf.step("verify", "td_target_check", args={"selector": "{{inputs.selector}}"}) - wf.step("assert", "td_execute_script", args={"code": 'return document.querySelector("{{inputs.selector}}") !== null;'}) + wf.step( + "assert", + "td_execute_script", + args={"code": 'return document.querySelector("{{inputs.selector}}") !== null;'}, + ) saved = wf.save(version="1.0.0") check("workflow saved verbatim", saved.get("status") == "PASS") run = wf.run() body = run.get("run", {}) - check("dumb execution SUCCESS", body.get("status") == "SUCCESS", str(body.get("error", ""))) + check( + "dumb execution SUCCESS", + body.get("status") == "SUCCESS", + str(body.get("error", "")), + ) check("deterministic record has metrics", "metrics" in body) - check("steps recorded with status", all("status" in s for s in body.get("steps", []))) + check( + "steps recorded with status", + all("status" in s for s in body.get("steps", [])), + ) replay = wf.replay(run["runId"]) check("verbatim replay works", replay.get("status") == "PASS") diff --git a/src/extension/background/service-worker.ts b/src/extension/background/service-worker.ts index 6b8ef8ae..097d4378 100644 --- a/src/extension/background/service-worker.ts +++ b/src/extension/background/service-worker.ts @@ -335,7 +335,11 @@ async function executeBackgroundCommand(command: string, payload: any): Promise< } (chrome as any).debugger.attach({ tabId }, '1.3', () => { if (chrome.runtime.lastError) { - return reject(new Error(`CDP_ATTACH failed: ${chrome.runtime.lastError.message}`)); + const errMsg = chrome.runtime.lastError.message || ''; + if (errMsg.includes('Another debugger is already attached')) { + return reject(new Error(`CDP_ATTACH failed: Chrome DevTools (F12) is already open on tab ${tabId}. Please close the F12 panel on that tab so TeleDOM can attach.`)); + } + return reject(new Error(`CDP_ATTACH failed: ${errMsg}`)); } // Bind the gateway session to this tab (used by CDP_COMMAND/DETACH). if (payload?.sessionId) cdpTargetsBySession.set(String(payload.sessionId), tabId); @@ -598,6 +602,28 @@ function ensureReconnect() { } } +// Manifest V3 Service Worker Keep-Alive via chrome.alarms (prevents 30s idle termination) +if (typeof chrome !== 'undefined' && chrome.alarms) { + try { + chrome.alarms.create('teledom_bridge_keepalive', { periodInMinutes: 0.4 }); + chrome.alarms.onAlarm.addListener((alarm) => { + if (alarm.name === 'teledom_bridge_keepalive') { + if (!wsBridge || wsBridge.readyState !== WebSocket.OPEN) { + connectBridge(); + } else { + try { + wsBridge.send(JSON.stringify({ type: 'HEARTBEAT', timestamp: Date.now() })); + } catch { + connectBridge(); + } + } + } + }); + } catch (err: any) { + console.warn('[ServiceWorker] Alarms keepalive setup failed:', err?.message); + } +} + // Start bridge connection connectBridge(); diff --git a/src/extension/content/content-script.ts b/src/extension/content/content-script.ts index b0865002..686be22c 100644 --- a/src/extension/content/content-script.ts +++ b/src/extension/content/content-script.ts @@ -415,194 +415,8 @@ import { InPageFloatingController } from './floating-controller'; }); } - // Direct WebSocket connection to MCP Bridge for immediate tab communication - let directWs: WebSocket | null = null; - let directReconnectTimer: any = null; - - function connectDirectBridge() { - if (typeof WebSocket === 'undefined') return; - try { - const ws = new WebSocket('ws://127.0.0.1:3847'); - ws.onopen = () => { - directWs = ws; - console.log('[Forensic ContentScript] Connected directly to MCP Bridge on ws://127.0.0.1:3847'); - if (directReconnectTimer) { - clearInterval(directReconnectTimer); - directReconnectTimer = null; - } - ws.send( - JSON.stringify({ - type: 'REGISTER_CLIENT', - clientType: 'CONTENT_SCRIPT', - url: window.location.href, - title: document.title, - }) - ); - }; - - ws.onclose = () => { - directWs = null; - ensureDirectReconnect(); - }; - - ws.onerror = () => { - directWs = null; - ensureDirectReconnect(); - }; - - ws.onmessage = async (event) => { - try { - const message = JSON.parse(event.data.toString()); - if (message.type === 'BROWSER_COMMAND_REQUEST') { - const { id, command, payload } = message; - - // 1. Background commands & Tab management - if (['LIST_TABS', 'OPEN_TAB', 'LIST_EXTENSIONS', 'RELOAD_EXTENSION', 'CLOSE_TAB', 'FOCUS_TAB', 'RELOAD_TAB', 'RESIZE_VIEWPORT', 'RESET_VIEWPORT'].includes(command)) { - if (typeof chrome !== 'undefined' && chrome.runtime?.sendMessage) { - chrome.runtime.sendMessage(message, (res) => { - if (chrome.runtime.lastError) { - // Local fallback if background unreachable - if (command === 'CLOSE_TAB') { - ws.send(JSON.stringify({ type: 'BROWSER_COMMAND_RESPONSE', id, command, success: true, data: { closed: true, url: window.location.href, title: document.title } })); - setTimeout(() => window.close(), 100); - return; - } - if (command === 'RELOAD_TAB') { - ws.send(JSON.stringify({ type: 'BROWSER_COMMAND_RESPONSE', id, command, success: true, data: { reloaded: true, url: window.location.href, title: document.title } })); - setTimeout(() => window.location.reload(), 100); - return; - } - ws.send( - JSON.stringify({ - type: 'BROWSER_COMMAND_RESPONSE', - id, - command, - success: false, - error: { code: 'FORWARD_ERROR', message: chrome.runtime.lastError.message }, - }) - ); - } else { - ws.send(JSON.stringify({ type: 'BROWSER_COMMAND_RESPONSE', ...(res || { id, command, success: true }) })); - } - }); - return; - } - - if (command === 'CLOSE_TAB') { - ws.send(JSON.stringify({ type: 'BROWSER_COMMAND_RESPONSE', id, command, success: true, data: { closed: true, url: window.location.href, title: document.title } })); - setTimeout(() => window.close(), 100); - return; - } - if (command === 'RELOAD_TAB') { - ws.send(JSON.stringify({ type: 'BROWSER_COMMAND_RESPONSE', id, command, success: true, data: { reloaded: true, url: window.location.href, title: document.title } })); - setTimeout(() => window.location.reload(), 100); - return; - } - } - - // 3. GET_TAB_CONSOLE_LOGS - if (command === 'GET_TAB_CONSOLE_LOGS') { - const { level, searchQuery, limit = 100, clearAfterRead } = payload || {}; - let logs = [...liveConsoleLogs]; - if (level && level !== 'all') { - logs = logs.filter((l) => l.level === level); - } - if (searchQuery) { - const q = String(searchQuery).toLowerCase(); - logs = logs.filter((l) => l.text?.toLowerCase().includes(q) || l.source?.toLowerCase().includes(q)); - } - if (limit > 0) { - logs = logs.slice(-limit); - } - if (clearAfterRead) { - liveConsoleLogs.length = 0; - } - ws.send( - JSON.stringify({ - type: 'BROWSER_COMMAND_RESPONSE', - id, - command, - success: true, - data: { - url: window.location.href, - title: document.title, - totalCaptured: liveConsoleLogs.length, - returnedCount: logs.length, - logs, - }, - }) - ); - return; - } - - // 4. GET_TAB_NETWORK_REQUESTS - if (command === 'GET_TAB_NETWORK_REQUESTS') { - const { method, searchQuery, status, onlyErrors, limit = 100, clearAfterRead } = payload || {}; - let reqs = [...liveNetworkRequests]; - if (method) { - reqs = reqs.filter((r) => r.method?.toUpperCase() === String(method).toUpperCase()); - } - if (status) { - reqs = reqs.filter((r) => r.status === Number(status)); - } - if (onlyErrors) { - reqs = reqs.filter((r) => r.error || (r.status && r.status >= 400)); - } - if (searchQuery) { - const q = String(searchQuery).toLowerCase(); - reqs = reqs.filter((r) => r.url?.toLowerCase().includes(q)); - } - if (limit > 0) { - reqs = reqs.slice(-limit); - } - if (clearAfterRead) { - liveNetworkRequests.length = 0; - } - ws.send( - JSON.stringify({ - type: 'BROWSER_COMMAND_RESPONSE', - id, - command, - success: true, - data: { - url: window.location.href, - title: document.title, - totalCaptured: liveNetworkRequests.length, - returnedCount: reqs.length, - requests: reqs, - }, - }) - ); - return; - } - - // 5. DOM Commands - const res = await liveController.handleCommand(message, document); - ws.send(JSON.stringify(res)); - } - } catch (err: any) { - console.error('[Forensic ContentScript] Bridge message error:', err); - } - }; - } catch { - directWs = null; - ensureDirectReconnect(); - } - } - - function ensureDirectReconnect() { - if (!directReconnectTimer) { - directReconnectTimer = setInterval(() => { - if (!directWs || directWs.readyState !== WebSocket.OPEN) { - connectDirectBridge(); - } - }, 4000); - } - } - - // Initialize + // Initialize injected page script injectPageScript(); - connectDirectBridge(); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initAutoReconnect); diff --git a/src/forensics/handler.ts b/src/forensics/handler.ts index dc0b7e5f..0d371171 100644 --- a/src/forensics/handler.ts +++ b/src/forensics/handler.ts @@ -445,7 +445,8 @@ export class ForensicsToolsHandler { try { const res = await unifiedRuntime.bridgeCommand('LIVE_DOM_SNAPSHOT', { format: 'json' }); return { snapshot: res }; - } catch { + } catch (err: any) { + console.warn(`[ForensicsHandler] Could not capture live snapshot: ${err?.message || err}`); return { snapshot: null }; } } @@ -455,7 +456,8 @@ async function runInPageSafe(code: string, tabId?: number): Promise (file: string): T | null { try { return JSON.parse(fs.readFileSync(file, 'utf-8')) as T; - } catch { + } catch (err: any) { + if (err?.code !== 'ENOENT') { + console.warn(`[WorkflowStore] Warning: Failed to read or parse ${file}:`, err?.message || err); + } return null; } } @@ -157,7 +160,10 @@ export class AgentStore { private listJsonNames(dir: string): string[] { try { return fs.readdirSync(dir).filter((f) => f.endsWith('.json')).sort(); - } catch { + } catch (err: any) { + if (err?.code !== 'ENOENT') { + console.warn(`[WorkflowStore] Warning: Failed to list directory ${dir}:`, err?.message || err); + } return []; } } diff --git a/src/mcp/bridge-server.ts b/src/mcp/bridge-server.ts index 689336c6..20347ad0 100644 --- a/src/mcp/bridge-server.ts +++ b/src/mcp/bridge-server.ts @@ -104,17 +104,19 @@ export class MCPBridgeServer implements BrowserBridgeClient { } } - // If no service worker connected, fallback to CONTENT_SCRIPT sockets + // If no service worker connected, fallback to a single primary CONTENT_SCRIPT socket (never broadcast commands to all tabs) if (targets.length === 0) { for (const [sock, meta] of this.socketMetadata.entries()) { if (meta.clientType === 'CONTENT_SCRIPT' && sock.readyState === WebSocket.OPEN) { - targets.push(sock); + targets = [sock]; + break; } } } - if (targets.length === 0) { - targets = Array.from(this.activeSockets); + if (targets.length === 0 && this.activeSockets.size > 0) { + const first = Array.from(this.activeSockets).find((s) => s.readyState === WebSocket.OPEN); + if (first) targets = [first]; } let sentCount = 0; @@ -142,11 +144,28 @@ export class MCPBridgeServer implements BrowserBridgeClient { public start(): Promise { return new Promise((resolve, reject) => { + const isTrustedOrigin = (origin?: string): boolean => { + if (!origin) return true; // Direct non-browser callers (Node, curl, stdio MCP) + if (origin.startsWith('chrome-extension://')) return true; + if (/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(origin)) return true; + return false; + }; + this.httpServer = http.createServer(async (req, res) => { - // Enable CORS - res.setHeader('Access-Control-Allow-Origin', '*'); + const origin = req.headers.origin; + if (origin) { + if (isTrustedOrigin(origin)) { + res.setHeader('Access-Control-Allow-Origin', origin); + res.setHeader('Access-Control-Allow-Credentials', 'true'); + res.setHeader('Vary', 'Origin'); + } else if (req.method === 'OPTIONS') { + res.writeHead(403, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ error: 'CORS Forbidden: Untrusted cross-origin request rejected' })); + return; + } + } res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); - res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); + res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, x-teledom-token'); if (req.method === 'OPTIONS') { res.writeHead(204); @@ -156,9 +175,29 @@ export class MCPBridgeServer implements BrowserBridgeClient { const url = req.url || ''; + // Security check for mutating and sensitive endpoints + const isAuthValid = (): boolean => { + if (!isTrustedOrigin(origin)) return false; + const expectedToken = process.env.TELEDOM_BRIDGE_TOKEN; + if (!expectedToken) return true; + const authHeader = req.headers.authorization; + const tokenHeader = req.headers['x-teledom-token']; + let queryToken: string | null = null; + try { + const parsed = new URL(url, 'http://127.0.0.1'); + queryToken = parsed.searchParams.get('token'); + } catch { /* ignored */ } + if (authHeader && authHeader.startsWith('Bearer ')) { + return authHeader.slice(7).trim() === expectedToken; + } + if (tokenHeader && tokenHeader === expectedToken) return true; + if (queryToken && queryToken === expectedToken) return true; + return false; + }; + // 1. Health check (v4.1 fix E-17: version derived from the // authoritative registry — was stale '3.0.0') - if (url === '/health' && req.method === 'GET') { + if (url.startsWith('/health') && req.method === 'GET') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end( JSON.stringify({ @@ -171,6 +210,15 @@ export class MCPBridgeServer implements BrowserBridgeClient { return; } + // Enforce authorization for sensitive endpoints + if (['/api/mcp/tool', '/api/tabs/close', '/api/sessions/upload'].some(p => url.startsWith(p))) { + if (!isAuthValid()) { + res.writeHead(403, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ error: 'Forbidden: Invalid or missing authorization credentials' })); + return; + } + } + const MAX_PAYLOAD_BYTES = 50 * 1024 * 1024; // 50MB limit // 2. Upload Session Bundle @@ -301,7 +349,13 @@ export class MCPBridgeServer implements BrowserBridgeClient { }, 30000); (this.healthSweepInterval as any)?.unref?.(); - this.wss.on('connection', (ws: WebSocket) => { + this.wss.on('connection', (ws: WebSocket, req: http.IncomingMessage) => { + const origin = req?.headers?.origin; + if (origin && !isTrustedOrigin(origin)) { + console.error(`[MCP Bridge] WebSocket connection rejected from untrusted origin: ${origin}`); + ws.close(4403, 'Forbidden origin'); + return; + } this.activeSockets.add(ws); console.error(`[MCP Bridge] Client connected. Total active clients: ${this.activeSockets.size}`); diff --git a/src/mcp/live-tools-handler.ts b/src/mcp/live-tools-handler.ts index 021a0908..0510fcaa 100644 --- a/src/mcp/live-tools-handler.ts +++ b/src/mcp/live-tools-handler.ts @@ -687,8 +687,18 @@ export class LiveToolsHandler { }, ], }; - } catch { - // Fallthrough + } catch (saveErr: any) { + return { + content: [ + { + type: 'text', + text: JSON.stringify({ + ...finalSummary, + fileSaveError: `Failed to write pipeline output to ${args.outputPath}: ${saveErr?.message || saveErr}`, + }, null, 2), + }, + ], + }; } } diff --git a/src/mcp/server.ts b/src/mcp/server.ts index e76ef4f8..892e30bd 100644 --- a/src/mcp/server.ts +++ b/src/mcp/server.ts @@ -11,8 +11,10 @@ import { LiveToolsHandler, BrowserBridgeClient } from './live-tools-handler'; import { MCPBridgeServer } from './bridge-server'; import { BrowserCommandType } from '../types/browser-control'; import { TELEDOM_VERSION } from '../intelligence/version'; +import { TELEDOM_PROFILE_TOOLS } from './tool-groups'; +import { PNGBuilder } from '../core/png-builder'; -export { FORENSIC_MCP_TOOLS, FileStorageProvider, MCPToolsHandler }; +export { FORENSIC_MCP_TOOLS, FileStorageProvider, MCPToolsHandler, TELEDOM_PROFILE_TOOLS, PNGBuilder }; export class ForensicMCPServer { private storage: ForensicStorageProvider; @@ -208,12 +210,21 @@ export class ForensicMCPServer { const disableDevTools = process.env.FORENSIC_DISABLE_DEVTOOLS === 'true'; const disableForensics = process.env.FORENSIC_DISABLE_FORENSICS === 'true'; const disableIntelligence = process.env.FORENSIC_DISABLE_INTELLIGENCE === 'true'; - const tools = FORENSIC_MCP_TOOLS.filter( + const profile = (process.env.TELEDOM_PROFILE || 'full').toLowerCase(); + const profileAllowed = TELEDOM_PROFILE_TOOLS[profile]; + + let tools = FORENSIC_MCP_TOOLS.filter( (t) => !(disableDevTools && t.name.startsWith('dt_')) && !(disableForensics && t.name.startsWith('fx_')) && !(disableIntelligence && t.name.startsWith('td_')), ); + + if (profileAllowed && Array.isArray(profileAllowed)) { + const allowedSet = new Set(profileAllowed); + tools = tools.filter((t) => allowedSet.has(t.name)); + } + return { jsonrpc: '2.0', id, diff --git a/src/mcp/tool-groups.ts b/src/mcp/tool-groups.ts index 68b3179c..27a81d5b 100644 --- a/src/mcp/tool-groups.ts +++ b/src/mcp/tool-groups.ts @@ -225,3 +225,41 @@ export function buildToolCatalog(): ToolDiscoveryInfo[] { export function findGroupOfTool(toolName: string): ToolGroupInfo | undefined { return TOOL_GROUPS.find((g) => g.tools.includes(toolName)); } + +export type TeledomProfileName = 'minimal' | 'core' | 'forensics' | 'full'; + +export const TELEDOM_PROFILE_TOOLS: Record = { + // Minimal profile: strictly essential browser actions (~22 tools, ~2.5k tokens) + minimal: [ + 'td_browser_navigate', 'td_browser_back', 'td_browser_forward', 'td_browser_refresh', + 'td_dom_inspect', 'td_dom_query', 'td_dom_extract', 'td_dom_snapshot', + 'td_target_find', 'td_target_check', + 'td_action_click', 'td_action_type', 'td_action_select', 'td_action_press', 'td_action_scroll', + 'td_wait', 'td_screenshot', 'td_execute_script', + 'list_tabs', 'focus_tab', 'close_tab', 'open_tab', + ], + // Core profile: browser primitives + workflow runtime + target memory (~44 tools, ~4.8k tokens) + core: [ + 'td_browser_navigate', 'td_browser_back', 'td_browser_forward', 'td_browser_refresh', + 'td_dom_inspect', 'td_dom_query', 'td_dom_extract', 'td_dom_snapshot', + 'td_target_find', 'td_target_check', 'td_target_describe', + 'td_action_click', 'td_action_type', 'td_action_select', 'td_action_hover', 'td_action_press', 'td_action_scroll', + 'td_wait', 'td_screenshot', 'td_execute_script', 'td_network_inspect', 'td_console_read', + 'td_workflow_save', 'td_workflow_get', 'td_workflow_list', 'td_workflow_update', 'td_workflow_delete', + 'td_workflow_validate', 'td_workflow_run', 'td_workflow_runs', 'td_workflow_replay', + 'td_target_memory_save', 'td_target_memory_get', 'td_target_memory_list', 'td_target_memory_delete', + 'list_tabs', 'focus_tab', 'reload_tab', 'close_tab', 'open_tab', + 'inspect_live_page', 'inspect_live_element', + ], + // Forensics profile: historical forensics + diffs + causality + live inspection (~50 tools) + forensics: [ + 'list_sessions', 'get_session', 'export_session', 'import_session', 'delete_session', + 'get_timeline', 'get_events', 'get_events_around', 'get_dom_state', 'get_dom_node', 'get_dom_subtree', + 'diff_dom', 'trace_element', 'find_disappearing_elements', 'why_did_element_disappear', + 'get_diagnostics', 'get_network_events', 'get_screenshots', + 'td_browser_navigate', 'td_dom_inspect', 'td_dom_query', 'td_dom_extract', 'td_screenshot', + 'td_action_click', 'td_action_type', 'td_workflow_run', 'list_tabs', 'focus_tab', + ], + // Full profile: all 350 tools (null means no filtering) + full: null, +}; diff --git a/src/projects/project-manager.ts b/src/projects/project-manager.ts index 1c1fe945..0965b1b6 100644 --- a/src/projects/project-manager.ts +++ b/src/projects/project-manager.ts @@ -124,8 +124,8 @@ export class ProjectManager { try { const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')); out.push({ ...manifest, projectDir: path.join(this.baseDir, entry.name), pageCount: manifest.pages?.length || 0 }); - } catch { - // Corrupt manifest — skip but do not crash the listing + } catch (err) { + console.warn(`[ProjectManager] Warning: Skipped corrupt project manifest at ${manifestPath}:`, err); } } return out.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0)); @@ -443,7 +443,9 @@ export class ProjectManager { if (fs.existsSync(p)) { try { out.push(JSON.parse(fs.readFileSync(p, 'utf-8'))); - } catch { /* skip corrupt */ } + } catch (err) { + console.warn(`[ProjectManager] Warning: Skipped corrupt region file ${p}:`, err); + } } } return out; diff --git a/src/storage/file-storage.ts b/src/storage/file-storage.ts index f119386f..e19033ed 100644 --- a/src/storage/file-storage.ts +++ b/src/storage/file-storage.ts @@ -1,6 +1,5 @@ import * as fs from 'fs'; import * as path from 'path'; -import * as readline from 'readline'; import { Annotation, SessionMetadata } from '../types/session'; import { BaseEvent } from '../types/events'; import { SnapshotCheckpoint } from '../types/checkpoint'; @@ -28,47 +27,54 @@ export class FileStorageProvider implements ForensicStorageProvider { public async saveSession(metadata: SessionMetadata): Promise { const dir = this.getSessionDir(metadata.id); const metaPath = path.join(dir, 'metadata.json'); - fs.writeFileSync(metaPath, JSON.stringify(metadata, null, 2), 'utf-8'); + await fs.promises.writeFile(metaPath, JSON.stringify(metadata, null, 2), 'utf-8'); } public async getSession(sessionId: string): Promise { const dir = path.join(this.baseDir, sessionId); const metaPath = path.join(dir, 'metadata.json'); - if (!fs.existsSync(metaPath)) return null; try { - const data = fs.readFileSync(metaPath, 'utf-8'); + const data = await fs.promises.readFile(metaPath, 'utf-8'); return JSON.parse(data) as SessionMetadata; - } catch { + } catch (err: any) { + if (err?.code !== 'ENOENT') { + console.warn(`[FileStorage] Warning: Failed to read session ${sessionId}: ${err?.message}`); + } return null; } } public async listSessions(): Promise { if (!fs.existsSync(this.baseDir)) return []; - const entries = fs.readdirSync(this.baseDir, { withFileTypes: true }); - const sessions: SessionMetadata[] = []; + try { + const entries = await fs.promises.readdir(this.baseDir, { withFileTypes: true }); + const sessions: SessionMetadata[] = []; - for (const entry of entries) { - if (entry.isDirectory()) { - const metaPath = path.join(this.baseDir, entry.name, 'metadata.json'); - if (fs.existsSync(metaPath)) { + for (const entry of entries) { + if (entry.isDirectory()) { + const metaPath = path.join(this.baseDir, entry.name, 'metadata.json'); try { - const data = fs.readFileSync(metaPath, 'utf-8'); + const data = await fs.promises.readFile(metaPath, 'utf-8'); sessions.push(JSON.parse(data) as SessionMetadata); - } catch { - // Corrupt file skipped + } catch (err: any) { + if (err?.code !== 'ENOENT') { + console.warn(`[FileStorage] Warning: Corrupt or unreadable session metadata at ${metaPath}: ${err?.message}`); + } } } } - } - return sessions.sort((a, b) => b.startTime - a.startTime); + return sessions.sort((a, b) => b.startTime - a.startTime); + } catch (err: any) { + console.error(`[FileStorage] Failed to list sessions from ${this.baseDir}:`, err?.message); + return []; + } } public async deleteSession(sessionId: string): Promise { const dir = path.join(this.baseDir, sessionId); if (fs.existsSync(dir)) { - fs.rmSync(dir, { recursive: true, force: true }); + await fs.promises.rm(dir, { recursive: true, force: true, maxRetries: 10, retryDelay: 50 }); return true; } return false; @@ -79,7 +85,7 @@ export class FileStorageProvider implements ForensicStorageProvider { const dir = this.getSessionDir(sessionId); const eventsPath = path.join(dir, 'events.jsonl'); const lines = events.map((e) => JSON.stringify(e)).join('\n') + '\n'; - fs.appendFileSync(eventsPath, lines, 'utf-8'); + await fs.promises.appendFile(eventsPath, lines, 'utf-8'); } public async getEvents(sessionId: string, filter?: EventFilter): Promise { @@ -87,25 +93,23 @@ export class FileStorageProvider implements ForensicStorageProvider { const eventsPath = path.join(dir, 'events.jsonl'); if (!fs.existsSync(eventsPath)) return []; - const fileStream = fs.createReadStream(eventsPath, { encoding: 'utf-8' }); - const rl = readline.createInterface({ - input: fileStream, - crlfDelay: Infinity, - }); + const content = await fs.promises.readFile(eventsPath, 'utf-8'); + const lines = content.split(/\r?\n/); const results: BaseEvent[] = []; let matchedCount = 0; const offset = typeof filter?.offset === 'number' ? filter.offset : 0; const limit = typeof filter?.limit === 'number' ? filter.limit : Infinity; - for await (const line of rl) { + for (const line of lines) { const trimmed = line.trim(); if (!trimmed) continue; let e: BaseEvent; try { e = JSON.parse(trimmed); - } catch { + } catch (parseErr) { + console.warn(`[FileStorage] Skipping malformed event line in session ${sessionId}:`, parseErr); continue; } @@ -135,8 +139,6 @@ export class FileStorageProvider implements ForensicStorageProvider { results.push(e); if (results.length >= limit) { - rl.close(); - fileStream.destroy(); break; } } @@ -149,14 +151,9 @@ export class FileStorageProvider implements ForensicStorageProvider { const eventsPath = path.join(dir, 'events.jsonl'); if (!fs.existsSync(eventsPath)) return 0; - const fileStream = fs.createReadStream(eventsPath, { encoding: 'utf-8' }); - const rl = readline.createInterface({ - input: fileStream, - crlfDelay: Infinity, - }); - + const content = await fs.promises.readFile(eventsPath, 'utf-8'); let count = 0; - for await (const line of rl) { + for (const line of content.split(/\r?\n/)) { if (line.trim()) count++; } return count; @@ -165,44 +162,52 @@ export class FileStorageProvider implements ForensicStorageProvider { public async saveCheckpoint(checkpoint: SnapshotCheckpoint): Promise { const dir = this.getSessionDir(checkpoint.sessionId); const chkDir = path.join(dir, 'checkpoints'); - if (!fs.existsSync(chkDir)) fs.mkdirSync(chkDir, { recursive: true }); + await fs.promises.mkdir(chkDir, { recursive: true }); const file = path.join(chkDir, `${checkpoint.checkpointId}.json`); - fs.writeFileSync(file, JSON.stringify(checkpoint, null, 2), 'utf-8'); + await fs.promises.writeFile(file, JSON.stringify(checkpoint, null, 2), 'utf-8'); } public async getCheckpoints(sessionId: string): Promise { const dir = path.join(this.baseDir, sessionId, 'checkpoints'); - if (!fs.existsSync(dir)) return []; - - const files = fs.readdirSync(dir).filter((f) => f.endsWith('.json')); - const checkpoints: SnapshotCheckpoint[] = []; + try { + const files = (await fs.promises.readdir(dir)).filter((f) => f.endsWith('.json')); + const checkpoints: SnapshotCheckpoint[] = []; + + for (const f of files) { + try { + const data = await fs.promises.readFile(path.join(dir, f), 'utf-8'); + checkpoints.push(JSON.parse(data)); + } catch (err) { + console.warn(`[FileStorage] Failed to read/parse checkpoint file ${f} in session ${sessionId}:`, err); + } + } - for (const f of files) { - try { - const data = fs.readFileSync(path.join(dir, f), 'utf-8'); - checkpoints.push(JSON.parse(data)); - } catch { - // Ignored + return checkpoints.sort((a, b) => a.sequence - b.sequence); + } catch (err: any) { + if (err?.code !== 'ENOENT') { + console.warn(`[FileStorage] Error accessing checkpoints directory for session ${sessionId}:`, err); } + return []; } - - return checkpoints.sort((a, b) => a.sequence - b.sequence); } public async saveInitialSnapshot(sessionId: string, snapshot: DOMSnapshot): Promise { const dir = this.getSessionDir(sessionId); const file = path.join(dir, 'initial_snapshot.json'); - fs.writeFileSync(file, JSON.stringify(snapshot, null, 2), 'utf-8'); + await fs.promises.writeFile(file, JSON.stringify(snapshot, null, 2), 'utf-8'); } public async getInitialSnapshot(sessionId: string): Promise { const dir = path.join(this.baseDir, sessionId); const file = path.join(dir, 'initial_snapshot.json'); - if (!fs.existsSync(file)) return null; try { - return JSON.parse(fs.readFileSync(file, 'utf-8')) as DOMSnapshot; - } catch { + const content = await fs.promises.readFile(file, 'utf-8'); + return JSON.parse(content) as DOMSnapshot; + } catch (err: any) { + if (err?.code !== 'ENOENT') { + console.warn(`[FileStorage] Error reading initial snapshot for session ${sessionId}:`, err); + } return null; } } @@ -211,24 +216,29 @@ export class FileStorageProvider implements ForensicStorageProvider { const dir = this.getSessionDir(annotation.sessionId); const annPath = path.join(dir, 'annotations.json'); let list: Annotation[] = []; - if (fs.existsSync(annPath)) { - try { - list = JSON.parse(fs.readFileSync(annPath, 'utf-8')); - } catch { - list = []; + try { + const content = await fs.promises.readFile(annPath, 'utf-8'); + list = JSON.parse(content); + } catch (err: any) { + if (err?.code !== 'ENOENT') { + console.warn(`[FileStorage] Corrupted annotations file for session ${annotation.sessionId}, starting fresh:`, err); } + list = []; } list.push(annotation); - fs.writeFileSync(annPath, JSON.stringify(list, null, 2), 'utf-8'); + await fs.promises.writeFile(annPath, JSON.stringify(list, null, 2), 'utf-8'); } public async getAnnotations(sessionId: string): Promise { const dir = path.join(this.baseDir, sessionId); const annPath = path.join(dir, 'annotations.json'); - if (!fs.existsSync(annPath)) return []; try { - return JSON.parse(fs.readFileSync(annPath, 'utf-8')) as Annotation[]; - } catch { + const content = await fs.promises.readFile(annPath, 'utf-8'); + return JSON.parse(content) as Annotation[]; + } catch (err: any) { + if (err?.code !== 'ENOENT') { + console.warn(`[FileStorage] Failed to read annotations for session ${sessionId}:`, err); + } return []; } } diff --git a/src/storage/recording-storage.ts b/src/storage/recording-storage.ts index 80d9fe65..9ee8e94c 100644 --- a/src/storage/recording-storage.ts +++ b/src/storage/recording-storage.ts @@ -33,7 +33,8 @@ export class CommandRecordingStorage { try { const raw = JSON.parse(fs.readFileSync(file, 'utf-8')); return raw.recording || raw; - } catch { + } catch (err) { + console.warn(`[RecordingStorage] Warning: Failed to parse recording file ${file}:`, err); return null; } } @@ -63,8 +64,8 @@ export class CommandRecordingStorage { tags: rec.tags || [], file: path.join(this.baseDir, entry.name), }); - } catch { - // skip corrupt files + } catch (err) { + console.warn(`[RecordingStorage] Warning: Skipped corrupt recording file ${entry.name}:`, err); } } return out.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0)); diff --git a/tests/integration/storage.test.ts b/tests/integration/storage.test.ts index 7cd8e0a1..ffe4c205 100644 --- a/tests/integration/storage.test.ts +++ b/tests/integration/storage.test.ts @@ -174,8 +174,12 @@ describe('Storage Providers (Memory & File)', () => { expect(userPaged.every((e) => e.category === 'USER')).toBe(true); } finally { if (fs.existsSync(testDir)) { - fs.rmSync(testDir, { recursive: true, force: true }); + try { + fs.rmSync(testDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }); + } catch { + // Allow transient lock in Windows test runners to drain + } } } - }); + }, 30_000); }); diff --git a/tests/intelligence/workflow.test.ts b/tests/intelligence/workflow.test.ts index 7d4fe5c4..4585128a 100644 --- a/tests/intelligence/workflow.test.ts +++ b/tests/intelligence/workflow.test.ts @@ -31,7 +31,13 @@ beforeEach(() => { afterEach(() => { delete process.env.TELEDOM_AGENT_STORE_DIR; - fs.rmSync(tmpDir, { recursive: true, force: true }); + if (tmpDir && fs.existsSync(tmpDir)) { + try { + fs.rmSync(tmpDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 50 }); + } catch { + // Allow transient lock in Windows test runners to drain + } + } }); function makeWorkflow(overrides: Partial = {}): AgentWorkflow { diff --git a/vitest.config.ts b/vitest.config.ts index e10ac743..94a6e247 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -5,5 +5,7 @@ export default defineConfig({ environment: 'jsdom', include: ['tests/**/*.test.ts'], exclude: ['dist/**', 'node_modules/**'], + testTimeout: 30000, + hookTimeout: 30000, }, });