@elementor/angie-sdk 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -103,7 +103,9 @@ The SDK covers three main abilities:
103
103
  **Not Available:**
104
104
  - Roots, STDIO transport (browser environment limitations)
105
105
 
106
- 📖 **For detailed feature documentation and best practices, see [MCP SDK Supported Features](./docs/angie-sdk-supported-features.md)**
106
+ 📖 **Documentation:**
107
+ - [MCP SDK Supported Features](./docs/angie-sdk-supported-features.md)
108
+ - [Tool Model Preferences](./docs/model-preferences.md) - Configure preferred AI models for your tools
107
109
 
108
110
  ---
109
111
 
package/dist/index.d.ts CHANGED
@@ -9,3 +9,4 @@ export { getAngieIframe } from './angie-iframe-utils';
9
9
  export { disableNavigationPrevention } from './iframe';
10
10
  export * from './types';
11
11
  export { BrowserContextTransport } from './browser-context-transport';
12
+ export { setReferrerRedirect, getReferrerRedirect, clearReferrerRedirect } from './referrer-redirect';
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{JSONRPCMessageSchema as e}from"@modelcontextprotocol/sdk/types.js";const t={none:0,error:1,warn:2,info:3,debug:4},n={error:"error",warn:"warn",info:"info",log:"info",debug:"debug"},i=(e,n)=>t[e]<=t[n],r=e=>"string"==typeof e?e:JSON.stringify(e),o=(e,t)=>`${r(e)} > ${r(t)}`,a=(e,t)=>{let n=`[${r(e)}]`;return typeof window<"u"?{text:`%c${n}`,style:`color: ${t.color||"#00bcd4"}; font-weight: bold;`}:{text:n}},s=(e,t,r,o)=>(...s)=>{if(!i(n[e],o()))return;if(!t)return void console[e](...s);let{text:d,style:g}=a(t,r);g?console[e](d,g,...s):console[e](d,...s)},d=(e,t)=>{let n=t.logLevel??"debug",i=()=>n;return{log:s("log",e,t,i),info:s("info",e,t,i),warn:s("warn",e,t,i),error:s("error",e,t,i),debug:s("debug",e,t,i),setLogLevel:e=>{n=e},extend:i=>d(e?o(e,i):i,{...t,logLevel:n})}},g=d("angie-sdk",{color:"#00bcd4",logLevel:"debug",color:"#00BCD4",logLevel:"error"}),c=e=>g.extend(e);var l,u,h,p,m,w,f;!function(e){e.POST_MESSAGE="postMessage"}(l||(l={})),function(e){e.POST_MESSAGE="postMessage"}(u||(u={})),function(e){e.STREAMABLE_HTTP="streamableHttp",e.SSE="sse"}(h||(h={})),function(e){e.LOCAL="local",e.REMOTE="remote"}(p||(p={})),function(e){e.SDK_ANGIE_READY_PING="sdk-angie-ready-ping",e.SDK_ANGIE_REFRESH_PING="sdk-angie-refresh-ping",e.SDK_ANGIE_ALL_SERVERS_REGISTERED="sdk-angie-all-servers-registered",e.SDK_REQUEST_CLIENT_CREATION="sdk-request-client-creation",e.SDK_REQUEST_INIT_SERVER="sdk-request-init-server",e.SDK_TRIGGER_ANGIE="sdk-trigger-angie",e.SDK_TRIGGER_ANGIE_RESPONSE="sdk-trigger-angie-response",e.ANGIE_SIDEBAR_RESIZED="angie-sidebar-resized",e.ANGIE_SIDEBAR_TOGGLED="angie-sidebar-toggled",e.ANGIE_CHAT_TOGGLE="angie-chat-toggle",e.ANGIE_STUDIO_TOGGLE="angie-studio-toggle",e.ANGIE_NAVIGATE_TO_URL="angie/navigate-to-url",e.ANGIE_PAGE_RELOAD="angie/page-reload",e.ANGIE_DISABLE_NAVIGATION_PREVENTION="angie/disable-navigation-prevention",e.ANGIE_NAVIGATE_AFTER_RESPONSE="angie/navigate-after-response"}(m||(m={})),function(e){e.SET="ANGIE_SET_LOCALSTORAGE",e.GET="ANGIE_GET_LOCALSTORAGE"}(w||(w={})),function(e){e.RESET_HASH="reset-hash",e.HOST_READY="host/ready",e.ANGIE_LOADED="angie/loaded",e.ANGIE_READY="angie/ready"}(f||(f={}));const E=c("angie-detector");class y{isAngieReady=!1;readyPromise;readyResolve;constructor(){if(this.readyPromise=new Promise(e=>{this.readyResolve=e}),"undefined"==typeof window)return;let e=0;const t=()=>{if(this.isAngieReady||e>=500)return void(!this.isAngieReady&&e>=500&&this.handleDetectionTimeout());const n=new MessageChannel;n.port1.onmessage=e=>{this.handleAngieReady(e.data),n.port1.close(),n.port2.close()};const i={type:m.SDK_ANGIE_READY_PING,timestamp:Date.now()};window.postMessage(i,window.location.origin,[n.port2]),e++,setTimeout(t,500)};t()}handleAngieReady(e){this.isAngieReady=!0;const t={isReady:!0,version:e.version,capabilities:e.capabilities};this.readyResolve&&this.readyResolve(t)}handleDetectionTimeout(){this.readyResolve&&this.readyResolve({isReady:!1}),E.warn("Detection timeout - Angie may not be available")}isReady(){return this.isAngieReady}async waitForReady(){return this.readyPromise}}class b{sessionId;onmessage;onerror;onclose;_port;_started=!1;_closed=!1;constructor(t){if(!t)throw new Error("MessagePort is required");this._port=t,this._port.onmessage=t=>{try{const n=e.parse(t.data);this.onmessage?.(n)}catch(e){const t=new Error(`Failed to parse message: ${e}`);this.onerror?.(t)}},this._port.onmessageerror=e=>{const t=new Error(`MessagePort error: ${JSON.stringify(e)}`);this.onerror?.(t)}}async start(){if(this._started)throw new Error("BrowserContextTransport already started! If using Client or Server class, note that connect() calls start() automatically.");if(this._closed)throw new Error("Cannot start a closed BrowserContextTransport");this._started=!0,this._port.start()}async send(e){if(this._closed)throw new Error("Cannot send on a closed BrowserContextTransport");return new Promise((t,n)=>{try{this._port.postMessage(e),t()}catch(e){const t=e instanceof Error?e:new Error(String(e));this.onerror?.(t),n(t)}})}async close(){this._closed||(this._closed=!0,this._port.close(),this.onclose?.())}}class v{async requestClientCreation(e){const{config:t}=e,n={serverId:e.id,serverName:t.name,serverTitle:t.title,serverVersion:t.version,description:t.description,transport:t.transport||u.POST_MESSAGE,capabilities:t.capabilities,instanceId:e.instanceId};return"type"in t&&"remote"===t.type&&(n.remote={url:t.url}),new Promise((e,t)=>{const i=new MessageChannel,r=setTimeout(()=>{t(new Error("Client creation request timed out after 15000ms"))},15e3);i.port1.onmessage=t=>{clearTimeout(r),e(t.data)};const o={type:m.SDK_REQUEST_CLIENT_CREATION,payload:n,timestamp:Date.now()};window.postMessage(o,window.location.origin,[i.port2])})}}const S={open:!1,iframe:null,iframeUrlObject:null},I=(e,t)=>{const n=document.getElementById("angie-sidebar-container");n&&n.setAttribute("aria-hidden",t?"false":"true"),t?e.removeAttribute("tabindex"):e.setAttribute("tabindex","-1")},A=(e,t)=>{e.postMessage({status:"success",payload:t})},_=(e,t)=>{e.postMessage({status:"error",payload:t})},R=()=>new Promise(e=>{"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e):e(null)}),T=c("oauth");function L(){const e=new URL(window.location.href);e.searchParams.set("start-oauth","1"),T.log("Redirecting to wp-admin with OAuth:",e.toString()),window.location.href=e.toString()}const G=()=>{window.addEventListener("message",e=>{if(e.origin===S.iframeUrlObject?.origin)switch(e.data.type){case"OAUTH_GET_CODE_AND_STATE":(e=>{const t=new URLSearchParams(window.location.search),n=t.get("oauth_code"),i=t.get("oauth_state");if(n&&i)A(e,{code:n,state:i});else{const r=t.get("oauth_error");if(r){_(e,{message:r,code:n||null,state:i||null});const t=new URL(window.location.href);t.searchParams.delete("oauth_error"),history.replaceState({},"",t.toString())}else A(e,{message:"No OAuth error found"})}})(e.ports[0]);break;case"OAUTH_GET_TOP_URL":T.log("Iframe requested top window URL via MessageChannel"),A(e.ports[0],{topUrl:window.location.href});break;case"OAUTH_REDIRECT_TOP_WINDOW":T.log("Iframe requested top window redirect to:",e.data.payload.url),window.location.href=e.data.payload.url;break;case"OAUTH_UPDATE_URL":T.log("Iframe requested URL update to:",e.data.payload.url),function(e,t){if(!history?.replaceState)return T.warn("history.replaceState not supported in this browser"),void _(t,{message:"URL update not supported in this browser"});try{const n=window.location.href;history.replaceState({},"",e),function(e,t){const n=new URL(t),i=new URL(e),r=n.searchParams,o=i.searchParams,a=["oauth_code","oauth_state","start-oauth"];return a.some(e=>o?.has(e))&&!a.some(e=>r?.has(e))}(n,e)&&function(){T.log("OAuth parameters cleaned, opening sidebar");try{localStorage.setItem("angie_sidebar_state","open")}catch(e){T.warn("localStorage not available")}setTimeout(()=>{window.toggleAngieSidebar(!0)},500)}(),A(t,{message:"URL updated successfully"})}catch(e){T.warn("Failed to update URL via history.replaceState:",e),_(t,{message:"URL update failed: "+(e instanceof Error?e.message:"Unknown error")})}}(e.data.payload.url,e.ports[0]);break;case"ANGIE_REDIRECT_TO_WP_ADMIN_WITH_OAUTH":L();break;case"ANGIE_REDIRECT_TO_AUTH_ORIGIN_LOGOUT":try{L()}catch(e){T.error("Auth origin logout fallback failed:",e),window.location.reload()}}})},D=c("sdk");var N;(N||(N={})).POST_MESSAGE="postMessage";const P=c("iframe-utils");let O=null;const C=()=>(O&&document.contains(O)||(O=document.querySelector('iframe[src*="angie/"]')),O),q=(e,t)=>{P.log("postMessageToAngieIframe",e,t);const n=C();if(!n?.contentWindow)return!1;const i=t||(()=>{const e=C();if(!e)return null;try{return new URL(e.src).origin}catch(e){return P.error("Error parsing iframe URL:",e),null}})();return i?(n.contentWindow.postMessage(e,i),!0):(P.error("Could not determine target origin for Angie iframe"),!1)},U=c("sidebar");let $=!1;const M="open",k="closed";function x(){if("undefined"==typeof window)return 370;try{const e=window.localStorage.getItem("angie_sidebar_width");if(e){const t=parseInt(e,10);if(t>=350&&t<=590)return t}}catch(e){U.warn("localStorage not available")}return 370}function H(){return"undefined"==typeof window?null:localStorage.getItem("angie_sidebar_state")}function K(e){try{localStorage.setItem("angie_sidebar_state",e)}catch(e){U.warn("localStorage not available")}}function z(e){try{localStorage.setItem("angie_sidebar_width",e.toString())}catch(e){U.warn("localStorage not available")}}function B(e){document.documentElement.style.setProperty("--angie-sidebar-width",`${e}px`)}function F(){!function(){const e=new URLSearchParams(window.location.search);return e.has("start-oauth")||e.has("oauth_code")||e.has("oauth_state")||e.has("oauth_error")}()?Q(H()||M):function(){Q(k);try{localStorage.setItem("angie_sidebar_state",k)}catch(e){U.warn("localStorage not available")}}()}function Q(e){"undefined"!=typeof window&&window.toggleAngieSidebar&&window.toggleAngieSidebar(e===M,!0)}function V(){const e=document.getElementById("angie-sidebar-container");if(!e)return;let t=!1,n=0,i=0;e.addEventListener("mousedown",r=>{const o=e.getBoundingClientRect();("rtl"===document.documentElement.dir?r.clientX<=o.left+4:r.clientX>=o.right-4)&&(t=!0,n=r.clientX,i=o.width,e.classList.add("angie-resizing"),document.body.style.cursor="ew-resize",document.body.style.userSelect="none",r.preventDefault(),r.stopPropagation())}),document.addEventListener("mousemove",e=>{if(!t)return;let r;r="rtl"===document.documentElement.dir?n-e.clientX:e.clientX-n,B(Math.max(350,Math.min(590,i+r))),e.preventDefault(),e.stopPropagation()}),document.addEventListener("mouseup",n=>{if(t){t=!1,e.classList.remove("angie-resizing"),document.body.style.cursor="",document.body.style.userSelect="";const r=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--angie-sidebar-width"),10);z(r),q({type:m.ANGIE_SIDEBAR_RESIZED,payload:{initialWidth:i,width:r}}),n.preventDefault(),n.stopPropagation()}}),B(x())}function j(e){!function(){if("undefined"==typeof document||$)return;const e="angie-sidebar-styles";if(document.getElementById(e))return void($=!0);const t=document.createElement("style");t.id=e,t.textContent="/* Angie Sidebar - CSS Variables */\n:root {\n --angie-sidebar-z-index: 1200; /* below MUI popups, elementor popups and media library modal */\n --angie-sidebar-width: 330px;\n --angie-sidebar-transition: margin 0.3s ease-in-out, transform 0.3s ease-in-out;\n /* Direction-aware transform values for sidebar positioning */\n --angie-sidebar-hide-transform: translateX(-100%); /* LTR: hide to the left */\n --angie-sidebar-show-transform: translateX(0);\n}\n\n/* RTL-specific transform values */\n[dir=\"rtl\"] {\n --angie-sidebar-hide-transform: translateX(100%); /* RTL: hide to the right */\n}\n\n/* Respect user's motion preferences */\n@media (prefers-reduced-motion: reduce) {\n :root {\n --angie-sidebar-transition: none;\n }\n}\n\n/* Apply transitions only when user is actively toggling */\nbody.angie-sidebar-transitioning {\n transition: var(--angie-sidebar-transition) !important;\n}\n\nbody.angie-sidebar-transitioning #angie-sidebar-container {\n transition: var(--angie-sidebar-transition) !important;\n}\n\n/* Layout (default) - Push content */\n@media (min-width: 768px) {\n body.angie-sidebar-active {\n padding-inline-start: var(--angie-sidebar-width) !important;\n }\n\n #angie-sidebar-container {\n position: fixed;\n top: 0;\n inset-inline-start: 0;\n width: var(--angie-sidebar-width);\n height: 100vh;\n z-index: var(--angie-sidebar-z-index) !important; /* below elementor popups and media library modal */\n background: #FCFCFC;\n transform: var(--angie-sidebar-hide-transform);\n outline: none;\n overflow: hidden;\n /* No default transition - only when transitioning */\n }\n\n /* Resize handle */\n #angie-sidebar-container::after {\n content: '';\n position: absolute;\n top: 0;\n inset-inline-end: 0;\n width: 4px;\n height: 100%;\n cursor: ew-resize;\n background: transparent;\n z-index: 1000001;\n }\n\n /* Pink border during resize */\n #angie-sidebar-container.angie-resizing {\n border-inline-end-color: #ff69b4 !important;\n border-inline-end-width: 2px !important;\n }\n\n /* Disable iframe pointer events during resize */\n #angie-sidebar-container.angie-resizing iframe#angie-iframe {\n pointer-events: none !important;\n }\n}\n\n/* Active states */\nbody.angie-sidebar-active #angie-sidebar-container {\n transform: var(--angie-sidebar-show-transform);\n}\n\n/* Studio mode - sidebar takes full width */\n@media (min-width: 768px) {\n html.angie-studio-active body.angie-sidebar-active #angie-sidebar-container {\n width: 100%;\n }\n}\n\n/* High contrast mode support */\n@media (prefers-contrast: high) {\n #angie-sidebar-container {\n border-color: #000;\n box-shadow: none;\n }\n}\n\n/* Screen reader only class */\n.angie-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n/* Plugin conflict resolution */\nbody.angie-sidebar-active {\n /* Reset common conflicting styles */\n box-sizing: border-box !important;\n position: relative !important;\n}\n\n#angie-sidebar-toggle {\n z-index: 99999 !important;\n}\n";const n=document.head||document.getElementsByTagName("head")[0];n.insertBefore(t,n.firstChild),$=!0}(),"undefined"!=typeof window&&(window.toggleAngieSidebar=function(e){return function(t,n){const i=document.body,r=document.getElementById("angie-sidebar-container");if(!r)return void U.warn("Required elements not found!");const o=i.classList.contains("angie-sidebar-active"),a=void 0!==t?t:!o;n||(i.classList.add("angie-sidebar-transitioning"),setTimeout(function(){i.classList.remove("angie-sidebar-transitioning")},300)),a?i.classList.add("angie-sidebar-active"):i.classList.remove("angie-sidebar-active"),a&&setTimeout(function(){q({type:"focusInput"})},n?0:300),e&&e(a,r,n),K(a?M:k);const s=new CustomEvent("angieSidebarToggle",{detail:{isOpen:a,sidebar:r,skipTransition:n}});document.dispatchEvent(s),q({type:m.ANGIE_SIDEBAR_TOGGLED,payload:{state:a?"opened":"closed"}})}}(e),window.addEventListener("message",function(e){if(e.data&&"toggleAngieSidebar"===e.data.type){const{force:t,skipTransition:n}=e.data.payload||{};window.toggleAngieSidebar&&window.toggleAngieSidebar(t,n)}}))}const W=c("iframe"),X=async()=>{if(S.iframe?.contentWindow&&S.iframeUrlObject)try{W.log("Disabling navigation prevention in Angie iframe"),S.iframe.contentWindow.postMessage({type:m.ANGIE_DISABLE_NAVIGATION_PREVENTION},S.iframeUrlObject.origin),await new Promise(e=>setTimeout(e,100))}catch(e){throw W.error("Failed to disable navigation prevention:",e),e}else W.warn("Cannot disable navigation prevention: iframe or origin not available")},Y=c("registration-queue");class J{queue=[];isProcessing=!1;add(e){const t={id:this.generateId(e),config:e,timestamp:Date.now(),status:"pending"};return this.queue.push(t),Y.log(`Added server "${e.name}" to queue`),t}getAll(){return[...this.queue]}getPending(){return this.queue.filter(e=>"pending"===e.status)}updateStatus(e,t,n){const i=this.queue.find(t=>t.id===e);i&&(i.status=t,n?i.error=n:"pending"!==t&&"registered"!==t||delete i.error,Y.log(`Updated server ${e} status to ${t}`))}async processQueue(e){if(this.isProcessing)return void Y.log("Already processing queue");this.isProcessing=!0;const t=this.getPending();Y.log(`Processing ${t.length} pending registrations`);try{for(const n of t)try{await e(n),this.updateStatus(n.id,"registered")}catch(e){const t=e instanceof Error?e.message:String(e);this.updateStatus(n.id,"failed",t),Y.error(`Failed to process registration ${n.id}:`,t)}}finally{this.isProcessing=!1}}clear(){this.queue=[],Y.log("Cleared all registrations")}resetAllToPending(){if(this.isProcessing)return Y.log("Cannot reset to pending - processing in progress"),!1;const e=this.queue.filter(e=>"registered"===e.status).length,t=this.queue.filter(e=>"failed"===e.status).length;return this.queue.forEach(e=>{"pending"!==e.status&&(e.status="pending",delete e.error)}),Y.log(`Reset ${e+t} registrations to pending`),!0}remove(e){const t=this.queue.findIndex(t=>t.id===e);return-1!==t&&(this.queue.splice(t,1),Y.log(`Removed registration ${e}`),!0)}generateId(e){return`reg_${e.name}_${e.version}_${Date.now()}`}}class Z{angieDetector;clientManager;logger;registrationQueue;isInitialized=!1;instanceId;constructor(){this.instanceId=Math.random().toString(36).substring(2,8),this.logger=c({instanceId:this.instanceId}),this.logger.log("Constructor called - initializing SDK"),this.angieDetector=new y,this.registrationQueue=new J,this.clientManager=new v,this.logger.log("Setting up event handlers"),this.setupAngieReadyHandler(),this.setupServerInitHandler(),this.setupReRegistrationHandler(),this.logger.log("SDK initialization complete")}async loadSidebar(e){j(),await(async e=>{if(window.screen.availWidth<=768)return void W.log("Mobile detected, skipping iframe injection");let t=document.getElementById("angie-sidebar-container");if(!t){const e=performance.now();if(W.log("⏱️ Waiting for sidebar container..."),await new Promise(e=>{let n=0;const i=setInterval(()=>{t=document.getElementById("angie-sidebar-container"),n++,(t||n>20)&&(clearInterval(i),t&&e())},100);setTimeout(()=>{if(clearInterval(i),t)return void e();const n=new MutationObserver(()=>{t=document.getElementById("angie-sidebar-container"),t&&(n.disconnect(),e())});n.observe(document.body,{childList:!0,subtree:!0}),setTimeout(()=>{n.disconnect(),e()},8e3)},2e3)}),W.log(`⏱️ Sidebar container detection took: ${(performance.now()-e).toFixed(2)}ms`),!t)return void W.error("Sidebar container not found")}const{iframe:n,iframeUrlObject:i}=await(async e=>{const t=e.origin,n=new URL(e.path,t),i=n.pathname.slice(1).replace(/\//,"--")+"-"+Math.random().toString(36).substring(7);return new Promise(r=>{const o=new URL(t);o.pathname=n.pathname;const a=window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light";if(o.searchParams.append("colorScheme",e.uiTheme||a||"light"),o.searchParams.append("sdkVersion",e.sdkVersion),o.searchParams.append("instanceId",i),o.searchParams.append("origin",window.location.origin),e.isRTL&&o.searchParams.append("isRTL",e.isRTL?"true":"false"),"localhost"===window.location.hostname&&window.location.search.includes("debug_error")){const e=new URLSearchParams(window.location.search).get("debug_error");e&&o.searchParams.append("debug_error",e)}n.searchParams.forEach((e,t)=>{o.searchParams.set(t,e)}),o.searchParams.set("ver",(new Date).getTime().toString());const s=e.parent||document,d=s.createElement("iframe"),g={"background-color":"transparent","color-scheme":"normal",...e.css};window.addEventListener("message",async e=>{if(e.origin===o.origin)switch(e.data.type){case f.ANGIE_READY:r({iframe:d,iframeUrlObject:o});break;case f.ANGIE_LOADED:d.contentWindow?.postMessage({type:f.HOST_READY,instanceId:i},o.origin)}}),d.setAttribute("src",o.href),d.id="angie-iframe",d.setAttribute("frameborder","0"),d.setAttribute("scrolling","no"),d.setAttribute("style",Object.entries(g).map(([e,t])=>`${e}: ${t}`).join("; ")),d.setAttribute("allow","clipboard-write; clipboard-read"),e.insertCallback?e.insertCallback(d):s.body.appendChild(d)})})({origin:e.origin||"https://angie.elementor.com",path:"angie/wp-admin",insertCallback:e=>{W.log("Injecting Angie iframe into sidebar container"),e.setAttribute("title","Angie AI Assistant"),e.setAttribute("role","application"),e.setAttribute("aria-label","Angie AI Assistant Interface");const n=document.getElementById("angie-sidebar-loading");n&&(n.textContent=""),t?.appendChild(e),I(e,!0),e.addEventListener("load",()=>{e.focus()})},css:{width:"100%",height:"100%",border:"none",outline:"none"},uiTheme:e.uiTheme,isRTL:e.isRTL,sdkVersion:"1.0.7"});S.iframe=n,S.iframeUrlObject=i,window.addEventListener("message",e=>{if(e.origin===S.iframeUrlObject?.origin)switch(e.data.type){case w.SET:window.localStorage.setItem(e.data.key,e.data.value);break;case w.GET:{const t=e.ports[0],n=window.localStorage.getItem(e.data.key);t.postMessage({value:n});break}}}),(e=>{window.addEventListener("message",async t=>{const n=t.origin===window.location.origin,i=t.origin===e.iframeUrlObject?.origin;if(n||i)switch(t?.data?.type){case m.SDK_ANGIE_ALL_SERVERS_REGISTERED:break;case m.SDK_ANGIE_READY_PING:{const e=t.ports[0];D.log("Angie is ready",t),A(e,{message:"Angie is ready"});break}case m.SDK_REQUEST_CLIENT_CREATION:{const n=t.data.payload;try{const i=t.ports[0],r=new MessageChannel;r.port1.onmessage=e=>{i.postMessage({success:!0,data:e.data})};const o={type:m.SDK_REQUEST_CLIENT_CREATION,payload:{success:!0,...n,clientId:`dynamic-client-${n.serverName}-${n.serverVersion}-${Date.now()}`,requestId:t.data.payload.requestId},timestamp:Date.now()};if(!e.iframe)throw new Error("Iframe not found");e.iframe.contentWindow?.postMessage(o,e.iframeUrlObject?.origin||"",[r.port2])}catch(e){D.error(`Failed to create client for SDK server "${n.serverName}":`,e)}break}case m.SDK_TRIGGER_ANGIE:D.log("SDK Trigger Angie received",t.data);try{const{requestId:n,prompt:i,context:r}=t.data.payload;if(!e.iframe)throw new Error("Iframe not found");e.iframe.contentWindow?.postMessage({type:m.SDK_TRIGGER_ANGIE,payload:{requestId:n,prompt:i,context:r}},e.iframeUrlObject?.origin||""),window.postMessage({type:m.SDK_TRIGGER_ANGIE_RESPONSE,payload:{success:!0,requestId:n,response:"Angie triggered successfully"}},window.location.origin)}catch(e){D.error("Failed to trigger Angie:",e),window.postMessage({type:m.SDK_TRIGGER_ANGIE_RESPONSE,payload:{success:!1,requestId:t.data.payload?.requestId,error:e instanceof Error?e.message:"Unknown error"}},window.location.origin)}}})})(S),G(),window.addEventListener("message",async t=>{if([window.location.origin,e.origin||"https://angie.elementor.com"].includes(t.origin))if(t?.data?.type===m.ANGIE_CHAT_TOGGLE)S.open=t.data.open,S.iframe&&I(S.iframe,S.open);else if(t?.data?.type===m.ANGIE_STUDIO_TOGGLE){const e=t.data.isStudioOpen;if(!S.iframe)return;if(e)document.documentElement.classList.add("angie-studio-active");else{const e=x();document.documentElement.style.setProperty("--angie-sidebar-width",`${e}px`),document.documentElement.classList.remove("angie-studio-active")}}else if(t?.data?.type===m.ANGIE_NAVIGATE_TO_URL){const{url:e="",confirmed:n=!1}=t.data.payload||{};if(!n)return void W.log("Navigation requires user confirmation");if(!((e,t=[])=>{const n=0===t.length&&"undefined"!=typeof window?[window.location.origin]:t;if(!e.startsWith("http"))return!1;try{const t=new URL(e);return n.includes(t.origin)}catch{return!1}})(e))return void W.error("Navigation blocked: Invalid or unsafe URL",{url:e});await X(),window.location.assign(e)}else if(t?.data?.type===m.ANGIE_PAGE_RELOAD){const{confirmed:e=!1}=t.data.payload||{};if(!e)return void W.log("Page reload requires user confirmation");W.log("Page reload confirmed - disabling navigation prevention and reloading"),await X(),setTimeout(()=>{window.location.reload()},50)}else t?.data?.type===f.RESET_HASH&&(window.location.hash="",A(t.ports[0],{message:"Hash reset successfully"}))})})({origin:e?.origin||"https://angie.elementor.com",uiTheme:e?.uiTheme||"light",isRTL:e?.isRTL||!1,...e}),this.setupPromptHashDetection()}setupReRegistrationHandler(){window.addEventListener("message",e=>{if(e.data?.type===m.SDK_ANGIE_REFRESH_PING)if(this.logger.log("Angie refresh ping received"),this.registrationQueue.resetAllToPending()){const e=this.registrationQueue.getPending().length;this.logger.log(`Successfully reset ${e} registrations, processing queue`),this.handleAngieReady()}else this.logger.log("Skipping queue reset - processing already in progress")})}setupAngieReadyHandler(){this.angieDetector.waitForReady().then(e=>{e.isReady?this.handleAngieReady():this.logger.warn("Angie not detected - servers will remain queued")}).catch(e=>{this.logger.error("Error waiting for Angie:",e)})}async handleAngieReady(){this.logger.log("Angie is ready, processing queued registrations");try{await this.registrationQueue.processQueue(async e=>{this.logger.log(`processQueue callback called for "${e.config.name}"`),await this.processRegistration(e)}),this.isInitialized=!0,this.logger.log("Initialization complete")}catch(e){this.logger.error("Error processing registration queue:",e)}}async processRegistration(e){this.logger.log(`Processing registration for server "${e.config.name}" (ID: ${e.id})`);try{this.logger.log(`Calling clientManager.requestClientCreation for "${e.config.name}"`);const t={...e,instanceId:this.instanceId};await this.clientManager.requestClientCreation(t),this.logger.log(`Successfully registered server "${e.config.name}"`)}catch(t){throw this.logger.error(`Failed to register server "${e.config.name}":`,t),t}}registerLocalServer(e){return e.type=p.LOCAL,e.transport=u.POST_MESSAGE,this.registerServer(e)}registerRemoteServer(e){return e.type=p.REMOTE,this.registerServer(e)}isLocalServerConfig(e){return e.type===p.LOCAL||!e.type&&"server"in e}isRemoteServerConfig(e){return e.type===p.REMOTE&&"url"in e}async registerServer(e){if(!e.type)return this.logger.warn("For a local server, please use registerLocalServer instead of registerServer"),void this.registerLocalServer(e);if(this.logger.log(`registerServer called for "${e.name}"`),!e.name)throw new Error("Server name is required");if(!e.description)throw new Error("Server description is required");if(this.isLocalServerConfig(e)&&!e.server)throw new Error("Server instance is required for local servers");this.logger.log(`Registering server "${e.name}"`);const t=this.registrationQueue.add(e);if(this.logger.log(`Added registration to queue: ${t.id}`),this.angieDetector.isReady())try{await this.processRegistration(t),this.registrationQueue.updateStatus(t.id,"registered"),this.logger.log(`Server "${e.name}" registered successfully`)}catch(e){const n=e instanceof Error?e.message:String(e);throw this.registrationQueue.updateStatus(t.id,"failed",n),e}else this.logger.log(`Server "${e.name}" queued until Angie is ready`)}getRegistrations(){return this.registrationQueue.getAll()}getPendingRegistrations(){return this.registrationQueue.getPending()}isAngieReady(){return this.angieDetector.isReady()}isReady(){return this.isInitialized}async waitForReady(){if(!(await this.angieDetector.waitForReady()).isReady)throw new Error("Angie is not available");for(;!this.isInitialized;)await new Promise(e=>setTimeout(e,100))}async triggerAngie(e){if(!this.isAngieReady())throw new Error("Angie is not ready. Please wait for Angie to be available before triggering.");const t=this.generateRequestId(),n=e.options?.timeout||3e4;return new Promise((i,r)=>{const o=setTimeout(()=>{r(new Error("Angie trigger request timed out"))},n),a=e=>{e.data?.type===m.SDK_TRIGGER_ANGIE_RESPONSE&&e.data?.payload?.requestId===t&&(clearTimeout(o),window.removeEventListener("message",a),i(e.data.payload))};window.addEventListener("message",a);const s={type:m.SDK_TRIGGER_ANGIE,payload:{requestId:t,prompt:e.prompt,options:e.options,context:{pageUrl:window.location.href,pageTitle:document.title,...e.context}},timestamp:Date.now()};this.logger.log(`Triggering Angie with prompt (Request ID: ${t})`),window.postMessage(s,window.location.origin)})}destroy(){this.registrationQueue.clear(),this.logger.log("SDK destroyed")}setupServerInitHandler(){window.addEventListener("message",e=>{e.data?.type===m.SDK_REQUEST_INIT_SERVER&&(this.logger.log("Server init request received"),this.handleServerInitRequest(e))})}handleServerInitRequest(e){const{clientId:t,serverId:n,instanceId:i}=e.data.payload||{};if(t&&n)if(this.logger.log(`Server init request received - Request instanceId: ${i}, This instanceId: ${this.instanceId}`),i&&i!==this.instanceId)this.logger.log(`Ignoring server init request for different instance. Request instanceId: ${i}, this instanceId: ${this.instanceId}`);else{this.logger.log(`Handling server init request for clientId: ${t}, serverId: ${n}`);try{const t=this.registrationQueue.getAll().find(e=>e.id===n);if(!t)return void this.logger.error(`No registration found for serverId: ${n}`);if("type"in t.config&&"remote"===t.config.type)return void this.logger.log("Remote server registration detected; skipping local connect");const i=e.ports[0];if(!i)return void this.logger.error("No port provided in server init request");const r=t.config.server,o=new b(i);r.connect(o),this.logger.log(`Server "${t.config.name}" initialized successfully`)}catch(e){this.logger.error(`Error initializing server for clientId ${t}:`,e)}}else this.logger.error("Invalid server init request - missing clientId or serverId")}generateRequestId(){return`${this.instanceId}-${Date.now()}-${Math.random().toString(36).substring(2,8)}`}async handlePromptHash(){const e=window.location.hash;if(e.startsWith("#angie-prompt="))try{const t=e.replace("#angie-prompt=",""),n=decodeURIComponent(t);if(!n)return void this.logger.warn("Empty prompt detected in hash");this.logger.log("Detected prompt in hash:",n),await this.waitForReady();const i=await this.triggerAngie({prompt:n,context:{source:"hash-parameter",pageUrl:window.location.href,timestamp:(new Date).toISOString()}});this.logger.log("Triggered successfully from hash:",i),window.location.hash=""}catch(e){this.logger.error("Failed to trigger from hash:",e)}}setupPromptHashDetection(){this.handlePromptHash(),window.addEventListener("hashchange",()=>this.handlePromptHash())}}const ee=c("navigation"),te=(e,t)=>{if(C()){t.isOpen&&window.toggleAngieSidebar&&window.toggleAngieSidebar(!0);const n=q({type:"angie-route-navigation",path:e,payload:t});return n||ee.error("Failed to post navigation message to Angie iframe"),n}return ee.error("Angie iframe not found"),!1};export{M as ANGIE_SIDEBAR_STATE_OPEN,y as AngieDetector,u as AngieLocalServerTransport,l as AngieMCPTransport,Z as AngieMcpSdk,h as AngieRemoteServerTransport,p as AngieServerType,b as BrowserContextTransport,v as ClientManager,f as HostEventType,w as HostLocalStorageEventType,m as MessageEventType,J as RegistrationQueue,B as applyWidth,X as disableNavigationPrevention,C as getAngieIframe,H as getAngieSidebarSavedState,j as initAngieSidebar,V as initializeResize,F as loadState,x as loadWidth,te as navigateAngieIframe,K as saveState,z as saveWidth,I as toggleAngieSidebar,R as waitForDocumentReady};
1
+ import{JSONRPCMessageSchema as e}from"@modelcontextprotocol/sdk/types.js";const t={none:0,error:1,warn:2,info:3,debug:4},n={error:"error",warn:"warn",info:"info",log:"info",debug:"debug"},i=(e,n)=>t[e]<=t[n],r=e=>"string"==typeof e?e:JSON.stringify(e),o=(e,t)=>`${r(e)} > ${r(t)}`,a=(e,t)=>{let n=`[${r(e)}]`;return typeof window<"u"?{text:`%c${n}`,style:`color: ${t.color||"#00bcd4"}; font-weight: bold;`}:{text:n}},s=(e,t,r,o)=>(...s)=>{if(!i(n[e],o()))return;if(!t)return void console[e](...s);let{text:d,style:g}=a(t,r);g?console[e](d,g,...s):console[e](d,...s)},d=(e,t)=>{let n=t.logLevel??"debug",i=()=>n;return{log:s("log",e,t,i),info:s("info",e,t,i),warn:s("warn",e,t,i),error:s("error",e,t,i),debug:s("debug",e,t,i),setLogLevel:e=>{n=e},extend:i=>d(e?o(e,i):i,{...t,logLevel:n})}},g=d("angie-sdk",{color:"#00bcd4",logLevel:"debug",color:"#00BCD4",logLevel:"error"}),c=e=>g.extend(e);var l,u,h,p,m,w,f;!function(e){e.POST_MESSAGE="postMessage"}(l||(l={})),function(e){e.POST_MESSAGE="postMessage"}(u||(u={})),function(e){e.STREAMABLE_HTTP="streamableHttp",e.SSE="sse"}(h||(h={})),function(e){e.LOCAL="local",e.REMOTE="remote"}(p||(p={})),function(e){e.SDK_ANGIE_READY_PING="sdk-angie-ready-ping",e.SDK_ANGIE_REFRESH_PING="sdk-angie-refresh-ping",e.SDK_ANGIE_ALL_SERVERS_REGISTERED="sdk-angie-all-servers-registered",e.SDK_REQUEST_CLIENT_CREATION="sdk-request-client-creation",e.SDK_REQUEST_INIT_SERVER="sdk-request-init-server",e.SDK_TRIGGER_ANGIE="sdk-trigger-angie",e.SDK_TRIGGER_ANGIE_RESPONSE="sdk-trigger-angie-response",e.ANGIE_SIDEBAR_RESIZED="angie-sidebar-resized",e.ANGIE_SIDEBAR_TOGGLED="angie-sidebar-toggled",e.ANGIE_CHAT_TOGGLE="angie-chat-toggle",e.ANGIE_STUDIO_TOGGLE="angie-studio-toggle",e.ANGIE_NAVIGATE_TO_URL="angie/navigate-to-url",e.ANGIE_PAGE_RELOAD="angie/page-reload",e.ANGIE_DISABLE_NAVIGATION_PREVENTION="angie/disable-navigation-prevention",e.ANGIE_NAVIGATE_AFTER_RESPONSE="angie/navigate-after-response"}(m||(m={})),function(e){e.SET="ANGIE_SET_LOCALSTORAGE",e.GET="ANGIE_GET_LOCALSTORAGE"}(w||(w={})),function(e){e.RESET_HASH="reset-hash",e.HOST_READY="host/ready",e.ANGIE_LOADED="angie/loaded",e.ANGIE_READY="angie/ready"}(f||(f={}));const E=c("angie-detector");class y{isAngieReady=!1;readyPromise;readyResolve;constructor(){if(this.readyPromise=new Promise(e=>{this.readyResolve=e}),"undefined"==typeof window)return;let e=0;const t=()=>{if(this.isAngieReady||e>=500)return void(!this.isAngieReady&&e>=500&&this.handleDetectionTimeout());const n=new MessageChannel;n.port1.onmessage=e=>{this.handleAngieReady(e.data),n.port1.close(),n.port2.close()};const i={type:m.SDK_ANGIE_READY_PING,timestamp:Date.now()};window.postMessage(i,window.location.origin,[n.port2]),e++,setTimeout(t,500)};t()}handleAngieReady(e){this.isAngieReady=!0;const t={isReady:!0,version:e.version,capabilities:e.capabilities};this.readyResolve&&this.readyResolve(t)}handleDetectionTimeout(){this.readyResolve&&this.readyResolve({isReady:!1}),E.warn("Detection timeout - Angie may not be available")}isReady(){return this.isAngieReady}async waitForReady(){return this.readyPromise}}class b{sessionId;onmessage;onerror;onclose;_port;_started=!1;_closed=!1;constructor(t){if(!t)throw new Error("MessagePort is required");this._port=t,this._port.onmessage=t=>{try{const n=e.parse(t.data);this.onmessage?.(n)}catch(e){const t=new Error(`Failed to parse message: ${e}`);this.onerror?.(t)}},this._port.onmessageerror=e=>{const t=new Error(`MessagePort error: ${JSON.stringify(e)}`);this.onerror?.(t)}}async start(){if(this._started)throw new Error("BrowserContextTransport already started! If using Client or Server class, note that connect() calls start() automatically.");if(this._closed)throw new Error("Cannot start a closed BrowserContextTransport");this._started=!0,this._port.start()}async send(e){if(this._closed)throw new Error("Cannot send on a closed BrowserContextTransport");return new Promise((t,n)=>{try{this._port.postMessage(e),t()}catch(e){const t=e instanceof Error?e:new Error(String(e));this.onerror?.(t),n(t)}})}async close(){this._closed||(this._closed=!0,this._port.close(),this.onclose?.())}}class v{async requestClientCreation(e){const{config:t}=e,n={serverId:e.id,serverName:t.name,serverTitle:t.title,serverVersion:t.version,description:t.description,transport:t.transport||u.POST_MESSAGE,capabilities:t.capabilities,instanceId:e.instanceId};return"type"in t&&"remote"===t.type&&(n.remote={url:t.url}),new Promise((e,t)=>{const i=new MessageChannel,r=setTimeout(()=>{t(new Error("Client creation request timed out after 15000ms"))},15e3);i.port1.onmessage=t=>{clearTimeout(r),e(t.data)};const o={type:m.SDK_REQUEST_CLIENT_CREATION,payload:n,timestamp:Date.now()};window.postMessage(o,window.location.origin,[i.port2])})}}const S={open:!1,iframe:null,iframeUrlObject:null},I=(e,t)=>{const n=document.getElementById("angie-sidebar-container");n&&n.setAttribute("aria-hidden",t?"false":"true"),t?e.removeAttribute("tabindex"):e.setAttribute("tabindex","-1")},A=(e,t)=>{e.postMessage({status:"success",payload:t})},_=(e,t)=>{e.postMessage({status:"error",payload:t})},R=()=>new Promise(e=>{"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e):e(null)}),T=c("oauth");function L(){const e=new URL(window.location.href);e.searchParams.set("start-oauth","1"),T.log("Redirecting to wp-admin with OAuth:",e.toString()),window.location.href=e.toString()}const G=()=>{window.addEventListener("message",e=>{if(e.origin===S.iframeUrlObject?.origin)switch(e.data.type){case"OAUTH_GET_CODE_AND_STATE":(e=>{const t=new URLSearchParams(window.location.search),n=t.get("oauth_code"),i=t.get("oauth_state");if(n&&i)A(e,{code:n,state:i});else{const r=t.get("oauth_error");if(r){_(e,{message:r,code:n||null,state:i||null});const t=new URL(window.location.href);t.searchParams.delete("oauth_error"),history.replaceState({},"",t.toString())}else A(e,{message:"No OAuth error found"})}})(e.ports[0]);break;case"OAUTH_GET_TOP_URL":T.log("Iframe requested top window URL via MessageChannel"),A(e.ports[0],{topUrl:window.location.href});break;case"OAUTH_REDIRECT_TOP_WINDOW":T.log("Iframe requested top window redirect to:",e.data.payload.url),window.location.href=e.data.payload.url;break;case"OAUTH_UPDATE_URL":T.log("Iframe requested URL update to:",e.data.payload.url),function(e,t){if(!history?.replaceState)return T.warn("history.replaceState not supported in this browser"),void _(t,{message:"URL update not supported in this browser"});try{const n=window.location.href;history.replaceState({},"",e),function(e,t){const n=new URL(t),i=new URL(e),r=n.searchParams,o=i.searchParams,a=["oauth_code","oauth_state","start-oauth"];return a.some(e=>o?.has(e))&&!a.some(e=>r?.has(e))}(n,e)&&function(){T.log("OAuth parameters cleaned, opening sidebar");try{localStorage.setItem("angie_sidebar_state","open")}catch(e){T.warn("localStorage not available")}setTimeout(()=>{window.toggleAngieSidebar(!0)},500)}(),A(t,{message:"URL updated successfully"})}catch(e){T.warn("Failed to update URL via history.replaceState:",e),_(t,{message:"URL update failed: "+(e instanceof Error?e.message:"Unknown error")})}}(e.data.payload.url,e.ports[0]);break;case"ANGIE_REDIRECT_TO_WP_ADMIN_WITH_OAUTH":L();break;case"ANGIE_REDIRECT_TO_AUTH_ORIGIN_LOGOUT":try{L()}catch(e){T.error("Auth origin logout fallback failed:",e),window.location.reload()}}})},D=c("sdk");var N;(N||(N={})).POST_MESSAGE="postMessage";const P=c("iframe-utils");let O=null;const C=()=>(O&&document.contains(O)||(O=document.querySelector('iframe[src*="angie/"]')),O),q=(e,t)=>{P.log("postMessageToAngieIframe",e,t);const n=C();if(!n?.contentWindow)return!1;const i=t||(()=>{const e=C();if(!e)return null;try{return new URL(e.src).origin}catch(e){return P.error("Error parsing iframe URL:",e),null}})();return i?(n.contentWindow.postMessage(e,i),!0):(P.error("Could not determine target origin for Angie iframe"),!1)},U=c("sidebar");let $=!1;const M="open",k="closed";function x(){if("undefined"==typeof window)return 370;try{const e=window.localStorage.getItem("angie_sidebar_width");if(e){const t=parseInt(e,10);if(t>=350&&t<=590)return t}}catch(e){U.warn("localStorage not available")}return 370}function H(){return"undefined"==typeof window?null:localStorage.getItem("angie_sidebar_state")}function K(e){try{localStorage.setItem("angie_sidebar_state",e)}catch(e){U.warn("localStorage not available")}}function z(e){try{localStorage.setItem("angie_sidebar_width",e.toString())}catch(e){U.warn("localStorage not available")}}function B(e){document.documentElement.style.setProperty("--angie-sidebar-width",`${e}px`)}function F(){!function(){const e=new URLSearchParams(window.location.search);return e.has("start-oauth")||e.has("oauth_code")||e.has("oauth_state")||e.has("oauth_error")}()?Q(H()||M):function(){Q(k);try{localStorage.setItem("angie_sidebar_state",k)}catch(e){U.warn("localStorage not available")}}()}function Q(e){"undefined"!=typeof window&&window.toggleAngieSidebar&&window.toggleAngieSidebar(e===M,!0)}function V(){const e=document.getElementById("angie-sidebar-container");if(!e)return;let t=!1,n=0,i=0;e.addEventListener("mousedown",r=>{const o=e.getBoundingClientRect();("rtl"===document.documentElement.dir?r.clientX<=o.left+4:r.clientX>=o.right-4)&&(t=!0,n=r.clientX,i=o.width,e.classList.add("angie-resizing"),document.body.style.cursor="ew-resize",document.body.style.userSelect="none",r.preventDefault(),r.stopPropagation())}),document.addEventListener("mousemove",e=>{if(!t)return;let r;r="rtl"===document.documentElement.dir?n-e.clientX:e.clientX-n,B(Math.max(350,Math.min(590,i+r))),e.preventDefault(),e.stopPropagation()}),document.addEventListener("mouseup",n=>{if(t){t=!1,e.classList.remove("angie-resizing"),document.body.style.cursor="",document.body.style.userSelect="";const r=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--angie-sidebar-width"),10);z(r),q({type:m.ANGIE_SIDEBAR_RESIZED,payload:{initialWidth:i,width:r}}),n.preventDefault(),n.stopPropagation()}}),B(x())}function j(e){!function(){if("undefined"==typeof document||$)return;const e="angie-sidebar-styles";if(document.getElementById(e))return void($=!0);const t=document.createElement("style");t.id=e,t.textContent="/* Angie Sidebar - CSS Variables */\n:root {\n --angie-sidebar-z-index: 1200; /* below MUI popups, elementor popups and media library modal */\n --angie-sidebar-width: 330px;\n --angie-sidebar-transition: margin 0.3s ease-in-out, transform 0.3s ease-in-out;\n /* Direction-aware transform values for sidebar positioning */\n --angie-sidebar-hide-transform: translateX(-100%); /* LTR: hide to the left */\n --angie-sidebar-show-transform: translateX(0);\n}\n\n/* RTL-specific transform values */\n[dir=\"rtl\"] {\n --angie-sidebar-hide-transform: translateX(100%); /* RTL: hide to the right */\n}\n\n/* Respect user's motion preferences */\n@media (prefers-reduced-motion: reduce) {\n :root {\n --angie-sidebar-transition: none;\n }\n}\n\n/* Apply transitions only when user is actively toggling */\nbody.angie-sidebar-transitioning {\n transition: var(--angie-sidebar-transition) !important;\n}\n\nbody.angie-sidebar-transitioning #angie-sidebar-container {\n transition: var(--angie-sidebar-transition) !important;\n}\n\n/* Layout (default) - Push content */\n@media (min-width: 768px) {\n body.angie-sidebar-active {\n padding-inline-start: var(--angie-sidebar-width) !important;\n }\n\n #angie-sidebar-container {\n position: fixed;\n top: 0;\n inset-inline-start: 0;\n width: var(--angie-sidebar-width);\n height: 100vh;\n z-index: var(--angie-sidebar-z-index) !important; /* below elementor popups and media library modal */\n background: #FCFCFC;\n transform: var(--angie-sidebar-hide-transform);\n outline: none;\n overflow: hidden;\n /* No default transition - only when transitioning */\n }\n\n /* Resize handle */\n #angie-sidebar-container::after {\n content: '';\n position: absolute;\n top: 0;\n inset-inline-end: 0;\n width: 4px;\n height: 100%;\n cursor: ew-resize;\n background: transparent;\n z-index: 1000001;\n }\n\n /* Pink border during resize */\n #angie-sidebar-container.angie-resizing {\n border-inline-end-color: #ff69b4 !important;\n border-inline-end-width: 2px !important;\n }\n\n /* Disable iframe pointer events during resize */\n #angie-sidebar-container.angie-resizing iframe#angie-iframe {\n pointer-events: none !important;\n }\n}\n\n/* Active states */\nbody.angie-sidebar-active #angie-sidebar-container {\n transform: var(--angie-sidebar-show-transform);\n}\n\n/* Studio mode - sidebar takes full width */\n@media (min-width: 768px) {\n html.angie-studio-active body.angie-sidebar-active #angie-sidebar-container {\n width: 100%;\n }\n}\n\n/* High contrast mode support */\n@media (prefers-contrast: high) {\n #angie-sidebar-container {\n border-color: #000;\n box-shadow: none;\n }\n}\n\n/* Screen reader only class */\n.angie-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n/* Plugin conflict resolution */\nbody.angie-sidebar-active {\n /* Reset common conflicting styles */\n box-sizing: border-box !important;\n position: relative !important;\n}\n\n#angie-sidebar-toggle {\n z-index: 99999 !important;\n}\n";const n=document.head||document.getElementsByTagName("head")[0];n.insertBefore(t,n.firstChild),$=!0}(),"undefined"!=typeof window&&(window.toggleAngieSidebar=function(e){return function(t,n){const i=document.body,r=document.getElementById("angie-sidebar-container");if(!r)return void U.warn("Required elements not found!");const o=i.classList.contains("angie-sidebar-active"),a=void 0!==t?t:!o;n||(i.classList.add("angie-sidebar-transitioning"),setTimeout(function(){i.classList.remove("angie-sidebar-transitioning")},300)),a?i.classList.add("angie-sidebar-active"):i.classList.remove("angie-sidebar-active"),a&&setTimeout(function(){q({type:"focusInput"})},n?0:300),e&&e(a,r,n),K(a?M:k);const s=new CustomEvent("angieSidebarToggle",{detail:{isOpen:a,sidebar:r,skipTransition:n}});document.dispatchEvent(s),q({type:m.ANGIE_SIDEBAR_TOGGLED,payload:{state:a?"opened":"closed"}})}}(e),window.addEventListener("message",function(e){if(e.data&&"toggleAngieSidebar"===e.data.type){const{force:t,skipTransition:n}=e.data.payload||{};window.toggleAngieSidebar&&window.toggleAngieSidebar(t,n)}}))}const W=c("iframe"),X=async()=>{if(S.iframe?.contentWindow&&S.iframeUrlObject)try{W.log("Disabling navigation prevention in Angie iframe"),S.iframe.contentWindow.postMessage({type:m.ANGIE_DISABLE_NAVIGATION_PREVENTION},S.iframeUrlObject.origin),await new Promise(e=>setTimeout(e,100))}catch(e){throw W.error("Failed to disable navigation prevention:",e),e}else W.warn("Cannot disable navigation prevention: iframe or origin not available")},Y=c("registration-queue");class J{queue=[];isProcessing=!1;add(e){const t={id:this.generateId(e),config:e,timestamp:Date.now(),status:"pending"};return this.queue.push(t),Y.log(`Added server "${e.name}" to queue`),t}getAll(){return[...this.queue]}getPending(){return this.queue.filter(e=>"pending"===e.status)}updateStatus(e,t,n){const i=this.queue.find(t=>t.id===e);i&&(i.status=t,n?i.error=n:"pending"!==t&&"registered"!==t||delete i.error,Y.log(`Updated server ${e} status to ${t}`))}async processQueue(e){if(this.isProcessing)return void Y.log("Already processing queue");this.isProcessing=!0;const t=this.getPending();Y.log(`Processing ${t.length} pending registrations`);try{for(const n of t)try{await e(n),this.updateStatus(n.id,"registered")}catch(e){const t=e instanceof Error?e.message:String(e);this.updateStatus(n.id,"failed",t),Y.error(`Failed to process registration ${n.id}:`,t)}}finally{this.isProcessing=!1}}clear(){this.queue=[],Y.log("Cleared all registrations")}resetAllToPending(){if(this.isProcessing)return Y.log("Cannot reset to pending - processing in progress"),!1;const e=this.queue.filter(e=>"registered"===e.status).length,t=this.queue.filter(e=>"failed"===e.status).length;return this.queue.forEach(e=>{"pending"!==e.status&&(e.status="pending",delete e.error)}),Y.log(`Reset ${e+t} registrations to pending`),!0}remove(e){const t=this.queue.findIndex(t=>t.id===e);return-1!==t&&(this.queue.splice(t,1),Y.log(`Removed registration ${e}`),!0)}generateId(e){return`reg_${e.name}_${e.version}_${Date.now()}`}}class Z{angieDetector;clientManager;logger;registrationQueue;isInitialized=!1;instanceId;constructor(){this.instanceId=Math.random().toString(36).substring(2,8),this.logger=c({instanceId:this.instanceId}),this.logger.log("Constructor called - initializing SDK"),this.angieDetector=new y,this.registrationQueue=new J,this.clientManager=new v,this.logger.log("Setting up event handlers"),this.setupAngieReadyHandler(),this.setupServerInitHandler(),this.setupReRegistrationHandler(),this.logger.log("SDK initialization complete")}async loadSidebar(e){j(),await(async e=>{if(window.screen.availWidth<=768)return void W.log("Mobile detected, skipping iframe injection");let t=document.getElementById("angie-sidebar-container");if(!t){const e=performance.now();if(W.log("⏱️ Waiting for sidebar container..."),await new Promise(e=>{let n=0;const i=setInterval(()=>{t=document.getElementById("angie-sidebar-container"),n++,(t||n>20)&&(clearInterval(i),t&&e())},100);setTimeout(()=>{if(clearInterval(i),t)return void e();const n=new MutationObserver(()=>{t=document.getElementById("angie-sidebar-container"),t&&(n.disconnect(),e())});n.observe(document.body,{childList:!0,subtree:!0}),setTimeout(()=>{n.disconnect(),e()},8e3)},2e3)}),W.log(`⏱️ Sidebar container detection took: ${(performance.now()-e).toFixed(2)}ms`),!t)return void W.error("Sidebar container not found")}const{iframe:n,iframeUrlObject:i}=await(async e=>{const t=e.origin,n=new URL(e.path,t),i=n.pathname.slice(1).replace(/\//,"--")+"-"+Math.random().toString(36).substring(7);return new Promise(r=>{const o=new URL(t);o.pathname=n.pathname;const a=window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light";if(o.searchParams.append("colorScheme",e.uiTheme||a||"light"),o.searchParams.append("sdkVersion",e.sdkVersion),o.searchParams.append("instanceId",i),o.searchParams.append("origin",window.location.origin),e.isRTL&&o.searchParams.append("isRTL",e.isRTL?"true":"false"),"localhost"===window.location.hostname&&window.location.search.includes("debug_error")){const e=new URLSearchParams(window.location.search).get("debug_error");e&&o.searchParams.append("debug_error",e)}n.searchParams.forEach((e,t)=>{o.searchParams.set(t,e)}),o.searchParams.set("ver",(new Date).getTime().toString());const s=e.parent||document,d=s.createElement("iframe"),g={"background-color":"transparent","color-scheme":"normal",...e.css};window.addEventListener("message",async e=>{if(e.origin===o.origin)switch(e.data.type){case f.ANGIE_READY:r({iframe:d,iframeUrlObject:o});break;case f.ANGIE_LOADED:d.contentWindow?.postMessage({type:f.HOST_READY,instanceId:i},o.origin)}}),d.setAttribute("src",o.href),d.id="angie-iframe",d.setAttribute("frameborder","0"),d.setAttribute("scrolling","no"),d.setAttribute("style",Object.entries(g).map(([e,t])=>`${e}: ${t}`).join("; ")),d.setAttribute("allow","clipboard-write; clipboard-read"),e.insertCallback?e.insertCallback(d):s.body.appendChild(d)})})({origin:e.origin||"https://angie.elementor.com",path:"angie/wp-admin",insertCallback:e=>{W.log("Injecting Angie iframe into sidebar container"),e.setAttribute("title","Angie AI Assistant"),e.setAttribute("role","application"),e.setAttribute("aria-label","Angie AI Assistant Interface");const n=document.getElementById("angie-sidebar-loading");n&&(n.textContent=""),t?.appendChild(e),I(e,!0),e.addEventListener("load",()=>{e.focus()})},css:{width:"100%",height:"100%",border:"none",outline:"none"},uiTheme:e.uiTheme,isRTL:e.isRTL,sdkVersion:"1.0.8"});S.iframe=n,S.iframeUrlObject=i,window.addEventListener("message",e=>{if(e.origin===S.iframeUrlObject?.origin)switch(e.data.type){case w.SET:window.localStorage.setItem(e.data.key,e.data.value);break;case w.GET:{const t=e.ports[0],n=window.localStorage.getItem(e.data.key);t.postMessage({value:n});break}}}),(e=>{window.addEventListener("message",async t=>{const n=t.origin===window.location.origin,i=t.origin===e.iframeUrlObject?.origin;if(n||i)switch(t?.data?.type){case m.SDK_ANGIE_ALL_SERVERS_REGISTERED:break;case m.SDK_ANGIE_READY_PING:{const e=t.ports[0];D.log("Angie is ready",t),A(e,{message:"Angie is ready"});break}case m.SDK_REQUEST_CLIENT_CREATION:{const n=t.data.payload;try{const i=t.ports[0],r=new MessageChannel;r.port1.onmessage=e=>{i.postMessage({success:!0,data:e.data})};const o={type:m.SDK_REQUEST_CLIENT_CREATION,payload:{success:!0,...n,clientId:`dynamic-client-${n.serverName}-${n.serverVersion}-${Date.now()}`,requestId:t.data.payload.requestId},timestamp:Date.now()};if(!e.iframe)throw new Error("Iframe not found");e.iframe.contentWindow?.postMessage(o,e.iframeUrlObject?.origin||"",[r.port2])}catch(e){D.error(`Failed to create client for SDK server "${n.serverName}":`,e)}break}case m.SDK_TRIGGER_ANGIE:D.log("SDK Trigger Angie received",t.data);try{const{requestId:n,prompt:i,context:r}=t.data.payload;if(!e.iframe)throw new Error("Iframe not found");e.iframe.contentWindow?.postMessage({type:m.SDK_TRIGGER_ANGIE,payload:{requestId:n,prompt:i,context:r}},e.iframeUrlObject?.origin||""),window.postMessage({type:m.SDK_TRIGGER_ANGIE_RESPONSE,payload:{success:!0,requestId:n,response:"Angie triggered successfully"}},window.location.origin)}catch(e){D.error("Failed to trigger Angie:",e),window.postMessage({type:m.SDK_TRIGGER_ANGIE_RESPONSE,payload:{success:!1,requestId:t.data.payload?.requestId,error:e instanceof Error?e.message:"Unknown error"}},window.location.origin)}}})})(S),G(),window.addEventListener("message",async t=>{if([window.location.origin,e.origin||"https://angie.elementor.com"].includes(t.origin))if(t?.data?.type===m.ANGIE_CHAT_TOGGLE)S.open=t.data.open,S.iframe&&I(S.iframe,S.open);else if(t?.data?.type===m.ANGIE_STUDIO_TOGGLE){const e=t.data.isStudioOpen;if(!S.iframe)return;if(e)document.documentElement.classList.add("angie-studio-active");else{const e=x();document.documentElement.style.setProperty("--angie-sidebar-width",`${e}px`),document.documentElement.classList.remove("angie-studio-active")}}else if(t?.data?.type===m.ANGIE_NAVIGATE_TO_URL){const{url:e="",confirmed:n=!1}=t.data.payload||{};if(!n)return void W.log("Navigation requires user confirmation");if(!((e,t=[])=>{const n=0===t.length&&"undefined"!=typeof window?[window.location.origin]:t;if(!e.startsWith("http"))return!1;try{const t=new URL(e);return n.includes(t.origin)}catch{return!1}})(e))return void W.error("Navigation blocked: Invalid or unsafe URL",{url:e});await X(),window.location.assign(e)}else if(t?.data?.type===m.ANGIE_PAGE_RELOAD){const{confirmed:e=!1}=t.data.payload||{};if(!e)return void W.log("Page reload requires user confirmation");W.log("Page reload confirmed - disabling navigation prevention and reloading"),await X(),setTimeout(()=>{window.location.reload()},50)}else t?.data?.type===f.RESET_HASH&&(window.location.hash="",A(t.ports[0],{message:"Hash reset successfully"}))})})({origin:e?.origin||"https://angie.elementor.com",uiTheme:e?.uiTheme||"light",isRTL:e?.isRTL||!1,...e}),this.setupPromptHashDetection()}setupReRegistrationHandler(){window.addEventListener("message",e=>{if(e.data?.type===m.SDK_ANGIE_REFRESH_PING)if(this.logger.log("Angie refresh ping received"),this.registrationQueue.resetAllToPending()){const e=this.registrationQueue.getPending().length;this.logger.log(`Successfully reset ${e} registrations, processing queue`),this.handleAngieReady()}else this.logger.log("Skipping queue reset - processing already in progress")})}setupAngieReadyHandler(){this.angieDetector.waitForReady().then(e=>{e.isReady?this.handleAngieReady():this.logger.warn("Angie not detected - servers will remain queued")}).catch(e=>{this.logger.error("Error waiting for Angie:",e)})}async handleAngieReady(){this.logger.log("Angie is ready, processing queued registrations");try{await this.registrationQueue.processQueue(async e=>{this.logger.log(`processQueue callback called for "${e.config.name}"`),await this.processRegistration(e)}),this.isInitialized=!0,this.logger.log("Initialization complete")}catch(e){this.logger.error("Error processing registration queue:",e)}}async processRegistration(e){this.logger.log(`Processing registration for server "${e.config.name}" (ID: ${e.id})`);try{this.logger.log(`Calling clientManager.requestClientCreation for "${e.config.name}"`);const t={...e,instanceId:this.instanceId};await this.clientManager.requestClientCreation(t),this.logger.log(`Successfully registered server "${e.config.name}"`)}catch(t){throw this.logger.error(`Failed to register server "${e.config.name}":`,t),t}}registerLocalServer(e){return e.type=p.LOCAL,e.transport=u.POST_MESSAGE,this.registerServer(e)}registerRemoteServer(e){return e.type=p.REMOTE,this.registerServer(e)}isLocalServerConfig(e){return e.type===p.LOCAL||!e.type&&"server"in e}isRemoteServerConfig(e){return e.type===p.REMOTE&&"url"in e}async registerServer(e){if(!e.type)return this.logger.warn("For a local server, please use registerLocalServer instead of registerServer"),void this.registerLocalServer(e);if(this.logger.log(`registerServer called for "${e.name}"`),!e.name)throw new Error("Server name is required");if(!e.description)throw new Error("Server description is required");if(this.isLocalServerConfig(e)&&!e.server)throw new Error("Server instance is required for local servers");this.logger.log(`Registering server "${e.name}"`);const t=this.registrationQueue.add(e);if(this.logger.log(`Added registration to queue: ${t.id}`),this.angieDetector.isReady())try{await this.processRegistration(t),this.registrationQueue.updateStatus(t.id,"registered"),this.logger.log(`Server "${e.name}" registered successfully`)}catch(e){const n=e instanceof Error?e.message:String(e);throw this.registrationQueue.updateStatus(t.id,"failed",n),e}else this.logger.log(`Server "${e.name}" queued until Angie is ready`)}getRegistrations(){return this.registrationQueue.getAll()}getPendingRegistrations(){return this.registrationQueue.getPending()}isAngieReady(){return this.angieDetector.isReady()}isReady(){return this.isInitialized}async waitForReady(){if(!(await this.angieDetector.waitForReady()).isReady)throw new Error("Angie is not available");for(;!this.isInitialized;)await new Promise(e=>setTimeout(e,100))}async triggerAngie(e){if(!this.isAngieReady())throw new Error("Angie is not ready. Please wait for Angie to be available before triggering.");const t=this.generateRequestId(),n=e.options?.timeout||3e4;return new Promise((i,r)=>{const o=setTimeout(()=>{r(new Error("Angie trigger request timed out"))},n),a=e=>{e.data?.type===m.SDK_TRIGGER_ANGIE_RESPONSE&&e.data?.payload?.requestId===t&&(clearTimeout(o),window.removeEventListener("message",a),i(e.data.payload))};window.addEventListener("message",a);const s={type:m.SDK_TRIGGER_ANGIE,payload:{requestId:t,prompt:e.prompt,options:e.options,context:{pageUrl:window.location.href,pageTitle:document.title,...e.context}},timestamp:Date.now()};this.logger.log(`Triggering Angie with prompt (Request ID: ${t})`),window.postMessage(s,window.location.origin)})}destroy(){this.registrationQueue.clear(),this.logger.log("SDK destroyed")}setupServerInitHandler(){window.addEventListener("message",e=>{e.data?.type===m.SDK_REQUEST_INIT_SERVER&&(this.logger.log("Server init request received"),this.handleServerInitRequest(e))})}handleServerInitRequest(e){const{clientId:t,serverId:n,instanceId:i}=e.data.payload||{};if(t&&n)if(this.logger.log(`Server init request received - Request instanceId: ${i}, This instanceId: ${this.instanceId}`),i&&i!==this.instanceId)this.logger.log(`Ignoring server init request for different instance. Request instanceId: ${i}, this instanceId: ${this.instanceId}`);else{this.logger.log(`Handling server init request for clientId: ${t}, serverId: ${n}`);try{const t=this.registrationQueue.getAll().find(e=>e.id===n);if(!t)return void this.logger.error(`No registration found for serverId: ${n}`);if("type"in t.config&&"remote"===t.config.type)return void this.logger.log("Remote server registration detected; skipping local connect");const i=e.ports[0];if(!i)return void this.logger.error("No port provided in server init request");const r=t.config.server,o=new b(i);r.connect(o),this.logger.log(`Server "${t.config.name}" initialized successfully`)}catch(e){this.logger.error(`Error initializing server for clientId ${t}:`,e)}}else this.logger.error("Invalid server init request - missing clientId or serverId")}generateRequestId(){return`${this.instanceId}-${Date.now()}-${Math.random().toString(36).substring(2,8)}`}async handlePromptHash(){const e=window.location.hash;if(e.startsWith("#angie-prompt="))try{const t=e.replace("#angie-prompt=",""),n=decodeURIComponent(t);if(!n)return void this.logger.warn("Empty prompt detected in hash");this.logger.log("Detected prompt in hash:",n),await this.waitForReady();const i=await this.triggerAngie({prompt:n,context:{source:"hash-parameter",pageUrl:window.location.href,timestamp:(new Date).toISOString()}});this.logger.log("Triggered successfully from hash:",i),window.location.hash=""}catch(e){this.logger.error("Failed to trigger from hash:",e)}}setupPromptHashDetection(){this.handlePromptHash(),window.addEventListener("hashchange",()=>this.handlePromptHash())}}const ee=c("navigation"),te=(e,t)=>{if(C()){t.isOpen&&window.toggleAngieSidebar&&window.toggleAngieSidebar(!0);const n=q({type:"angie-route-navigation",path:e,payload:t});return n||ee.error("Failed to post navigation message to Angie iframe"),n}return ee.error("Angie iframe not found"),!1},ne="angie_return_url",ie=c("referrer-redirect");function re(e){try{return new URL(e,window.location.origin).origin===window.location.origin}catch{return!1}}function oe(e){if(!re(e))return ie.warn("Invalid redirect URL rejected:",e),!1;try{return localStorage.setItem(ne,e),!0}catch(e){return ie.warn("localStorage not available"),!1}}function ae(){try{const e=localStorage.getItem(ne);return e&&re(e)?e:(e&&ie.warn("Stored redirect URL is invalid, returning null:",e),null)}catch(e){return ie.warn("localStorage not available"),null}}function se(){try{localStorage.removeItem(ne)}catch(e){ie.warn("localStorage not available")}}export{M as ANGIE_SIDEBAR_STATE_OPEN,y as AngieDetector,u as AngieLocalServerTransport,l as AngieMCPTransport,Z as AngieMcpSdk,h as AngieRemoteServerTransport,p as AngieServerType,b as BrowserContextTransport,v as ClientManager,f as HostEventType,w as HostLocalStorageEventType,m as MessageEventType,J as RegistrationQueue,B as applyWidth,se as clearReferrerRedirect,X as disableNavigationPrevention,C as getAngieIframe,H as getAngieSidebarSavedState,ae as getReferrerRedirect,j as initAngieSidebar,V as initializeResize,F as loadState,x as loadWidth,te as navigateAngieIframe,K as saveState,z as saveWidth,oe as setReferrerRedirect,I as toggleAngieSidebar,R as waitForDocumentReady};
@@ -0,0 +1,3 @@
1
+ export declare function setReferrerRedirect(url: string): boolean;
2
+ export declare function getReferrerRedirect(): string | null;
3
+ export declare function clearReferrerRedirect(): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elementor/angie-sdk",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "TypeScript SDK for Angie AI assistant",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",