@flowengage/react-chatbot 1.1.7 → 1.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -23292,30 +23292,30 @@ var h_ = {
23292
23292
  listening: "#10b981",
23293
23293
  speaking: "#f59e0b",
23294
23294
  error: "#ef4444"
23295
- }, __ = 13;
23296
- function v_(e, t) {
23295
+ }, __ = 17, v_ = 6;
23296
+ function y_(e, t) {
23297
23297
  let n = (t || "").trim();
23298
23298
  return n ? !!(/\b(let'?s|let us)\s+(end|stop|finish|wrap up|close)\s+(the\s+)?(voice\s+)?(session|call|chat)\b/i.test(n) || /\bend\s+(this\s+)?(the\s+)?(voice\s+)?(session|call|chat)\b/i.test(n) || /\b(hang\s+up|disconnect)\b/i.test(n) || /\b(that'?s all|we'?re done)\b/i.test(n) || e === "bot" && (/\b(I'?ll|I will|Let me|I can|I'?m going to)\s+(end|close)\s+(the\s+)?(voice\s+)?(session|call)\b/i.test(n) || /\b(ending|closing)\s+(the\s+)?(voice\s+)?session\b|\bvoice\s+session\s+(is\s+)?(now\s+)?(ended|over|closing)\b/i.test(n) || /\b(session|call)\s+(is\s+)?(now\s+)?(ended|over)\b/i.test(n) || /\bwe\s+can\s+end\s+(the\s+)?(session|call)?\s*(here|now)\b/i.test(n) || /\b(wrapping\s+up|signing\s+off)\b/i.test(n)) || /^(goodbye|bye|that'?s all|we'?re done|hang up|disconnect)\b/i.test(n)) : !1;
23299
23299
  }
23300
- function y_({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, historyRef: d, hasSyncedRef: f, onMessageSync: p, onStartSync: m }) {
23301
- let [h, g] = s("idle"), [ee, te] = s(null), [_, ne] = s(!1), re = o(null), ie = o(null), ae = o(""), oe = o(async () => {}), se = o(!1), v = o(""), ce = o(null), le = o(null), ue = o(null), y = n(() => {
23302
- le.current &&= (clearTimeout(le.current), null), ue.current &&= (clearInterval(ue.current), null), v.current = "", ce.current = null;
23300
+ function b_({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, historyRef: d, hasSyncedRef: f, onMessageSync: p, onStartSync: m }) {
23301
+ let [h, g] = s("idle"), [ee, te] = s(null), [_, ne] = s(!1), re = o(null), ie = o(null), ae = o(""), oe = o(async () => {}), se = o(!1), v = o(""), ce = o(null), le = o(null), ue = o(null), y = o(null), b = o(null), de = n(() => {
23302
+ ue.current &&= (clearTimeout(ue.current), null), y.current &&= (clearInterval(y.current), null), v.current = "", ce.current = null, le.current = null, b.current != null && (cancelAnimationFrame(b.current), b.current = null);
23303
23303
  try {
23304
23304
  hn();
23305
23305
  } catch {}
23306
- }, []), b = n(async () => {
23307
- y();
23306
+ }, []), fe = n(async () => {
23307
+ de();
23308
23308
  try {
23309
23309
  await re.current?.endSession?.();
23310
23310
  } catch {}
23311
23311
  re.current = null, ne(!1), g("idle"), se.current = !1, typeof p == "function" && await p(d.current), typeof c == "function" && c();
23312
23312
  }, [
23313
- y,
23313
+ de,
23314
23314
  d,
23315
23315
  p,
23316
23316
  c
23317
23317
  ]);
23318
- oe.current = b, i(() => {
23318
+ oe.current = fe, i(() => {
23319
23319
  let t = !1, n = null;
23320
23320
  return (async () => {
23321
23321
  try {
@@ -23334,38 +23334,57 @@ function y_({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
23334
23334
  try {
23335
23335
  let e = v.current, t = ce.current;
23336
23336
  if (!e?.trim() || t == null) return;
23337
- let n = Math.max(0, (Date.now() - t) / 1e3), r = Math.min(e.length, Math.floor(n * __)), i = e.slice(0, r);
23338
- if (i.trim().length < 12) return;
23337
+ let n = le.current, r = Date.now(), i;
23338
+ if (n != null) {
23339
+ let t = Math.max(0, (r - n) / 1e3);
23340
+ i = Math.min(e.length, Math.floor(t * __));
23341
+ } else {
23342
+ let n = Math.max(0, (r - t) / 1e3);
23343
+ if (n > 2.1 && e.length > 36) i = Math.min(e.length, Math.floor(Math.max(0, n - .4) * __));
23344
+ else {
23345
+ let t = Math.min(96, Math.floor(n * v_));
23346
+ i = Math.min(e.length, t);
23347
+ }
23348
+ }
23349
+ let a = e.slice(0, i);
23350
+ if (a.trim().length < 8) return;
23339
23351
  rn();
23340
- let a = pn(i);
23341
- a && mn(a, { speaking: !0 });
23352
+ let o = pn(a);
23353
+ o && mn(o, { speaking: !0 });
23342
23354
  } catch (e) {
23343
23355
  console.warn("[VoiceInterface] speech highlight failed", e?.message);
23344
23356
  }
23345
23357
  }, s = () => {
23346
- le.current && clearTimeout(le.current), le.current = setTimeout(() => {
23347
- le.current = null, o();
23348
- }, 200);
23358
+ b.current ??= requestAnimationFrame(() => {
23359
+ b.current = null, o();
23360
+ });
23349
23361
  }, c = () => {
23350
- ue.current ||= setInterval(() => {
23362
+ ue.current && clearTimeout(ue.current), ue.current = setTimeout(() => {
23363
+ ue.current = null, o();
23364
+ }, 120);
23365
+ }, l = () => {
23366
+ y.current ||= setInterval(() => {
23351
23367
  o();
23352
- }, 400);
23353
- }, l = await Bh.startSession({
23368
+ }, 160);
23369
+ }, u = await Bh.startSession({
23354
23370
  agentId: e,
23355
23371
  clientTools: i,
23356
23372
  onUnhandledClientToolCall: (e) => {
23357
23373
  console.error("[VoiceInterface] ElevenLabs requested a client tool that is not registered in the widget:", e?.tool_name, e?.parameters, "Add a matching handler in voiceClientTools (snake_case and camelCase are both supported).");
23358
23374
  },
23359
23375
  onModeChange: ({ mode: e }) => {
23360
- t || (g(e === "speaking" ? "speaking" : "listening"), e === "listening" && (le.current &&= (clearTimeout(le.current), null), ue.current &&= (clearInterval(ue.current), null)));
23376
+ t || g(e === "speaking" ? "speaking" : "listening");
23377
+ },
23378
+ onAudio: () => {
23379
+ t || (le.current ??= Date.now(), l(), s());
23361
23380
  },
23362
23381
  onAgentChatResponsePart: (e) => {
23363
23382
  if (t) return;
23364
23383
  let n = e?.text_response_part ?? e, r = n?.type, i = n?.text ?? "";
23365
- r === "start" ? (le.current &&= (clearTimeout(le.current), null), ue.current &&= (clearInterval(ue.current), null), v.current = i, ce.current = Date.now(), c()) : r === "delta" ? (v.current += i, ce.current ??= Date.now(), c()) : r === "stop" ? (v.current += i, c()) : (v.current += i, ce.current == null && i && (ce.current = Date.now()), c()), v.current.trim().length >= 18 && s();
23384
+ r === "start" ? (ue.current &&= (clearTimeout(ue.current), null), y.current &&= (clearInterval(y.current), null), b.current != null && (cancelAnimationFrame(b.current), b.current = null), le.current = null, v.current = i, ce.current = Date.now(), l()) : r === "delta" ? (v.current += i, ce.current ??= Date.now(), l()) : r === "stop" ? (v.current += i, l()) : (v.current += i, ce.current == null && i && (ce.current = Date.now()), l()), v.current.trim().length >= 10 && (c(), s());
23366
23385
  },
23367
23386
  onInterruption: () => {
23368
- y();
23387
+ de();
23369
23388
  },
23370
23389
  onMessage: (e) => {
23371
23390
  if (t) return;
@@ -23376,22 +23395,22 @@ function y_({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
23376
23395
  message: r,
23377
23396
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
23378
23397
  };
23379
- n === "user" && (ae.current = r), d.current = [...d.current, i], v_(n, r) && queueMicrotask(() => {
23398
+ n === "user" && (ae.current = r, de()), d.current = [...d.current, i], y_(n, r) && queueMicrotask(() => {
23380
23399
  se.current || (se.current = !0, oe.current?.());
23381
23400
  });
23382
23401
  },
23383
23402
  onError: (e) => {
23384
- t || (console.error("[VoiceInterface] ElevenLabs error", e), y(), g("error"), te("Voice session encountered an error."));
23403
+ t || (console.error("[VoiceInterface] ElevenLabs error", e), de(), g("error"), te("Voice session encountered an error."));
23385
23404
  },
23386
23405
  onDisconnect: () => {
23387
- t || (console.log("[VoiceInterface] session disconnected"), y(), ne(!1), g("idle"));
23406
+ t || (console.log("[VoiceInterface] session disconnected"), de(), ne(!1), g("idle"));
23388
23407
  }
23389
23408
  });
23390
23409
  if (t) {
23391
- l.endSession().catch(() => {});
23410
+ u.endSession().catch(() => {});
23392
23411
  return;
23393
23412
  }
23394
- n = l, re.current = l, ne(!0), g("listening");
23413
+ n = u, re.current = u, ne(!0), g("listening");
23395
23414
  try {
23396
23415
  let e = typeof window < "u" ? window.location.href : "", t = "";
23397
23416
  try {
@@ -23399,14 +23418,14 @@ function y_({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
23399
23418
  } catch {
23400
23419
  t = "[]";
23401
23420
  }
23402
- l.sendContextualUpdate(`Current page URL: ${e}. Site ID: ${r || "unknown"}. Page fields/buttons JSON: ${t}. Navigation: when the user wants to go to any page (contact, pricing, about, services, etc.), call search_site_content then navigate_to_page immediately — never ask permission. After navigating to a page with a form, call list_page_forms and proactively start helping the user fill it. Contact / lead forms: use only the main contact form (Full Name, Email, Message). Ignore footer or secondary marketing URL fields unless the user explicitly asks to use them. Fill in order: name → email → message. Message must be a short visitor note (what they want from the team), not a transcript of the conversation. Forms: use fill_form_fields then click_page_button (e.g. Send Message) when appropriate. Fill each field right after the user gives that value — do not click submit until required fields are filled. Voice: if the user wants to end the voice session, call end_voice_session or confirm and end.`);
23421
+ u.sendContextualUpdate(`Current page URL: ${e}. Site ID: ${r || "unknown"}. Page fields/buttons JSON: ${t}. Navigation: when the user wants to go to any page (contact, pricing, about, services, etc.), call search_site_content then navigate_to_page immediately — never ask permission. After navigating to a page with a form, call list_page_forms and proactively start helping the user fill it. Contact / lead forms: use only the main contact form (Full Name, Email, Message). Ignore footer or secondary marketing URL fields unless the user explicitly asks to use them. Fill in order: name → email → message. Message must be a short visitor note (what they want from the team), not a transcript of the conversation. Forms: use fill_form_fields then click_page_button (e.g. Send Message) when appropriate. Fill each field right after the user gives that value — do not click submit until required fields are filled. Voice: if the user wants to end the voice session, call end_voice_session or confirm and end.`);
23403
23422
  } catch {}
23404
23423
  typeof m == "function" && m();
23405
23424
  } catch (e) {
23406
23425
  t || (console.error("[VoiceInterface] startSession failed", e), g("error"), te("Could not start voice session. Please try again."));
23407
23426
  }
23408
23427
  })(), () => {
23409
- t = !0, y(), n ? n.endSession().catch(() => {}) : re.current && re.current.endSession().catch(() => {});
23428
+ t = !0, de(), n ? n.endSession().catch(() => {}) : re.current && re.current.endSession().catch(() => {});
23410
23429
  };
23411
23430
  }, [
23412
23431
  e,
@@ -23414,9 +23433,9 @@ function y_({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
23414
23433
  a,
23415
23434
  d,
23416
23435
  m,
23417
- y
23436
+ de
23418
23437
  ]);
23419
- let de = h === "listening" || h === "speaking", fe = g_[h] || g_.idle, pe = h_[h] || h_.idle;
23438
+ let pe = h === "listening" || h === "speaking", me = g_[h] || g_.idle, he = h_[h] || h_.idle;
23420
23439
  return /* @__PURE__ */ u("div", {
23421
23440
  ref: ie,
23422
23441
  style: {
@@ -23440,19 +23459,19 @@ function y_({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
23440
23459
  justifyContent: "center"
23441
23460
  },
23442
23461
  children: [
23443
- de && /* @__PURE__ */ l("div", { style: {
23462
+ pe && /* @__PURE__ */ l("div", { style: {
23444
23463
  position: "absolute",
23445
23464
  inset: "-16px",
23446
23465
  borderRadius: "50%",
23447
- border: `2px solid ${fe}`,
23466
+ border: `2px solid ${me}`,
23448
23467
  animation: "fe-orb-pulse 1.4s ease-in-out infinite",
23449
23468
  opacity: .6
23450
23469
  } }),
23451
- de && /* @__PURE__ */ l("div", { style: {
23470
+ pe && /* @__PURE__ */ l("div", { style: {
23452
23471
  position: "absolute",
23453
23472
  inset: "-8px",
23454
23473
  borderRadius: "50%",
23455
- border: `2px solid ${fe}`,
23474
+ border: `2px solid ${me}`,
23456
23475
  animation: "fe-orb-pulse 1.4s ease-in-out 0.35s infinite",
23457
23476
  opacity: .4
23458
23477
  } }),
@@ -23461,18 +23480,18 @@ function y_({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
23461
23480
  width: "140px",
23462
23481
  height: "140px",
23463
23482
  borderRadius: "50%",
23464
- background: pe,
23465
- border: `3px solid ${fe}`,
23483
+ background: he,
23484
+ border: `3px solid ${me}`,
23466
23485
  display: "flex",
23467
23486
  alignItems: "center",
23468
23487
  justifyContent: "center",
23469
23488
  transition: "all 0.35s ease",
23470
23489
  transform: h === "speaking" ? "scale(1.08)" : "scale(1)",
23471
- boxShadow: `0 0 40px ${pe}, 0 8px 32px rgba(0,0,0,0.08)`
23490
+ boxShadow: `0 0 40px ${he}, 0 8px 32px rgba(0,0,0,0.08)`
23472
23491
  },
23473
23492
  children: /* @__PURE__ */ l(An, {
23474
23493
  size: 44,
23475
- color: fe
23494
+ color: me
23476
23495
  })
23477
23496
  })
23478
23497
  ]
@@ -23493,7 +23512,7 @@ function y_({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
23493
23512
  ]
23494
23513
  }),
23495
23514
  /* @__PURE__ */ u("button", {
23496
- onClick: b,
23515
+ onClick: fe,
23497
23516
  style: {
23498
23517
  display: "flex",
23499
23518
  alignItems: "center",
@@ -23522,7 +23541,7 @@ function y_({ agentId: e, chatId: t, siteId: r, apiBaseUrl: a, onEnd: c, history
23522
23541
  }
23523
23542
  //#endregion
23524
23543
  //#region src/components/FlowEngageWidget.jsx
23525
- var b_ = [
23544
+ var x_ = [
23526
23545
  {
23527
23546
  key: "become_client",
23528
23547
  label: "Become a Client"
@@ -23543,7 +23562,7 @@ var b_ = [
23543
23562
  key: "looking_for_job",
23544
23563
  label: "Looking for a Job"
23545
23564
  }
23546
- ], x_ = () => /* @__PURE__ */ l("div", {
23565
+ ], S_ = () => /* @__PURE__ */ l("div", {
23547
23566
  style: {
23548
23567
  display: "flex",
23549
23568
  marginBottom: "12px",
@@ -23574,7 +23593,7 @@ var b_ = [
23574
23593
  } }, e)), /* @__PURE__ */ l("style", { children: "\n @keyframes fe-dot-bounce {\n 0%, 80%, 100% { transform: translateY(0); opacity: 0.5; }\n 40% { transform: translateY(-5px); opacity: 1; }\n }\n " })]
23575
23594
  })
23576
23595
  });
23577
- function S_() {
23596
+ function C_() {
23578
23597
  let { status: e, runtimeConfig: t, resolvedConfig: n, chatId: r, chatHistory: o, isOpen: c, activeScreen: d, isHumanHandled: f, agentName: p, agentHeadshot: m, visitorEmail: h, isAgentTyping: g, isAiTyping: ee, isLoading: te, isVoiceMode: _, isRateLimited: ne, rateLimitMessage: re, isConversationEnded: ie, incomingCall: ae, activeCallId: oe, callConnectionState: se, callConnectedAt: v, isCallMuted: ce, webRTCError: le, language: ue, historyRef: y, onMessageSync: b, endConversation: de, acceptCall: fe, rejectCall: pe, endWebRTCCall: me, toggleCallMute: he, dismissCallError: ge, captureVisitorEmail: _e, openWidget: ve, closeWidget: ye, sendMessage: be, setVoiceMode: xe, startTyping: Se, stopTyping: Ce, updateTypingDraft: we } = Xt(), [Te, Ee] = s(""), [De, Oe] = s(null), [ke, Ae] = s(null), [je, Me] = s(null), [Ne, Pe] = s(0), [x, Fe] = s(h || ""), [Ie, Le] = s("");
23579
23598
  i(() => {
23580
23599
  try {
@@ -23602,7 +23621,7 @@ function S_() {
23602
23621
  outline: "none",
23603
23622
  fontFamily: "ui-sans-serif, system-ui, sans-serif",
23604
23623
  ...c ? {} : Ue
23605
- }, Ge = S.recommendations?.[ue] || Re.recommendations?.[ue] || b_, Ke = S.greetings?.[ue] || Re.greetings?.[ue], qe = ze.chatButtonText || "Chat with us", Je = ze.headerName || t?.websiteName || "OpenSense Labs", C = ze.logoUrl || null, w = ze.hideWatermark || !1, T = Re.elevenLabsAgentId || t?.elevenLabsAgentId || null, Ye = t?.siteId || n?.siteId || null, Xe = t?.apiBaseUrl || "", Ze = ze.fallbackAgentName || "Agent", Qe = ze.botLabel || "AI", $e = m && String(m).trim() || t?.ownerProfileImageUrl && String(t.ownerProfileImageUrl).trim() || null, et = ae?.agentName || p || Ze, tt = o.some((e) => e.sender === "user"), nt = a(() => {
23624
+ }, Ge = S.recommendations?.[ue] || Re.recommendations?.[ue] || x_, Ke = S.greetings?.[ue] || Re.greetings?.[ue], qe = ze.chatButtonText || "Chat with us", Je = ze.headerName || t?.websiteName || "OpenSense Labs", C = ze.logoUrl || null, w = ze.hideWatermark || !1, T = Re.elevenLabsAgentId || t?.elevenLabsAgentId || null, Ye = t?.siteId || n?.siteId || null, Xe = t?.apiBaseUrl || "", Ze = ze.fallbackAgentName || "Agent", Qe = ze.botLabel || "AI", $e = m && String(m).trim() || t?.ownerProfileImageUrl && String(t.ownerProfileImageUrl).trim() || null, et = ae?.agentName || p || Ze, tt = o.some((e) => e.sender === "user"), nt = a(() => {
23606
23625
  let e = o.findIndex((e) => e.sender === "user");
23607
23626
  return e === -1 ? !1 : o.slice(e + 1).some((e) => e.sender === "bot" || e.sender === "ai" || e.sender === "agent");
23608
23627
  }, [o]), rt = !h && tt && nt;
@@ -23730,7 +23749,7 @@ function S_() {
23730
23749
  flexDirection: "column"
23731
23750
  },
23732
23751
  className: "fe-screen-fade-in",
23733
- children: /* @__PURE__ */ l(y_, {
23752
+ children: /* @__PURE__ */ l(b_, {
23734
23753
  agentId: T,
23735
23754
  chatId: r,
23736
23755
  siteId: Ye,
@@ -23763,7 +23782,7 @@ function S_() {
23763
23782
  isAiTyping: ee,
23764
23783
  isAgentTyping: g,
23765
23784
  setReplyContext: Me,
23766
- TypingDots: x_,
23785
+ TypingDots: S_,
23767
23786
  primaryColor: Ve,
23768
23787
  agentHeadshot: $e,
23769
23788
  agentDisplayName: p || Ze
@@ -23842,4 +23861,4 @@ function S_() {
23842
23861
  }) : null;
23843
23862
  }
23844
23863
  //#endregion
23845
- export { Dn as FlowEngageProvider, S_ as FlowEngageWidget, Xt as useFlowEngage };
23864
+ export { Dn as FlowEngageProvider, C_ as FlowEngageWidget, Xt as useFlowEngage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowengage/react-chatbot",
3
- "version": "1.1.7",
3
+ "version": "1.1.8",
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",