@spilki/widget 1.0.31 → 1.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/widget.es.js CHANGED
@@ -1,4 +1,4 @@
1
- const F = `
1
+ const W = `
2
2
  <style>
3
3
  :host {
4
4
  all: initial;
@@ -71,13 +71,13 @@ const F = `
71
71
  <span class="badge" hidden aria-hidden="true">0</span>
72
72
  </button>
73
73
  `;
74
- function R(r) {
74
+ function F(o) {
75
75
  const e = document.createElement("div");
76
- e.setAttribute("part", "bubble-root"), e.setAttribute("data-position", r.position), e.style.setProperty("--spilki-accent", r.color);
76
+ e.setAttribute("part", "bubble-root"), e.setAttribute("data-position", o.position), e.style.setProperty("--spilki-accent", o.color);
77
77
  const t = e.attachShadow({ mode: "open" });
78
- t.innerHTML = F;
78
+ t.innerHTML = W;
79
79
  const s = t.querySelector("button"), i = t.querySelector(".badge");
80
- return s.addEventListener("click", () => r.onClick()), {
80
+ return s.addEventListener("click", () => o.onClick()), {
81
81
  element: e,
82
82
  mount() {
83
83
  document.body.appendChild(e);
@@ -98,65 +98,68 @@ function R(r) {
98
98
  }
99
99
  };
100
100
  }
101
- const K = "https://api.spilki.app", T = {
101
+ const R = "https://api.spilki.app", C = {
102
102
  welcome: "Hi! I'm your assistant.",
103
103
  placeholder: "Type a message…",
104
104
  sendLabel: "Send",
105
- typing: "Assistant is typing",
105
+ typing: "Assistant is typing",
106
+ thinking: "Assistant is thinking",
107
+ searching: "Searching",
108
+ executingTool: "Working on it",
106
109
  offline: "Unable to connect. Please try again later.",
107
110
  title: "Spilki Assistant"
108
- }, k = {
109
- apiBase: K,
111
+ }, w = {
112
+ apiBase: R,
110
113
  position: "bottom-right",
111
114
  theme: "auto",
112
115
  color: "#6366f1",
113
- welcome: T.welcome,
116
+ welcome: C.welcome,
114
117
  persist: !0,
115
118
  sound: !0,
116
- i18n: T
119
+ i18n: C
117
120
  };
118
- function N(r) {
119
- var t, s, i, o, a, n, l, g;
120
- const e = { ...T, ...(t = r.i18n) != null ? t : {} };
121
+ function K(o) {
122
+ var t, s, i, r, a, n, l, g;
123
+ const e = { ...C, ...(t = o.i18n) != null ? t : {} };
121
124
  return {
122
- ...k,
123
- ...r,
124
- apiBase: (s = r.apiBase) != null ? s : k.apiBase,
125
+ ...w,
126
+ ...o,
127
+ apiBase: (s = o.apiBase) != null ? s : w.apiBase,
125
128
  i18n: e,
126
- welcome: (i = r.welcome) != null ? i : e.welcome,
127
- position: (o = r.position) != null ? o : k.position,
128
- theme: (a = r.theme) != null ? a : k.theme,
129
- color: (n = r.color) != null ? n : k.color,
130
- persist: (l = r.persist) != null ? l : k.persist,
131
- sound: (g = r.sound) != null ? g : k.sound
129
+ welcome: (i = o.welcome) != null ? i : e.welcome,
130
+ position: (r = o.position) != null ? r : w.position,
131
+ theme: (a = o.theme) != null ? a : w.theme,
132
+ color: (n = o.color) != null ? n : w.color,
133
+ persist: (l = o.persist) != null ? l : w.persist,
134
+ sound: (g = o.sound) != null ? g : w.sound
132
135
  };
133
136
  }
134
- function H(r = "msg") {
135
- return typeof crypto != "undefined" && crypto.randomUUID ? crypto.randomUUID() : `${r}-${Math.random().toString(16).slice(2)}`;
137
+ function H(o = "msg") {
138
+ return typeof crypto != "undefined" && crypto.randomUUID ? crypto.randomUUID() : `${o}-${Math.random().toString(16).slice(2)}`;
136
139
  }
137
140
  function z() {
138
- var r, e;
139
- return (e = (r = window.matchMedia) == null ? void 0 : r.call(window, "(prefers-color-scheme: dark)").matches) != null ? e : !1;
141
+ var o, e;
142
+ return (e = (o = window.matchMedia) == null ? void 0 : o.call(window, "(prefers-color-scheme: dark)").matches) != null ? e : !1;
140
143
  }
141
- function j(r) {
142
- return r === "light" || r === "dark" ? r : z() ? "dark" : "light";
144
+ function P(o) {
145
+ return o === "light" || o === "dark" ? o : z() ? "dark" : "light";
143
146
  }
144
- function x(r, e = 30) {
145
- return r.slice(-e);
147
+ function x(o, e = 30) {
148
+ return o.slice(-e);
146
149
  }
147
- function q(r) {
148
- if (!r || r.length === 0) return;
150
+ function _(o) {
151
+ if (!o || o.length === 0) return;
149
152
  const e = window.location.origin;
150
- r.includes(e) || console.warn(
151
- `SpilkiWidget: current origin ${e} not in allowedOriginsHint: ${r.join(", ")}`
153
+ o.includes(e) || console.warn(
154
+ `SpilkiWidget: current origin ${e} not in allowedOriginsHint: ${o.join(", ")}`
152
155
  );
153
156
  }
154
- const _ = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
155
- function J(r) {
156
- const e = new Date(r), t = /* @__PURE__ */ new Date(), s = (l) => String(l).padStart(2, "0"), i = `${s(e.getHours())}:${s(e.getMinutes())}`, o = new Date(t.getFullYear(), t.getMonth(), t.getDate()).getTime(), a = o - 864e5, n = new Date(e.getFullYear(), e.getMonth(), e.getDate()).getTime();
157
- return n === o ? `Today at ${i}` : n === a ? `Yesterday at ${i}` : `${_[e.getMonth()]} ${e.getDate()}, ${i}`;
157
+ const G = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
158
+ function q(o) {
159
+ const e = new Date(o), t = /* @__PURE__ */ new Date(), s = (l) => String(l).padStart(2, "0"), i = `${s(e.getHours())}:${s(e.getMinutes())}`, r = new Date(t.getFullYear(), t.getMonth(), t.getDate()).getTime(), a = r - 864e5, n = new Date(e.getFullYear(), e.getMonth(), e.getDate()).getTime();
160
+ return n === r ? `Today at ${i}` : n === a ? `Yesterday at ${i}` : `${G[e.getMonth()]} ${e.getDate()}, ${i}`;
158
161
  }
159
- 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:.5rem;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}.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}', P = 24 * 60 * 60 * 1e3, Y = 2 * 60 * 1e3, G = 200, X = [
162
+ const Y = ':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}', j = 24 * 60 * 60 * 1e3, V = 2 * 60 * 1e3, J = 200, X = [
160
163
  "😀",
161
164
  "😂",
162
165
  "🤣",
@@ -208,8 +211,8 @@ const V = ':host{--spilki-bg-light: #ffffff;--spilki-bg-dark: #0f172a;--spilki-t
208
211
  "☕",
209
212
  "🍕"
210
213
  ];
211
- function v(r) {
212
- return r.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
214
+ function E(o) {
215
+ return o.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
213
216
  }
214
217
  class Z {
215
218
  constructor(e) {
@@ -226,9 +229,9 @@ class Z {
226
229
  day: "numeric",
227
230
  year: "numeric"
228
231
  }), this.renderedMessages = [], this.focusable = [], this.seenIds = /* @__PURE__ */ 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" });
229
- const t = v(e.i18n.title), s = v(e.i18n.typing), i = v(e.i18n.offline), o = v(e.i18n.placeholder), a = v(e.i18n.sendLabel);
232
+ const t = E(e.i18n.title), s = E(e.i18n.typing), i = E(e.i18n.offline), r = E(e.i18n.placeholder), a = E(e.i18n.sendLabel);
230
233
  this.shadow.innerHTML = `
231
- <style>${V}</style>
234
+ <style>${Y}</style>
232
235
  <div class="wrapper" role="dialog" aria-modal="true" aria-label="${t}">
233
236
  <header>
234
237
  <h1><span class="status-dot" aria-hidden="true"></span>${t}</h1>
@@ -245,7 +248,7 @@ class Z {
245
248
  <div class="emoji-picker" aria-label="Emoji picker"></div>
246
249
  <div class="input-area">
247
250
  <div class="input-wrap">
248
- <textarea rows="1" placeholder="${o}" aria-label="${o}"></textarea>
251
+ <textarea rows="1" placeholder="${r}" aria-label="${r}"></textarea>
249
252
  <div class="input-actions">
250
253
  <button class="emoji-btn" type="button" aria-label="Insert emoji">
251
254
  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" aria-hidden="true">
@@ -326,7 +329,7 @@ class Z {
326
329
  this.messagesEl.innerHTML = "", this.seenIds.clear(), this.renderedMessages.length = 0, this.lastTimelineMessage = null;
327
330
  for (const s of e) {
328
331
  s.messages.forEach((n) => this.seenIds.add(n.id));
329
- const i = this.createHistoryContainer(s.messages), o = s.messages[s.messages.length - 1].ts, a = this.createSeparatorElement(o, i);
332
+ const i = this.createHistoryContainer(s.messages), r = s.messages[s.messages.length - 1].ts, a = this.createSeparatorElement(r, i);
330
333
  this.messagesEl.appendChild(i), this.messagesEl.appendChild(a);
331
334
  }
332
335
  t.forEach((s) => {
@@ -355,6 +358,20 @@ class Z {
355
358
  hideSuggestedReplies() {
356
359
  this.suggestedRepliesEl.toggleAttribute("hidden", !0), this.suggestedRepliesEl.replaceChildren(), this.collectFocusable(), this.focusInput();
357
360
  }
361
+ setAgentActivity(e, t) {
362
+ var i;
363
+ if (e === null) {
364
+ this.typingEl.toggleAttribute("hidden", !0);
365
+ return;
366
+ }
367
+ const s = {
368
+ TYPING: t.typing,
369
+ THINKING: t.thinking,
370
+ SEARCHING: t.searching,
371
+ EXECUTING_TOOL: t.executingTool
372
+ };
373
+ this.typingEl.textContent = (i = s[e]) != null ? i : t.typing, this.typingEl.toggleAttribute("hidden", !1);
374
+ }
358
375
  setTyping(e) {
359
376
  this.typingEl.toggleAttribute("hidden", !e);
360
377
  }
@@ -378,16 +395,16 @@ class Z {
378
395
  }
379
396
  createSeparatorElement(e, t) {
380
397
  const s = document.createElement("div");
381
- 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 = J(e);
398
+ 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 = q(e);
382
399
  const i = () => {
383
- const o = t.classList.toggle("expanded");
384
- s.setAttribute("aria-expanded", String(o)), s.setAttribute(
400
+ const r = t.classList.toggle("expanded");
401
+ s.setAttribute("aria-expanded", String(r)), s.setAttribute(
385
402
  "aria-label",
386
- o ? "Hide previous conversation" : "Show previous conversation"
403
+ r ? "Hide previous conversation" : "Show previous conversation"
387
404
  );
388
405
  };
389
- return s.addEventListener("click", i), s.addEventListener("keydown", (o) => {
390
- const a = o;
406
+ return s.addEventListener("click", i), s.addEventListener("keydown", (r) => {
407
+ const a = r;
391
408
  (a.key === "Enter" || a.key === " ") && (a.preventDefault(), i());
392
409
  }), s;
393
410
  }
@@ -397,8 +414,8 @@ class Z {
397
414
  let s = null;
398
415
  return e.forEach((i) => {
399
416
  this.appendDateSeparatorIfNeeded(s, i, t);
400
- const { item: o } = this.createMessageElement(i);
401
- t.appendChild(o), s = i;
417
+ const { item: r } = this.createMessageElement(i);
418
+ t.appendChild(r), s = i;
402
419
  }), t;
403
420
  }
404
421
  appendTimelineMessage(e) {
@@ -414,24 +431,24 @@ class Z {
414
431
  }
415
432
  updateTimestampVisibility() {
416
433
  for (let e = 0; e < this.renderedMessages.length; e += 1) {
417
- 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;
434
+ const t = this.renderedMessages[e], s = this.renderedMessages[e + 1], i = !!s && s.message.author === t.message.author && s.message.ts - t.message.ts <= V && s.message.ts >= t.message.ts;
418
435
  t.timeEl.toggleAttribute("hidden", i), t.timeEl.textContent = this.formatMessageTimestamp(t.message.ts);
419
436
  }
420
437
  }
421
438
  formatMessageTimestamp(e) {
422
439
  const s = Date.now() - e;
423
- if (s < P) {
440
+ if (s < j) {
424
441
  const i = Math.max(1, Math.round(s / 6e4));
425
442
  if (i < 60)
426
443
  return this.relativeTimeFormat.format(-i, "minute");
427
- const o = Math.max(1, Math.round(i / 60));
428
- return this.relativeTimeFormat.format(-o, "hour");
444
+ const r = Math.max(1, Math.round(i / 60));
445
+ return this.relativeTimeFormat.format(-r, "hour");
429
446
  }
430
447
  return this.absoluteTimeFormat.format(new Date(e));
431
448
  }
432
449
  formatDateSeparator(e) {
433
450
  const t = new Date(e), s = this.startOfDay(Date.now()), i = this.startOfDay(e);
434
- return i === s ? "Today" : i === s - P ? "Yesterday" : this.dateSeparatorFormat.format(t);
451
+ return i === s ? "Today" : i === s - j ? "Yesterday" : this.dateSeparatorFormat.format(t);
435
452
  }
436
453
  isSameDay(e, t) {
437
454
  return this.startOfDay(e) === this.startOfDay(t);
@@ -441,7 +458,7 @@ class Z {
441
458
  return new Date(t.getFullYear(), t.getMonth(), t.getDate()).getTime();
442
459
  }
443
460
  isScrolledUp() {
444
- return this.distanceFromBottom() > G;
461
+ return this.distanceFromBottom() > J;
445
462
  }
446
463
  distanceFromBottom() {
447
464
  return this.messagesEl.scrollHeight - this.messagesEl.scrollTop - this.messagesEl.clientHeight;
@@ -499,8 +516,8 @@ class Z {
499
516
  var a, n;
500
517
  const t = this.input.value, s = (a = this.input.selectionStart) != null ? a : t.length, i = (n = this.input.selectionEnd) != null ? n : t.length;
501
518
  this.input.value = `${t.slice(0, s)}${e}${t.slice(i)}`;
502
- const o = s + e.length;
503
- this.input.setSelectionRange(o, o), this.input.dispatchEvent(new Event("input", { bubbles: !0 })), this.input.focus();
519
+ const r = s + e.length;
520
+ this.input.setSelectionRange(r, r), this.input.dispatchEvent(new Event("input", { bubbles: !0 })), this.input.focus();
504
521
  }
505
522
  collectFocusable() {
506
523
  const e = this.shadow.querySelectorAll(
@@ -516,10 +533,10 @@ class Z {
516
533
  e.shiftKey && i === t ? (e.preventDefault(), s.focus()) : !e.shiftKey && i === s && (e.preventDefault(), t.focus());
517
534
  }
518
535
  }
519
- const w = 1500, D = 8e3;
536
+ const v = 1500, D = 8e3;
520
537
  class Q {
521
538
  constructor(e, t) {
522
- this.sessionId = null, this.currentKind = null, this.stopped = !1, this.backoff = w, this.connectPromise = null, this.options = e, this.handlers = t;
539
+ this.sessionId = null, this.currentKind = null, this.stopped = !1, this.backoff = v, this.connectPromise = null, this.options = e, this.handlers = t;
523
540
  }
524
541
  setAccessToken(e) {
525
542
  this.options.accessToken = e;
@@ -560,8 +577,8 @@ class Q {
560
577
  });
561
578
  if (!i.ok)
562
579
  throw new Error(`SpilkiWidget: connect failed (${i.status})`);
563
- const o = await i.json();
564
- return this.sessionId = o.sessionId, this.options.sessionId = o.sessionId, this.backoff = w, await this.startTransport(o), o;
580
+ const r = await i.json();
581
+ return this.sessionId = r.sessionId, this.options.sessionId = r.sessionId, this.backoff = v, await this.startTransport(r), r;
565
582
  }
566
583
  async send(e, t) {
567
584
  var a, n;
@@ -576,7 +593,7 @@ class Q {
576
593
  this.ws.send(JSON.stringify({ type: "message", payload: s }));
577
594
  return;
578
595
  }
579
- const i = `${this.options.apiBase.replace(/\/$/, "")}/widget/message`, o = await fetch(i, {
596
+ const i = `${this.options.apiBase.replace(/\/$/, "")}/widget/message`, r = await fetch(i, {
580
597
  method: "POST",
581
598
  headers: {
582
599
  "Content-Type": "application/json",
@@ -584,12 +601,12 @@ class Q {
584
601
  },
585
602
  body: JSON.stringify(s)
586
603
  });
587
- if (!o.ok)
588
- throw new Error(`SpilkiWidget: send failed (${o.status})`);
604
+ if (!r.ok)
605
+ throw new Error(`SpilkiWidget: send failed (${r.status})`);
589
606
  }
590
607
  // #1: accept resetBackoff param; #8 #9: clear retryTimer
591
608
  stop(e = !0) {
592
- 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;
609
+ 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;
593
610
  }
594
611
  async startTransport(e) {
595
612
  if (this.stopped) return;
@@ -614,8 +631,8 @@ class Q {
614
631
  i.close();
615
632
  return;
616
633
  }
617
- this.currentKind = "ws", this.handlers.onOpen("ws"), this.backoff = w, t();
618
- }, this.wsOnMessage = (o) => this.handleIncoming(o.data), this.wsOnClose = () => {
634
+ this.currentKind = "ws", this.handlers.onOpen("ws"), this.backoff = v, t();
635
+ }, this.wsOnMessage = (r) => this.handleIncoming(r.data), this.wsOnClose = () => {
619
636
  this.stopped || this.retryFallback("ws");
620
637
  }, this.wsOnError = () => {
621
638
  this.handlers.onError(new Error("SpilkiWidget: websocket error")), i.readyState !== WebSocket.OPEN && s(new Error("WebSocket failed"));
@@ -635,8 +652,8 @@ class Q {
635
652
  "X-Authorization": `Bearer ${this.options.accessToken}`
636
653
  },
637
654
  signal: i.signal
638
- }).then((o) => {
639
- if (!o.ok || !o.body) {
655
+ }).then((r) => {
656
+ if (!r.ok || !r.body) {
640
657
  s(new Error("SSE failed"));
641
658
  return;
642
659
  }
@@ -644,39 +661,39 @@ class Q {
644
661
  i.abort();
645
662
  return;
646
663
  }
647
- this.currentKind = "sse", this.handlers.onOpen("sse"), this.backoff = w, t();
648
- const a = o.body.getReader(), n = new TextDecoder();
664
+ this.currentKind = "sse", this.handlers.onOpen("sse"), this.backoff = v, t();
665
+ const a = r.body.getReader(), n = new TextDecoder();
649
666
  let l = "";
650
667
  const g = () => {
651
- a.read().then(({ done: m, value: d }) => {
652
- var f;
653
- if (m || this.stopped) {
668
+ a.read().then(({ done: u, value: h }) => {
669
+ var m;
670
+ if (u || this.stopped) {
654
671
  this.stopped || (this.handlers.onError(new Error("SpilkiWidget: SSE stream ended")), this.retryFallback("sse"));
655
672
  return;
656
673
  }
657
- l += n.decode(d, { stream: !0 });
658
- const h = l.split(`
674
+ l += n.decode(h, { stream: !0 });
675
+ const d = l.split(`
659
676
 
660
677
  `);
661
- l = (f = h.pop()) != null ? f : "";
662
- for (const b of h)
663
- for (const p of b.split(`
678
+ l = (m = d.pop()) != null ? m : "";
679
+ for (const f of d)
680
+ for (const p of f.split(`
664
681
  `))
665
682
  p.startsWith("data:") && this.handleIncoming(p.slice(5).trim());
666
683
  g();
667
- }).catch((m) => {
668
- i.signal.aborted || (this.handlers.onError(m), this.stopped || this.retryFallback("sse"));
684
+ }).catch((u) => {
685
+ i.signal.aborted || (this.handlers.onError(u), this.stopped || this.retryFallback("sse"));
669
686
  });
670
687
  };
671
688
  g();
672
- }).catch((o) => {
673
- i.signal.aborted || s(o);
689
+ }).catch((r) => {
690
+ i.signal.aborted || s(r);
674
691
  });
675
692
  });
676
693
  }
677
694
  // #15: add auth header to poll fetch
678
695
  async startPoll(e) {
679
- this.currentKind = "poll", this.handlers.onOpen("poll"), this.backoff = w;
696
+ this.currentKind = "poll", this.handlers.onOpen("poll"), this.backoff = v;
680
697
  const t = async () => {
681
698
  if (!this.stopped)
682
699
  try {
@@ -687,7 +704,7 @@ class Q {
687
704
  });
688
705
  if (!s.ok) throw new Error(`Poll failed ${s.status}`);
689
706
  const i = await s.json();
690
- x(i).forEach((o) => this.handlers.onMessage(o)), this.backoff = w;
707
+ x(i).forEach((r) => this.handlers.onMessage(r)), this.backoff = v;
691
708
  } catch (s) {
692
709
  this.handlers.onError(s), this.backoff = Math.min(this.backoff * 1.5, D);
693
710
  } finally {
@@ -718,18 +735,24 @@ class Q {
718
735
  dispatchIncoming(e) {
719
736
  var t;
720
737
  if ("type" in e) {
721
- e.type === "message" ? this.handlers.onMessage(e.payload) : e.type === "typing" && this.handlers.onTyping(!!((t = e.payload) != null && t.active));
738
+ 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);
722
739
  return;
723
740
  }
724
741
  this.handlers.onMessage(e);
725
742
  }
726
743
  }
727
- const L = 30 * 60 * 1e3, S = 30;
728
- class ee {
744
+ const ee = /* @__PURE__ */ new Set(["TYPING", "THINKING", "SEARCHING", "EXECUTING_TOOL"]);
745
+ function te(o) {
746
+ if (typeof o != "object" || o === null) return !1;
747
+ const e = o;
748
+ return ee.has(e.eventType) && typeof e.active == "boolean";
749
+ }
750
+ const L = 30 * 60 * 1e3, se = 3e4, T = 30;
751
+ class ie {
729
752
  constructor(e, t) {
730
- this.org = e, this.listeners = /* @__PURE__ */ new Set(), this.state = {
753
+ this.org = e, this.listeners = /* @__PURE__ */ new Set(), this.activityTimer = null, this.activeEvents = /* @__PURE__ */ new Set(), this.state = {
731
754
  isOpen: !1,
732
- isTyping: !1,
755
+ agentActivity: null,
733
756
  isConnected: !1,
734
757
  messages: []
735
758
  }, 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();
@@ -737,7 +760,7 @@ class ee {
737
760
  get snapshot() {
738
761
  return {
739
762
  isOpen: this.state.isOpen,
740
- isTyping: this.state.isTyping,
763
+ agentActivity: this.state.agentActivity,
741
764
  isConnected: this.state.isConnected,
742
765
  messages: this.state.messages
743
766
  };
@@ -751,8 +774,27 @@ class ee {
751
774
  close() {
752
775
  this.state.isOpen && (this.state.isOpen = !1, this.emit());
753
776
  }
777
+ handleAgentEvent(e, t) {
778
+ t ? this.activeEvents.add(e) : this.activeEvents.delete(e), this.updateDisplayedActivity();
779
+ }
754
780
  setTyping(e) {
755
- this.state.isTyping !== e && (this.state.isTyping = e, this.emit());
781
+ this.handleAgentEvent("TYPING", e);
782
+ }
783
+ updateDisplayedActivity() {
784
+ this.activityTimer && (clearTimeout(this.activityTimer), this.activityTimer = null), this.activeEvents.size > 0 && (this.activityTimer = setTimeout(() => {
785
+ this.activeEvents.clear(), this.state.agentActivity = null, this.activityTimer = null, this.emit();
786
+ }, se));
787
+ const e = this.resolveTopActivity();
788
+ this.state.agentActivity !== e && (this.state.agentActivity = e, this.emit());
789
+ }
790
+ resolveTopActivity() {
791
+ var t;
792
+ return this.activeEvents.size === 0 ? null : (t = [
793
+ "EXECUTING_TOOL",
794
+ "SEARCHING",
795
+ "THINKING",
796
+ "TYPING"
797
+ ].find((s) => this.activeEvents.has(s))) != null ? t : null;
756
798
  }
757
799
  setConnected(e) {
758
800
  this.state.isConnected !== e && (this.state.isConnected = e, this.emit());
@@ -765,10 +807,10 @@ class ee {
765
807
  author: e.author,
766
808
  text: e.text
767
809
  };
768
- return this.state.messages.some((o) => o.id === t.id) ? null : (this.state.messages = x([...this.state.messages, t], S), this.persistMessages(), this.touchActivity(), this.emit(), t);
810
+ return this.state.messages.some((r) => r.id === t.id) ? null : (this.state.messages = x([...this.state.messages, t], T), this.persistMessages(), this.touchActivity(), this.emit(), t);
769
811
  }
770
812
  setMessages(e) {
771
- this.state.messages = x(e, S), this.persistMessages(), this.emit();
813
+ this.state.messages = x(e, T), this.persistMessages(), this.emit();
772
814
  }
773
815
  clearMessages() {
774
816
  this.state.messages = [], this.persistMessages(), this.emit();
@@ -888,14 +930,14 @@ class ee {
888
930
  const e = localStorage.getItem(this.historyKey);
889
931
  if (!e) return [];
890
932
  const t = JSON.parse(e);
891
- return Array.isArray(t) ? x(t, S) : [];
933
+ return Array.isArray(t) ? x(t, T) : [];
892
934
  } catch (e) {
893
935
  return console.error("SpilkiWidget: unable to load messages", e), [];
894
936
  }
895
937
  }
896
938
  }
897
- function te(r) {
898
- const e = r.replace(/-/g, "+").replace(/_/g, "/"), t = e.padEnd(e.length + (4 - e.length % 4) % 4, "=");
939
+ function oe(o) {
940
+ const e = o.replace(/-/g, "+").replace(/_/g, "/"), t = e.padEnd(e.length + (4 - e.length % 4) % 4, "=");
899
941
  if (typeof atob == "function")
900
942
  return decodeURIComponent(
901
943
  Array.prototype.map.call(atob(t), (i) => `%${`00${i.charCodeAt(0).toString(16)}`.slice(-2)}`).join("")
@@ -905,24 +947,24 @@ function te(r) {
905
947
  return s.from(t, "base64").toString("utf8");
906
948
  throw new Error("SpilkiWidget: no base64 decoder available");
907
949
  }
908
- function se(r) {
909
- if (!r) return null;
910
- const e = r.split(".");
950
+ function re(o) {
951
+ if (!o) return null;
952
+ const e = o.split(".");
911
953
  if (e.length < 2) return null;
912
954
  try {
913
- const t = te(e[1]);
955
+ const t = oe(e[1]);
914
956
  return JSON.parse(t);
915
957
  } catch (t) {
916
958
  return console.error("SpilkiWidget: unable to parse JWT", t), null;
917
959
  }
918
960
  }
919
- function ie(r) {
920
- const e = se(r);
961
+ function ne(o) {
962
+ const e = re(o);
921
963
  if (!(e != null && e.exp) || typeof e.exp != "number") return !0;
922
964
  const t = Math.floor(Date.now() / 1e3);
923
965
  return e.exp < t + 60;
924
966
  }
925
- const re = {
967
+ const ae = {
926
968
  onOpen() {
927
969
  },
928
970
  onClose() {
@@ -934,8 +976,8 @@ const re = {
934
976
  onTransportChange() {
935
977
  }
936
978
  };
937
- async function oe(r, e, t) {
938
- const s = `${r.replace(/\/$/, "")}/widget/install`, i = await fetch(s, {
979
+ async function le(o, e, t) {
980
+ const s = `${o.replace(/\/$/, "")}/widget/install`, i = await fetch(s, {
939
981
  method: "POST",
940
982
  headers: { "Content-Type": "application/json", Origin: window.location.origin },
941
983
  body: JSON.stringify({ token: e, organisationId: t })
@@ -943,19 +985,19 @@ async function oe(r, e, t) {
943
985
  if (!i.ok) throw new Error(`SpilkiWidget: install failed (${i.status})`);
944
986
  return (await i.json()).accessToken;
945
987
  }
946
- async function ne(r, e) {
947
- const t = `${r.replace(/\/$/, "")}/widget/refresh`, s = await fetch(t, {
988
+ async function ce(o, e) {
989
+ const t = `${o.replace(/\/$/, "")}/widget/refresh`, s = await fetch(t, {
948
990
  method: "POST",
949
991
  headers: { "X-Authorization": `Bearer ${e}`, Origin: window.location.origin }
950
992
  });
951
993
  if (!s.ok) throw new Error(`SpilkiWidget: refresh failed (${s.status})`);
952
994
  return (await s.json()).accessToken;
953
995
  }
954
- function ae(r) {
996
+ function he(o) {
955
997
  let e = !1, t = null;
956
998
  const s = [], i = () => {
957
999
  var n;
958
- if (!r) return null;
1000
+ if (!o) return null;
959
1001
  if (t) return t;
960
1002
  try {
961
1003
  const l = (n = window.AudioContext) != null ? n : window.webkitAudioContext;
@@ -965,7 +1007,7 @@ function ae(r) {
965
1007
  return null;
966
1008
  }
967
1009
  return t;
968
- }, o = () => {
1010
+ }, r = () => {
969
1011
  e = !0;
970
1012
  try {
971
1013
  const n = i();
@@ -975,23 +1017,23 @@ function ae(r) {
975
1017
  }
976
1018
  }, a = (n) => {
977
1019
  const l = () => {
978
- o(), window.removeEventListener(n, l, !0);
1020
+ r(), window.removeEventListener(n, l, !0);
979
1021
  };
980
1022
  s.push({ type: n, listener: l }), window.addEventListener(n, l, { capture: !0, passive: !0 });
981
1023
  };
982
1024
  return a("pointerdown"), a("keydown"), {
983
- markUserInteraction: o,
1025
+ markUserInteraction: r,
984
1026
  play() {
985
- if (!r || !e) return;
1027
+ if (!o || !e) return;
986
1028
  const n = i();
987
1029
  if (!n || n.state !== "running") return;
988
1030
  const l = n.createGain();
989
1031
  l.gain.value = 0.15, l.connect(n.destination);
990
- const g = (d, h, f) => {
991
- const b = n.createOscillator(), p = n.createGain();
992
- b.type = "sine", b.frequency.setValueAtTime(d, h), p.gain.setValueAtTime(1e-4, h), p.gain.exponentialRampToValueAtTime(1, h + 0.012), p.gain.exponentialRampToValueAtTime(1e-4, h + f), b.connect(p), p.connect(l), b.start(h), b.stop(h + f + 0.02);
993
- }, m = n.currentTime;
994
- g(880, m, 0.08), g(1175, m + 0.09, 0.08);
1032
+ const g = (h, d, m) => {
1033
+ const f = n.createOscillator(), p = n.createGain();
1034
+ f.type = "sine", f.frequency.setValueAtTime(h, d), p.gain.setValueAtTime(1e-4, d), p.gain.exponentialRampToValueAtTime(1, d + 0.012), p.gain.exponentialRampToValueAtTime(1e-4, d + m), f.connect(p), p.connect(l), f.start(d), f.stop(d + m + 0.02);
1035
+ }, u = n.currentTime;
1036
+ g(880, u, 0.08), g(1175, u + 0.09, 0.08);
995
1037
  },
996
1038
  destroy() {
997
1039
  s.forEach(({ type: n, listener: l }) => {
@@ -1001,112 +1043,115 @@ function ae(r) {
1001
1043
  }
1002
1044
  };
1003
1045
  }
1004
- function U(r) {
1005
- var O, M, I, A;
1006
- if (!r.org)
1046
+ function U(o) {
1047
+ var I, O, M, B;
1048
+ if (!o.org)
1007
1049
  throw new Error("SpilkiWidget: org is required");
1008
- const e = N(r);
1009
- q(e.allowedOriginsHint);
1010
- const t = { ...re, ...(O = e.hooks) != null ? O : {} }, s = new ee(e.org, { persist: e.persist }), i = ae(e.sound);
1011
- let o = (M = s.accessToken) != null ? M : void 0, a = null;
1050
+ const e = K(o);
1051
+ _(e.allowedOriginsHint);
1052
+ const t = { ...ae, ...(I = e.hooks) != null ? I : {} }, s = new ie(e.org, { persist: e.persist }), i = he(e.sound);
1053
+ let r = (O = s.accessToken) != null ? O : void 0, a = null;
1012
1054
  const n = () => {
1013
- m.setBadge(s.countUnread());
1055
+ u.setBadge(s.countUnread());
1014
1056
  }, l = () => {
1015
- s.markRead(), m.setBadge(0);
1057
+ s.markRead(), u.setBadge(0);
1016
1058
  }, g = async () => a || (a = (async () => {
1017
1059
  try {
1018
- if (o && ie(o))
1060
+ if (r && ne(r))
1019
1061
  try {
1020
- o = await ne(e.apiBase, o), s.persistAccessToken(o), h.setAccessToken(o);
1062
+ r = await ce(e.apiBase, r), s.persistAccessToken(r), d.setAccessToken(r);
1021
1063
  return;
1022
1064
  } catch {
1023
- o = void 0, s.clearAccessToken();
1065
+ r = void 0, s.clearAccessToken();
1024
1066
  }
1025
- if (!o) {
1026
- if (!r.installationToken) throw new Error("SpilkiWidget: missing installationToken");
1027
- if (!r.org) throw new Error("SpilkiWidget: missing org");
1028
- o = await oe(e.apiBase, r.installationToken, r.org), s.persistAccessToken(o), h.setAccessToken(o);
1067
+ if (!r) {
1068
+ if (!o.installationToken) throw new Error("SpilkiWidget: missing installationToken");
1069
+ if (!o.org) throw new Error("SpilkiWidget: missing org");
1070
+ r = await le(e.apiBase, o.installationToken, o.org), s.persistAccessToken(r), d.setAccessToken(r);
1029
1071
  }
1030
1072
  } finally {
1031
1073
  a = null;
1032
1074
  }
1033
- })(), a), m = R({
1075
+ })(), a), u = F({
1034
1076
  color: e.color,
1035
- position: (I = e.position) != null ? I : "bottom-right",
1077
+ position: (M = e.position) != null ? M : "bottom-right",
1036
1078
  onClick: () => {
1037
1079
  s.snapshot.isOpen ? (s.close(), t.onClose()) : (i.markUserInteraction(), s.open(), l(), t.onOpen());
1038
1080
  }
1039
- }), d = new Z({
1081
+ }), h = new Z({
1040
1082
  color: e.color,
1041
- theme: j(e.theme),
1042
- position: (A = e.position) != null ? A : "bottom-right",
1083
+ theme: P(e.theme),
1084
+ position: (B = e.position) != null ? B : "bottom-right",
1043
1085
  i18n: e.i18n,
1044
1086
  onClose: () => {
1045
1087
  s.close(), t.onClose();
1046
1088
  },
1047
1089
  onSend: (c) => {
1048
- const u = s.addMessage({ author: "user", text: c });
1049
- u && (d.appendMessage(u), g().then(() => h.send(c, u.id)).catch((y) => {
1050
- t.onError(y), s.setConnected(!1), d.setOffline(!0);
1090
+ const k = s.addMessage({ author: "user", text: c });
1091
+ k && (h.appendMessage(k), g().then(() => d.send(c, k.id)).catch((b) => {
1092
+ t.onError(b), s.setConnected(!1), h.setOffline(!0);
1051
1093
  }));
1052
1094
  }
1053
- }), h = new Q(
1095
+ }), d = new Q(
1054
1096
  {
1055
1097
  apiBase: e.apiBase,
1056
- accessToken: o,
1098
+ accessToken: r,
1057
1099
  org: e.org,
1058
1100
  sessionId: s.sessionId
1059
1101
  },
1060
1102
  {
1061
1103
  onOpen(c) {
1062
- C.transport = c, t.onTransportChange(c), s.setConnected(!0), d.setOffline(!1);
1104
+ A.transport = c, t.onTransportChange(c), s.setConnected(!0), h.setOffline(!1);
1063
1105
  },
1064
1106
  onMessage(c) {
1065
- const u = s.addMessage(c);
1066
- u && (d.appendMessage(u), !s.snapshot.isOpen && u.author === "bot" && (n(), i.play()), t.onMessage(u));
1107
+ const b = c.suggestedReplies, y = s.addMessage(c);
1108
+ y && (h.appendMessage(y), y.author === "bot" && b && b.length > 0 && h.setSuggestedReplies(b), !s.snapshot.isOpen && y.author === "bot" && (n(), i.play()), t.onMessage(y));
1067
1109
  },
1068
1110
  onTyping(c) {
1069
1111
  s.setTyping(c);
1070
1112
  },
1113
+ onAgentEvent(c) {
1114
+ s.handleAgentEvent(c.eventType, c.active);
1115
+ },
1071
1116
  onError(c) {
1072
- t.onError(c), s.setConnected(!1), s.snapshot.isOpen && d.setOffline(!0);
1117
+ t.onError(c), s.setConnected(!1), s.snapshot.isOpen && h.setOffline(!0);
1073
1118
  }
1074
1119
  }
1075
1120
  );
1076
- m.mount(), d.mount();
1077
- const f = s.snapshot.messages, b = s.isSessionExpired(), p = s.getConversationGroups();
1078
- if (f.length === 0 && e.welcome) {
1121
+ u.mount(), h.mount();
1122
+ const m = s.snapshot.messages, f = s.isSessionExpired(), p = s.getConversationGroups();
1123
+ if (m.length === 0 && e.welcome) {
1079
1124
  const c = {
1080
1125
  id: "welcome",
1081
1126
  author: "bot",
1082
1127
  text: e.welcome,
1083
1128
  ts: Date.now()
1084
1129
  };
1085
- s.addMessage(c), d.appendMessage(c);
1086
- } else b && f.length > 0 ? d.renderWithConversations(p, []) : p.length > 1 ? d.renderWithConversations(p.slice(0, -1), p[p.length - 1].messages) : d.updateMessages(f);
1087
- let E = !1;
1088
- const $ = s.subscribe(() => {
1130
+ s.addMessage(c), h.appendMessage(c);
1131
+ } else f && m.length > 0 ? h.renderWithConversations(p, []) : p.length > 1 ? h.renderWithConversations(p.slice(0, -1), p[p.length - 1].messages) : h.updateMessages(m);
1132
+ let S = !1;
1133
+ const N = s.subscribe(() => {
1089
1134
  const c = s.snapshot;
1090
- if (m.setOpen(c.isOpen), d.setTyping(c.isTyping), d.setOffline(!c.isConnected), d.updateTheme(j(e.theme)), c.isOpen) {
1091
- if (!E) {
1092
- const u = s.countUnread() > 0, y = s.lastReadTs;
1093
- l(), u && d.scrollToFirstUnread(y);
1135
+ if (u.setOpen(c.isOpen), h.setAgentActivity(c.agentActivity, e.i18n), h.setOffline(!c.isConnected), h.updateTheme(P(e.theme)), c.isOpen) {
1136
+ if (!S) {
1137
+ const k = s.countUnread() > 0, b = s.lastReadTs;
1138
+ l(), k && h.scrollToFirstUnread(b);
1094
1139
  }
1095
- E = !0, d.show();
1140
+ S = !0, h.show();
1096
1141
  } else
1097
- E = !1, d.hide();
1098
- }), W = f.length === 0 || b;
1142
+ S = !1, h.hide();
1143
+ }), $ = m.length === 0 || f;
1099
1144
  n(), g().then(
1100
- () => h.connect().then((c) => {
1101
- var y, B;
1102
- e.persist && s.persistSession(c.sessionId), s.setConnected(!0), t.onTransportChange((y = h.kind) != null ? y : "ws");
1103
- const u = (B = c.suggestedReplies) != null ? B : [];
1104
- u.length > 0 && W && d.setSuggestedReplies(u);
1145
+ () => d.connect().then((c) => {
1146
+ var b, y;
1147
+ e.persist && s.persistSession(c.sessionId), s.setConnected(!0), t.onTransportChange((b = d.kind) != null ? b : "ws");
1148
+ const k = (y = c.suggestedReplies) != null ? y : [];
1149
+ k.length > 0 && $ && h.setSuggestedReplies(k);
1105
1150
  })
1106
1151
  ).catch((c) => {
1107
- t.onError(c), s.setConnected(!1), d.setOffline(!0);
1152
+ t.onError(c), s.setConnected(!1), h.setOffline(!0);
1108
1153
  });
1109
- const C = {
1154
+ const A = {
1110
1155
  transport: null,
1111
1156
  open() {
1112
1157
  i.markUserInteraction(), s.open(), l(), t.onOpen();
@@ -1115,17 +1160,17 @@ function U(r) {
1115
1160
  s.close(), t.onClose();
1116
1161
  },
1117
1162
  destroy() {
1118
- $(), h.stop(), i.destroy(), m.destroy(), d.destroy();
1163
+ N(), d.stop(), i.destroy(), u.destroy(), h.destroy();
1119
1164
  }
1120
1165
  };
1121
- return C;
1166
+ return A;
1122
1167
  }
1123
- function le() {
1168
+ function de() {
1124
1169
  var s, i;
1125
1170
  if (typeof document == "undefined") return;
1126
- const r = document.currentScript;
1127
- if (!r) return;
1128
- const e = r.dataset;
1171
+ const o = document.currentScript;
1172
+ if (!o) return;
1173
+ const e = o.dataset;
1129
1174
  if (e.autoinit === "false") return;
1130
1175
  const t = e.org;
1131
1176
  if (!t) {
@@ -1140,10 +1185,10 @@ function le() {
1140
1185
  theme: (i = e.theme) != null ? i : void 0
1141
1186
  });
1142
1187
  }
1143
- typeof window != "undefined" && (window.SpilkiWidget = window.SpilkiWidget || {}, window.SpilkiWidget.init = (r) => U(r));
1144
- le();
1188
+ typeof window != "undefined" && (window.SpilkiWidget = window.SpilkiWidget || {}, window.SpilkiWidget.init = (o) => U(o));
1189
+ de();
1145
1190
  export {
1146
- le as autoInit,
1191
+ de as autoInit,
1147
1192
  U as initSpilkiWidget
1148
1193
  };
1149
1194
  //# sourceMappingURL=widget.es.js.map