@yassirbenmoussa/aicommerce-sdk 1.3.0 → 1.5.0

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.
@@ -1,11 +1,11 @@
1
1
  var AICommerceSDK=(function(exports){'use strict';/*! AI Commerce SDK v1.0.0 | MIT License | https://aicommerce.dev */
2
- var O=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var de=Object.getOwnPropertyNames;var le=Object.prototype.hasOwnProperty;var B=(o,r)=>()=>(o&&(r=o(o=0)),r);var X=(o,r)=>{for(var e in r)O(o,e,{get:r[e],enumerable:true});},me=(o,r,e,a)=>{if(r&&typeof r=="object"||typeof r=="function")for(let u of de(r))!le.call(o,u)&&u!==e&&O(o,u,{get:()=>r[u],enumerable:!(a=ce(r,u))||a.enumerable});return o};var W=o=>me(O({},"__esModule",{value:true}),o);var z={};X(z,{AICommerce:()=>exports.AICommerce,AICommerceError:()=>exports.AICommerceError});exports.AICommerce=void 0;exports.AICommerceError=void 0;var A=B(()=>{exports.AICommerce=class o{constructor(r){this.sessionToken=null;this.products={create:async r=>this.request("/api/v1/products",{method:"POST",body:JSON.stringify(r)}),batchUpsert:async r=>this.request("/api/v1/products",{method:"POST",body:JSON.stringify({products:r})}),list:async r=>{let e=new URLSearchParams;r?.page&&e.set("page",String(r.page)),r?.perPage&&e.set("perPage",String(r.perPage)),r?.search&&e.set("search",r.search),r?.categoryId&&e.set("categoryId",r.categoryId),r?.isActive!==void 0&&e.set("isActive",String(r.isActive));let a=e.toString();return this.request(`/api/v1/products${a?`?${a}`:""}`)},get:async r=>this.request(`/api/v1/products/${r}`),update:async(r,e)=>this.request(`/api/v1/products/${r}`,{method:"PUT",body:JSON.stringify(e)}),delete:async r=>this.request(`/api/v1/products/${r}`,{method:"DELETE"})};if(!r.apiKey)throw new Error("AICommerce: apiKey is required");this.apiKey=r.apiKey,this.baseUrl=this.normalizeUrl(r.baseUrl||this.detectBaseUrl()),this.timeout=r.timeout||3e4;}detectBaseUrl(){return typeof window<"u"?window.location.origin:"https://api.aicommerce.dev"}normalizeUrl(r){return r.replace(/\/$/,"")}async request(r,e={}){let a=`${this.baseUrl}${r}`,u=new AbortController,s=setTimeout(()=>u.abort(),this.timeout);try{let m=await fetch(a,{...e,signal:u.signal,headers:{"Content-Type":"application/json","X-API-Key":this.apiKey,...this.sessionToken&&{"X-Session-Token":this.sessionToken},...e.headers}});if(clearTimeout(s),!m.ok){let T=await m.json().catch(()=>({})),f={code:T.code||"UNKNOWN_ERROR",message:T.message||T.error||`HTTP ${m.status}`,status:m.status};throw new exports.AICommerceError(f.message,f.code,f.status)}return m.json()}catch(m){throw clearTimeout(s),m instanceof exports.AICommerceError?m:m instanceof Error&&m.name==="AbortError"?new exports.AICommerceError("Request timeout","TIMEOUT",408):new exports.AICommerceError(m instanceof Error?m.message:"Unknown error","NETWORK_ERROR",0)}}async chat(r,e){let a=typeof r=="string"?{message:r,context:e,sessionToken:this.sessionToken||void 0}:{...r,sessionToken:r.sessionToken||this.sessionToken||void 0},u=await this.request("/api/v1/chat",{method:"POST",body:JSON.stringify(a)});return u.sessionToken&&(this.sessionToken=u.sessionToken),u}async chatWithAudio(r,e){let a=await r.arrayBuffer(),s={audioBase64:btoa(new Uint8Array(a).reduce((T,f)=>T+String.fromCharCode(f),"")),audioMimeType:r.type||"audio/webm",context:e,sessionToken:this.sessionToken||void 0},m=await this.request("/api/v1/chat",{method:"POST",body:JSON.stringify(s)});return m.sessionToken&&(this.sessionToken=m.sessionToken),m}async createSession(){let r=await this.request("/api/v1/chat/session",{method:"POST"});return this.sessionToken=r.session.token,r.session}clearSession(){this.sessionToken=null;}getSessionToken(){return this.sessionToken}setSessionToken(r){this.sessionToken=r;}async upload(r,e){let a=new FormData;a.append("file",r),e?.folder&&a.append("folder",e.folder),e?.productId&&a.append("productId",e.productId),e?.isPrimary&&a.append("isPrimary","true");let u=`${this.baseUrl}/api/v1/upload`,s=await fetch(u,{method:"POST",headers:{"X-API-Key":this.apiKey},body:a});if(!s.ok){let m=await s.json().catch(()=>({}));throw new exports.AICommerceError(m.message||m.error||`HTTP ${s.status}`,m.code||"UPLOAD_ERROR",s.status)}return s.json()}static async quickChat(r){return new o({apiKey:r.apiKey,baseUrl:r.baseUrl}).chat(r.message,r.context)}},exports.AICommerceError=class o extends Error{constructor(r,e,a){super(r),this.name="AICommerceError",this.code=e,this.status=a,Object.setPrototypeOf(this,o.prototype);}};});function ue(o){let r=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(o);return r?{r:parseInt(r[1],16),g:parseInt(r[2],16),b:parseInt(r[3],16)}:{r:99,g:102,b:241}}function D(o){let r=o.primaryColor,e=ue(r),a=o.position==="bottom-left";return `
2
+ var O=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var de=Object.getOwnPropertyNames;var le=Object.prototype.hasOwnProperty;var B=(t,e)=>()=>(t&&(e=t(t=0)),e);var Y=(t,e)=>{for(var r in e)O(t,r,{get:e[r],enumerable:true});},me=(t,e,r,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let u of de(e))!le.call(t,u)&&u!==r&&O(t,u,{get:()=>e[u],enumerable:!(a=ce(e,u))||a.enumerable});return t};var W=t=>me(O({},"__esModule",{value:true}),t);var z={};Y(z,{AICommerce:()=>exports.AICommerce,AICommerceError:()=>exports.AICommerceError});exports.AICommerce=void 0;exports.AICommerceError=void 0;var $=B(()=>{exports.AICommerce=class t{constructor(e){this.sessionToken=null;this.products={create:async e=>this.request("/api/v1/products",{method:"POST",body:JSON.stringify(e)}),batchUpsert:async e=>this.request("/api/v1/products",{method:"POST",body:JSON.stringify({products:e})}),list:async e=>{let r=new URLSearchParams;e?.page&&r.set("page",String(e.page)),e?.perPage&&r.set("perPage",String(e.perPage)),e?.search&&r.set("search",e.search),e?.categoryId&&r.set("categoryId",e.categoryId),e?.isActive!==void 0&&r.set("isActive",String(e.isActive));let a=r.toString();return this.request(`/api/v1/products${a?`?${a}`:""}`)},get:async e=>this.request(`/api/v1/products/${e}`),update:async(e,r)=>this.request(`/api/v1/products/${e}`,{method:"PUT",body:JSON.stringify(r)}),delete:async e=>this.request(`/api/v1/products/${e}`,{method:"DELETE"})};if(!e.apiKey)throw new Error("AICommerce: apiKey is required");this.apiKey=e.apiKey,this.storeId=e.storeId,this.baseUrl=this.normalizeUrl(e.baseUrl||this.detectBaseUrl()),this.timeout=e.timeout||3e4;}detectBaseUrl(){if(typeof window<"u"){let e=document.querySelector("script[data-aicommerce-url]");if(e)return e.getAttribute("data-aicommerce-url")||"https://api.aicommerce.dev"}return "https://api.aicommerce.dev"}normalizeUrl(e){return e.replace(/\/$/,"")}async request(e,r={}){let a=`${this.baseUrl}${e}`,u=new AbortController,s=setTimeout(()=>u.abort(),this.timeout);try{let m=await fetch(a,{...r,signal:u.signal,headers:{"Content-Type":"application/json","x-api-key":this.apiKey,...this.storeId&&{"x-store-id":this.storeId},...this.sessionToken&&{"X-Session-Token":this.sessionToken},...r.headers}});if(clearTimeout(s),!m.ok){let T=await m.json().catch(()=>({})),f={code:T.code||"UNKNOWN_ERROR",message:T.message||T.error||`HTTP ${m.status}`,status:m.status};throw new exports.AICommerceError(f.message,f.code,f.status)}return m.json()}catch(m){throw clearTimeout(s),m instanceof exports.AICommerceError?m:m instanceof Error&&m.name==="AbortError"?new exports.AICommerceError("Request timeout","TIMEOUT",408):new exports.AICommerceError(m instanceof Error?m.message:"Unknown error","NETWORK_ERROR",0)}}async chat(e,r){let a=typeof e=="string"?{message:e,context:r,sessionToken:this.sessionToken||void 0}:{...e,sessionToken:e.sessionToken||this.sessionToken||void 0},u=await this.request("/api/v1/chat",{method:"POST",body:JSON.stringify(a)});return u.sessionToken&&(this.sessionToken=u.sessionToken),u}async chatWithAudio(e,r){let a=await e.arrayBuffer(),s={audioBase64:btoa(new Uint8Array(a).reduce((T,f)=>T+String.fromCharCode(f),"")),audioMimeType:e.type||"audio/webm",context:r,sessionToken:this.sessionToken||void 0},m=await this.request("/api/v1/chat",{method:"POST",body:JSON.stringify(s)});return m.sessionToken&&(this.sessionToken=m.sessionToken),m}async createSession(){let e=await this.request("/api/v1/chat/session",{method:"POST"});return this.sessionToken=e.session.token,e.session}clearSession(){this.sessionToken=null;}getSessionToken(){return this.sessionToken}setSessionToken(e){this.sessionToken=e;}async upload(e,r){let a=new FormData;a.append("file",e),r?.folder&&a.append("folder",r.folder),r?.productId&&a.append("productId",r.productId),r?.isPrimary&&a.append("isPrimary","true");let u=`${this.baseUrl}/api/v1/upload`,s=await fetch(u,{method:"POST",headers:{"X-API-Key":this.apiKey},body:a});if(!s.ok){let m=await s.json().catch(()=>({}));throw new exports.AICommerceError(m.message||m.error||`HTTP ${s.status}`,m.code||"UPLOAD_ERROR",s.status)}return s.json()}static async quickChat(e){return new t({apiKey:e.apiKey,baseUrl:e.baseUrl}).chat(e.message,e.context)}},exports.AICommerceError=class t extends Error{constructor(e,r,a){super(e),this.name="AICommerceError",this.code=r,this.status=a,Object.setPrototypeOf(this,t.prototype);}};});function ue(t){let e=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return e?{r:parseInt(e[1],16),g:parseInt(e[2],16),b:parseInt(e[3],16)}:{r:99,g:102,b:241}}function D(t){let e=t.primaryColor,r=ue(e),a=t.position==="bottom-left";return `
3
3
  /* AI Commerce Widget Styles */
4
4
  #aicommerce-widget {
5
- --aic-primary: ${r};
6
- --aic-primary-rgb: ${e.r}, ${e.g}, ${e.b};
7
- --aic-primary-light: rgba(${e.r}, ${e.g}, ${e.b}, 0.1);
8
- --aic-primary-dark: rgba(${e.r}, ${e.g}, ${e.b}, 0.9);
5
+ --aic-primary: ${e};
6
+ --aic-primary-rgb: ${r.r}, ${r.g}, ${r.b};
7
+ --aic-primary-light: rgba(${r.r}, ${r.g}, ${r.b}, 0.1);
8
+ --aic-primary-dark: rgba(${r.r}, ${r.g}, ${r.b}, 0.9);
9
9
  --aic-bg: #ffffff;
10
10
  --aic-bg-secondary: #f8fafc;
11
11
  --aic-text: #1e293b;
@@ -13,7 +13,7 @@ var O=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var de=Object
13
13
  --aic-border: #e2e8f0;
14
14
  --aic-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
15
15
  --aic-radius: 16px;
16
- --aic-z-index: ${o.zIndex};
16
+ --aic-z-index: ${t.zIndex};
17
17
 
18
18
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
19
19
  font-size: 14px;
@@ -547,18 +547,18 @@ var O=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var de=Object
547
547
  .aicommerce-messages::-webkit-scrollbar-thumb:hover {
548
548
  background: var(--aic-text-secondary);
549
549
  }
550
- `}function Y(o){let r=document.createElement("style");r.id="aicommerce-widget-styles",r.textContent=o;let e=document.getElementById("aicommerce-widget-styles");return e&&e.remove(),document.head.appendChild(r),r}var J=B(()=>{});var V={};X(V,{AICommerceWidget:()=>exports.AICommerceWidget,createWidget:()=>j});function j(o){if(!o.apiKey)throw new Error("AICommerceWidget: apiKey is required");let r=new exports.AICommerce({apiKey:o.apiKey,baseUrl:o.baseUrl}),e={isOpen:false,isLoading:true,isRecording:false,messages:[],storeConfig:null},a=null,u=[],s=null,f=null,p;async function G(){try{let t=o.baseUrl||K(),i=await fetch(`${t}/api/v1/store`,{headers:{"x-api-key":o.apiKey}});return i.ok?(await i.json()).store:null}catch(t){return console.error("Failed to fetch store config:",t),null}}function K(){if(typeof window<"u"){let t=document.querySelector("script[data-aicommerce-url]");if(t)return t.getAttribute("data-aicommerce-url")||""}return "https://api.aicommerce.dev"}async function _(){e.storeConfig=await G(),p={apiKey:o.apiKey,baseUrl:o.baseUrl||K(),position:o.position||"bottom-right",theme:o.theme||"auto",primaryColor:o.primaryColor||e.storeConfig?.primaryColor||"#6366f1",welcomeMessage:o.welcomeMessage||e.storeConfig?.welcomeMessage||"Hi! How can I help you find the perfect product today?",botName:o.botName||e.storeConfig?.chatBotName||"Shopping Assistant",zIndex:o.zIndex||9999,buttonText:o.buttonText||"\u{1F4AC}",hideLauncher:o.hideLauncher||false,onOpen:o.onOpen,onClose:o.onClose,onProductClick:o.onProductClick,onMessage:o.onMessage};let t=D(p);f=Y(t),s=document.createElement("div"),s.id="aicommerce-widget",s.className=`aicommerce-widget aicommerce-${p.position} aicommerce-theme-${p.theme}`,document.body.appendChild(s),b(),e.messages.push({role:"assistant",content:p.welcomeMessage}),e.isLoading=false,b();}function b(){if(!s)return;let t=`
550
+ `}function J(t){let e=document.createElement("style");e.id="aicommerce-widget-styles",e.textContent=t;let r=document.getElementById("aicommerce-widget-styles");return r&&r.remove(),document.head.appendChild(e),e}var V=B(()=>{});var X={};Y(X,{AICommerceWidget:()=>exports.AICommerceWidget,createWidget:()=>j});function j(t){if(!t.apiKey)throw new Error("AICommerceWidget: apiKey is required");let e=new exports.AICommerce({apiKey:t.apiKey,storeId:t.storeId,baseUrl:t.baseUrl}),r={isOpen:false,isLoading:true,isRecording:false,messages:[],storeConfig:null},a=null,u=[],s=null,f=null,p;async function G(){try{let o=t.baseUrl||K(),i=await fetch(`${o}/api/v1/store`,{headers:{"x-api-key":t.apiKey}});return i.ok?(await i.json()).store:null}catch(o){return console.error("Failed to fetch store config:",o),null}}function K(){if(typeof window<"u"){let o=document.querySelector("script[data-aicommerce-url]");if(o)return o.getAttribute("data-aicommerce-url")||""}return "https://api.aicommerce.dev"}async function _(){r.storeConfig=await G(),p={apiKey:t.apiKey,storeId:t.storeId,baseUrl:t.baseUrl||K(),position:t.position||"bottom-right",theme:t.theme||"auto",primaryColor:t.primaryColor||r.storeConfig?.primaryColor||"#6366f1",welcomeMessage:t.welcomeMessage||r.storeConfig?.welcomeMessage||"Hi! How can I help you find the perfect product today?",botName:t.botName||r.storeConfig?.chatBotName||"Shopping Assistant",zIndex:t.zIndex||9999,buttonText:t.buttonText||"\u{1F4AC}",hideLauncher:t.hideLauncher||false,onOpen:t.onOpen,onClose:t.onClose,onProductClick:t.onProductClick,onMessage:t.onMessage};let o=D(p);f=J(o),s=document.createElement("div"),s.id="aicommerce-widget",s.className=`aicommerce-widget aicommerce-${p.position} aicommerce-theme-${p.theme}`,document.body.appendChild(s),b(),r.messages.push({role:"assistant",content:p.welcomeMessage}),r.isLoading=false,b();}function b(){if(!s)return;let o=`
551
551
  ${p.hideLauncher?"":`
552
- <button class="aicommerce-launcher ${e.isOpen?"aicommerce-hidden":""}" aria-label="Open chat">
552
+ <button class="aicommerce-launcher ${r.isOpen?"aicommerce-hidden":""}" aria-label="Open chat">
553
553
  <span class="aicommerce-launcher-icon">${p.buttonText}</span>
554
554
  </button>
555
555
  `}
556
556
 
557
- <div class="aicommerce-chat ${e.isOpen?"aicommerce-open":"aicommerce-closed"}">
557
+ <div class="aicommerce-chat ${r.isOpen?"aicommerce-open":"aicommerce-closed"}">
558
558
  <div class="aicommerce-header">
559
559
  <div class="aicommerce-header-info">
560
560
  <div class="aicommerce-avatar">
561
- ${e.storeConfig?.logo?`<img src="${e.storeConfig.logo}" alt="${p.botName}" />`:"<span>\u{1F916}</span>"}
561
+ ${r.storeConfig?.logo?`<img src="${r.storeConfig.logo}" alt="${p.botName}" />`:"<span>\u{1F916}</span>"}
562
562
  </div>
563
563
  <div class="aicommerce-header-text">
564
564
  <span class="aicommerce-bot-name">${p.botName}</span>
@@ -569,23 +569,23 @@ var O=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var de=Object
569
569
  </div>
570
570
 
571
571
  <div class="aicommerce-messages">
572
- ${e.messages.map((n,y)=>{let l=te(n.content),P=n.role==="user";return `
572
+ ${r.messages.map((n,y)=>{let l=te(n.content),P=n.role==="user";return `
573
573
  <div class="aicommerce-message aicommerce-${n.role}">
574
574
  <div class="aicommerce-message-content ${l?"aicommerce-rtl":"aicommerce-ltr"}">
575
- ${n.audioUrl?Q(n,y,P):E(n.content)}
575
+ ${n.audioUrl?Q(n,y,P):R(n.content)}
576
576
  </div>
577
577
  ${n.products&&n.products.length>0?`
578
578
  <div class="aicommerce-products">
579
579
  ${n.products.map(g=>`
580
580
  <div class="aicommerce-product-card" data-product-id="${g.id}">
581
581
  ${g.image||g.imageUrl?`
582
- <img src="${g.image||g.imageUrl}" alt="${E(g.name)}" class="aicommerce-product-image" />
582
+ <img src="${g.image||g.imageUrl}" alt="${R(g.name)}" class="aicommerce-product-image" />
583
583
  `:`
584
584
  <div class="aicommerce-product-placeholder">\u{1F4E6}</div>
585
585
  `}
586
586
  <div class="aicommerce-product-info">
587
- <span class="aicommerce-product-name" title="${E(g.name)}">${E(g.name)}</span>
588
- ${g.description?`<p class="aicommerce-product-desc">${E(g.description)}</p>`:""}
587
+ <span class="aicommerce-product-name" title="${R(g.name)}">${R(g.name)}</span>
588
+ ${g.description?`<p class="aicommerce-product-desc">${R(g.description)}</p>`:""}
589
589
  <span class="aicommerce-product-price">${ne(g.price,g.currency)}</span>
590
590
  </div>
591
591
  </div>
@@ -594,7 +594,7 @@ var O=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var de=Object
594
594
  `:""}
595
595
  </div>
596
596
  `}).join("")}
597
- ${e.isLoading?`
597
+ ${r.isLoading?`
598
598
  <div class="aicommerce-message aicommerce-assistant">
599
599
  <div class="aicommerce-typing">
600
600
  <span></span><span></span><span></span>
@@ -608,10 +608,10 @@ var O=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var de=Object
608
608
  type="text"
609
609
  class="aicommerce-input"
610
610
  placeholder="Type your message..."
611
- ${e.isLoading||e.isRecording?"disabled":""}
611
+ ${r.isLoading||r.isRecording?"disabled":""}
612
612
  />
613
- <button class="aicommerce-mic ${e.isRecording?"aicommerce-recording":""}" ${e.isLoading?"disabled":""} aria-label="${e.isRecording?"Stop recording":"Voice input"}">
614
- ${e.isRecording?`
613
+ <button class="aicommerce-mic ${r.isRecording?"aicommerce-recording":""}" ${r.isLoading?"disabled":""} aria-label="${r.isRecording?"Stop recording":"Voice input"}">
614
+ ${r.isRecording?`
615
615
  <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
616
616
  <rect x="6" y="6" width="12" height="12" rx="2"/>
617
617
  </svg>
@@ -624,30 +624,30 @@ var O=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var de=Object
624
624
  </svg>
625
625
  `}
626
626
  </button>
627
- <button class="aicommerce-send" ${e.isLoading||e.isRecording?"disabled":""} aria-label="Send message">
627
+ <button class="aicommerce-send" ${r.isLoading||r.isRecording?"disabled":""} aria-label="Send message">
628
628
  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
629
629
  <path d="M22 2L11 13M22 2L15 22L11 13M22 2L2 9L11 13"/>
630
630
  </svg>
631
631
  </button>
632
632
  </div>
633
633
  </div>
634
- `;s.innerHTML=t,Z();let i=s.querySelector(".aicommerce-messages");i&&(i.scrollTop=i.scrollHeight);}function Q(t,i,n){return `
634
+ `;s.innerHTML=o,Z();let i=s.querySelector(".aicommerce-messages");i&&(i.scrollTop=i.scrollHeight);}function Q(o,i,n){return `
635
635
  <div class="aicommerce-audio-player" data-message-index="${i}">
636
636
  <button class="aicommerce-audio-btn">
637
637
  <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg>
638
638
  </button>
639
639
  <div class="aicommerce-audio-waveform">
640
640
  <div class="aicommerce-waveform-bars">
641
- ${(t.waveformBars||Array(40).fill(10)).map(y=>`
641
+ ${(o.waveformBars||Array(40).fill(10)).map(y=>`
642
642
  <div class="aicommerce-waveform-bar" style="height: ${y}%; background-color: ${n?"rgba(255,255,255,0.4)":"rgba(99,102,241,0.3)"}"></div>
643
643
  `).join("")}
644
644
  </div>
645
645
  <div class="aicommerce-audio-time">
646
646
  <span class="aicommerce-current-time">0:00</span>
647
- <span>${N(t.audioDuration||0)}</span>
647
+ <span>${N(o.audioDuration||0)}</span>
648
648
  </div>
649
649
  </div>
650
- <audio src="${t.audioUrl}" preload="metadata"></audio>
650
+ <audio src="${o.audioUrl}" preload="metadata"></audio>
651
651
  </div>
652
- `}function Z(){if(!s)return;let t=s.querySelector(".aicommerce-launcher");t&&t.addEventListener("click",()=>I());let i=s.querySelector(".aicommerce-close");i&&i.addEventListener("click",()=>M());let n=s.querySelector(".aicommerce-input"),y=s.querySelector(".aicommerce-send");n&&n.addEventListener("keypress",c=>{c.key==="Enter"&&n.value.trim()&&(L(n.value.trim()),n.value="");}),y&&n&&y.addEventListener("click",()=>{n.value.trim()&&(L(n.value.trim()),n.value="");});let l=s.querySelector(".aicommerce-mic");l&&l.addEventListener("click",()=>ee()),s.querySelectorAll(".aicommerce-product-card").forEach(c=>{c.addEventListener("click",()=>{let d=c.getAttribute("data-product-id"),h=e.messages.flatMap(x=>x.products||[]).find(x=>x.id===d);h&&p.onProductClick&&p.onProductClick(h);});}),s.querySelectorAll(".aicommerce-products").forEach(c=>{let d=false,h=0,x=0;c.addEventListener("mousedown",k=>{d=true,c.style.cursor="grabbing",h=k.pageX-c.offsetLeft,x=c.scrollLeft;}),c.addEventListener("mouseleave",()=>{d=false,c.style.cursor="grab";}),c.addEventListener("mouseup",()=>{d=false,c.style.cursor="grab";}),c.addEventListener("mousemove",k=>{if(!d)return;k.preventDefault();let v=(k.pageX-c.offsetLeft-h)*2;c.scrollLeft=x-v;});}),s.querySelectorAll(".aicommerce-audio-player").forEach(c=>{let d=c.querySelector("audio"),h=c.querySelector(".aicommerce-audio-btn"),x=c.querySelectorAll(".aicommerce-waveform-bar"),k=c.querySelector(".aicommerce-current-time");if(!d||!h)return;h.addEventListener("click",()=>{!d.paused?(d.pause(),h.innerHTML='<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg>'):(s?.querySelectorAll("audio").forEach(w=>{if(w!==d&&!w.paused){w.pause();let $=w.closest(".aicommerce-audio-player")?.querySelector(".aicommerce-audio-btn");$&&($.innerHTML='<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg>');}}),d.play(),h.innerHTML='<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2"><rect x="6" y="4" width="4" height="16"></rect><rect x="14" y="4" width="4" height="16"></rect></svg>');}),d.addEventListener("timeupdate",()=>{if(k&&(k.textContent=N(d.currentTime)),d.duration){let v=d.currentTime/d.duration*100;x.forEach((w,q)=>{q/x.length*100<=v?w.style.backgroundColor=c.closest(".aicommerce-user")?"rgba(255,255,255,1)":"var(--aic-primary)":w.style.backgroundColor=c.closest(".aicommerce-user")?"rgba(255,255,255,0.4)":"rgba(99,102,241,0.3)";});}}),d.addEventListener("ended",()=>{h.innerHTML='<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg>';});let S=c.querySelector(".aicommerce-waveform-bars");S&&S.addEventListener("click",v=>{let w=S.getBoundingClientRect(),$=(v.clientX-w.left)/w.width;d.duration&&(d.currentTime=$*d.duration);});});}async function ee(){if(e.isRecording)a&&a.state!=="inactive"&&a.stop();else try{let t=await navigator.mediaDevices.getUserMedia({audio:!0});u=[],a=new MediaRecorder(t,{mimeType:MediaRecorder.isTypeSupported("audio/webm")?"audio/webm":"audio/mp4"}),a.ondataavailable=i=>{i.data.size>0&&u.push(i.data);},a.onstop=async()=>{if(t.getTracks().forEach(i=>i.stop()),u.length>0){let i=new Blob(u,{type:a?.mimeType||"audio/webm"});await re(i);}e.isRecording=!1,b();},a.start(),e.isRecording=!0,b();}catch(t){console.error("Failed to start recording:",t),e.messages.push({role:"assistant",content:"Unable to access microphone. Please check your permissions."}),b();}}async function re(t){let i=URL.createObjectURL(t),n=Array(40).fill(10),y=0;try{n=await oe(t);let l=new Audio(i);await new Promise(P=>{l.onloadedmetadata=()=>{y=l.duration,P();},l.onerror=()=>P();});}catch(l){console.error("Audio analysis failed",l);}e.messages.push({role:"user",content:"Voice message",audioUrl:i,audioDuration:y,waveformBars:n}),e.isLoading=true,b();try{let l=await r.chatWithAudio(t);return e.messages.push({role:"assistant",content:l.reply,products:l.products}),p.onMessage&&p.onMessage("Voice message",l),l}catch(l){throw e.messages.push({role:"assistant",content:"Sorry, I encountered an error processing your voice message. Please try again."}),l}finally{e.isLoading=false,b();}}function te(t){return /[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]/.test(t)}function N(t){let i=Math.floor(t/60),n=Math.floor(t%60);return `${i}:${n.toString().padStart(2,"0")}`}async function oe(t){try{let i=new(window.AudioContext||window.webkitAudioContext),n=await t.arrayBuffer(),l=(await i.decodeAudioData(n)).getChannelData(0),P=40,g=Math.floor(l.length/P),U=[];for(let c=0;c<P;c++){let d=c*g,h=d+g,x=0;for(let v=d;v<h;v++)l[v]&&(x+=l[v]*l[v]);let k=Math.sqrt(x/g),S=Math.min(100,Math.max(10,k*400));U.push(S);}return U}catch(i){return console.error("Analysis error",i),Array.from({length:40},()=>20+Math.random()*60)}}async function L(t){e.messages.push({role:"user",content:t}),e.isLoading=true,b();try{let i=await r.chat(t);return e.messages.push({role:"assistant",content:i.reply,products:i.products}),p.onMessage&&p.onMessage(t,i),i}catch(i){throw e.messages.push({role:"assistant",content:"Sorry, I encountered an error. Please try again."}),i}finally{e.isLoading=false,b();}}function I(){e.isOpen=true,b(),p.onOpen?.(),setTimeout(()=>{s?.querySelector(".aicommerce-input")?.focus();},100);}function M(){e.isOpen=false,b(),p.onClose?.();}function ie(){e.isOpen?M():I();}function ae(){s&&(s.remove(),s=null),f&&(f.remove(),f=null);}function se(t){if(Object.assign(p,t),t.primaryColor){let i=D(p);f&&(f.textContent=i);}b();}function E(t){let i=document.createElement("div");return i.textContent=t,i.innerHTML}function ne(t,i){let y={USD:"$",EUR:"\u20AC",GBP:"\xA3",MAD:"DH",SAR:"SAR",AED:"AED",JPY:"\xA5",CNY:"\xA5"}[i||"USD"]||i||"$";return `${t.toFixed(2)} ${y}`}return _(),{open:I,close:M,toggle:ie,destroy:ae,sendMessage:L,updateConfig:se}}exports.AICommerceWidget=void 0;var F=B(()=>{A();J();exports.AICommerceWidget={init:j,VERSION:"1.0.0"};typeof window<"u"&&(window.AICommerceWidget=exports.AICommerceWidget);});A();F();var be="1.0.0";typeof window<"u"&&(window.AICommerce=(A(),W(z)).AICommerce,window.AICommerceError=(A(),W(z)).AICommerceError,window.AICommerceWidget=(F(),W(V)).AICommerceWidget);exports.VERSION=be;exports.createWidget=j;return exports;})({});//# sourceMappingURL=index.min.js.map
652
+ `}function Z(){if(!s)return;let o=s.querySelector(".aicommerce-launcher");o&&o.addEventListener("click",()=>L());let i=s.querySelector(".aicommerce-close");i&&i.addEventListener("click",()=>M());let n=s.querySelector(".aicommerce-input"),y=s.querySelector(".aicommerce-send");n&&n.addEventListener("keypress",c=>{c.key==="Enter"&&n.value.trim()&&(A(n.value.trim()),n.value="");}),y&&n&&y.addEventListener("click",()=>{n.value.trim()&&(A(n.value.trim()),n.value="");});let l=s.querySelector(".aicommerce-mic");l&&l.addEventListener("click",()=>ee()),s.querySelectorAll(".aicommerce-product-card").forEach(c=>{c.addEventListener("click",()=>{let d=c.getAttribute("data-product-id"),h=r.messages.flatMap(x=>x.products||[]).find(x=>x.id===d);h&&p.onProductClick&&p.onProductClick(h);});}),s.querySelectorAll(".aicommerce-products").forEach(c=>{let d=false,h=0,x=0;c.addEventListener("mousedown",k=>{d=true,c.style.cursor="grabbing",h=k.pageX-c.offsetLeft,x=c.scrollLeft;}),c.addEventListener("mouseleave",()=>{d=false,c.style.cursor="grab";}),c.addEventListener("mouseup",()=>{d=false,c.style.cursor="grab";}),c.addEventListener("mousemove",k=>{if(!d)return;k.preventDefault();let v=(k.pageX-c.offsetLeft-h)*2;c.scrollLeft=x-v;});}),s.querySelectorAll(".aicommerce-audio-player").forEach(c=>{let d=c.querySelector("audio"),h=c.querySelector(".aicommerce-audio-btn"),x=c.querySelectorAll(".aicommerce-waveform-bar"),k=c.querySelector(".aicommerce-current-time");if(!d||!h)return;h.addEventListener("click",()=>{!d.paused?(d.pause(),h.innerHTML='<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg>'):(s?.querySelectorAll("audio").forEach(w=>{if(w!==d&&!w.paused){w.pause();let E=w.closest(".aicommerce-audio-player")?.querySelector(".aicommerce-audio-btn");E&&(E.innerHTML='<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg>');}}),d.play(),h.innerHTML='<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2"><rect x="6" y="4" width="4" height="16"></rect><rect x="14" y="4" width="4" height="16"></rect></svg>');}),d.addEventListener("timeupdate",()=>{if(k&&(k.textContent=N(d.currentTime)),d.duration){let v=d.currentTime/d.duration*100;x.forEach((w,q)=>{q/x.length*100<=v?w.style.backgroundColor=c.closest(".aicommerce-user")?"rgba(255,255,255,1)":"var(--aic-primary)":w.style.backgroundColor=c.closest(".aicommerce-user")?"rgba(255,255,255,0.4)":"rgba(99,102,241,0.3)";});}}),d.addEventListener("ended",()=>{h.innerHTML='<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg>';});let S=c.querySelector(".aicommerce-waveform-bars");S&&S.addEventListener("click",v=>{let w=S.getBoundingClientRect(),E=(v.clientX-w.left)/w.width;d.duration&&(d.currentTime=E*d.duration);});});}async function ee(){if(r.isRecording)a&&a.state!=="inactive"&&a.stop();else try{let o=await navigator.mediaDevices.getUserMedia({audio:!0});u=[],a=new MediaRecorder(o,{mimeType:MediaRecorder.isTypeSupported("audio/webm")?"audio/webm":"audio/mp4"}),a.ondataavailable=i=>{i.data.size>0&&u.push(i.data);},a.onstop=async()=>{if(o.getTracks().forEach(i=>i.stop()),u.length>0){let i=new Blob(u,{type:a?.mimeType||"audio/webm"});await re(i);}r.isRecording=!1,b();},a.start(),r.isRecording=!0,b();}catch(o){console.error("Failed to start recording:",o),r.messages.push({role:"assistant",content:"Unable to access microphone. Please check your permissions."}),b();}}async function re(o){let i=URL.createObjectURL(o),n=Array(40).fill(10),y=0;try{n=await oe(o);let l=new Audio(i);await new Promise(P=>{l.onloadedmetadata=()=>{y=l.duration,P();},l.onerror=()=>P();});}catch(l){console.error("Audio analysis failed",l);}r.messages.push({role:"user",content:"Voice message",audioUrl:i,audioDuration:y,waveformBars:n}),r.isLoading=true,b();try{let l=await e.chatWithAudio(o);return r.messages.push({role:"assistant",content:l.reply,products:l.products}),p.onMessage&&p.onMessage("Voice message",l),l}catch(l){throw r.messages.push({role:"assistant",content:"Sorry, I encountered an error processing your voice message. Please try again."}),l}finally{r.isLoading=false,b();}}function te(o){return /[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]/.test(o)}function N(o){let i=Math.floor(o/60),n=Math.floor(o%60);return `${i}:${n.toString().padStart(2,"0")}`}async function oe(o){try{let i=new(window.AudioContext||window.webkitAudioContext),n=await o.arrayBuffer(),l=(await i.decodeAudioData(n)).getChannelData(0),P=40,g=Math.floor(l.length/P),U=[];for(let c=0;c<P;c++){let d=c*g,h=d+g,x=0;for(let v=d;v<h;v++)l[v]&&(x+=l[v]*l[v]);let k=Math.sqrt(x/g),S=Math.min(100,Math.max(10,k*400));U.push(S);}return U}catch(i){return console.error("Analysis error",i),Array.from({length:40},()=>20+Math.random()*60)}}async function A(o){r.messages.push({role:"user",content:o}),r.isLoading=true,b();try{let i=await e.chat(o);return r.messages.push({role:"assistant",content:i.reply,products:i.products}),p.onMessage&&p.onMessage(o,i),i}catch(i){throw r.messages.push({role:"assistant",content:"Sorry, I encountered an error. Please try again."}),i}finally{r.isLoading=false,b();}}function L(){r.isOpen=true,b(),p.onOpen?.(),setTimeout(()=>{s?.querySelector(".aicommerce-input")?.focus();},100);}function M(){r.isOpen=false,b(),p.onClose?.();}function ie(){r.isOpen?M():L();}function ae(){s&&(s.remove(),s=null),f&&(f.remove(),f=null);}function se(o){if(Object.assign(p,o),o.primaryColor){let i=D(p);f&&(f.textContent=i);}b();}function R(o){let i=document.createElement("div");return i.textContent=o,i.innerHTML}function ne(o,i){let y={USD:"$",EUR:"\u20AC",GBP:"\xA3",MAD:"DH",SAR:"SAR",AED:"AED",JPY:"\xA5",CNY:"\xA5"}[i||"USD"]||i||"$";return `${o.toFixed(2)} ${y}`}return _(),{open:L,close:M,toggle:ie,destroy:ae,sendMessage:A,updateConfig:se}}exports.AICommerceWidget=void 0;var F=B(()=>{$();V();exports.AICommerceWidget={init:j,VERSION:"1.0.0"};typeof window<"u"&&(window.AICommerceWidget=exports.AICommerceWidget);});$();F();var be="1.0.0";typeof window<"u"&&(window.AICommerce=($(),W(z)).AICommerce,window.AICommerceError=($(),W(z)).AICommerceError,window.AICommerceWidget=(F(),W(X)).AICommerceWidget);exports.VERSION=be;exports.createWidget=j;return exports;})({});//# sourceMappingURL=index.min.js.map
653
653
  //# sourceMappingURL=index.min.js.map
package/dist/index.cjs CHANGED
@@ -99,6 +99,7 @@ var init_client = __esm({
99
99
  throw new Error("AICommerce: apiKey is required");
100
100
  }
101
101
  this.apiKey = config.apiKey;
102
+ this.storeId = config.storeId;
102
103
  this.baseUrl = this.normalizeUrl(config.baseUrl || this.detectBaseUrl());
103
104
  this.timeout = config.timeout || 3e4;
104
105
  }
@@ -107,7 +108,10 @@ var init_client = __esm({
107
108
  */
108
109
  detectBaseUrl() {
109
110
  if (typeof window !== "undefined") {
110
- return window.location.origin;
111
+ const script = document.querySelector("script[data-aicommerce-url]");
112
+ if (script) {
113
+ return script.getAttribute("data-aicommerce-url") || "https://api.aicommerce.dev";
114
+ }
111
115
  }
112
116
  return "https://api.aicommerce.dev";
113
117
  }
@@ -130,7 +134,8 @@ var init_client = __esm({
130
134
  signal: controller.signal,
131
135
  headers: {
132
136
  "Content-Type": "application/json",
133
- "X-API-Key": this.apiKey,
137
+ "x-api-key": this.apiKey,
138
+ ...this.storeId && { "x-store-id": this.storeId },
134
139
  ...this.sessionToken && { "X-Session-Token": this.sessionToken },
135
140
  ...options.headers
136
141
  }
@@ -927,6 +932,7 @@ function createWidget(config) {
927
932
  }
928
933
  const client = new exports.AICommerce({
929
934
  apiKey: config.apiKey,
935
+ storeId: config.storeId,
930
936
  baseUrl: config.baseUrl
931
937
  });
932
938
  const state = {
@@ -968,6 +974,7 @@ function createWidget(config) {
968
974
  state.storeConfig = await fetchStoreConfig();
969
975
  resolvedConfig = {
970
976
  apiKey: config.apiKey,
977
+ storeId: config.storeId,
971
978
  baseUrl: config.baseUrl || detectBaseUrl(),
972
979
  position: config.position || "bottom-right",
973
980
  theme: config.theme || "auto",