@flowengage/react-chatbot 5.0.44 → 5.0.45

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.
@@ -29988,11 +29988,11 @@ function Nk({ copy: e, orbColors: t, primaryColor: n, onVoice: r, onText: i, onC
29988
29988
  });
29989
29989
  }
29990
29990
  function Pk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, voiceId: i, siteId: a, apiBaseUrl: s, chatId: l, historyRef: u, onMessageSync: d, voiceEndCounter: f }) {
29991
- let [h, v] = m("idle"), [y, b] = m(!1), [x, S] = m(!1), C = p(null), w = p(""), T = p(async () => {}), ee = p(!1), te = p(!1), ne = p(!1), re = p(!1), E = p("minimized"), ie = p(null), ae = p(null), oe = p(null), D = p(0), se = p(!1), ce = p("idle"), le = p(!1), ue = p(null), de = p(null), fe = p(!1), pe = o((e = "minimized") => {
29991
+ let [h, v] = m("idle"), [y, b] = m(!1), [x, S] = m(!1), C = p(null), w = p(""), T = p(async () => {}), ee = p(!1), te = p(!1), ne = p(!1), re = p(!1), E = p("minimized"), ie = p(null), ae = p(null), oe = p(null), D = p(0), se = p(!1), ce = p("idle"), le = p(!1), ue = p(null), de = p(null), fe = p(!1), pe = p([]), me = p(null), he = p(null), ge = p(null), _e = o((e = "minimized") => {
29992
29992
  E.current = e, re.current = !0, queueMicrotask(() => {
29993
29993
  ee.current || (ee.current = !0, T.current?.());
29994
29994
  });
29995
- }, [u]), me = o(async (e) => {
29995
+ }, [u]), ve = o(async (e) => {
29996
29996
  re.current = !0;
29997
29997
  try {
29998
29998
  CD();
@@ -30025,12 +30025,44 @@ function Pk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, voiceId: i
30025
30025
  l,
30026
30026
  s
30027
30027
  ]);
30028
- return T.current = () => me(E.current === "chat" ? t : n), c(() => {
30028
+ T.current = () => ve(E.current === "chat" ? t : n);
30029
+ let ye = o(() => {
30030
+ let e = he.current, t = me.current;
30031
+ if (e) {
30032
+ he.current = null;
30033
+ try {
30034
+ t && ge.current && (ge.current.gain.setValueAtTime(ge.current.gain.value, t.currentTime), ge.current.gain.linearRampToValueAtTime(0, t.currentTime + .12), ge.current = null), setTimeout(() => {
30035
+ try {
30036
+ e.stop();
30037
+ } catch {}
30038
+ }, 130);
30039
+ } catch {
30040
+ try {
30041
+ e.stop();
30042
+ } catch {}
30043
+ }
30044
+ }
30045
+ }, []), be = o(() => {
30046
+ let e = pe.current, t = me.current;
30047
+ if (!(!e.length || !t)) {
30048
+ ye();
30049
+ try {
30050
+ t.state === "suspended" && t.resume().catch(() => {});
30051
+ let n = e[Math.floor(Math.random() * e.length)], r = t.createBufferSource();
30052
+ r.buffer = n;
30053
+ let i = t.createGain();
30054
+ i.gain.setValueAtTime(1, t.currentTime), r.connect(i), i.connect(t.destination), r.onended = () => {
30055
+ he.current === r && (he.current = null);
30056
+ }, r.start(0), he.current = r, ge.current = i;
30057
+ } catch {}
30058
+ }
30059
+ }, [ye]);
30060
+ return c(() => {
30029
30061
  te.current = y;
30030
30062
  }, [y]), c(() => {
30031
- f && pe("chat");
30063
+ f && _e("chat");
30032
30064
  }, [f]), c(() => {
30033
- let e = !1, i = null, o = null, c = null;
30065
+ let e = !1, o = null, c = null, f = null;
30034
30066
  return (async () => {
30035
30067
  if (!r) {
30036
30068
  v("error");
@@ -30069,13 +30101,13 @@ function Pk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, voiceId: i
30069
30101
  requestEndSession: () => {
30070
30102
  se.current = !0;
30071
30103
  }
30072
- })), n = a ? je(a) : null, d = !!n?.transcript, f = !!(a && Ve(a)), p = typeof window < "u" ? window.location.pathname : "/", m = typeof document < "u" ? document.title : "", h = p === "/" || p === "", g = null;
30104
+ })), n = a ? je(a) : null, d = !!n?.transcript, p = !!(a && Ve(a)), m = typeof window < "u" ? window.location.pathname : "/", h = typeof document < "u" ? document.title : "", g = m === "/" || m === "", _ = null;
30073
30105
  try {
30074
30106
  let e = await fetch(`${s}/api/voice/signed-url?siteId=${encodeURIComponent(a || "")}`, {
30075
30107
  method: "GET",
30076
30108
  headers: { "Content-Type": "application/json" }
30077
30109
  });
30078
- if (e.ok) g = (await e.json()).signedUrl || null, g && console.log("[FlowEngage] ✅ Using signed ElevenLabs URL");
30110
+ if (e.ok) _ = (await e.json()).signedUrl || null, _ && console.log("[FlowEngage] ✅ Using signed ElevenLabs URL");
30079
30111
  else if (e.status === 429) {
30080
30112
  let t = await e.json().catch(() => ({}));
30081
30113
  throw Error(t.message || "Too many voice sessions started. Please wait a minute before trying again.");
@@ -30084,16 +30116,35 @@ function Pk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, voiceId: i
30084
30116
  if (e.message && e.message.includes("Too many voice sessions")) throw e;
30085
30117
  console.warn("[FlowEngage] ⚠️ Signed URL fetch error:", e.message);
30086
30118
  }
30087
- let _ = {
30119
+ (async () => {
30120
+ try {
30121
+ let e = new URLSearchParams({ siteId: a || "" });
30122
+ i && e.set("voiceId", i);
30123
+ let t = await fetch(`${s}/api/voice/fillers?${e}`);
30124
+ if (!t.ok) return;
30125
+ let n = await t.json();
30126
+ if (!n.success || !Array.isArray(n.fillers) || !n.fillers.length) return;
30127
+ let r = new (window.AudioContext || window.webkitAudioContext)(), o = (await Promise.all(n.fillers.map(async (e) => {
30128
+ try {
30129
+ let t = Uint8Array.from(atob(e), (e) => e.charCodeAt(0));
30130
+ return await r.decodeAudioData(t.buffer);
30131
+ } catch {
30132
+ return null;
30133
+ }
30134
+ }))).filter(Boolean);
30135
+ o.length && (pe.current = o, me.current = r, console.log(`[FlowEngage] 🔊 ${o.length} filler clips ready`));
30136
+ } catch {}
30137
+ })();
30138
+ let y = {
30088
30139
  clientTools: t,
30089
30140
  connectionType: "websocket",
30090
- ...g ? { signedUrl: g } : { agentId: r }
30091
- }, y = (p.split("/").filter(Boolean).pop() || "").replace(/[-_]/g, " ").replace(/\b\w/g, (e) => e.toUpperCase()), x = "";
30092
- m && m.includes("|") && (x = m.split("|").map((e) => e.trim()).filter(Boolean).reduce((e, t) => e.length <= t.length ? e : t));
30093
- let S = x || y || "this page";
30094
- g ? f ? (_.overrides = { agent: { firstMessage: `I've navigated you to the ${S} page. Let me walk you through what's here.` } }, console.log(`[FlowEngage] 🔄 Agent-nav resume: firstMessage set for "${S}" (${p})`)) : d ? _.overrides = { agent: { firstMessage: "I'm still here. Go ahead!" } } : h || (_.overrides = { agent: { firstMessage: `Hi! I see you are currently on the ${S} page. Are you looking for something specific here?` } }, console.log(`[FlowEngage] 🏠 Page-context override: "${S}" for ${p}`)) : d && (_.overrides = { agent: { firstMessage: "" } });
30095
- let T = !1, oe = f ? `NAVIGATION RESUME — Your intro has been spoken. NOW — without waiting for the visitor to say anything — call flowengage_highlight for the first content section on this page, then speak one sentence about it. Continue section by section (highlight + one sentence each) until you have covered the key content. Prior conversation context:\n${(a ? je(a) : null)?.transcript || ""}\n\n` : null, me = await _D.startSession({
30096
- ..._,
30141
+ ..._ ? { signedUrl: _ } : { agentId: r }
30142
+ }, x = (m.split("/").filter(Boolean).pop() || "").replace(/[-_]/g, " ").replace(/\b\w/g, (e) => e.toUpperCase()), S = "";
30143
+ h && h.includes("|") && (S = h.split("|").map((e) => e.trim()).filter(Boolean).reduce((e, t) => e.length <= t.length ? e : t));
30144
+ let T = S || x || "this page";
30145
+ _ ? p ? (y.overrides = { agent: { firstMessage: `I've navigated you to the ${T} page. Let me walk you through what's here.` } }, console.log(`[FlowEngage] 🔄 Agent-nav resume: firstMessage set for "${T}" (${m})`)) : d ? y.overrides = { agent: { firstMessage: "I'm still here. Go ahead!" } } : g || (y.overrides = { agent: { firstMessage: `Hi! I see you are currently on the ${T} page. Are you looking for something specific here?` } }, console.log(`[FlowEngage] 🏠 Page-context override: "${T}" for ${m}`)) : d && (y.overrides = { agent: { firstMessage: "" } });
30146
+ let oe = !1, he = p ? `NAVIGATION RESUME — Your intro has been spoken. NOW — without waiting for the visitor to say anything — call flowengage_highlight for the first content section on this page, then speak one sentence about it. Continue section by section (highlight + one sentence each) until you have covered the key content. Prior conversation context:\n${(a ? je(a) : null)?.transcript || ""}\n\n` : null, ge = await _D.startSession({
30147
+ ...y,
30097
30148
  onConnect: ({ conversationId: e }) => {
30098
30149
  ie.current = e, ae.current = Date.now(), console.log("[FlowEngage] 🎙️ AI chat session connected:", e);
30099
30150
  },
@@ -30101,15 +30152,15 @@ function Pk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, voiceId: i
30101
30152
  onModeChange: ({ mode: t }) => {
30102
30153
  if (!e) {
30103
30154
  if (t === "speaking") {
30104
- de.current &&= (clearTimeout(de.current), null), v("speaking"), ce.current = "speaking", le.current = !0, fe.current = !1, ue.current &&= (clearTimeout(ue.current), null);
30155
+ ye(), de.current &&= (clearTimeout(de.current), null), v("speaking"), ce.current = "speaking", le.current = !0, fe.current = !1, ue.current &&= (clearTimeout(ue.current), null);
30105
30156
  return;
30106
30157
  }
30107
30158
  if (ce.current = "listening", se.current) {
30108
- se.current = !1, pe();
30159
+ se.current = !1, _e();
30109
30160
  return;
30110
30161
  }
30111
- if (oe && !T) {
30112
- T = !0;
30162
+ if (he && !oe) {
30163
+ oe = !0;
30113
30164
  try {
30114
30165
  C.current?.sendUserMessage?.("continue with the tour");
30115
30166
  } catch {}
@@ -30127,7 +30178,7 @@ function Pk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, voiceId: i
30127
30178
  if (e) return;
30128
30179
  let n = t.role === "user" ? "user" : "bot", r = t.message || t.text || t.content || "";
30129
30180
  if (r) {
30130
- if (n === "user" && (w.current = r, fe.current = !0, de.current &&= (clearTimeout(de.current), null), ce.current = "thinking", ue.current &&= (clearTimeout(ue.current), null)), u.current = [...u.current, {
30181
+ if (n === "user" && (w.current = r, fe.current = !0, de.current &&= (clearTimeout(de.current), null), ce.current = "thinking", ue.current &&= (clearTimeout(ue.current), null), be()), u.current = [...u.current, {
30131
30182
  sender: n,
30132
30183
  message: r,
30133
30184
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
@@ -30136,13 +30187,13 @@ function Pk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, voiceId: i
30136
30187
  e && Ae(a, e);
30137
30188
  } catch {}
30138
30189
  if (Ak(n, r)) {
30139
- pe("minimized");
30190
+ _e("minimized");
30140
30191
  return;
30141
30192
  }
30142
30193
  if (te.current && n === "bot" && /are you still there|still there\??|hello\?|anyone there|checking in|you there|are you available|is anyone|did you step away/i.test(r)) if (D.current += 1, D.current === 2) try {
30143
30194
  C.current?.sendContextualUpdate?.("IMPORTANT: The visitor is muted and has not responded to your last 2 checks. Make exactly ONE more check. If there is still no response, say: 'I feel like you are not active, so I'm ending this session. You can connect with me anytime.' then immediately call the flowengage_end_session tool to end the voice session. Do NOT ask again after that.");
30144
30195
  } catch {}
30145
- else D.current >= 5 && pe("minimized");
30196
+ else D.current >= 5 && _e("minimized");
30146
30197
  }
30147
30198
  },
30148
30199
  onError: (t) => {
@@ -30155,7 +30206,7 @@ function Pk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, voiceId: i
30155
30206
  try {
30156
30207
  C.current?.setMicMuted?.(!0);
30157
30208
  } catch {}
30158
- b(!0), v("error"), pe("chat");
30209
+ b(!0), v("error"), _e("chat");
30159
30210
  }
30160
30211
  },
30161
30212
  onDisconnect: (t) => {
@@ -30172,21 +30223,21 @@ function Pk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, voiceId: i
30172
30223
  try {
30173
30224
  C.current?.setMicMuted?.(!0);
30174
30225
  } catch {}
30175
- b(!0), pe("chat");
30226
+ b(!0), _e("chat");
30176
30227
  }
30177
30228
  });
30178
30229
  if (e) {
30179
- me.endSession().catch(() => {});
30230
+ ge.endSession().catch(() => {});
30180
30231
  return;
30181
30232
  }
30182
- i = me, C.current = me, v("listening");
30233
+ o = ge, C.current = ge, v("listening");
30183
30234
  try {
30184
30235
  let e = typeof window < "u" ? window.location.href : "", r = "[]";
30185
30236
  try {
30186
30237
  r = await t.list_page_forms();
30187
30238
  } catch {}
30188
- let i = d && !f ? `RESUMING PRIOR SESSION — DO NOT GREET. The visitor is continuing the same conversation after a page reload. Do not introduce yourself or re-state your capabilities. Wait silently until the visitor speaks; if you must speak first, briefly acknowledge where you left off in one short sentence.\nPrior transcript:\n${n?.transcript || ""}\n\n` : "";
30189
- me.sendContextualUpdate(`${i}Page: ${e}. SiteId: ${a || "unknown"}. Forms: ${r}. Voice: call end_voice_session or say you are ending the session to stop.`);
30239
+ let i = d && !p ? `RESUMING PRIOR SESSION — DO NOT GREET. The visitor is continuing the same conversation after a page reload. Do not introduce yourself or re-state your capabilities. Wait silently until the visitor speaks; if you must speak first, briefly acknowledge where you left off in one short sentence.\nPrior transcript:\n${n?.transcript || ""}\n\n` : "";
30240
+ ge.sendContextualUpdate(`${i}Page: ${e}. SiteId: ${a || "unknown"}. Forms: ${r}. Voice: call end_voice_session or say you are ending the session to stop.`);
30190
30241
  } catch {}
30191
30242
  if (typeof window < "u") {
30192
30243
  let t = window.location.pathname, n = () => {
@@ -30206,9 +30257,9 @@ function Pk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, voiceId: i
30206
30257
  C.current?.sendContextualUpdate?.(`PAGE CHANGED — visitor navigated manually. Current URL is now: ${r}. Page title: "${i}". Sections on this page: ${JSON.stringify(a)}. When the visitor asks about "this page", "current page", or "what page am I on", refer to this new URL — not any previously mentioned page.`);
30207
30258
  } catch {}
30208
30259
  };
30209
- o = window.history.pushState.bind(window.history), window.history.pushState = (...e) => {
30210
- o(...e), setTimeout(n, 50);
30211
- }, c = () => setTimeout(n, 50), window.addEventListener("popstate", c);
30260
+ c = window.history.pushState.bind(window.history), window.history.pushState = (...e) => {
30261
+ c(...e), setTimeout(n, 50);
30262
+ }, f = () => setTimeout(n, 50), window.addEventListener("popstate", f);
30212
30263
  }
30213
30264
  } catch (r) {
30214
30265
  e || (console.error("[FlowEngage] startSession failed", r), r.message && r.message.includes("Too many voice sessions") ? (alert(r.message), n && n("minimized")) : (v("error"), E.current = "chat", window.setTimeout(() => {
@@ -30216,8 +30267,14 @@ function Pk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, voiceId: i
30216
30267
  }, 0)));
30217
30268
  }
30218
30269
  })(), () => {
30219
- e = !0, re.current = !0, kr(), ue.current &&= (clearTimeout(ue.current), null), de.current &&= (clearTimeout(de.current), null), le.current = !1, fe.current = !1, ce.current = "idle", o && typeof window < "u" && (window.history.pushState = o), c && typeof window < "u" && window.removeEventListener("popstate", c);
30220
- let t = i || C.current, n = ie.current, r = ae.current;
30270
+ if (e = !0, re.current = !0, kr(), ue.current &&= (clearTimeout(ue.current), null), de.current &&= (clearTimeout(de.current), null), le.current = !1, fe.current = !1, ce.current = "idle", he.current) {
30271
+ try {
30272
+ he.current.stop();
30273
+ } catch {}
30274
+ he.current = null;
30275
+ }
30276
+ me.current && (me.current.close().catch(() => {}), me.current = null, pe.current = [], ge.current = null), c && typeof window < "u" && (window.history.pushState = c), f && typeof window < "u" && window.removeEventListener("popstate", f);
30277
+ let t = o || C.current, n = ie.current, r = ae.current;
30221
30278
  if (t?.endSession?.().catch(() => {}), n && l && s) {
30222
30279
  let e = r ? Math.round((Date.now() - r) / 1e3) : 0, t = JSON.stringify({
30223
30280
  chatId: l,
@@ -30238,7 +30295,7 @@ function Pk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, voiceId: i
30238
30295
  r,
30239
30296
  a,
30240
30297
  s,
30241
- pe
30298
+ _e
30242
30299
  ]), c(() => {
30243
30300
  if (!x) return;
30244
30301
  let e = (e) => {
@@ -30424,7 +30481,7 @@ function Pk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, voiceId: i
30424
30481
  children: [
30425
30482
  /* @__PURE__ */ _("button", {
30426
30483
  onClick: () => {
30427
- S(!1), E.current = "chat", me(t);
30484
+ S(!1), E.current = "chat", ve(t);
30428
30485
  },
30429
30486
  style: {
30430
30487
  display: "flex",
@@ -30453,7 +30510,7 @@ function Pk({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, voiceId: i
30453
30510
  }),
30454
30511
  /* @__PURE__ */ _("button", {
30455
30512
  onClick: () => {
30456
- S(!1), E.current = "minimized", me(n);
30513
+ S(!1), E.current = "minimized", ve(n);
30457
30514
  },
30458
30515
  style: {
30459
30516
  display: "flex",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowengage/react-chatbot",
3
- "version": "5.0.44",
3
+ "version": "5.0.45",
4
4
  "description": "Embeddable AI chat widget for React — powered by FlowEngage. Drop it in with a single siteId.",
5
5
  "keywords": [
6
6
  "chatbot",