@spilki/widget 1.0.35 โ†’ 1.0.36

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,4 +1,4 @@
1
- (function(S){typeof define=="function"&&define.amd?define(S):S()})(function(){"use strict";const S=`
1
+ (function(T){typeof define=="function"&&define.amd?define(T):T()})(function(){"use strict";const T=`
2
2
  <style>
3
3
  :host {
4
4
  all: initial;
@@ -12,6 +12,9 @@
12
12
  :host([data-position="bottom-left"]) {
13
13
  left: 24px;
14
14
  }
15
+ :host([data-dimmed]) button {
16
+ opacity: 0.4;
17
+ }
15
18
  button {
16
19
  all: unset;
17
20
  position: relative;
@@ -25,7 +28,7 @@
25
28
  background: var(--spilki-accent);
26
29
  color: #fff;
27
30
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
28
- transition: transform 0.18s ease, box-shadow 0.18s ease;
31
+ transition: transform 0.18s ease, box-shadow 0.18s ease, opacity 0.2s ease;
29
32
  }
30
33
  button:focus-visible {
31
34
  outline: 2px solid #fff;
@@ -70,8 +73,8 @@
70
73
  </span>
71
74
  <span class="badge" hidden aria-hidden="true">0</span>
72
75
  </button>
73
- `;function F(r){const e=document.createElement("div");e.setAttribute("part","bubble-root"),e.setAttribute("data-position",r.position),e.style.setProperty("--spilki-accent",r.color);const t=e.attachShadow({mode:"open"});t.innerHTML=S;const s=t.querySelector("button"),i=t.querySelector(".badge");return s.addEventListener("click",()=>r.onClick()),{element:e,mount(){document.body.appendChild(e)},destroy(){e.remove()},setOpen(l){s.setAttribute("aria-expanded",String(l)),s.setAttribute("aria-label",l?"Close chat":"Open chat")},setBadge(l){const n=Math.max(0,l),a=s.getAttribute("aria-expanded")==="true";if(n===0){i.toggleAttribute("hidden",!0),i.textContent="0",a||s.setAttribute("aria-label","Open chat");return}i.toggleAttribute("hidden",!1),i.textContent=n>99?"99+":String(n),a||s.setAttribute("aria-label",`Open chat, ${n} unread`)}}}const R="https://api.spilki.app",C={welcome:"Hi! I'm your assistant.",placeholder:"Type a messageโ€ฆ",sendLabel:"Send",typing:"Assistant is typing",thinking:"Assistant is thinking",searching:"Searching",executingTool:"Working on it",offline:"Unable to connect. Please try again later.",title:"Spilki Assistant"},w={apiBase:R,position:"bottom-right",theme:"auto",color:"#6366f1",welcome:C.welcome,persist:!0,sound:!0,i18n:C};function K(r){var t,s,i,o,l,n,a,g;const e={...C,...(t=r.i18n)!=null?t:{}};return{...w,...r,apiBase:(s=r.apiBase)!=null?s:w.apiBase,i18n:e,welcome:(i=r.welcome)!=null?i:e.welcome,position:(o=r.position)!=null?o:w.position,theme:(l=r.theme)!=null?l:w.theme,color:(n=r.color)!=null?n:w.color,persist:(a=r.persist)!=null?a:w.persist,sound:(g=r.sound)!=null?g:w.sound}}function H(r="msg"){return typeof crypto!="undefined"&&crypto.randomUUID?crypto.randomUUID():`${r}-${Math.random().toString(16).slice(2)}`}function z(){var r,e;return(e=(r=window.matchMedia)==null?void 0:r.call(window,"(prefers-color-scheme: dark)").matches)!=null?e:!1}function M(r){return r==="light"||r==="dark"?r:z()?"dark":"light"}function T(r,e=30){return r.slice(-e)}function _(r){if(!r||r.length===0)return;const e=window.location.origin;r.includes(e)||console.warn(`SpilkiWidget: current origin ${e} not in allowedOriginsHint: ${r.join(", ")}`)}const q=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function G(r){const e=new Date(r),t=new Date,s=a=>String(a).padStart(2,"0"),i=`${s(e.getHours())}:${s(e.getMinutes())}`,o=new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime(),l=o-864e5,n=new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime();return n===o?`Today at ${i}`:n===l?`Yesterday at ${i}`:`${q[e.getMonth()]} ${e.getDate()}, ${i}`}const V=':host{--spilki-bg-light: #ffffff;--spilki-bg-dark: #0f172a;--spilki-text-light: #0f172a;--spilki-text-dark: #f8fafc;--spilki-border-light: rgba(15, 23, 42, .1);--spilki-border-dark: rgba(148, 163, 184, .25);--spilki-muted-light: #64748b;--spilki-muted-dark: #94a3b8;--spilki-shadow: 0 10px 40px rgba(15, 23, 42, .2);--spilki-radius: 16px;--spilki-font: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;color:inherit;font-family:var(--spilki-font)}.wrapper{position:relative;width:100%;height:100%;display:flex;flex-direction:column;background:var(--spilki-surface);color:var(--spilki-text);border-radius:var(--spilki-radius);box-shadow:var(--spilki-shadow);border:1px solid var(--spilki-border);overflow:hidden}header{display:flex;align-items:center;justify-content:space-between;padding:.75rem 1rem;background:var(--spilki-surface);border-bottom:1px solid var(--spilki-border)}header h1{font-size:1rem;margin:0;display:flex;align-items:center;gap:.5rem}header button.close{border:none;background:transparent;color:inherit;font-size:1.25rem;cursor:pointer}header button.close:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:2px;border-radius:4px}header .status-dot{width:10px;height:10px;border-radius:999px;background:var(--spilki-accent)}.messages{flex:1;overflow-y:auto;padding:1rem;display:flex;flex-direction:column;gap:.75rem;scrollbar-width:thin;scrollbar-color:rgba(148,163,184,.3) transparent;scroll-behavior:smooth}.message{display:flex;flex-direction:column;gap:.15rem;max-width:85%;width:fit-content;line-height:1.4;word-wrap:break-word;overflow-wrap:anywhere;white-space:pre-wrap}.message.user{align-self:flex-end;align-items:flex-end}.message .bubble{padding:.6rem .8rem;border-radius:1rem;background:#6366f126}.message.user .bubble{background:var(--spilki-accent);color:#fff}.message.bot .bubble{background:#94a3b826}.msg-time{font-size:.7rem;color:var(--spilki-muted);margin-top:2px}.date-separator{display:flex;align-items:center;gap:.5rem;padding:.4rem 0;font-size:.72rem;color:var(--spilki-muted);white-space:nowrap}.date-separator:before,.date-separator:after{content:"";flex:1;height:1px;background:var(--spilki-border)}.scroll-bottom{position:absolute;right:1rem;bottom:88px;width:38px;height:38px;border:none;border-radius:999px;background:var(--spilki-accent);color:#fff;box-shadow:0 8px 20px #0f172a40;cursor:pointer;opacity:0;pointer-events:none;transform:translateY(4px);transition:opacity .18s ease,transform .18s ease;z-index:3}.scroll-bottom.visible{opacity:1;pointer-events:auto;transform:translateY(0)}.scroll-arrow{font-size:.8rem;line-height:1}.scroll-count{position:absolute;top:-5px;right:-5px;min-width:16px;height:16px;border-radius:999px;background:#ef4444;color:#fff;font-size:10px;line-height:16px;text-align:center;padding:0 4px}.suggested-replies{display:flex;flex-wrap:wrap;gap:.4rem;padding:.5rem 1rem;border-top:1px solid var(--spilki-border)}.suggested-chip{border:1px solid var(--spilki-accent);background:transparent;color:var(--spilki-accent);border-radius:999px;padding:.35rem .75rem;font-size:.8rem;font-family:inherit;cursor:pointer;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:background .15s,color .15s}.suggested-chip:hover{background:var(--spilki-accent);color:#fff}.suggested-chip:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:2px}.input-area{padding:.5rem .75rem}.input-wrap{display:flex;align-items:center;border:1px solid var(--spilki-border);border-radius:1.5rem;background:transparent;padding-left:0}.input-area textarea{flex:1;resize:none;min-height:2.4rem;max-height:6rem;border:0;border-radius:0;outline:0;background:transparent;box-shadow:none;-webkit-box-shadow:none;-webkit-appearance:none;appearance:none;padding:.55rem 0 .55rem 1rem;font-family:inherit;font-size:.95rem;color:var(--spilki-text);scrollbar-width:thin;scrollbar-color:rgba(148,163,184,.3) transparent}.input-actions{display:flex;align-items:center;gap:.25rem;padding:.25rem .35rem;flex-shrink:0}.input-actions button{width:32px;height:32px;display:grid;place-items:center;border:none;border-radius:50%;cursor:pointer;padding:0;transition:opacity .15s}.emoji-btn{background:#6366f126;color:var(--spilki-accent)}.emoji-btn:hover{background:#6366f140}.emoji-btn:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:1px}.send-btn{background:var(--spilki-accent);color:#fff}.send-btn:hover{opacity:.85}.send-btn:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:2px}.emoji-picker{position:absolute;right:1rem;bottom:80px;width:240px;max-height:180px;overflow-y:auto;display:none;grid-template-columns:repeat(10,minmax(0,1fr));gap:.25rem;padding:.5rem;background:var(--spilki-surface);border:1px solid var(--spilki-border);border-radius:12px;box-shadow:0 14px 30px #0f172a40;z-index:4}.emoji-option{width:100%;aspect-ratio:1;border:none;border-radius:8px;background:transparent;font-size:1rem;cursor:pointer}.emoji-option:hover,.emoji-option:focus-visible{background:#94a3b833}.typing{font-size:.75rem;color:var(--spilki-muted);padding:0 1rem .75rem}.typing:after{content:"";animation:dots 1.2s steps(4,end) infinite}@keyframes dots{0%{content:""}25%{content:"."}50%{content:".."}75%{content:"..."}}.offline{font-size:.8rem;padding:0 1rem;color:#f97316}:host([data-theme="dark"]){--spilki-surface: var(--spilki-bg-dark);--spilki-text: var(--spilki-text-dark);--spilki-border: var(--spilki-border-dark);--spilki-muted: var(--spilki-muted-dark)}:host([data-theme="dark"]) .messages,:host([data-theme="dark"]) .input-area textarea,:host([data-theme="dark"]) .emoji-picker{scrollbar-color:rgba(255,255,255,.2) transparent}:host([data-theme="light"]){--spilki-surface: var(--spilki-bg-light);--spilki-text: var(--spilki-text-light);--spilki-border: var(--spilki-border-light);--spilki-muted: var(--spilki-muted-light)}:host([data-theme="dark"]) .message .bubble{background:#94a3b81f}:host([data-theme="dark"]) .message.bot .bubble{background:#6366f126}:host([data-theme="dark"]) .input-area textarea{background:transparent}.messages::-webkit-scrollbar,.input-area textarea::-webkit-scrollbar,.emoji-picker::-webkit-scrollbar{width:6px}.messages::-webkit-scrollbar-track,.input-area textarea::-webkit-scrollbar-track,.emoji-picker::-webkit-scrollbar-track{background:transparent}.messages::-webkit-scrollbar-thumb,.input-area textarea::-webkit-scrollbar-thumb,.emoji-picker::-webkit-scrollbar-thumb{background:#94a3b84d;border-radius:999px}.messages::-webkit-scrollbar-thumb:hover,.input-area textarea::-webkit-scrollbar-thumb:hover,.emoji-picker::-webkit-scrollbar-thumb:hover{background:#94a3b880}:host([data-theme="dark"]) .messages::-webkit-scrollbar-thumb,:host([data-theme="dark"]) .input-area textarea::-webkit-scrollbar-thumb,:host([data-theme="dark"]) .emoji-picker::-webkit-scrollbar-thumb{background:#fff3}:host([data-theme="dark"]) .messages::-webkit-scrollbar-thumb:hover,:host([data-theme="dark"]) .input-area textarea::-webkit-scrollbar-thumb:hover,:host([data-theme="dark"]) .emoji-picker::-webkit-scrollbar-thumb:hover{background:#ffffff59}.conversation-separator{display:flex;align-items:center;gap:.5rem;padding:.5rem 0;cursor:pointer;user-select:none;font-size:.7rem;color:var(--spilki-muted);white-space:nowrap}.conversation-separator:before,.conversation-separator:after{content:"";flex:1;height:1px;background:var(--spilki-border)}.conversation-separator:hover{color:var(--spilki-text)}.conversation-separator:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:2px;border-radius:4px}.conversation-history{display:none;flex-direction:column;gap:.5rem}.conversation-history.expanded{display:flex}',B=24*60*60*1e3,Y=2*60*1e3,J=200,X=["๐Ÿ˜€","๐Ÿ˜‚","๐Ÿคฃ","๐Ÿ˜Š","๐Ÿ˜","๐Ÿฅฐ","๐Ÿ˜˜","๐Ÿ˜‰","๐Ÿค”","๐Ÿ˜","๐Ÿ˜Ž","๐Ÿค—","๐Ÿ˜ข","๐Ÿ˜ญ","๐Ÿ˜ก","๐Ÿคฏ","๐Ÿ˜ฑ","๐Ÿฅณ","๐Ÿ˜ด","๐Ÿคฎ","๐Ÿ‘","๐Ÿ‘Ž","๐Ÿ‘‹","๐Ÿค","๐Ÿ™","๐Ÿ’ช","โœŒ๏ธ","๐Ÿคž","๐Ÿ‘","๐Ÿซถ","โค๏ธ","๐Ÿ”ฅ","โญ","๐Ÿ’ฏ","โœ…","โŒ","โšก","๐ŸŽ‰","๐Ÿ’ฐ","๐Ÿ“ฆ","๐Ÿ“…","๐Ÿ“","๐Ÿ“ž","๐Ÿ’ฌ","๐Ÿ””","๐Ÿ”—","๐Ÿ“ธ","๐ŸŽต","โ˜•","๐Ÿ•"];function E(r){return r.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}class Z{constructor(e){this.options=e,this.relativeTimeFormat=new Intl.RelativeTimeFormat(void 0,{numeric:"auto"}),this.absoluteTimeFormat=new Intl.DateTimeFormat(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1}),this.dateSeparatorFormat=new Intl.DateTimeFormat(void 0,{month:"short",day:"numeric",year:"numeric"}),this.renderedMessages=[],this.focusable=[],this.seenIds=new Set,this.lastTimelineMessage=null,this.scrollUnreadCount=0,this.emojiPickerOpen=!1,this.open=!1,this.host=document.createElement("div"),this.host.setAttribute("part","panel-root"),this.host.style.position="fixed",this.host.style.bottom="96px",this.host.style[e.position==="bottom-right"?"right":"left"]="24px",this.host.style.width="360px",this.host.style.maxWidth="calc(100vw - 32px)",this.host.style.height="520px",this.host.style.display="none",this.host.style.zIndex="2147483001",this.shadow=this.host.attachShadow({mode:"open"});const t=E(e.i18n.title),s=E(e.i18n.typing),i=E(e.i18n.offline),o=E(e.i18n.placeholder),l=E(e.i18n.sendLabel);this.shadow.innerHTML=`
74
- <style>${V}</style>
76
+ `;function Y(o){const e=document.createElement("div");e.setAttribute("part","bubble-root"),e.setAttribute("data-position",o.position),e.style.setProperty("--spilki-accent",o.color);const t=e.attachShadow({mode:"open"});t.innerHTML=T;const s=t.querySelector("button"),i=t.querySelector(".badge");return s.addEventListener("click",()=>o.onClick()),{element:e,mount(){document.body.appendChild(e)},destroy(){e.remove()},setOpen(a){s.setAttribute("aria-expanded",String(a)),s.setAttribute("aria-label",a?"Close chat":"Open chat")},setBadge(a){const r=Math.max(0,a),l=s.getAttribute("aria-expanded")==="true";if(r===0){i.toggleAttribute("hidden",!0),i.textContent="0",l||s.setAttribute("aria-label","Open chat");return}i.toggleAttribute("hidden",!1),i.textContent=r>99?"99+":String(r),l||s.setAttribute("aria-label",`Open chat, ${r} unread`)},setDimmed(a){e.toggleAttribute("data-dimmed",a)},setPassthrough(a){e.style.pointerEvents=a?"none":""},setPosition(a){e.setAttribute("data-position",a)}}}const G="https://api.spilki.app",I={welcome:"Hi! I'm your assistant.",placeholder:"Type a messageโ€ฆ",sendLabel:"Send",typing:"Assistant is typing",thinking:"Assistant is thinking",searching:"Searching",executingTool:"Working on it",offline:"Unable to connect. Please try again later.",title:"Spilki Assistant"},y={apiBase:G,position:"bottom-right",theme:"auto",color:"#6366f1",welcome:I.welcome,persist:!0,sound:!0,i18n:I};function V(o){var t,s,i,n,a,r,l,p;const e={...I,...(t=o.i18n)!=null?t:{}};return{...y,...o,apiBase:(s=o.apiBase)!=null?s:y.apiBase,i18n:e,welcome:(i=o.welcome)!=null?i:e.welcome,position:(n=o.position)!=null?n:y.position,theme:(a=o.theme)!=null?a:y.theme,color:(r=o.color)!=null?r:y.color,persist:(l=o.persist)!=null?l:y.persist,sound:(p=o.sound)!=null?p:y.sound}}function J(o="msg"){return typeof crypto!="undefined"&&crypto.randomUUID?crypto.randomUUID():`${o}-${Math.random().toString(16).slice(2)}`}function X(){var o,e;return(e=(o=window.matchMedia)==null?void 0:o.call(window,"(prefers-color-scheme: dark)").matches)!=null?e:!1}function B(o){return o==="light"||o==="dark"?o:X()?"dark":"light"}function A(o,e=30){return o.slice(-e)}function Z(o){if(!o||o.length===0)return;const e=window.location.origin;o.includes(e)||console.warn(`SpilkiWidget: current origin ${e} not in allowedOriginsHint: ${o.join(", ")}`)}const Q=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function ee(o){const e=new Date(o),t=new Date,s=l=>String(l).padStart(2,"0"),i=`${s(e.getHours())}:${s(e.getMinutes())}`,n=new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime(),a=n-864e5,r=new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime();return r===n?`Today at ${i}`:r===a?`Yesterday at ${i}`:`${Q[e.getMonth()]} ${e.getDate()}, ${i}`}const te=':host{--spilki-bg-light: #ffffff;--spilki-bg-dark: #0f172a;--spilki-text-light: #0f172a;--spilki-text-dark: #f8fafc;--spilki-border-light: rgba(15, 23, 42, .1);--spilki-border-dark: rgba(148, 163, 184, .25);--spilki-muted-light: #64748b;--spilki-muted-dark: #94a3b8;--spilki-shadow: 0 10px 40px rgba(15, 23, 42, .2);--spilki-radius: 16px;--spilki-font: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;color:inherit;font-family:var(--spilki-font)}.wrapper{position:relative;width:100%;height:100%;display:flex;flex-direction:column;background:var(--spilki-surface);color:var(--spilki-text);border-radius:var(--spilki-radius);box-shadow:var(--spilki-shadow);border:1px solid var(--spilki-border);overflow:hidden}header{display:flex;align-items:center;justify-content:space-between;padding:.75rem 1rem;background:var(--spilki-surface);border-bottom:1px solid var(--spilki-border)}header h1{font-size:1rem;margin:0;display:flex;align-items:center;gap:.5rem}header button.close{border:none;background:transparent;color:inherit;font-size:1.25rem;cursor:pointer}header button.close:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:2px;border-radius:4px}header .status-dot{width:10px;height:10px;border-radius:999px;background:var(--spilki-accent)}.messages{flex:1;overflow-y:auto;padding:1rem;display:flex;flex-direction:column;gap:.75rem;scrollbar-width:thin;scrollbar-color:rgba(148,163,184,.3) transparent;scroll-behavior:smooth}.message{display:flex;flex-direction:column;gap:.15rem;max-width:85%;width:fit-content;line-height:1.4;word-wrap:break-word;overflow-wrap:anywhere;white-space:pre-wrap}.message.user{align-self:flex-end;align-items:flex-end}.message .bubble{padding:.6rem .8rem;border-radius:1rem;background:#6366f126}.message.user .bubble{background:var(--spilki-accent);color:#fff}.message.bot .bubble{background:#94a3b826}.msg-time{font-size:.7rem;color:var(--spilki-muted);margin-top:2px}.date-separator{display:flex;align-items:center;gap:.5rem;padding:.4rem 0;font-size:.72rem;color:var(--spilki-muted);white-space:nowrap}.date-separator:before,.date-separator:after{content:"";flex:1;height:1px;background:var(--spilki-border)}.scroll-bottom{position:absolute;right:1rem;bottom:88px;width:38px;height:38px;border:none;border-radius:999px;background:var(--spilki-accent);color:#fff;box-shadow:0 8px 20px #0f172a40;cursor:pointer;opacity:0;pointer-events:none;transform:translateY(4px);transition:opacity .18s ease,transform .18s ease;z-index:3}.scroll-bottom.visible{opacity:1;pointer-events:auto;transform:translateY(0)}.scroll-arrow{font-size:.8rem;line-height:1}.scroll-count{position:absolute;top:-5px;right:-5px;min-width:16px;height:16px;border-radius:999px;background:#ef4444;color:#fff;font-size:10px;line-height:16px;text-align:center;padding:0 4px}.suggested-replies{display:flex;flex-wrap:wrap;gap:.4rem;padding:.5rem 1rem;border-top:1px solid var(--spilki-border)}.suggested-chip{border:1px solid var(--spilki-accent);background:transparent;color:var(--spilki-accent);border-radius:999px;padding:.35rem .75rem;font-size:.8rem;font-family:inherit;cursor:pointer;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:background .15s,color .15s}.suggested-chip:hover{background:var(--spilki-accent);color:#fff}.suggested-chip:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:2px}.input-area{padding:.5rem .75rem}.input-wrap{display:flex;align-items:center;border:1px solid var(--spilki-border);border-radius:1.5rem;background:transparent;padding-left:0}.input-area textarea{flex:1;resize:none;min-height:2.4rem;max-height:6rem;border:0;border-radius:0;outline:0;background:transparent;box-shadow:none;-webkit-box-shadow:none;-webkit-appearance:none;appearance:none;padding:.55rem 0 .55rem 1rem;font-family:inherit;font-size:.95rem;color:var(--spilki-text);scrollbar-width:thin;scrollbar-color:rgba(148,163,184,.3) transparent}.input-actions{display:flex;align-items:center;gap:.25rem;padding:.25rem .35rem;flex-shrink:0}.input-actions button{width:32px;height:32px;display:grid;place-items:center;border:none;border-radius:50%;cursor:pointer;padding:0;transition:opacity .15s}.emoji-btn{background:#6366f126;color:var(--spilki-accent)}.emoji-btn:hover{background:#6366f140}.emoji-btn:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:1px}.send-btn{background:var(--spilki-accent);color:#fff}.send-btn:hover{opacity:.85}.send-btn:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:2px}.emoji-picker{position:absolute;right:1rem;bottom:80px;width:240px;max-height:180px;overflow-y:auto;display:none;grid-template-columns:repeat(10,minmax(0,1fr));gap:.25rem;padding:.5rem;background:var(--spilki-surface);border:1px solid var(--spilki-border);border-radius:12px;box-shadow:0 14px 30px #0f172a40;z-index:4}.emoji-option{width:100%;aspect-ratio:1;border:none;border-radius:8px;background:transparent;font-size:1rem;cursor:pointer}.emoji-option:hover,.emoji-option:focus-visible{background:#94a3b833}.typing{font-size:.75rem;color:var(--spilki-muted);padding:0 1rem .75rem}.typing:after{content:"";animation:dots 1.2s steps(4,end) infinite}@keyframes dots{0%{content:""}25%{content:"."}50%{content:".."}75%{content:"..."}}.offline{font-size:.8rem;padding:0 1rem;color:#f97316}:host([data-theme="dark"]){--spilki-surface: var(--spilki-bg-dark);--spilki-text: var(--spilki-text-dark);--spilki-border: var(--spilki-border-dark);--spilki-muted: var(--spilki-muted-dark)}:host([data-theme="dark"]) .messages,:host([data-theme="dark"]) .input-area textarea,:host([data-theme="dark"]) .emoji-picker{scrollbar-color:rgba(255,255,255,.2) transparent}:host([data-theme="light"]){--spilki-surface: var(--spilki-bg-light);--spilki-text: var(--spilki-text-light);--spilki-border: var(--spilki-border-light);--spilki-muted: var(--spilki-muted-light)}:host([data-theme="dark"]) .message .bubble{background:#94a3b81f}:host([data-theme="dark"]) .message.bot .bubble{background:#6366f126}:host([data-theme="dark"]) .input-area textarea{background:transparent}.messages::-webkit-scrollbar,.input-area textarea::-webkit-scrollbar,.emoji-picker::-webkit-scrollbar{width:6px}.messages::-webkit-scrollbar-track,.input-area textarea::-webkit-scrollbar-track,.emoji-picker::-webkit-scrollbar-track{background:transparent}.messages::-webkit-scrollbar-thumb,.input-area textarea::-webkit-scrollbar-thumb,.emoji-picker::-webkit-scrollbar-thumb{background:#94a3b84d;border-radius:999px}.messages::-webkit-scrollbar-thumb:hover,.input-area textarea::-webkit-scrollbar-thumb:hover,.emoji-picker::-webkit-scrollbar-thumb:hover{background:#94a3b880}:host([data-theme="dark"]) .messages::-webkit-scrollbar-thumb,:host([data-theme="dark"]) .input-area textarea::-webkit-scrollbar-thumb,:host([data-theme="dark"]) .emoji-picker::-webkit-scrollbar-thumb{background:#fff3}:host([data-theme="dark"]) .messages::-webkit-scrollbar-thumb:hover,:host([data-theme="dark"]) .input-area textarea::-webkit-scrollbar-thumb:hover,:host([data-theme="dark"]) .emoji-picker::-webkit-scrollbar-thumb:hover{background:#ffffff59}.conversation-separator{display:flex;align-items:center;gap:.5rem;padding:.5rem 0;cursor:pointer;user-select:none;font-size:.7rem;color:var(--spilki-muted);white-space:nowrap}.conversation-separator:before,.conversation-separator:after{content:"";flex:1;height:1px;background:var(--spilki-border)}.conversation-separator:hover{color:var(--spilki-text)}.conversation-separator:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:2px;border-radius:4px}.conversation-history{display:none;flex-direction:column;gap:.5rem}.conversation-history.expanded{display:flex}',L=24*60*60*1e3,se=2*60*1e3,ie=200,oe=["๐Ÿ˜€","๐Ÿ˜‚","๐Ÿคฃ","๐Ÿ˜Š","๐Ÿ˜","๐Ÿฅฐ","๐Ÿ˜˜","๐Ÿ˜‰","๐Ÿค”","๐Ÿ˜","๐Ÿ˜Ž","๐Ÿค—","๐Ÿ˜ข","๐Ÿ˜ญ","๐Ÿ˜ก","๐Ÿคฏ","๐Ÿ˜ฑ","๐Ÿฅณ","๐Ÿ˜ด","๐Ÿคฎ","๐Ÿ‘","๐Ÿ‘Ž","๐Ÿ‘‹","๐Ÿค","๐Ÿ™","๐Ÿ’ช","โœŒ๏ธ","๐Ÿคž","๐Ÿ‘","๐Ÿซถ","โค๏ธ","๐Ÿ”ฅ","โญ","๐Ÿ’ฏ","โœ…","โŒ","โšก","๐ŸŽ‰","๐Ÿ’ฐ","๐Ÿ“ฆ","๐Ÿ“…","๐Ÿ“","๐Ÿ“ž","๐Ÿ’ฌ","๐Ÿ””","๐Ÿ”—","๐Ÿ“ธ","๐ŸŽต","โ˜•","๐Ÿ•"];function x(o){return o.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}class ne{constructor(e){this.options=e,this.relativeTimeFormat=new Intl.RelativeTimeFormat(void 0,{numeric:"auto"}),this.absoluteTimeFormat=new Intl.DateTimeFormat(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1}),this.dateSeparatorFormat=new Intl.DateTimeFormat(void 0,{month:"short",day:"numeric",year:"numeric"}),this.renderedMessages=[],this.focusable=[],this.seenIds=new Set,this.lastTimelineMessage=null,this.scrollUnreadCount=0,this.emojiPickerOpen=!1,this.open=!1,this.host=document.createElement("div"),this.host.setAttribute("part","panel-root"),this.host.style.position="fixed",this.host.style.bottom="96px",this.host.style[e.position==="bottom-right"?"right":"left"]="24px",this.host.style.width="360px",this.host.style.maxWidth="calc(100vw - 32px)",this.host.style.height="520px",this.host.style.display="none",this.host.style.zIndex="2147483001",this.shadow=this.host.attachShadow({mode:"open"});const t=x(e.i18n.title),s=x(e.i18n.typing),i=x(e.i18n.offline),n=x(e.i18n.placeholder),a=x(e.i18n.sendLabel);this.shadow.innerHTML=`
77
+ <style>${te}</style>
75
78
  <div class="wrapper" role="dialog" aria-modal="true" aria-label="${t}">
76
79
  <header>
77
80
  <h1><span class="status-dot" aria-hidden="true"></span>${t}</h1>
@@ -88,7 +91,7 @@
88
91
  <div class="emoji-picker" aria-label="Emoji picker"></div>
89
92
  <div class="input-area">
90
93
  <div class="input-wrap">
91
- <textarea rows="1" placeholder="${o}" aria-label="${o}"></textarea>
94
+ <textarea rows="1" placeholder="${n}" aria-label="${n}"></textarea>
92
95
  <div class="input-actions">
93
96
  <button class="emoji-btn" type="button" aria-label="Insert emoji">
94
97
  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" aria-hidden="true">
@@ -98,7 +101,7 @@
98
101
  <circle cx="15" cy="10" r="1" fill="currentColor"/>
99
102
  </svg>
100
103
  </button>
101
- <button type="button" class="send-btn" aria-label="${l}">
104
+ <button type="button" class="send-btn" aria-label="${a}">
102
105
  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" aria-hidden="true">
103
106
  <path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" fill="currentColor"/>
104
107
  </svg>
@@ -107,8 +110,8 @@
107
110
  </div>
108
111
  </div>
109
112
  </div>
110
- `,this.host.dataset.theme=e.theme,this.host.style.setProperty("--spilki-accent",e.color),this.messagesEl=this.shadow.querySelector(".messages"),this.typingEl=this.shadow.querySelector(".typing"),this.input=this.shadow.querySelector("textarea"),this.offlineEl=this.shadow.querySelector(".offline"),this.sendButton=this.shadow.querySelector(".send-btn"),this.emojiButton=this.shadow.querySelector(".emoji-btn"),this.emojiPickerEl=this.shadow.querySelector(".emoji-picker"),this.scrollBottomButton=this.shadow.querySelector(".scroll-bottom"),this.scrollBottomCountEl=this.shadow.querySelector(".scroll-count"),this.closeButton=this.shadow.querySelector("header .close"),this.suggestedRepliesEl=this.shadow.querySelector(".suggested-replies"),this.handleCloseClick=()=>this.options.onClose(),this.handleSendClick=()=>this.send(),this.handleInputKeydown=n=>{if(n.key==="Enter"&&!n.shiftKey)n.preventDefault(),this.send();else if(n.key==="Escape"){if(this.emojiPickerOpen){n.stopPropagation(),this.closeEmojiPicker();return}this.options.onClose()}},this.handleShadowKeydown=n=>{const a=n;if(a.key==="Escape"){if(this.emojiPickerOpen){a.preventDefault(),this.closeEmojiPicker();return}this.options.onClose()}a.key==="Tab"&&this.trapFocus(a)},this.handleFocusin=()=>this.collectFocusable(),this.handleMessagesScroll=()=>this.updateScrollBottomState(),this.handleScrollBottomClick=()=>{this.scrollToBottom(),this.resetScrollUnreadCount()},this.handleEmojiClick=()=>{this.toggleEmojiPicker()},this.handleDocumentPointerDown=n=>{if(!this.emojiPickerOpen)return;const a=n.composedPath();a.includes(this.emojiPickerEl)||a.includes(this.emojiButton)||this.closeEmojiPicker()},this.closeButton.addEventListener("click",this.handleCloseClick),this.sendButton.addEventListener("click",this.handleSendClick),this.emojiButton.addEventListener("click",this.handleEmojiClick),this.scrollBottomButton.addEventListener("click",this.handleScrollBottomClick),this.input.addEventListener("keydown",this.handleInputKeydown),this.messagesEl.addEventListener("scroll",this.handleMessagesScroll),this.shadow.addEventListener("keydown",this.handleShadowKeydown),this.shadow.addEventListener("focusin",this.handleFocusin),document.addEventListener("pointerdown",this.handleDocumentPointerDown,!0),this.renderEmojiPicker(),this.updateScrollBottomState(),this.collectFocusable()}mount(){document.body.appendChild(this.host)}destroy(){this.closeButton.removeEventListener("click",this.handleCloseClick),this.sendButton.removeEventListener("click",this.handleSendClick),this.emojiButton.removeEventListener("click",this.handleEmojiClick),this.scrollBottomButton.removeEventListener("click",this.handleScrollBottomClick),this.input.removeEventListener("keydown",this.handleInputKeydown),this.messagesEl.removeEventListener("scroll",this.handleMessagesScroll),this.shadow.removeEventListener("keydown",this.handleShadowKeydown),this.shadow.removeEventListener("focusin",this.handleFocusin),document.removeEventListener("pointerdown",this.handleDocumentPointerDown,!0),this.host.remove()}show(){this.open||(this.open=!0,this.host.style.display="block",this.focusInput())}hide(){this.open&&(this.open=!1,this.closeEmojiPicker(),this.host.style.display="none")}focusInput(){queueMicrotask(()=>{this.input.focus()})}updateTheme(e){this.host.dataset.theme=e}updateMessages(e){this.messagesEl.innerHTML="",this.seenIds.clear(),this.renderedMessages.length=0,this.lastTimelineMessage=null,e.forEach(t=>{this.seenIds.add(t.id),this.appendTimelineMessage(t)}),this.updateTimestampVisibility(),this.scrollToBottom(),this.resetScrollUnreadCount(),this.collectFocusable()}renderWithConversations(e,t){this.messagesEl.innerHTML="",this.seenIds.clear(),this.renderedMessages.length=0,this.lastTimelineMessage=null;for(const s of e){s.messages.forEach(n=>this.seenIds.add(n.id));const i=this.createHistoryContainer(s.messages),o=s.messages[s.messages.length-1].ts,l=this.createSeparatorElement(o,i);this.messagesEl.appendChild(i),this.messagesEl.appendChild(l)}t.forEach(s=>{this.seenIds.add(s.id),this.appendTimelineMessage(s)}),this.updateTimestampVisibility(),this.scrollToBottom(),this.resetScrollUnreadCount(),this.collectFocusable()}appendMessage(e){if(this.seenIds.has(e.id))return;const t=this.isScrolledUp();this.seenIds.add(e.id),this.appendTimelineMessage(e),this.updateTimestampVisibility(),t?(this.scrollUnreadCount+=1,this.updateScrollBottomState()):(this.scrollToBottom(),this.resetScrollUnreadCount()),this.collectFocusable()}setSuggestedReplies(e){if(e.length===0){this.hideSuggestedReplies();return}this.suggestedRepliesEl.replaceChildren(),e.forEach(t=>{const s=document.createElement("button");s.className="suggested-chip",s.type="button",s.textContent=t.text,s.addEventListener("click",()=>{var i;this.options.onSend((i=t.payload)!=null?i:t.text),this.hideSuggestedReplies()}),this.suggestedRepliesEl.appendChild(s)}),this.suggestedRepliesEl.toggleAttribute("hidden",!1),this.collectFocusable()}hideSuggestedReplies(){this.suggestedRepliesEl.toggleAttribute("hidden",!0),this.suggestedRepliesEl.replaceChildren(),this.collectFocusable(),this.focusInput()}setAgentActivity(e,t){var i;if(e===null){this.typingEl.toggleAttribute("hidden",!0);return}const s={TYPING:t.typing,THINKING:t.thinking,SEARCHING:t.searching,EXECUTING_TOOL:t.executingTool};this.typingEl.textContent=(i=s[e])!=null?i:t.typing,this.typingEl.toggleAttribute("hidden",!1)}setTyping(e){this.typingEl.toggleAttribute("hidden",!e)}setOffline(e){this.offlineEl.toggleAttribute("hidden",!e)}clearInput(){this.input.value="",this.input.dispatchEvent(new Event("input"))}send(){const e=this.input.value.trim();e&&(this.options.onSend(e),this.clearInput(),this.hideSuggestedReplies())}createMessageElement(e){const t=document.createElement("div");t.className=`message ${e.author}`,t.setAttribute("data-author",e.author),t.setAttribute("role","article"),t.setAttribute("aria-label",e.author==="user"?"You":"Assistant");const s=document.createElement("div");s.className="bubble",s.textContent=e.text;const i=document.createElement("span");return i.className="msg-time",i.textContent=this.formatMessageTimestamp(e.ts),t.appendChild(s),t.appendChild(i),{item:t,timeEl:i}}createSeparatorElement(e,t){const s=document.createElement("div");s.className="conversation-separator",s.setAttribute("role","button"),s.setAttribute("tabindex","0"),s.setAttribute("aria-expanded","false"),s.setAttribute("aria-label","Show previous conversation"),s.textContent=G(e);const i=()=>{const o=t.classList.toggle("expanded");s.setAttribute("aria-expanded",String(o)),s.setAttribute("aria-label",o?"Hide previous conversation":"Show previous conversation")};return s.addEventListener("click",i),s.addEventListener("keydown",o=>{const l=o;(l.key==="Enter"||l.key===" ")&&(l.preventDefault(),i())}),s}createHistoryContainer(e){const t=document.createElement("div");t.className="conversation-history";let s=null;return e.forEach(i=>{this.appendDateSeparatorIfNeeded(s,i,t);const{item:o}=this.createMessageElement(i);t.appendChild(o),s=i}),t}appendTimelineMessage(e){this.appendDateSeparatorIfNeeded(this.lastTimelineMessage,e,this.messagesEl);const t=this.createMessageElement(e);this.messagesEl.appendChild(t.item),this.renderedMessages.push({message:e,timeEl:t.timeEl}),this.lastTimelineMessage=e}appendDateSeparatorIfNeeded(e,t,s){if(!e||this.isSameDay(e.ts,t.ts))return;const i=document.createElement("div");i.className="date-separator",i.textContent=this.formatDateSeparator(t.ts),s.appendChild(i)}updateTimestampVisibility(){for(let e=0;e<this.renderedMessages.length;e+=1){const t=this.renderedMessages[e],s=this.renderedMessages[e+1],i=!!s&&s.message.author===t.message.author&&s.message.ts-t.message.ts<=Y&&s.message.ts>=t.message.ts;t.timeEl.toggleAttribute("hidden",i),t.timeEl.textContent=this.formatMessageTimestamp(t.message.ts)}}formatMessageTimestamp(e){const s=Date.now()-e;if(s<B){const i=Math.max(1,Math.round(s/6e4));if(i<60)return this.relativeTimeFormat.format(-i,"minute");const o=Math.max(1,Math.round(i/60));return this.relativeTimeFormat.format(-o,"hour")}return this.absoluteTimeFormat.format(new Date(e))}formatDateSeparator(e){const t=new Date(e),s=this.startOfDay(Date.now()),i=this.startOfDay(e);return i===s?"Today":i===s-B?"Yesterday":this.dateSeparatorFormat.format(t)}isSameDay(e,t){return this.startOfDay(e)===this.startOfDay(t)}startOfDay(e){const t=new Date(e);return new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()}isScrolledUp(){return this.distanceFromBottom()>J}distanceFromBottom(){return this.messagesEl.scrollHeight-this.messagesEl.scrollTop-this.messagesEl.clientHeight}scrollToFirstUnread(e){if(e<=0){this.scrollToBottom();return}const t=this.renderedMessages.find(i=>i.message.author==="bot"&&i.message.ts>e);if(!t){this.scrollToBottom();return}const s=t.timeEl.closest(".message");s&&s.scrollIntoView({behavior:"smooth",block:"start"})}scrollToBottom(){if(typeof this.messagesEl.scrollTo=="function"){this.messagesEl.scrollTo({top:this.messagesEl.scrollHeight,behavior:"smooth"});return}this.messagesEl.scrollTop=this.messagesEl.scrollHeight}updateScrollBottomState(){const e=this.isScrolledUp();this.scrollBottomButton.classList.toggle("visible",e),this.scrollBottomButton.setAttribute("aria-hidden",String(!e)),this.scrollBottomButton.tabIndex=e?0:-1,e||this.resetScrollUnreadCount();const t=this.scrollUnreadCount>0;this.scrollBottomCountEl.toggleAttribute("hidden",!t),this.scrollBottomCountEl.textContent=t?this.scrollUnreadCount>99?"99+":String(this.scrollUnreadCount):"0"}resetScrollUnreadCount(){this.scrollUnreadCount!==0&&(this.scrollUnreadCount=0,this.updateScrollBottomState())}toggleEmojiPicker(){if(this.emojiPickerOpen){this.closeEmojiPicker();return}this.emojiPickerOpen=!0,this.emojiPickerEl.style.display="grid",this.emojiButton.setAttribute("aria-expanded","true"),this.collectFocusable()}closeEmojiPicker(){this.emojiPickerOpen&&(this.emojiPickerOpen=!1,this.emojiPickerEl.style.display="none",this.emojiButton.setAttribute("aria-expanded","false"),this.collectFocusable())}renderEmojiPicker(){this.emojiPickerEl.replaceChildren(),X.forEach(e=>{const t=document.createElement("button");t.type="button",t.className="emoji-option",t.textContent=e,t.setAttribute("aria-label",`Insert ${e}`),t.addEventListener("click",()=>{this.insertEmojiAtCursor(e),this.closeEmojiPicker()}),this.emojiPickerEl.appendChild(t)})}insertEmojiAtCursor(e){var l,n;const t=this.input.value,s=(l=this.input.selectionStart)!=null?l:t.length,i=(n=this.input.selectionEnd)!=null?n:t.length;this.input.value=`${t.slice(0,s)}${e}${t.slice(i)}`;const o=s+e.length;this.input.setSelectionRange(o,o),this.input.dispatchEvent(new Event("input",{bubbles:!0})),this.input.focus()}collectFocusable(){const e=this.shadow.querySelectorAll('button, textarea, [href], [tabindex]:not([tabindex="-1"])');this.focusable.length=0,e.forEach(t=>{!t.hasAttribute("disabled")&&!t.hasAttribute("hidden")&&t.tabIndex>=0&&this.focusable.push(t)})}trapFocus(e){if(this.focusable.length===0)return;const t=this.focusable[0],s=this.focusable[this.focusable.length-1],i=this.shadow.activeElement;e.shiftKey&&i===t?(e.preventDefault(),s.focus()):!e.shiftKey&&i===s&&(e.preventDefault(),t.focus())}}const v=1500,j=8e3;class Q{constructor(e,t){this.sessionId=null,this.currentKind=null,this.stopped=!1,this.backoff=v,this.connectPromise=null,this.options=e,this.handlers=t}setAccessToken(e){this.options.accessToken=e}setUser(e){const t={};for(const[s,i]of Object.entries(e))if(typeof i=="string"){const o=i.trim();o&&(t[s]=o)}this.user=t,this.sessionId&&this.sendIdentify().catch(s=>this.handlers.onError(s))}async sendIdentify(){const e=`${this.options.apiBase.replace(/\/$/,"")}/widget/identify`,t=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json",...this.options.accessToken?{"X-Authorization":`Bearer ${this.options.accessToken}`}:{}},body:JSON.stringify({sessionId:this.sessionId,user:this.user})});if(!t.ok)throw new Error(`SpilkiWidget: identify failed (${t.status})`)}get kind(){return this.currentKind}get activeSession(){var e,t;return(t=(e=this.sessionId)!=null?e:this.options.sessionId)!=null?t:null}async connect(){if(this.connectPromise)return this.connectPromise;this.connectPromise=this.doConnect();try{return await this.connectPromise}finally{this.connectPromise=null}}async doConnect(){var l,n;this.stopped=!1;const e=`${this.options.apiBase.replace(/\/$/,"")}/widget/session`,t=(n=(l=this.sessionId)!=null?l:this.options.sessionId)!=null?n:void 0,s={organisationId:this.options.org,sessionId:t,userAgent:typeof navigator!="undefined"?navigator.userAgent:"",referrer:typeof document!="undefined"?document.referrer:"",origin:typeof window!="undefined"?window.location.origin:"",...this.user?{user:this.user}:{}},i=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json",...this.options.accessToken?{"X-Authorization":`Bearer ${this.options.accessToken}`}:{}},body:JSON.stringify(s)});if(!i.ok)throw new Error(`SpilkiWidget: connect failed (${i.status})`);const o=await i.json();return this.sessionId=o.sessionId,this.options.sessionId=o.sessionId,this.backoff=v,await this.startTransport(o),o}async send(e,t){var l,n,a;const s={sessionId:(n=(l=this.sessionId)!=null?l:this.options.sessionId)!=null?n:"",text:e,...t?{messageId:t}:{},...(a=this.user)!=null&&a.userId?{userId:this.user.userId}:{}};if(!s.sessionId)throw new Error("SpilkiWidget: missing session id");if(this.currentKind==="ws"&&this.ws&&this.ws.readyState===WebSocket.OPEN){this.ws.send(JSON.stringify({type:"message",payload:s}));return}const i=`${this.options.apiBase.replace(/\/$/,"")}/widget/message`,o=await fetch(i,{method:"POST",headers:{"Content-Type":"application/json","X-Authorization":`Bearer ${this.options.accessToken}`},body:JSON.stringify(s)});if(!o.ok)throw new Error(`SpilkiWidget: send failed (${o.status})`)}stop(e=!0){this.stopped=!0,e&&(this.backoff=v),this.retryTimer&&(clearTimeout(this.retryTimer),this.retryTimer=void 0),this.ws&&(this.wsOnOpen&&this.ws.removeEventListener("open",this.wsOnOpen),this.wsOnMessage&&this.ws.removeEventListener("message",this.wsOnMessage),this.wsOnClose&&this.ws.removeEventListener("close",this.wsOnClose),this.wsOnError&&this.ws.removeEventListener("error",this.wsOnError),this.ws.close(),this.ws=void 0),this.wsOnOpen=this.wsOnMessage=this.wsOnClose=this.wsOnError=void 0,this.sseAbort&&(this.sseAbort.abort(),this.sseAbort=void 0),this.pollTimer&&(clearTimeout(this.pollTimer),this.pollTimer=void 0),this.currentKind=null}async startTransport(e){if(this.stopped)return;const t=[];e.wsUrl&&t.push(()=>this.startWs(e.wsUrl)),e.sseUrl&&t.push(()=>this.startSse(e.sseUrl)),e.pollUrl&&t.push(()=>this.startPoll(e.pollUrl));for(const s of t)try{await s();return}catch(i){this.handlers.onError(i)}throw new Error("SpilkiWidget: unable to establish transport")}startWs(e){return new Promise((t,s)=>{try{const i=new WebSocket(e);this.ws=i,this.wsOnOpen=()=>{if(this.stopped){i.close();return}this.currentKind="ws",this.handlers.onOpen("ws"),this.backoff=v,t()},this.wsOnMessage=o=>this.handleIncoming(o.data),this.wsOnClose=()=>{this.stopped||this.retryFallback("ws")},this.wsOnError=()=>{this.handlers.onError(new Error("SpilkiWidget: websocket error")),i.readyState!==WebSocket.OPEN&&s(new Error("WebSocket failed"))},i.addEventListener("open",this.wsOnOpen),i.addEventListener("message",this.wsOnMessage),i.addEventListener("close",this.wsOnClose),i.addEventListener("error",this.wsOnError)}catch(i){s(i)}})}startSse(e){return new Promise((t,s)=>{const i=new AbortController;this.sseAbort=i,fetch(e,{headers:{Accept:"text/event-stream","X-Authorization":`Bearer ${this.options.accessToken}`},signal:i.signal}).then(o=>{if(!o.ok||!o.body){s(new Error("SSE failed"));return}if(this.stopped){i.abort();return}this.currentKind="sse",this.handlers.onOpen("sse"),this.backoff=v,t();const l=o.body.getReader(),n=new TextDecoder;let a="";const g=()=>{l.read().then(({done:u,value:d})=>{var m;if(u||this.stopped){this.stopped||(this.handlers.onError(new Error("SpilkiWidget: SSE stream ended")),this.retryFallback("sse"));return}a+=n.decode(d,{stream:!0});const h=a.split(`
113
+ `,this.host.dataset.theme=e.theme,this.host.style.setProperty("--spilki-accent",e.color),this.messagesEl=this.shadow.querySelector(".messages"),this.typingEl=this.shadow.querySelector(".typing"),this.input=this.shadow.querySelector("textarea"),this.offlineEl=this.shadow.querySelector(".offline"),this.sendButton=this.shadow.querySelector(".send-btn"),this.emojiButton=this.shadow.querySelector(".emoji-btn"),this.emojiPickerEl=this.shadow.querySelector(".emoji-picker"),this.scrollBottomButton=this.shadow.querySelector(".scroll-bottom"),this.scrollBottomCountEl=this.shadow.querySelector(".scroll-count"),this.closeButton=this.shadow.querySelector("header .close"),this.suggestedRepliesEl=this.shadow.querySelector(".suggested-replies"),this.handleCloseClick=()=>this.options.onClose(),this.handleSendClick=()=>this.send(),this.handleInputKeydown=r=>{if(r.key==="Enter"&&!r.shiftKey)r.preventDefault(),this.send();else if(r.key==="Escape"){if(this.emojiPickerOpen){r.stopPropagation(),this.closeEmojiPicker();return}this.options.onClose()}},this.handleShadowKeydown=r=>{const l=r;if(l.key==="Escape"){if(this.emojiPickerOpen){l.preventDefault(),this.closeEmojiPicker();return}this.options.onClose()}l.key==="Tab"&&this.trapFocus(l)},this.handleFocusin=()=>this.collectFocusable(),this.handleMessagesScroll=()=>this.updateScrollBottomState(),this.handleScrollBottomClick=()=>{this.scrollToBottom(),this.resetScrollUnreadCount()},this.handleEmojiClick=()=>{this.toggleEmojiPicker()},this.handleDocumentPointerDown=r=>{if(!this.emojiPickerOpen)return;const l=r.composedPath();l.includes(this.emojiPickerEl)||l.includes(this.emojiButton)||this.closeEmojiPicker()},this.closeButton.addEventListener("click",this.handleCloseClick),this.sendButton.addEventListener("click",this.handleSendClick),this.emojiButton.addEventListener("click",this.handleEmojiClick),this.scrollBottomButton.addEventListener("click",this.handleScrollBottomClick),this.input.addEventListener("keydown",this.handleInputKeydown),this.messagesEl.addEventListener("scroll",this.handleMessagesScroll),this.shadow.addEventListener("keydown",this.handleShadowKeydown),this.shadow.addEventListener("focusin",this.handleFocusin),document.addEventListener("pointerdown",this.handleDocumentPointerDown,!0),this.renderEmojiPicker(),this.updateScrollBottomState(),this.collectFocusable()}get element(){return this.host}mount(){document.body.appendChild(this.host)}destroy(){this.closeButton.removeEventListener("click",this.handleCloseClick),this.sendButton.removeEventListener("click",this.handleSendClick),this.emojiButton.removeEventListener("click",this.handleEmojiClick),this.scrollBottomButton.removeEventListener("click",this.handleScrollBottomClick),this.input.removeEventListener("keydown",this.handleInputKeydown),this.messagesEl.removeEventListener("scroll",this.handleMessagesScroll),this.shadow.removeEventListener("keydown",this.handleShadowKeydown),this.shadow.removeEventListener("focusin",this.handleFocusin),document.removeEventListener("pointerdown",this.handleDocumentPointerDown,!0),this.host.remove()}show(){this.open||(this.open=!0,this.host.style.display="block",this.focusInput())}hide(){this.open&&(this.open=!1,this.closeEmojiPicker(),this.host.style.display="none")}focusInput(){queueMicrotask(()=>{this.input.focus()})}updateTheme(e){this.host.dataset.theme=e}updateMessages(e){this.messagesEl.innerHTML="",this.seenIds.clear(),this.renderedMessages.length=0,this.lastTimelineMessage=null,e.forEach(t=>{this.seenIds.add(t.id),this.appendTimelineMessage(t)}),this.updateTimestampVisibility(),this.scrollToBottom(),this.resetScrollUnreadCount(),this.collectFocusable()}renderWithConversations(e,t){this.messagesEl.innerHTML="",this.seenIds.clear(),this.renderedMessages.length=0,this.lastTimelineMessage=null;for(const s of e){s.messages.forEach(r=>this.seenIds.add(r.id));const i=this.createHistoryContainer(s.messages),n=s.messages[s.messages.length-1].ts,a=this.createSeparatorElement(n,i);this.messagesEl.appendChild(i),this.messagesEl.appendChild(a)}t.forEach(s=>{this.seenIds.add(s.id),this.appendTimelineMessage(s)}),this.updateTimestampVisibility(),this.scrollToBottom(),this.resetScrollUnreadCount(),this.collectFocusable()}appendMessage(e){if(this.seenIds.has(e.id))return;const t=this.isScrolledUp();this.seenIds.add(e.id),this.appendTimelineMessage(e),this.updateTimestampVisibility(),t?(this.scrollUnreadCount+=1,this.updateScrollBottomState()):(this.scrollToBottom(),this.resetScrollUnreadCount()),this.collectFocusable()}setSuggestedReplies(e){if(e.length===0){this.hideSuggestedReplies();return}this.suggestedRepliesEl.replaceChildren(),e.forEach(t=>{const s=document.createElement("button");s.className="suggested-chip",s.type="button",s.textContent=t.text,s.addEventListener("click",()=>{var i;this.options.onSend((i=t.payload)!=null?i:t.text),this.hideSuggestedReplies()}),this.suggestedRepliesEl.appendChild(s)}),this.suggestedRepliesEl.toggleAttribute("hidden",!1),this.collectFocusable()}hideSuggestedReplies(){this.suggestedRepliesEl.toggleAttribute("hidden",!0),this.suggestedRepliesEl.replaceChildren(),this.collectFocusable(),this.focusInput()}setAgentActivity(e,t){var i;if(e===null){this.typingEl.toggleAttribute("hidden",!0);return}const s={TYPING:t.typing,THINKING:t.thinking,SEARCHING:t.searching,EXECUTING_TOOL:t.executingTool};this.typingEl.textContent=(i=s[e])!=null?i:t.typing,this.typingEl.toggleAttribute("hidden",!1)}setTyping(e){this.typingEl.toggleAttribute("hidden",!e)}setOffline(e){this.offlineEl.toggleAttribute("hidden",!e)}clearInput(){this.input.value="",this.input.dispatchEvent(new Event("input"))}send(){const e=this.input.value.trim();e&&(this.options.onSend(e),this.clearInput(),this.hideSuggestedReplies())}createMessageElement(e){const t=document.createElement("div");t.className=`message ${e.author}`,t.setAttribute("data-author",e.author),t.setAttribute("role","article"),t.setAttribute("aria-label",e.author==="user"?"You":"Assistant");const s=document.createElement("div");s.className="bubble",s.textContent=e.text;const i=document.createElement("span");return i.className="msg-time",i.textContent=this.formatMessageTimestamp(e.ts),t.appendChild(s),t.appendChild(i),{item:t,timeEl:i}}createSeparatorElement(e,t){const s=document.createElement("div");s.className="conversation-separator",s.setAttribute("role","button"),s.setAttribute("tabindex","0"),s.setAttribute("aria-expanded","false"),s.setAttribute("aria-label","Show previous conversation"),s.textContent=ee(e);const i=()=>{const n=t.classList.toggle("expanded");s.setAttribute("aria-expanded",String(n)),s.setAttribute("aria-label",n?"Hide previous conversation":"Show previous conversation")};return s.addEventListener("click",i),s.addEventListener("keydown",n=>{const a=n;(a.key==="Enter"||a.key===" ")&&(a.preventDefault(),i())}),s}createHistoryContainer(e){const t=document.createElement("div");t.className="conversation-history";let s=null;return e.forEach(i=>{this.appendDateSeparatorIfNeeded(s,i,t);const{item:n}=this.createMessageElement(i);t.appendChild(n),s=i}),t}appendTimelineMessage(e){this.appendDateSeparatorIfNeeded(this.lastTimelineMessage,e,this.messagesEl);const t=this.createMessageElement(e);this.messagesEl.appendChild(t.item),this.renderedMessages.push({message:e,timeEl:t.timeEl}),this.lastTimelineMessage=e}appendDateSeparatorIfNeeded(e,t,s){if(!e||this.isSameDay(e.ts,t.ts))return;const i=document.createElement("div");i.className="date-separator",i.textContent=this.formatDateSeparator(t.ts),s.appendChild(i)}updateTimestampVisibility(){for(let e=0;e<this.renderedMessages.length;e+=1){const t=this.renderedMessages[e],s=this.renderedMessages[e+1],i=!!s&&s.message.author===t.message.author&&s.message.ts-t.message.ts<=se&&s.message.ts>=t.message.ts;t.timeEl.toggleAttribute("hidden",i),t.timeEl.textContent=this.formatMessageTimestamp(t.message.ts)}}formatMessageTimestamp(e){const s=Date.now()-e;if(s<L){const i=Math.max(1,Math.round(s/6e4));if(i<60)return this.relativeTimeFormat.format(-i,"minute");const n=Math.max(1,Math.round(i/60));return this.relativeTimeFormat.format(-n,"hour")}return this.absoluteTimeFormat.format(new Date(e))}formatDateSeparator(e){const t=new Date(e),s=this.startOfDay(Date.now()),i=this.startOfDay(e);return i===s?"Today":i===s-L?"Yesterday":this.dateSeparatorFormat.format(t)}isSameDay(e,t){return this.startOfDay(e)===this.startOfDay(t)}startOfDay(e){const t=new Date(e);return new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()}isScrolledUp(){return this.distanceFromBottom()>ie}distanceFromBottom(){return this.messagesEl.scrollHeight-this.messagesEl.scrollTop-this.messagesEl.clientHeight}scrollToFirstUnread(e){if(e<=0){this.scrollToBottom();return}const t=this.renderedMessages.find(i=>i.message.author==="bot"&&i.message.ts>e);if(!t){this.scrollToBottom();return}const s=t.timeEl.closest(".message");s&&s.scrollIntoView({behavior:"smooth",block:"start"})}scrollToBottom(){if(typeof this.messagesEl.scrollTo=="function"){this.messagesEl.scrollTo({top:this.messagesEl.scrollHeight,behavior:"smooth"});return}this.messagesEl.scrollTop=this.messagesEl.scrollHeight}updateScrollBottomState(){const e=this.isScrolledUp();this.scrollBottomButton.classList.toggle("visible",e),this.scrollBottomButton.setAttribute("aria-hidden",String(!e)),this.scrollBottomButton.tabIndex=e?0:-1,e||this.resetScrollUnreadCount();const t=this.scrollUnreadCount>0;this.scrollBottomCountEl.toggleAttribute("hidden",!t),this.scrollBottomCountEl.textContent=t?this.scrollUnreadCount>99?"99+":String(this.scrollUnreadCount):"0"}resetScrollUnreadCount(){this.scrollUnreadCount!==0&&(this.scrollUnreadCount=0,this.updateScrollBottomState())}toggleEmojiPicker(){if(this.emojiPickerOpen){this.closeEmojiPicker();return}this.emojiPickerOpen=!0,this.emojiPickerEl.style.display="grid",this.emojiButton.setAttribute("aria-expanded","true"),this.collectFocusable()}closeEmojiPicker(){this.emojiPickerOpen&&(this.emojiPickerOpen=!1,this.emojiPickerEl.style.display="none",this.emojiButton.setAttribute("aria-expanded","false"),this.collectFocusable())}renderEmojiPicker(){this.emojiPickerEl.replaceChildren(),oe.forEach(e=>{const t=document.createElement("button");t.type="button",t.className="emoji-option",t.textContent=e,t.setAttribute("aria-label",`Insert ${e}`),t.addEventListener("click",()=>{this.insertEmojiAtCursor(e),this.closeEmojiPicker()}),this.emojiPickerEl.appendChild(t)})}insertEmojiAtCursor(e){var a,r;const t=this.input.value,s=(a=this.input.selectionStart)!=null?a:t.length,i=(r=this.input.selectionEnd)!=null?r:t.length;this.input.value=`${t.slice(0,s)}${e}${t.slice(i)}`;const n=s+e.length;this.input.setSelectionRange(n,n),this.input.dispatchEvent(new Event("input",{bubbles:!0})),this.input.focus()}collectFocusable(){const e=this.shadow.querySelectorAll('button, textarea, [href], [tabindex]:not([tabindex="-1"])');this.focusable.length=0,e.forEach(t=>{!t.hasAttribute("disabled")&&!t.hasAttribute("hidden")&&t.tabIndex>=0&&this.focusable.push(t)})}trapFocus(e){if(this.focusable.length===0)return;const t=this.focusable[0],s=this.focusable[this.focusable.length-1],i=this.shadow.activeElement;e.shiftKey&&i===t?(e.preventDefault(),s.focus()):!e.shiftKey&&i===s&&(e.preventDefault(),t.focus())}}function re(o){if(!(o instanceof HTMLElement)||o.hasAttribute("disabled")||o.getAttribute("aria-disabled")==="true"||o.hasAttribute("inert"))return!1;const e=getComputedStyle(o);if(e.display==="none"||e.visibility==="hidden"||e.pointerEvents==="none")return!1;const t=o.tagName;if(t==="BUTTON"||t==="SELECT"||t==="TEXTAREA"||t==="A"&&o.hasAttribute("href")||t==="INPUT"&&o.type!=="hidden"||t==="IFRAME")return!0;const s=o.getAttribute("role");if(s==="button"||s==="link"||o.getAttribute("contenteditable")==="true")return!0;const i=o.getAttribute("tabindex");return i!==null&&i!=="-1"}function D(o,e,t){const s=document.elementsFromPoint(o,e);for(const i of s){if(t.has(i))continue;let n=!1;for(const a of t)if(a.contains(i)){n=!0;break}if(!n&&re(i))return!0}return!1}function j(o,e){const t=[[o.x+o.width/2,o.y+o.height/2],[o.x+o.width/2,o.y+4],[o.x+o.width/2,o.y+o.height-4],[o.x+4,o.y+o.height/2],[o.x+o.width-4,o.y+o.height/2]];for(const[s,i]of t)if(D(s,i,e))return!0;return!1}function U(){var o,e;return(e=(o=window.matchMedia)==null?void 0:o.call(window,"(pointer: coarse)").matches)!=null?e:!1}function ae(o){return o==="bottom-right"?"bottom-left":"bottom-right"}class le{constructor(e){this.rafId=0,this.pendingX=0,this.pendingY=0,this.pendingUpdate=!1,this.passthrough=!1,this.cachedRect=null,this.bubble=e.bubble,this.widgetHosts=e.widgetHosts,this.currentPosition=e.position,this.handlePointerMove=t=>this.onPointerMove(t),this.handlePointerUp=()=>this.exitPassthrough(),this.handleScroll=()=>this.onLayoutChange(),this.handleResize=()=>this.onLayoutChange(),window.addEventListener("scroll",this.handleScroll,{passive:!0}),window.addEventListener("resize",this.handleResize,{passive:!0}),U()?this.scheduleAutoDockCheck():(document.addEventListener("pointermove",this.handlePointerMove,{passive:!0}),document.addEventListener("pointerup",this.handlePointerUp,{passive:!0})),requestAnimationFrame(()=>this.onLayoutChange())}destroy(){document.removeEventListener("pointermove",this.handlePointerMove),document.removeEventListener("pointerup",this.handlePointerUp),window.removeEventListener("scroll",this.handleScroll),window.removeEventListener("resize",this.handleResize),this.rafId&&cancelAnimationFrame(this.rafId),this.exitPassthrough()}onPointerMove(e){this.pendingX=e.clientX,this.pendingY=e.clientY,this.pendingUpdate||(this.pendingUpdate=!0,this.rafId=requestAnimationFrame(()=>this.tick()))}tick(){this.pendingUpdate=!1;const e=this.getBubbleRect(),t=this.pendingX,s=this.pendingY;if(!(t>=e.left&&t<=e.right&&s>=e.top&&s<=e.bottom)){this.passthrough&&this.exitPassthrough();return}const n=this.bubble.element,a=n.style.pointerEvents;n.style.pointerEvents="none";const r=D(t,s,this.widgetHosts);n.style.pointerEvents=a,r&&!this.passthrough?this.enterPassthrough():!r&&this.passthrough&&this.exitPassthrough()}enterPassthrough(){this.passthrough=!0,this.bubble.setDimmed(!0),this.bubble.setPassthrough(!0)}exitPassthrough(){this.passthrough&&(this.passthrough=!1,this.bubble.setDimmed(!1),this.bubble.setPassthrough(!1))}scheduleAutoDockCheck(){requestAnimationFrame(()=>this.autoDockIfNeeded())}autoDockIfNeeded(){this.invalidateRect();const e=this.getBubbleRect(),t=this.bubble.element,s=t.style.pointerEvents;t.style.pointerEvents="none";const i=j(e,this.widgetHosts);if(t.style.pointerEvents=s,!i)return;const n=ae(this.currentPosition);this.currentPosition=n,this.bubble.setPosition(n),this.invalidateRect(),requestAnimationFrame(()=>{const a=this.getBubbleRect(),r=this.bubble.element,l=r.style.pointerEvents;r.style.pointerEvents="none";const p=j(a,this.widgetHosts);r.style.pointerEvents=l,p&&this.bubble.setDimmed(!0)})}onLayoutChange(){this.invalidateRect(),U()&&this.autoDockIfNeeded()}getBubbleRect(){return this.cachedRect||(this.cachedRect=this.bubble.element.getBoundingClientRect()),this.cachedRect}invalidateRect(){this.cachedRect=null}}const w=1500,R=8e3;class ce{constructor(e,t){this.sessionId=null,this.currentKind=null,this.stopped=!1,this.backoff=w,this.connectPromise=null,this.options=e,this.handlers=t}setAccessToken(e){this.options.accessToken=e}setUser(e){const t={};for(const[s,i]of Object.entries(e))if(typeof i=="string"){const n=i.trim();n&&(t[s]=n)}this.user=t,this.sessionId&&this.sendIdentify().catch(s=>this.handlers.onError(s))}async sendIdentify(){const e=`${this.options.apiBase.replace(/\/$/,"")}/widget/identify`,t=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json",...this.options.accessToken?{"X-Authorization":`Bearer ${this.options.accessToken}`}:{}},body:JSON.stringify({sessionId:this.sessionId,user:this.user})});if(!t.ok)throw new Error(`SpilkiWidget: identify failed (${t.status})`)}get kind(){return this.currentKind}get activeSession(){var e,t;return(t=(e=this.sessionId)!=null?e:this.options.sessionId)!=null?t:null}async connect(){if(this.connectPromise)return this.connectPromise;this.connectPromise=this.doConnect();try{return await this.connectPromise}finally{this.connectPromise=null}}async doConnect(){var a,r;this.stopped=!1;const e=`${this.options.apiBase.replace(/\/$/,"")}/widget/session`,t=(r=(a=this.sessionId)!=null?a:this.options.sessionId)!=null?r:void 0,s={organisationId:this.options.org,sessionId:t,userAgent:typeof navigator!="undefined"?navigator.userAgent:"",referrer:typeof document!="undefined"?document.referrer:"",origin:typeof window!="undefined"?window.location.origin:"",...this.user?{user:this.user}:{}},i=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json",...this.options.accessToken?{"X-Authorization":`Bearer ${this.options.accessToken}`}:{}},body:JSON.stringify(s)});if(!i.ok)throw new Error(`SpilkiWidget: connect failed (${i.status})`);const n=await i.json();return this.sessionId=n.sessionId,this.options.sessionId=n.sessionId,this.backoff=w,await this.startTransport(n),n}async send(e,t){var a,r,l;const s={sessionId:(r=(a=this.sessionId)!=null?a:this.options.sessionId)!=null?r:"",text:e,...t?{messageId:t}:{},...(l=this.user)!=null&&l.userId?{userId:this.user.userId}:{}};if(!s.sessionId)throw new Error("SpilkiWidget: missing session id");if(this.currentKind==="ws"&&this.ws&&this.ws.readyState===WebSocket.OPEN){this.ws.send(JSON.stringify({type:"message",payload:s}));return}const i=`${this.options.apiBase.replace(/\/$/,"")}/widget/message`,n=await fetch(i,{method:"POST",headers:{"Content-Type":"application/json","X-Authorization":`Bearer ${this.options.accessToken}`},body:JSON.stringify(s)});if(!n.ok)throw new Error(`SpilkiWidget: send failed (${n.status})`)}stop(e=!0){this.stopped=!0,e&&(this.backoff=w),this.retryTimer&&(clearTimeout(this.retryTimer),this.retryTimer=void 0),this.ws&&(this.wsOnOpen&&this.ws.removeEventListener("open",this.wsOnOpen),this.wsOnMessage&&this.ws.removeEventListener("message",this.wsOnMessage),this.wsOnClose&&this.ws.removeEventListener("close",this.wsOnClose),this.wsOnError&&this.ws.removeEventListener("error",this.wsOnError),this.ws.close(),this.ws=void 0),this.wsOnOpen=this.wsOnMessage=this.wsOnClose=this.wsOnError=void 0,this.sseAbort&&(this.sseAbort.abort(),this.sseAbort=void 0),this.pollTimer&&(clearTimeout(this.pollTimer),this.pollTimer=void 0),this.currentKind=null}async startTransport(e){if(this.stopped)return;const t=[];e.wsUrl&&t.push(()=>this.startWs(e.wsUrl)),e.sseUrl&&t.push(()=>this.startSse(e.sseUrl)),e.pollUrl&&t.push(()=>this.startPoll(e.pollUrl));for(const s of t)try{await s();return}catch(i){this.handlers.onError(i)}throw new Error("SpilkiWidget: unable to establish transport")}startWs(e){return new Promise((t,s)=>{try{const i=new WebSocket(e);this.ws=i,this.wsOnOpen=()=>{if(this.stopped){i.close();return}this.currentKind="ws",this.handlers.onOpen("ws"),this.backoff=w,t()},this.wsOnMessage=n=>this.handleIncoming(n.data),this.wsOnClose=()=>{this.stopped||this.retryFallback("ws")},this.wsOnError=()=>{this.handlers.onError(new Error("SpilkiWidget: websocket error")),i.readyState!==WebSocket.OPEN&&s(new Error("WebSocket failed"))},i.addEventListener("open",this.wsOnOpen),i.addEventListener("message",this.wsOnMessage),i.addEventListener("close",this.wsOnClose),i.addEventListener("error",this.wsOnError)}catch(i){s(i)}})}startSse(e){return new Promise((t,s)=>{const i=new AbortController;this.sseAbort=i,fetch(e,{headers:{Accept:"text/event-stream","X-Authorization":`Bearer ${this.options.accessToken}`},signal:i.signal}).then(n=>{if(!n.ok||!n.body){s(new Error("SSE failed"));return}if(this.stopped){i.abort();return}this.currentKind="sse",this.handlers.onOpen("sse"),this.backoff=w,t();const a=n.body.getReader(),r=new TextDecoder;let l="";const p=()=>{a.read().then(({done:u,value:h})=>{var E;if(u||this.stopped){this.stopped||(this.handlers.onError(new Error("SpilkiWidget: SSE stream ended")),this.retryFallback("sse"));return}l+=r.decode(h,{stream:!0});const d=l.split(`
111
114
 
112
- `);a=(m=h.pop())!=null?m:"";for(const f of h)for(const p of f.split(`
113
- `))p.startsWith("data:")&&this.handleIncoming(p.slice(5).trim());g()}).catch(u=>{i.signal.aborted||(this.handlers.onError(u),this.stopped||this.retryFallback("sse"))})};g()}).catch(o=>{i.signal.aborted||s(o)})})}async startPoll(e){this.currentKind="poll",this.handlers.onOpen("poll"),this.backoff=v;const t=async()=>{if(!this.stopped)try{const s=await fetch(e,{headers:{"X-Authorization":`Bearer ${this.options.accessToken}`}});if(!s.ok)throw new Error(`Poll failed ${s.status}`);const i=await s.json();T(i).forEach(o=>this.handlers.onMessage(o)),this.backoff=v}catch(s){this.handlers.onError(s),this.backoff=Math.min(this.backoff*1.5,j)}finally{this.stopped||(this.pollTimer=window.setTimeout(t,this.backoff))}};await t()}retryFallback(e){this.stopped||(this.stop(!1),this.backoff=Math.min(this.backoff*1.5,j),this.retryTimer=window.setTimeout(()=>{this.stopped||(this.handlers.onError(new Error(`SpilkiWidget: retrying after ${e}`)),this.connect().catch(t=>this.handlers.onError(t)))},this.backoff))}handleIncoming(e){try{const t=JSON.parse(e);if(Array.isArray(t)){t.forEach(s=>this.dispatchIncoming(s));return}this.dispatchIncoming(t)}catch{console.error("SpilkiWidget: failed to parse incoming message",e)}}dispatchIncoming(e){var t;if("type"in e){e.type==="message"?this.handlers.onMessage(e.payload):e.type==="typing"?this.handlers.onTyping(!!((t=e.payload)!=null&&t.active)):e.type==="AGENT_EVENT"&&te(e.payload)&&this.handlers.onAgentEvent(e.payload);return}this.handlers.onMessage(e)}}const ee=new Set(["TYPING","THINKING","SEARCHING","EXECUTING_TOOL"]);function te(r){if(typeof r!="object"||r===null)return!1;const e=r;return ee.has(e.eventType)}const P=30*60*1e3,se=3e4,A=30;class ie{constructor(e,t){this.org=e,this.listeners=new Set,this.activityTimer=null,this.state={isOpen:!1,agentActivity:null,isConnected:!1,messages:[]},this.historyKey=`spilki-history:${e}`,this.sessionKey=`spilki-session:${e}`,this.tokenKey=`spilki-token:${e}`,this.activityKey=`spilki-activity:${e}`,this.lastReadKey=`spilki-lastread:${e}`,this.persist=t.persist,this.state.messages=this.loadMessages()}get snapshot(){return{isOpen:this.state.isOpen,agentActivity:this.state.agentActivity,isConnected:this.state.isConnected,messages:this.state.messages}}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}open(){this.state.isOpen||(this.state.isOpen=!0,this.emit())}close(){this.state.isOpen&&(this.state.isOpen=!1,this.emit())}handleAgentEvent(e){this.activityTimer&&(clearTimeout(this.activityTimer),this.activityTimer=null),this.activityTimer=setTimeout(()=>{this.state.agentActivity=null,this.activityTimer=null,this.emit()},se),this.state.agentActivity!==e&&(this.state.agentActivity=e,this.emit())}clearAgentActivity(){this.resetAgentActivity()&&this.emit()}resetAgentActivity(){return this.activityTimer&&(clearTimeout(this.activityTimer),this.activityTimer=null),this.state.agentActivity===null?!1:(this.state.agentActivity=null,!0)}setConnected(e){this.state.isConnected!==e&&(this.state.isConnected=e,this.emit())}addMessage(e){var s,i;const t={id:(s=e.id)!=null?s:H("msg"),ts:(i=e.ts)!=null?i:Date.now(),author:e.author,text:e.text};return this.state.messages.some(o=>o.id===t.id)?null:(this.state.messages=T([...this.state.messages,t],A),this.resetAgentActivity(),this.persistMessages(),this.touchActivity(),this.emit(),t)}setMessages(e){this.state.messages=T(e,A),this.persistMessages(),this.emit()}clearMessages(){this.state.messages=[],this.persistMessages(),this.emit()}get sessionId(){if(!this.persist)return null;try{return localStorage.getItem(this.sessionKey)}catch(e){return console.error("SpilkiWidget: unable to get item",e),null}}persistSession(e){if(this.persist)try{localStorage.setItem(this.sessionKey,e)}catch(t){console.error("SpilkiWidget: unable to set item",t)}}clearSession(){if(this.persist)try{localStorage.removeItem(this.sessionKey)}catch(e){console.error("SpilkiWidget: unable to remove item",e)}}get accessToken(){if(!this.persist)return null;try{return localStorage.getItem(this.tokenKey)}catch(e){return console.error("SpilkiWidget: unable to get item",e),null}}persistAccessToken(e){if(this.persist)try{localStorage.setItem(this.tokenKey,e)}catch(t){console.error("SpilkiWidget: unable to set item",t)}}clearAccessToken(){if(this.persist)try{localStorage.removeItem(this.tokenKey)}catch(e){console.error("SpilkiWidget: unable to remove item",e)}}get lastActivityTs(){if(!this.persist)return 0;try{const e=localStorage.getItem(this.activityKey);return e?Number(e):0}catch{return 0}}touchActivity(){if(this.persist)try{localStorage.setItem(this.activityKey,String(Date.now()))}catch(e){console.error("SpilkiWidget: unable to set item",e)}}get lastReadTs(){if(!this.persist)return 0;try{const e=localStorage.getItem(this.lastReadKey);return e?Number(e):0}catch{return 0}}markRead(){if(this.persist)try{localStorage.setItem(this.lastReadKey,String(Date.now()))}catch{}}countUnread(){const e=this.lastReadTs;return e===0?0:this.state.messages.filter(t=>t.author==="bot"&&t.ts>e).length}isSessionExpired(){const e=this.lastActivityTs;return e===0?!1:Date.now()-e>=P}getConversationGroups(){const e=this.state.messages;if(e.length===0)return[];const t=[];let s={startTs:e[0].ts,messages:[e[0]]};for(let i=1;i<e.length;i++)e[i].ts-e[i-1].ts>=P?(t.push(s),s={startTs:e[i].ts,messages:[e[i]]}):s.messages.push(e[i]);return t.push(s),t}emit(){this.listeners.forEach(e=>e())}persistMessages(){if(this.persist)try{localStorage.setItem(this.historyKey,JSON.stringify(this.state.messages))}catch(e){console.error("SpilkiWidget: unable to set item",e)}}loadMessages(){if(!this.persist)return[];try{const e=localStorage.getItem(this.historyKey);if(!e)return[];const t=JSON.parse(e);return Array.isArray(t)?T(t,A):[]}catch(e){return console.error("SpilkiWidget: unable to load messages",e),[]}}}function re(r){const e=r.replace(/-/g,"+").replace(/_/g,"/"),t=e.padEnd(e.length+(4-e.length%4)%4,"=");if(typeof atob=="function")return decodeURIComponent(Array.prototype.map.call(atob(t),i=>`%${`00${i.charCodeAt(0).toString(16)}`.slice(-2)}`).join(""));const s=globalThis.Buffer;if(s)return s.from(t,"base64").toString("utf8");throw new Error("SpilkiWidget: no base64 decoder available")}function oe(r){if(!r)return null;const e=r.split(".");if(e.length<2)return null;try{const t=re(e[1]);return JSON.parse(t)}catch(t){return console.error("SpilkiWidget: unable to parse JWT",t),null}}function ne(r){const e=oe(r);if(!(e!=null&&e.exp)||typeof e.exp!="number")return!0;const t=Math.floor(Date.now()/1e3);return e.exp<t+60}const ae={onOpen(){},onClose(){},onMessage(){},onError(){},onTransportChange(){}};async function le(r,e,t){const s=`${r.replace(/\/$/,"")}/widget/install`,i=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Origin:window.location.origin},body:JSON.stringify({token:e,organisationId:t})});if(!i.ok)throw new Error(`SpilkiWidget: install failed (${i.status})`);return(await i.json()).accessToken}async function ce(r,e){const t=`${r.replace(/\/$/,"")}/widget/refresh`,s=await fetch(t,{method:"POST",headers:{"X-Authorization":`Bearer ${e}`,Origin:window.location.origin}});if(!s.ok)throw new Error(`SpilkiWidget: refresh failed (${s.status})`);return(await s.json()).accessToken}function de(r){let e=!1,t=null;const s=[],i=()=>{var n;if(!r)return null;if(t)return t;try{const a=(n=window.AudioContext)!=null?n:window.webkitAudioContext;if(!a)return null;t=new a}catch{return null}return t},o=()=>{e=!0;try{const n=i();(n==null?void 0:n.state)==="suspended"&&n.resume().catch(()=>{})}catch{}},l=n=>{const a=()=>{o(),window.removeEventListener(n,a,!0)};s.push({type:n,listener:a}),window.addEventListener(n,a,{capture:!0,passive:!0})};return l("pointerdown"),l("keydown"),{markUserInteraction:o,play(){if(!r||!e)return;const n=i();if(!n||n.state!=="running")return;const a=n.createGain();a.gain.value=.15,a.connect(n.destination);const g=(d,h,m)=>{const f=n.createOscillator(),p=n.createGain();f.type="sine",f.frequency.setValueAtTime(d,h),p.gain.setValueAtTime(1e-4,h),p.gain.exponentialRampToValueAtTime(1,h+.012),p.gain.exponentialRampToValueAtTime(1e-4,h+m),f.connect(p),p.connect(a),f.start(h),f.stop(h+m+.02)},u=n.currentTime;g(880,u,.08),g(1175,u+.09,.08)},destroy(){s.forEach(({type:n,listener:a})=>{window.removeEventListener(n,a,!0)}),s.length=0,t&&t.close().catch(()=>{}),t=null}}}function D(r){var U,$,N,W;if(!r.org)throw new Error("SpilkiWidget: org is required");const e=K(r);_(e.allowedOriginsHint);const t={...ae,...(U=e.hooks)!=null?U:{}},s=new ie(e.org,{persist:e.persist}),i=de(e.sound);let o=($=s.accessToken)!=null?$:void 0,l=null;const n=()=>{u.setBadge(s.countUnread())},a=()=>{s.markRead(),u.setBadge(0)},g=async()=>l||(l=(async()=>{try{if(o&&ne(o))try{o=await ce(e.apiBase,o),s.persistAccessToken(o),h.setAccessToken(o);return}catch{o=void 0,s.clearAccessToken()}if(!o){if(!r.installationToken)throw new Error("SpilkiWidget: missing installationToken");if(!r.org)throw new Error("SpilkiWidget: missing org");o=await le(e.apiBase,r.installationToken,r.org),s.persistAccessToken(o),h.setAccessToken(o)}}finally{l=null}})(),l),u=F({color:e.color,position:(N=e.position)!=null?N:"bottom-right",onClick:()=>{s.snapshot.isOpen?(s.close(),t.onClose()):(i.markUserInteraction(),s.open(),a(),t.onOpen())}}),d=new Z({color:e.color,theme:M(e.theme),position:(W=e.position)!=null?W:"bottom-right",i18n:e.i18n,onClose:()=>{s.close(),t.onClose()},onSend:c=>{const k=s.addMessage({author:"user",text:c});k&&(d.appendMessage(k),g().then(()=>h.send(c,k.id)).catch(b=>{t.onError(b),s.setConnected(!1),d.setOffline(!0)}))}}),h=new Q({apiBase:e.apiBase,accessToken:o,org:e.org,sessionId:s.sessionId},{onOpen(c){O.transport=c,t.onTransportChange(c),s.setConnected(!0),d.setOffline(!1)},onMessage(c){const b=c.suggestedReplies,y=s.addMessage(c);y&&(d.appendMessage(y),y.author==="bot"&&b&&b.length>0&&d.setSuggestedReplies(b),!s.snapshot.isOpen&&y.author==="bot"&&(n(),i.play()),t.onMessage(y))},onTyping(){s.handleAgentEvent("TYPING")},onAgentEvent(c){s.handleAgentEvent(c.eventType)},onError(c){t.onError(c),s.setConnected(!1),s.snapshot.isOpen&&d.setOffline(!0)}});u.mount(),d.mount();const m=s.snapshot.messages,f=s.isSessionExpired(),p=s.getConversationGroups();if(m.length===0&&e.welcome){const c={id:"welcome",author:"bot",text:e.welcome,ts:Date.now()};s.addMessage(c),d.appendMessage(c)}else f&&m.length>0?d.renderWithConversations(p,[]):p.length>1?d.renderWithConversations(p.slice(0,-1),p[p.length-1].messages):d.updateMessages(m);let I=!1;const he=s.subscribe(()=>{const c=s.snapshot;if(u.setOpen(c.isOpen),d.setAgentActivity(c.agentActivity,e.i18n),d.setOffline(!c.isConnected),d.updateTheme(M(e.theme)),c.isOpen){if(!I){const k=s.countUnread()>0,b=s.lastReadTs;a(),k&&d.scrollToFirstUnread(b)}I=!0,d.show()}else I=!1,d.hide()}),pe=m.length===0||f;n(),g().then(()=>h.connect().then(c=>{var b,y;e.persist&&s.persistSession(c.sessionId),s.setConnected(!0),t.onTransportChange((b=h.kind)!=null?b:"ws");const k=(y=c.suggestedReplies)!=null?y:[];k.length>0&&pe&&d.setSuggestedReplies(k)})).catch(c=>{t.onError(c),s.setConnected(!1),d.setOffline(!0)});const O={transport:null,open(){i.markUserInteraction(),s.open(),a(),t.onOpen()},close(){s.close(),t.onClose()},identify(c){h.setUser(c)},destroy(){he(),h.stop(),i.destroy(),u.destroy(),d.destroy(),x===O&&(x=null)}};return O}function L(){var s,i;if(typeof document=="undefined")return;const r=document.currentScript;if(!r)return;const e=r.dataset;if(e.autoinit==="false")return;const t=e.org;if(!t){console.error("SpilkiWidget: data-org and is required for auto init");return}x=D({org:t,installationToken:e.installationToken,apiBase:e.apiBase,position:(s=e.position)!=null?s:void 0,theme:(i=e.theme)!=null?i:void 0})}let x=null;typeof window!="undefined"&&(window.SpilkiWidget=window.SpilkiWidget||{},window.SpilkiWidget.init=r=>(x=D(r),x),window.SpilkiWidget.identify=r=>{x?x.identify(r):console.warn("SpilkiWidget: call init() before identify()")}),L(),L()});
115
+ `);l=(E=d.pop())!=null?E:"";for(const f of d)for(const g of f.split(`
116
+ `))g.startsWith("data:")&&this.handleIncoming(g.slice(5).trim());p()}).catch(u=>{i.signal.aborted||(this.handlers.onError(u),this.stopped||this.retryFallback("sse"))})};p()}).catch(n=>{i.signal.aborted||s(n)})})}async startPoll(e){this.currentKind="poll",this.handlers.onOpen("poll"),this.backoff=w;const t=async()=>{if(!this.stopped)try{const s=await fetch(e,{headers:{"X-Authorization":`Bearer ${this.options.accessToken}`}});if(!s.ok)throw new Error(`Poll failed ${s.status}`);const i=await s.json();A(i).forEach(n=>this.handlers.onMessage(n)),this.backoff=w}catch(s){this.handlers.onError(s),this.backoff=Math.min(this.backoff*1.5,R)}finally{this.stopped||(this.pollTimer=window.setTimeout(t,this.backoff))}};await t()}retryFallback(e){this.stopped||(this.stop(!1),this.backoff=Math.min(this.backoff*1.5,R),this.retryTimer=window.setTimeout(()=>{this.stopped||(this.handlers.onError(new Error(`SpilkiWidget: retrying after ${e}`)),this.connect().catch(t=>this.handlers.onError(t)))},this.backoff))}handleIncoming(e){try{const t=JSON.parse(e);if(Array.isArray(t)){t.forEach(s=>this.dispatchIncoming(s));return}this.dispatchIncoming(t)}catch{console.error("SpilkiWidget: failed to parse incoming message",e)}}dispatchIncoming(e){var t;if("type"in e){e.type==="message"?this.handlers.onMessage(e.payload):e.type==="typing"?this.handlers.onTyping(!!((t=e.payload)!=null&&t.active)):e.type==="AGENT_EVENT"&&de(e.payload)&&this.handlers.onAgentEvent(e.payload);return}this.handlers.onMessage(e)}}const he=new Set(["TYPING","THINKING","SEARCHING","EXECUTING_TOOL"]);function de(o){if(typeof o!="object"||o===null)return!1;const e=o;return he.has(e.eventType)}const $=30*60*1e3,ue=3e4,O=30;class pe{constructor(e,t){this.org=e,this.listeners=new Set,this.activityTimer=null,this.state={isOpen:!1,agentActivity:null,isConnected:!1,messages:[]},this.historyKey=`spilki-history:${e}`,this.sessionKey=`spilki-session:${e}`,this.tokenKey=`spilki-token:${e}`,this.activityKey=`spilki-activity:${e}`,this.lastReadKey=`spilki-lastread:${e}`,this.persist=t.persist,this.state.messages=this.loadMessages()}get snapshot(){return{isOpen:this.state.isOpen,agentActivity:this.state.agentActivity,isConnected:this.state.isConnected,messages:this.state.messages}}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}open(){this.state.isOpen||(this.state.isOpen=!0,this.emit())}close(){this.state.isOpen&&(this.state.isOpen=!1,this.emit())}handleAgentEvent(e){this.activityTimer&&(clearTimeout(this.activityTimer),this.activityTimer=null),this.activityTimer=setTimeout(()=>{this.state.agentActivity=null,this.activityTimer=null,this.emit()},ue),this.state.agentActivity!==e&&(this.state.agentActivity=e,this.emit())}clearAgentActivity(){this.resetAgentActivity()&&this.emit()}resetAgentActivity(){return this.activityTimer&&(clearTimeout(this.activityTimer),this.activityTimer=null),this.state.agentActivity===null?!1:(this.state.agentActivity=null,!0)}setConnected(e){this.state.isConnected!==e&&(this.state.isConnected=e,this.emit())}addMessage(e){var s,i;const t={id:(s=e.id)!=null?s:J("msg"),ts:(i=e.ts)!=null?i:Date.now(),author:e.author,text:e.text};return this.state.messages.some(n=>n.id===t.id)?null:(this.state.messages=A([...this.state.messages,t],O),this.resetAgentActivity(),this.persistMessages(),this.touchActivity(),this.emit(),t)}setMessages(e){this.state.messages=A(e,O),this.persistMessages(),this.emit()}clearMessages(){this.state.messages=[],this.persistMessages(),this.emit()}get sessionId(){if(!this.persist)return null;try{return localStorage.getItem(this.sessionKey)}catch(e){return console.error("SpilkiWidget: unable to get item",e),null}}persistSession(e){if(this.persist)try{localStorage.setItem(this.sessionKey,e)}catch(t){console.error("SpilkiWidget: unable to set item",t)}}clearSession(){if(this.persist)try{localStorage.removeItem(this.sessionKey)}catch(e){console.error("SpilkiWidget: unable to remove item",e)}}get accessToken(){if(!this.persist)return null;try{return localStorage.getItem(this.tokenKey)}catch(e){return console.error("SpilkiWidget: unable to get item",e),null}}persistAccessToken(e){if(this.persist)try{localStorage.setItem(this.tokenKey,e)}catch(t){console.error("SpilkiWidget: unable to set item",t)}}clearAccessToken(){if(this.persist)try{localStorage.removeItem(this.tokenKey)}catch(e){console.error("SpilkiWidget: unable to remove item",e)}}get lastActivityTs(){if(!this.persist)return 0;try{const e=localStorage.getItem(this.activityKey);return e?Number(e):0}catch{return 0}}touchActivity(){if(this.persist)try{localStorage.setItem(this.activityKey,String(Date.now()))}catch(e){console.error("SpilkiWidget: unable to set item",e)}}get lastReadTs(){if(!this.persist)return 0;try{const e=localStorage.getItem(this.lastReadKey);return e?Number(e):0}catch{return 0}}markRead(){if(this.persist)try{localStorage.setItem(this.lastReadKey,String(Date.now()))}catch{}}countUnread(){const e=this.lastReadTs;return e===0?0:this.state.messages.filter(t=>t.author==="bot"&&t.ts>e).length}isSessionExpired(){const e=this.lastActivityTs;return e===0?!1:Date.now()-e>=$}getConversationGroups(){const e=this.state.messages;if(e.length===0)return[];const t=[];let s={startTs:e[0].ts,messages:[e[0]]};for(let i=1;i<e.length;i++)e[i].ts-e[i-1].ts>=$?(t.push(s),s={startTs:e[i].ts,messages:[e[i]]}):s.messages.push(e[i]);return t.push(s),t}emit(){this.listeners.forEach(e=>e())}persistMessages(){if(this.persist)try{localStorage.setItem(this.historyKey,JSON.stringify(this.state.messages))}catch(e){console.error("SpilkiWidget: unable to set item",e)}}loadMessages(){if(!this.persist)return[];try{const e=localStorage.getItem(this.historyKey);if(!e)return[];const t=JSON.parse(e);return Array.isArray(t)?A(t,O):[]}catch(e){return console.error("SpilkiWidget: unable to load messages",e),[]}}}function ge(o){const e=o.replace(/-/g,"+").replace(/_/g,"/"),t=e.padEnd(e.length+(4-e.length%4)%4,"=");if(typeof atob=="function")return decodeURIComponent(Array.prototype.map.call(atob(t),i=>`%${`00${i.charCodeAt(0).toString(16)}`.slice(-2)}`).join(""));const s=globalThis.Buffer;if(s)return s.from(t,"base64").toString("utf8");throw new Error("SpilkiWidget: no base64 decoder available")}function me(o){if(!o)return null;const e=o.split(".");if(e.length<2)return null;try{const t=ge(e[1]);return JSON.parse(t)}catch(t){return console.error("SpilkiWidget: unable to parse JWT",t),null}}function fe(o){const e=me(o);if(!(e!=null&&e.exp)||typeof e.exp!="number")return!0;const t=Math.floor(Date.now()/1e3);return e.exp<t+60}const be={onOpen(){},onClose(){},onMessage(){},onError(){},onTransportChange(){}};async function ke(o,e,t){const s=`${o.replace(/\/$/,"")}/widget/install`,i=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Origin:window.location.origin},body:JSON.stringify({token:e,organisationId:t})});if(!i.ok)throw new Error(`SpilkiWidget: install failed (${i.status})`);return(await i.json()).accessToken}async function ye(o,e){const t=`${o.replace(/\/$/,"")}/widget/refresh`,s=await fetch(t,{method:"POST",headers:{"X-Authorization":`Bearer ${e}`,Origin:window.location.origin}});if(!s.ok)throw new Error(`SpilkiWidget: refresh failed (${s.status})`);return(await s.json()).accessToken}function we(o){let e=!1,t=null;const s=[],i=()=>{var r;if(!o)return null;if(t)return t;try{const l=(r=window.AudioContext)!=null?r:window.webkitAudioContext;if(!l)return null;t=new l}catch{return null}return t},n=()=>{e=!0;try{const r=i();(r==null?void 0:r.state)==="suspended"&&r.resume().catch(()=>{})}catch{}},a=r=>{const l=()=>{n(),window.removeEventListener(r,l,!0)};s.push({type:r,listener:l}),window.addEventListener(r,l,{capture:!0,passive:!0})};return a("pointerdown"),a("keydown"),{markUserInteraction:n,play(){if(!o||!e)return;const r=i();if(!r||r.state!=="running")return;const l=r.createGain();l.gain.value=.15,l.connect(r.destination);const p=(h,d,E)=>{const f=r.createOscillator(),g=r.createGain();f.type="sine",f.frequency.setValueAtTime(h,d),g.gain.setValueAtTime(1e-4,d),g.gain.exponentialRampToValueAtTime(1,d+.012),g.gain.exponentialRampToValueAtTime(1e-4,d+E),f.connect(g),g.connect(l),f.start(d),f.stop(d+E+.02)},u=r.currentTime;p(880,u,.08),p(1175,u+.09,.08)},destroy(){s.forEach(({type:r,listener:l})=>{window.removeEventListener(r,l,!0)}),s.length=0,t&&t.close().catch(()=>{}),t=null}}}function N(o){var H,K,z,_,q;if(!o.org)throw new Error("SpilkiWidget: org is required");const e=V(o);Z(e.allowedOriginsHint);const t={...be,...(H=e.hooks)!=null?H:{}},s=new pe(e.org,{persist:e.persist}),i=we(e.sound);let n=(K=s.accessToken)!=null?K:void 0,a=null;const r=()=>{u.setBadge(s.countUnread())},l=()=>{s.markRead(),u.setBadge(0)},p=async()=>a||(a=(async()=>{try{if(n&&fe(n))try{n=await ye(e.apiBase,n),s.persistAccessToken(n),d.setAccessToken(n);return}catch{n=void 0,s.clearAccessToken()}if(!n){if(!o.installationToken)throw new Error("SpilkiWidget: missing installationToken");if(!o.org)throw new Error("SpilkiWidget: missing org");n=await ke(e.apiBase,o.installationToken,o.org),s.persistAccessToken(n),d.setAccessToken(n)}}finally{a=null}})(),a),u=Y({color:e.color,position:(z=e.position)!=null?z:"bottom-right",onClick:()=>{s.snapshot.isOpen?(s.close(),t.onClose()):(i.markUserInteraction(),s.open(),l(),t.onOpen())}}),h=new ne({color:e.color,theme:B(e.theme),position:(_=e.position)!=null?_:"bottom-right",i18n:e.i18n,onClose:()=>{s.close(),t.onClose()},onSend:c=>{const b=s.addMessage({author:"user",text:c});b&&(h.appendMessage(b),p().then(()=>d.send(c,b.id)).catch(m=>{t.onError(m),s.setConnected(!1),h.setOffline(!0)}))}}),d=new ce({apiBase:e.apiBase,accessToken:n,org:e.org,sessionId:s.sessionId},{onOpen(c){P.transport=c,t.onTransportChange(c),s.setConnected(!0),h.setOffline(!1)},onMessage(c){const m=c.suggestedReplies,k=s.addMessage(c);k&&(h.appendMessage(k),k.author==="bot"&&m&&m.length>0&&h.setSuggestedReplies(m),!s.snapshot.isOpen&&k.author==="bot"&&(r(),i.play()),t.onMessage(k))},onTyping(){s.handleAgentEvent("TYPING")},onAgentEvent(c){s.handleAgentEvent(c.eventType)},onError(c){t.onError(c),s.setConnected(!1),s.snapshot.isOpen&&h.setOffline(!0)}});u.mount(),h.mount();const E=(q=e.position)!=null?q:"bottom-right",f=new Set([u.element,h.element]),g=new le({bubble:u,widgetHosts:f,position:E}),C=s.snapshot.messages,W=s.isSessionExpired(),S=s.getConversationGroups();if(C.length===0&&e.welcome){const c={id:"welcome",author:"bot",text:e.welcome,ts:Date.now()};s.addMessage(c),h.appendMessage(c)}else W&&C.length>0?h.renderWithConversations(S,[]):S.length>1?h.renderWithConversations(S.slice(0,-1),S[S.length-1].messages):h.updateMessages(C);let M=!1;const ve=s.subscribe(()=>{const c=s.snapshot;if(u.setOpen(c.isOpen),h.setAgentActivity(c.agentActivity,e.i18n),h.setOffline(!c.isConnected),h.updateTheme(B(e.theme)),c.isOpen){if(!M){const b=s.countUnread()>0,m=s.lastReadTs;l(),b&&h.scrollToFirstUnread(m)}M=!0,h.show()}else M=!1,h.hide()}),Ee=C.length===0||W;r(),p().then(()=>d.connect().then(c=>{var m,k;e.persist&&s.persistSession(c.sessionId),s.setConnected(!0),t.onTransportChange((m=d.kind)!=null?m:"ws");const b=(k=c.suggestedReplies)!=null?k:[];b.length>0&&Ee&&h.setSuggestedReplies(b)})).catch(c=>{t.onError(c),s.setConnected(!1),h.setOffline(!0)});const P={transport:null,open(){i.markUserInteraction(),s.open(),l(),t.onOpen()},close(){s.close(),t.onClose()},identify(c){d.setUser(c)},destroy(){ve(),g.destroy(),d.stop(),i.destroy(),u.destroy(),h.destroy(),v===P&&(v=null)}};return P}function F(){var s,i;if(typeof document=="undefined")return;const o=document.currentScript;if(!o)return;const e=o.dataset;if(e.autoinit==="false")return;const t=e.org;if(!t){console.error("SpilkiWidget: data-org and is required for auto init");return}v=N({org:t,installationToken:e.installationToken,apiBase:e.apiBase,position:(s=e.position)!=null?s:void 0,theme:(i=e.theme)!=null?i:void 0})}let v=null;typeof window!="undefined"&&(window.SpilkiWidget=window.SpilkiWidget||{},window.SpilkiWidget.init=o=>(v=N(o),v),window.SpilkiWidget.identify=o=>{v?v.identify(o):console.warn("SpilkiWidget: call init() before identify()")}),F(),F()});
114
117
  //# sourceMappingURL=bootstrap.umd.js.map