@flowengage/react-chatbot 8.0.63 → 8.0.68

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.
@@ -34,11 +34,11 @@ var v = Object.defineProperty, y = Object.getOwnPropertyDescriptor, b = Object.g
34
34
  agentName: "flowengage.agentName",
35
35
  agentHeadshot: "flowengage.agentHeadshot",
36
36
  visitorEmail: "flowengage.visitorEmail"
37
- }, ee = 6e4, te = 480 * 60, ne = 3e4, j = typeof window < "u", M = (e) => e ? `flowengage.visitorEmail.${e}` : null, re = () => {
37
+ }, ee = 6e4, te = 480 * 60, ne = 3e4, j = typeof window < "u", re = (e) => e ? `flowengage.visitorEmail.${e}` : null, ie = () => {
38
38
  if (!j) return null;
39
39
  let e = window.localStorage.getItem(A.chatId);
40
40
  return e && String(e).trim() ? String(e).trim() : null;
41
- }, ie = () => {
41
+ }, M = () => {
42
42
  if (j) try {
43
43
  window.localStorage.removeItem(A.chatId);
44
44
  } catch {}
@@ -100,7 +100,7 @@ var v = Object.defineProperty, y = Object.getOwnPropertyDescriptor, b = Object.g
100
100
  });
101
101
  }, he = (e) => {
102
102
  if (!j || !e) return "";
103
- let t = M(e), n = window.localStorage.getItem(t);
103
+ let t = re(e), n = window.localStorage.getItem(t);
104
104
  if (!n) {
105
105
  let e = window.sessionStorage.getItem(A.visitorEmail);
106
106
  e && (window.localStorage.setItem(t, e), window.sessionStorage.removeItem(A.visitorEmail), n = e);
@@ -108,7 +108,7 @@ var v = Object.defineProperty, y = Object.getOwnPropertyDescriptor, b = Object.g
108
108
  return n || "";
109
109
  }, N = (e, t) => {
110
110
  if (!j) return;
111
- let n = M(t);
111
+ let n = re(t);
112
112
  if (!n) return;
113
113
  let r = typeof e == "string" ? e.trim() : "";
114
114
  if (!r) {
@@ -2919,7 +2919,7 @@ function Mr({ siteId: e, config: t, children: n, language: r = "en" }) {
2919
2919
  message: "Looks like you're already on this page!",
2920
2920
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
2921
2921
  }]);
2922
- }, []), [T, D] = m(pe().isOpen), [O, k] = m(pe().activeScreen), [A, j] = m(pe().isHumanHandled), [M, oe] = m(pe().agentName), [se, ce] = m(pe().agentHeadshot), [le, ge] = m(() => he(i?.siteId)), [_e, ve] = m(!1), [be, xe] = m(!1), [Se, Ce] = m("idle"), [P, we] = m(!1), [Te, F] = m(!1), [De, Oe] = m(""), [I, ke] = m(!1), [Ae, je] = m(0), [Me, Ne] = m(0), [Pe, L] = m(!1), [R, Re] = m(null), [ze, Be] = m(null), [Ve, He] = m("idle"), [Ue, We] = m(null), [Ge, Ke] = m(!1), [qe, Je] = m(""), [Ye, Xe] = m(!1), z = p(null), B = p(null), Ze = p(""), Qe = p(!1), $e = p(null), et = p(null), tt = p(null), V = p(null), H = p(null), nt = p(null), rt = p(null), it = p(!1), U = p({
2922
+ }, []), [T, D] = m(pe().isOpen), [O, k] = m(pe().activeScreen), [A, j] = m(pe().isHumanHandled), [re, oe] = m(pe().agentName), [se, ce] = m(pe().agentHeadshot), [le, ge] = m(() => he(i?.siteId)), [_e, ve] = m(!1), [be, xe] = m(!1), [Se, Ce] = m("idle"), [P, we] = m(!1), [Te, F] = m(!1), [De, Oe] = m(""), [I, ke] = m(!1), [Ae, je] = m(0), [Me, Ne] = m(0), [Pe, L] = m(!1), [R, Re] = m(null), [ze, Be] = m(null), [Ve, He] = m("idle"), [Ue, We] = m(null), [Ge, Ke] = m(!1), [qe, Je] = m(""), [Ye, Xe] = m(!1), z = p(null), B = p(null), Ze = p(""), Qe = p(!1), $e = p(null), et = p(null), tt = p(null), V = p(null), H = p(null), nt = p(null), rt = p(null), it = p(!1), U = p({
2923
2923
  url: null,
2924
2924
  at: 0
2925
2925
  }), at = o((e, t) => {
@@ -2935,7 +2935,7 @@ function Mr({ siteId: e, config: t, children: n, language: r = "en" }) {
2935
2935
  url: n,
2936
2936
  at: Date.now()
2937
2937
  }, br(e, t));
2938
- }, []), ot = p([]), W = p(null), st = p(null), ct = p(null), lt = p(!1), ut = p(!1), dt = p(""), ft = p(null), pt = p(null), mt = p([]), ht = p(0), gt = p(M), _t = p([]), vt = p(!1), yt = p(!1), bt = p(i), xt = p({
2938
+ }, []), ot = p([]), W = p(null), st = p(null), ct = p(null), lt = p(!1), ut = p(!1), dt = p(""), ft = p(null), pt = p(null), mt = p([]), ht = p(0), gt = p(re), _t = p([]), vt = p(!1), yt = p(!1), bt = p(i), xt = p({
2939
2939
  notifyRouteChange: () => {},
2940
2940
  cleanup: () => {}
2941
2941
  }), St = o((e = {}) => {
@@ -2948,8 +2948,8 @@ function Mr({ siteId: e, config: t, children: n, language: r = "en" }) {
2948
2948
  c(() => {
2949
2949
  et.current = R;
2950
2950
  }, [R]), c(() => {
2951
- gt.current = M;
2952
- }, [M]), c(() => {
2951
+ gt.current = re;
2952
+ }, [re]), c(() => {
2953
2953
  yt.current = I;
2954
2954
  }, [I]), c(() => {
2955
2955
  bt.current = i;
@@ -3104,14 +3104,14 @@ function Mr({ siteId: e, config: t, children: n, language: r = "en" }) {
3104
3104
  isOpen: T,
3105
3105
  activeScreen: O,
3106
3106
  isHumanHandled: A,
3107
- agentName: M,
3107
+ agentName: re,
3108
3108
  agentHeadshot: se
3109
3109
  });
3110
3110
  }, [
3111
3111
  T,
3112
3112
  O,
3113
3113
  A,
3114
- M,
3114
+ re,
3115
3115
  se
3116
3116
  ]), c(() => {
3117
3117
  let e = !0;
@@ -3127,12 +3127,12 @@ function Mr({ siteId: e, config: t, children: n, language: r = "en" }) {
3127
3127
  apiBaseUrl: t.apiBaseUrl,
3128
3128
  userId: n.userId,
3129
3129
  siteId: a,
3130
- priorChatId: e || r ? null : o || re(),
3130
+ priorChatId: e || r ? null : o || ie(),
3131
3131
  forceNew: e,
3132
3132
  resumeChatId: r,
3133
3133
  visitorId: s
3134
3134
  }))?.data?.chatId, !c) throw Error("resolve-session returned no chatId");
3135
- ie(), fe(a, c);
3135
+ M(), fe(a, c);
3136
3136
  } catch (e) {
3137
3137
  console.warn("[FlowEngageProvider] resolve-session failed, reusing persisted or ephemeral chat id", e?.message || e), c = o || ae(), fe(a, c);
3138
3138
  }
@@ -3808,7 +3808,7 @@ function Mr({ siteId: e, config: t, children: n, language: r = "en" }) {
3808
3808
  isOpen: T,
3809
3809
  activeScreen: O,
3810
3810
  isHumanHandled: A,
3811
- agentName: M,
3811
+ agentName: re,
3812
3812
  agentHeadshot: se,
3813
3813
  visitorEmail: le,
3814
3814
  isAgentTyping: _e,
@@ -3869,7 +3869,7 @@ function Mr({ siteId: e, config: t, children: n, language: r = "en" }) {
3869
3869
  T,
3870
3870
  O,
3871
3871
  A,
3872
- M,
3872
+ re,
3873
3873
  se,
3874
3874
  le,
3875
3875
  _e,
@@ -8826,7 +8826,7 @@ var _m = {
8826
8826
  ..._m,
8827
8827
  ...nm,
8828
8828
  ...vm
8829
- }, hp), bm = 24e3, xm = 2048, Sm = 1200, Cm = .05, wm = 3;
8829
+ }, hp), bm = 24e3, xm = 2048, Sm = 1200, Cm = .05, wm = 4;
8830
8830
  function Tm(e) {
8831
8831
  let t = 0;
8832
8832
  for (let n = 0; n < e.length; n++) t += e[n] * e[n];
@@ -8845,28 +8845,29 @@ function Dm(e) {
8845
8845
  for (let n = 0; n < e.length; n++) t[n] = e[n] / 32768;
8846
8846
  return t;
8847
8847
  }
8848
- var Om = .18;
8848
+ var Om = .09;
8849
8849
  function km(e, t) {
8850
- let n = 0, r = [], i = () => {
8851
- r.forEach((e) => {
8850
+ let n = 0, r = 0, i = [], a = () => {
8851
+ i.forEach((e) => {
8852
8852
  try {
8853
8853
  e.stop();
8854
8854
  } catch {}
8855
- }), r = [], n = 0;
8856
- }, a = () => n > e.currentTime;
8855
+ }), i = [], n = 0;
8856
+ }, o = () => n > e.currentTime;
8857
8857
  return {
8858
- enqueue: (i) => {
8859
- let o = Dm(i), s = e.createBuffer(1, o.length, bm);
8860
- s.copyToChannel(o, 0);
8861
- let c = e.createBufferSource();
8862
- c.buffer = s, c.connect(e.destination);
8863
- let l = a() ? n : e.currentTime + Om;
8864
- c.start(l), n = l + s.duration, r.push(c), c.onended = () => {
8865
- r = r.filter((e) => e !== c), !r.length && !a() && t?.();
8858
+ enqueue: (a) => {
8859
+ let s = Dm(a), c = e.createBuffer(1, s.length, bm);
8860
+ c.copyToChannel(s, 0);
8861
+ let l = e.createBufferSource();
8862
+ l.buffer = c, l.connect(e.destination);
8863
+ let u = !o(), d = u ? e.currentTime + Om : n;
8864
+ u && (r = d), l.start(d), n = d + c.duration, i.push(l), l.onended = () => {
8865
+ i = i.filter((e) => e !== l), !i.length && !o() && t?.();
8866
8866
  };
8867
8867
  },
8868
- stop: i,
8869
- isPlaying: a
8868
+ stop: a,
8869
+ isPlaying: o,
8870
+ playedMs: () => Math.max(0, (e.currentTime - r) * 1e3)
8870
8871
  };
8871
8872
  }
8872
8873
  async function Am(e, t, n) {
@@ -8921,26 +8922,26 @@ async function jm(e) {
8921
8922
  }
8922
8923
  }, C = (e, t) => {
8923
8924
  t && (b.role && b.role !== e && S(), b.role = e, b.text = b.text ? `${b.text} ${t}`.replace(/\s+/g, " ") : t, b.timer && clearTimeout(b.timer), b.timer = setTimeout(S, Sm));
8924
- }, w = !1, T = !1, E = !1, D = !1, O = !0, k = 0, A = !1, ee = !1, te = null, ne = !1, j = () => {
8925
- te && clearTimeout(te);
8925
+ }, w = !1, T = !1, E = !1, D = !1, O = !0, k = 0, A = !1, ee = !1, te = Cm, ne = wm, j = null, re = !1, ie = () => {
8926
+ j && clearTimeout(j);
8926
8927
  let e = () => {
8927
8928
  if (!w) {
8928
8929
  if (M.isPlaying()) {
8929
- te = setTimeout(e, 150);
8930
+ j = setTimeout(e, 150);
8930
8931
  return;
8931
8932
  }
8932
- if (te = null, ne) {
8933
+ if (j = null, re) {
8933
8934
  p?.();
8934
8935
  return;
8935
8936
  }
8936
8937
  !w && v.readyState === WebSocket.OPEN && v.send(JSON.stringify({ type: "PlaybackDrained" })), d?.();
8937
8938
  }
8938
8939
  };
8939
- te = setTimeout(e, 150);
8940
+ j = setTimeout(e, 150);
8940
8941
  }, M = km(_, () => {
8941
8942
  D && (D = !1, c?.({ mode: "listening" }));
8942
- }), re = _.createMediaStreamSource(g), ie = _.createScriptProcessor(xm, 1, 1);
8943
- ie.onaudioprocess = (e) => {
8943
+ }), ae = _.createMediaStreamSource(g), oe = _.createScriptProcessor(xm, 1, 1);
8944
+ oe.onaudioprocess = (e) => {
8944
8945
  if (w || v.readyState !== WebSocket.OPEN) return;
8945
8946
  let t = e.inputBuffer.getChannelData(0), n = () => v.send(new Int16Array(t.length).buffer);
8946
8947
  if (T) {
@@ -8948,27 +8949,32 @@ async function jm(e) {
8948
8949
  return;
8949
8950
  }
8950
8951
  if ((M.isPlaying() || ee) && !A) {
8951
- if (Tm(t) < Cm) {
8952
+ if (Tm(t) < te) {
8952
8953
  k = 0, n();
8953
8954
  return;
8954
8955
  }
8955
- if (k += 1, k < wm) {
8956
+ if (k += 1, k < ne) {
8956
8957
  n();
8957
8958
  return;
8958
8959
  }
8959
- A = !0, k = 0, M.stop(), O = !1, console.debug("[FlowEngage] barge-in — visitor spoke over the agent");
8960
+ A = !0, k = 0;
8961
+ let e = M.playedMs();
8962
+ M.stop(), O = !1, ee = !1, v.send(JSON.stringify({
8963
+ type: "VisitorInterrupted",
8964
+ played_ms: Math.round(e)
8965
+ })), console.debug("[FlowEngage] barge-in — visitor spoke over the agent");
8960
8966
  }
8961
8967
  v.send(Em(t).buffer);
8962
- }, re.connect(ie), ie.connect(_.destination);
8963
- let ae = () => {
8968
+ }, ae.connect(oe), oe.connect(_.destination);
8969
+ let se = () => {
8964
8970
  if (!w) {
8965
- w = !0, te &&= (clearTimeout(te), null), S(), M.stop();
8971
+ w = !0, j &&= (clearTimeout(j), null), S(), M.stop();
8966
8972
  try {
8967
- ie.disconnect(), re.disconnect();
8973
+ oe.disconnect(), ae.disconnect();
8968
8974
  } catch {}
8969
8975
  g.getTracks().forEach((e) => e.stop()), _.close().catch(() => {}), (v.readyState === WebSocket.OPEN || v.readyState === WebSocket.CONNECTING) && v.close();
8970
8976
  }
8971
- }, oe = async (e) => {
8977
+ }, ce = async (e) => {
8972
8978
  let t = i[e.name];
8973
8979
  if (!t) return u?.({ tool_name: e.name }), { error: `Unknown tool ${e.name}` };
8974
8980
  let n = {};
@@ -8980,10 +8986,10 @@ async function jm(e) {
8980
8986
  } catch (e) {
8981
8987
  return { error: e?.message || "Tool execution failed" };
8982
8988
  }
8983
- }, se = async (e) => {
8989
+ }, le = async (e) => {
8984
8990
  for (let t of e.functions || []) {
8985
8991
  if (!t.client_side) continue;
8986
- let e = await oe(t);
8992
+ let e = await ce(t);
8987
8993
  if (w || v.readyState !== WebSocket.OPEN) return;
8988
8994
  v.send(JSON.stringify({
8989
8995
  type: "FunctionCallResponse",
@@ -8992,10 +8998,10 @@ async function jm(e) {
8992
8998
  content: typeof e == "string" ? e : JSON.stringify(e ?? {})
8993
8999
  }));
8994
9000
  }
8995
- }, ce = (e) => {
9001
+ }, ue = (e) => {
8996
9002
  switch (e.type) {
8997
9003
  case "Welcome":
8998
- a?.({ conversationId: e.session_id || r || n });
9004
+ Number.isFinite(e.barge_in_rms) && e.barge_in_rms > 0 && (te = e.barge_in_rms), Number.isFinite(e.barge_in_frames) && e.barge_in_frames > 0 && (ne = e.barge_in_frames), a?.({ conversationId: e.session_id || r || n });
8999
9005
  break;
9000
9006
  case "ConversationText": {
9001
9007
  let t = String(e.content || "");
@@ -9020,16 +9026,16 @@ async function jm(e) {
9020
9026
  O = !0, D = !0, A = !1, k = 0, c?.({ mode: "speaking" });
9021
9027
  break;
9022
9028
  case "AgentAudioDone":
9023
- ee = !1, S(), j(), M.isPlaying() || (D = !1, c?.({ mode: "listening" }));
9029
+ ee = !1, S(), ie(), M.isPlaying() || (D = !1, c?.({ mode: "listening" }));
9024
9030
  break;
9025
9031
  case "FunctionCallRequest":
9026
- se(e);
9032
+ le(e);
9027
9033
  break;
9028
9034
  case "AgentPreparing":
9029
9035
  ee = !0;
9030
9036
  break;
9031
9037
  case "SessionEnding":
9032
- console.debug("[FlowEngage] server is ending the session:", e.reason || "unspecified"), ne = !0;
9038
+ console.debug("[FlowEngage] server is ending the session:", e.reason || "unspecified"), re = !0;
9033
9039
  break;
9034
9040
  case "PromptUpdated":
9035
9041
  case "AgentThinking": break;
@@ -9048,12 +9054,12 @@ async function jm(e) {
9048
9054
  return;
9049
9055
  }
9050
9056
  try {
9051
- ce(JSON.parse(e.data));
9057
+ ue(JSON.parse(e.data));
9052
9058
  } catch {}
9053
9059
  }, v.onerror = () => l?.(/* @__PURE__ */ Error("Voice connection failed")), v.onclose = () => {
9054
- ae(), o?.();
9060
+ se(), o?.();
9055
9061
  }, {
9056
- endSession: async () => ae(),
9062
+ endSession: async () => se(),
9057
9063
  sendContextualUpdate: (e) => {
9058
9064
  w || v.readyState !== WebSocket.OPEN || !e || v.send(JSON.stringify({
9059
9065
  type: "UpdatePrompt",
@@ -12144,7 +12150,7 @@ function hg(e) {
12144
12150
  let { headings: e } = pg(), t = e.length ? `Page headings: ${e.map((e) => `"${e}"`).join(" | ")}. Use one of these EXACT strings for section_text — no numbers, no quotes around them.` : "No headings found — skip highlight and continue speaking.";
12145
12151
  return `HIGHLIGHT_NOT_FOUND: "${i || n}" on the current page. ${t}`;
12146
12152
  }
12147
- return Dn(a), $("fwh-highlight-mvp ✓", i || n), `OK_HIGHLIGHT: "${i || n}". Your NEXT response must be speech only (no tool call) describing THIS section — "${i || n}" — using its own content, then end with the continue question.`;
12153
+ return Dn(a), $("fwh-highlight-mvp ✓", i || n), `OK_HIGHLIGHT: "${i || n}". Your NEXT response must be speech only (no tool call) describing THIS section — "${i || n}" — using its own content. Do not ask whether to continue.`;
12148
12154
  },
12149
12155
  "fwh-read-content-mvp": async (e) => {
12150
12156
  $("fwh-read-content-mvp ▶", e);
@@ -12786,7 +12792,7 @@ function Og({ copy: e, orbColors: t, primaryColor: n, onVoice: r, onText: i, onC
12786
12792
  }
12787
12793
  function kg({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i, apiBaseUrl: a, chatId: s, historyRef: l, onMessageSync: u, voiceEndCounter: d, websiteName: f, voiceFirstMessage: h, captureVisitorEmail: v, emailRequired: y, emailCaptureEnabled: b = !0, listeningLabel: x = "Listening...", enterChatModeLabel: S = "Enter Chat Mode", endConversationLabel: C = "End Conversation" }) {
12788
12794
  c(() => (console.log("[FlowEngage:VoiceDebug] 🔵 VoiceMode MOUNTED"), () => console.log("[FlowEngage:VoiceDebug] 🔴 VoiceMode UNMOUNTED")), []);
12789
- let [w, T] = m("idle"), [E, D] = m(!1), [O, k] = m(!1), [A, ee] = m(!1), [te, ne] = m(""), [j, M] = m(""), re = p(!1), ie = p(!1), ae = p(null), oe = p(0), se = p(""), ce = p(!1), le = p(0), ue = p(!1), de = p(!1), fe = p([]), pe = p(null), me = (e) => {
12795
+ let [w, T] = m("idle"), [E, D] = m(!1), [O, k] = m(!1), [A, ee] = m(!1), [te, ne] = m(""), [j, re] = m(""), ie = p(!1), M = p(!1), ae = p(null), oe = p(0), se = p(""), ce = p(!1), le = p(0), ue = p(!1), de = p(!1), fe = p([]), pe = p(null), me = (e) => {
12790
12796
  ue.current = e, N.current?.setWalkthroughActive?.(e);
12791
12797
  };
12792
12798
  pe.current = async () => {
@@ -12814,10 +12820,10 @@ function kg({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
12814
12820
  }, []);
12815
12821
  c(() => {
12816
12822
  if (y) {
12817
- re.current = !1;
12823
+ ie.current = !1;
12818
12824
  return;
12819
12825
  }
12820
- if (re.current = !0, ie.current = !1, ee(!1), L(), ce.current) {
12826
+ if (ie.current = !0, M.current = !1, ee(!1), L(), ce.current) {
12821
12827
  ce.current = !1, N.current?.setMicMuted?.(!1);
12822
12828
  let e = se.current;
12823
12829
  se.current = "", N.current?.injectAgentSpeech?.("Thanks — I already have your email on file.", "interrupt"), e && N.current?.sendUserMessage?.(`The visitor's email is already on file — do not ask for it. Answer their question now: "${e}"`);
@@ -12826,7 +12832,7 @@ function kg({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
12826
12832
  }, [y, L]);
12827
12833
  let Fe = /(walk\s*(me\s*)?through|walkthrough|take me through|complete overview|full overview|give me (a|an|the) (overview|tour|walk)|tell me about (each|all)|go through (it|them|each|all)|overview of|one by one|tell me everything|show me (each|all|around))/i, Ie = /(that covers everything|that was all|covered everything|anything else)/i, Le = o(() => {
12828
12834
  L(), ae.current = setTimeout(() => {
12829
- if (!(!ie.current || re.current)) if (oe.current < 3) {
12835
+ if (!(!M.current || ie.current)) if (oe.current < 3) {
12830
12836
  oe.current += 1;
12831
12837
  try {
12832
12838
  N.current?.injectAgentSpeech?.("I still need your email in the box below to continue — could you enter it, please?", "queue");
@@ -12836,7 +12842,7 @@ function kg({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
12836
12842
  try {
12837
12843
  N.current?.injectAgentSpeech?.("Since I haven't received your email, I'll close this session for now. Feel free to come back anytime — take care!", "queue");
12838
12844
  } catch {}
12839
- ie.current = !1, ee(!1), L(), I.current = !0;
12845
+ M.current = !1, ee(!1), L(), I.current = !0;
12840
12846
  }
12841
12847
  }, 1e4);
12842
12848
  }, [L]), R = o(async (e) => {
@@ -12921,7 +12927,7 @@ function kg({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
12921
12927
  I.current = !0;
12922
12928
  },
12923
12929
  requestEmailCollection: () => {
12924
- b && (re.current || ie.current || (ie.current = !0, oe.current = 0, ee(!0), Le()));
12930
+ b && (ie.current || M.current || (M.current = !0, oe.current = 0, ee(!0), Le()));
12925
12931
  }
12926
12932
  })), n = i ? we(i) : null, r = !!n?.transcript, u = i ? Ne(i) : null, p = !!u, m = typeof window < "u" ? window.location.pathname : "/", g = typeof document < "u" ? document.title : "", _ = m.replace(/^\/[a-z]{2}(?:-[a-z]{2})?(?=\/|$)/i, "") || "/", v = _ === "/" || _ === "", x = {
12927
12933
  apiBaseUrl: a,
@@ -12947,14 +12953,14 @@ function kg({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
12947
12953
  let e = f || "";
12948
12954
  x.greeting = h || (v ? e ? `Hi, welcome to ${e}! How may I help you?` : "Hi, welcome! How may I help you?" : `Welcome to the ${w} page!`), v || console.log(`[FlowEngage] 🏠 Page-context greeting: "${w}" for ${m}`);
12949
12955
  }
12950
- let O = !1, k = p ? `NAVIGATION COMPLETE — The exact phrase "I have navigated you on [page] page. Do you want to know about any specific section or want a complete overview?" has already been spoken as your firstMessage. DO NOT repeat it. PRIOR CONVERSATION CONTEXT:\n${n?.transcript ? `Prior transcript:\n${n.transcript}\n` : "(no prior transcript)"}\nNow STOP — wait silently for the visitor's reply. Do NOT speak, do NOT call any tool until the visitor responds. When they reply: if they name a specific section → call fwh-get-current-page-mvp then answer immediately; if they say "overview" or anything non-specific → call fwh-get-current-page-mvp (zero speech) then do a full highlighted walkthrough.` : null, A = !1, te = !p && !r ? "Your greeting has been spoken. Wait for the visitor to ask a question or tell you what they need. Do NOT auto-start a walkthrough or highlight any sections — let the visitor lead." : null, ne = r && !p, j = !1, M = ne ? `The question "Would you like me to continue what I was explaining before, or would you like to know about this page instead?" has already been spoken as your firstMessage. DO NOT repeat it. PRIOR CONVERSATION CONTEXT:\n${n?.transcript ? `Prior transcript:\n${n.transcript}\n` : "(no prior transcript, or the visitor navigated before saying much)"}\nNow STOP — wait silently for the visitor's reply. Do NOT speak, do NOT call any tool until they respond. When they reply: if they want you to CONTINUE the previous topic → resume verbally from the prior transcript above, do NOT call fwh-get-current-page-mvp or describe the new page unless they ask. If they want to know about THIS page → call fwh-get-current-page-mvp (zero speech) then proceed as a normal fresh-page walkthrough/description. If their reply is ambiguous, ask them to clarify which they'd prefer rather than guessing.` : null, ae = !1, _e = !1, Te = b && !!y && !de.current, De = await Mm.startSession({
12956
+ let O = !1, k = p ? `NAVIGATION COMPLETE — The exact phrase "I have navigated you on [page] page. Do you want to know about any specific section or want a complete overview?" has already been spoken as your firstMessage. DO NOT repeat it. PRIOR CONVERSATION CONTEXT:\n${n?.transcript ? `Prior transcript:\n${n.transcript}\n` : "(no prior transcript)"}\nNow STOP — wait silently for the visitor's reply. Do NOT speak, do NOT call any tool until the visitor responds. When they reply: if they name a specific section → call fwh-get-current-page-mvp then answer immediately; if they say "overview" or anything non-specific → call fwh-get-current-page-mvp (zero speech) then do a full highlighted walkthrough.` : null, A = !1, te = !p && !r ? "Your greeting has been spoken. Wait for the visitor to ask a question or tell you what they need. Do NOT auto-start a walkthrough or highlight any sections — let the visitor lead." : null, ne = r && !p, j = !1, re = ne ? `The question "Would you like me to continue what I was explaining before, or would you like to know about this page instead?" has already been spoken as your firstMessage. DO NOT repeat it. PRIOR CONVERSATION CONTEXT:\n${n?.transcript ? `Prior transcript:\n${n.transcript}\n` : "(no prior transcript, or the visitor navigated before saying much)"}\nNow STOP — wait silently for the visitor's reply. Do NOT speak, do NOT call any tool until they respond. When they reply: if they want you to CONTINUE the previous topic → resume verbally from the prior transcript above, do NOT call fwh-get-current-page-mvp or describe the new page unless they ask. If they want to know about THIS page → call fwh-get-current-page-mvp (zero speech) then proceed as a normal fresh-page walkthrough/description. If their reply is ambiguous, ask them to clarify which they'd prefer rather than guessing.` : null, ae = !1, _e = !1, Te = b && !!y && !de.current, De = await Mm.startSession({
12951
12957
  ...x,
12952
12958
  onConnect: ({ conversationId: e }) => {
12953
12959
  Ce.current = e, F.current = Date.now(), console.log("[FlowEngage] 🎙️ AI chat session connected:", e);
12954
12960
  },
12955
12961
  onUnhandledClientToolCall: (e) => console.error("[FlowEngage] Unhandled tool:", e?.tool_name),
12956
12962
  onSessionInfo: ({ emailOnFile: e }) => {
12957
- de.current = !!e, e && (re.current = !0, ie.current = !1, ee(!1), L(), console.log("[FlowEngage] email already on file per server — gate disabled"));
12963
+ de.current = !!e, e && (ie.current = !0, M.current = !1, ee(!1), L(), console.log("[FlowEngage] email already on file per server — gate disabled"));
12958
12964
  },
12959
12965
  onAgentTurnEnd: () => {
12960
12966
  e || ue.current && (ce.current || setTimeout(() => pe.current?.(), 250));
@@ -12972,7 +12978,7 @@ function kg({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
12972
12978
  I.current = !1, Pe();
12973
12979
  return;
12974
12980
  }
12975
- if (Te && !_e && !re.current && !de.current) {
12981
+ if (Te && !_e && !ie.current && !de.current) {
12976
12982
  _e = !0, O = !0, A = !0;
12977
12983
  try {
12978
12984
  N.current?.sendContextualUpdate?.("CRITICAL — EMAIL REQUIRED BEFORE ANYTHING ELSE. The visitor has not provided their email. Do NOT speak right now. Wait silently for the visitor to speak first. The MOMENT the visitor says ANYTHING — a question, a request, or just a greeting — your ENTIRE next response must be EXACTLY this one sentence: \"Before I answer that, could you please enter your email in the text box below?\" Do NOT answer their question. Do NOT say anything about the topic. Do NOT begin an answer and then switch — your first word must be \"Before\". After you say that sentence, stay completely silent until you receive an EMAIL_SAVED message, then thank them briefly and answer their question in full.");
@@ -12984,10 +12990,10 @@ function kg({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
12984
12990
  N.current?.sendContextualUpdate?.(k);
12985
12991
  } catch {}
12986
12992
  }
12987
- if (M && !j) {
12993
+ if (re && !j) {
12988
12994
  j = !0;
12989
12995
  try {
12990
- N.current?.sendContextualUpdate?.(M);
12996
+ N.current?.sendContextualUpdate?.(re);
12991
12997
  } catch {}
12992
12998
  }
12993
12999
  if (te && !A) {
@@ -13003,15 +13009,15 @@ function kg({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
13003
13009
  },
13004
13010
  onMessage: (t) => {
13005
13011
  if (e || ce.current && t.role !== "user" && !/email/i.test(String(t.message || ""))) return;
13006
- t.role === "user" && Fe.test(String(t.message || "")) && (me(!0), le.current = 0, he.current = -1, fe.current = _g(), setTimeout(() => pe.current?.(), 400), console.log(`[FlowEngage] walkthrough armed — ${fe.current.length} sections on this page`)), t.role !== "user" && Ie.test(String(t.message || "")) && me(!1);
13012
+ t.role === "user" && Fe.test(String(t.message || "")) && (typeof window < "u" && (window.__fe_user_nav_during_speech = null), me(!0), le.current = 0, he.current = -1, fe.current = _g(), setTimeout(() => pe.current?.(), 400), console.log(`[FlowEngage] walkthrough armed — ${fe.current.length} sections on this page`)), t.role !== "user" && Ie.test(String(t.message || "")) && me(!1);
13007
13013
  let n = t.role === "user" ? "user" : "bot", r = t.message || t.text || t.content || "";
13008
13014
  if (r) {
13009
13015
  if (n === "user") {
13010
- ge.current = r, Me.current = !0, je.current &&= (clearTimeout(je.current), null);
13016
+ ge.current = r, typeof window < "u" && (window.__fe_user_nav_during_speech = null), Me.current = !0, je.current &&= (clearTimeout(je.current), null);
13011
13017
  try {
13012
13018
  On();
13013
13019
  } catch {}
13014
- Te && !ae && !re.current && !de.current && (ae = !0, se.current = r, ce.current = !0, N.current?.injectAgentSpeech?.("Before I answer that, could you please enter your email in the text box below?", "interrupt"), N.current?.setMicMuted?.(!0), ie.current || (ie.current = !0, oe.current = 0, ee(!0), Le()));
13020
+ Te && !ae && !ie.current && !de.current && (ae = !0, se.current = r, ce.current = !0, N.current?.injectAgentSpeech?.("Before I answer that, could you please enter your email in the text box below?", "interrupt"), N.current?.setMicMuted?.(!0), M.current || (M.current = !0, oe.current = 0, ee(!0), Le()));
13015
13021
  }
13016
13022
  if (l.current = [...l.current, {
13017
13023
  sender: n,
@@ -13179,18 +13185,18 @@ function kg({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
13179
13185
  e?.preventDefault?.();
13180
13186
  let t = te.trim().toLowerCase();
13181
13187
  if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)) {
13182
- M("Please enter a valid email address.");
13188
+ re("Please enter a valid email address.");
13183
13189
  return;
13184
13190
  }
13185
- M("");
13191
+ re("");
13186
13192
  try {
13187
13193
  typeof v == "function" && await v(t);
13188
13194
  } catch {}
13189
- re.current = !0, ie.current = !1, L(), ee(!1), ne(""), ce.current = !1, N.current?.setMicMuted?.(!1);
13195
+ ie.current = !0, M.current = !1, L(), ee(!1), ne(""), ce.current = !1, N.current?.setMicMuted?.(!1);
13190
13196
  let n = se.current;
13191
13197
  se.current = "";
13192
13198
  try {
13193
- N.current?.sendUserMessage?.("[SYSTEM: EMAIL_SAVED the visitor typed and submitted their email address. Say a brief 'Thank you!' and then " + (n ? `immediately answer their original question fully: "${n}".` : "continue helping them.") + " Do NOT ask for their email again.]");
13199
+ N.current?.injectAgentSpeech?.("Thank you for submitting your email."), N.current?.sendUserMessage?.(n || "The visitor's email is on file. Carry on helping them and never ask for it again.");
13194
13200
  } catch {}
13195
13201
  }, [
13196
13202
  te,
@@ -13242,7 +13248,7 @@ function kg({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
13242
13248
  autoFocus: !0,
13243
13249
  value: te,
13244
13250
  onChange: (e) => {
13245
- ne(e.target.value), j && M("");
13251
+ ne(e.target.value), j && re("");
13246
13252
  },
13247
13253
  placeholder: "you@example.com",
13248
13254
  style: {
@@ -13591,7 +13597,7 @@ var jg = () => /* @__PURE__ */ g("div", {
13591
13597
  } }, e))
13592
13598
  })
13593
13599
  });
13594
- function Mg({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i, quickChatOptions: a, onQuickChatSelect: o, isMobile: s, chatHistory: l, isAiTyping: u, isAgentTyping: d, activeScreen: f, agentName: v, agentHeadshot: y, fallbackAgentName: b, input: x, setInput: S, onSubmit: C, isConversationEnded: w, isLoading: T, isRateLimited: E, rateLimitMessage: D, selectedFile: O, onFileSelect: k, onRemoveSelectedFile: A, attachmentError: ee, isUploadingAttachment: te, requiresEmail: ne, emailInput: j, setEmailInput: M, emailError: re, emailCaptureSuccess: ie, replyContext: ae, setReplyContext: oe, webRTCError: se, micError: ce, setMicError: le, dismissCallError: ue, activeCallId: de, isCallMuted: fe, toggleCallMute: pe, endWebRTCCall: me, formatCallDuration: he, callDurationSeconds: N, isCallMinimized: ge, onExpand: _e, onCollapse: ve, onStartVoice: ye, voiceEnabled: be, headerBgColor: xe, onNewChat: Se, showPoweredBy: Ce, privacyPolicyUrl: P, getVisitorChatHistory: we, resumeChat: Te, isSessionRestoring: F, isClosing: Ee }) {
13600
+ function Mg({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i, quickChatOptions: a, onQuickChatSelect: o, isMobile: s, chatHistory: l, isAiTyping: u, isAgentTyping: d, activeScreen: f, agentName: v, agentHeadshot: y, fallbackAgentName: b, input: x, setInput: S, onSubmit: C, isConversationEnded: w, isLoading: T, isRateLimited: E, rateLimitMessage: D, selectedFile: O, onFileSelect: k, onRemoveSelectedFile: A, attachmentError: ee, isUploadingAttachment: te, requiresEmail: ne, emailInput: j, setEmailInput: re, emailError: ie, emailCaptureSuccess: M, replyContext: ae, setReplyContext: oe, webRTCError: se, micError: ce, setMicError: le, dismissCallError: ue, activeCallId: de, isCallMuted: fe, toggleCallMute: pe, endWebRTCCall: me, formatCallDuration: he, callDurationSeconds: N, isCallMinimized: ge, onExpand: _e, onCollapse: ve, onStartVoice: ye, voiceEnabled: be, headerBgColor: xe, onNewChat: Se, showPoweredBy: Ce, privacyPolicyUrl: P, getVisitorChatHistory: we, resumeChat: Te, isSessionRestoring: F, isClosing: Ee }) {
13595
13601
  let De = l.length > 0, Oe = T || E || w, I = !!de, [ke, Ae] = m(!1), [je, Me] = m(!1), [Ne, Pe] = m([]), [L, Fe] = m(!1), Ie = p(null), [Le, R] = m(() => typeof window < "u" ? window.visualViewport?.height ?? window.innerHeight : 600), [Re, ze] = m(0);
13596
13602
  c(() => {
13597
13603
  if (!s) return;
@@ -14270,7 +14276,7 @@ function Mg({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i
14270
14276
  ]
14271
14277
  })]
14272
14278
  }),
14273
- ie && /* @__PURE__ */ _("div", {
14279
+ M && /* @__PURE__ */ _("div", {
14274
14280
  style: {
14275
14281
  margin: "0 16px 8px",
14276
14282
  padding: "9px 14px",
@@ -14330,8 +14336,8 @@ function Mg({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i
14330
14336
  isUploadingAttachment: te,
14331
14337
  requiresEmail: ne,
14332
14338
  emailInput: j,
14333
- setEmailInput: M,
14334
- emailError: re,
14339
+ setEmailInput: re,
14340
+ emailError: ie,
14335
14341
  inputPlaceholder: e.inputPlaceholder
14336
14342
  })
14337
14343
  }),
@@ -14386,7 +14392,7 @@ function Mg({ copy: e, orbColors: t, primaryColor: n, chatBgGradient: r, logo: i
14386
14392
  });
14387
14393
  }
14388
14394
  function Ng() {
14389
- let { status: e, runtimeConfig: t, resolvedConfig: n, chatHistory: r, isOpen: i, activeScreen: a, isHumanHandled: s, agentName: l, agentHeadshot: u, visitorEmail: h, isAgentTyping: v, isAiTyping: y, isLoading: b, isRateLimited: x, rateLimitMessage: S, isConversationEnded: C, incomingCall: w, activeCallId: T, callConnectionState: E, callConnectedAt: D, isCallMuted: O, webRTCError: k, language: A, chatId: ee, historyRef: te, onMessageSync: ne, sendMessage: j, uploadChatFile: M, openWidget: re, captureVisitorEmail: ie, setVoiceMode: ae, endConversation: oe, startNewChat: le, acceptCall: ue, rejectCall: de, endWebRTCCall: fe, toggleCallMute: pe, dismissCallError: me, startTyping: he, stopTyping: N, updateTypingDraft: ge, getVisitorChatHistory: _e, resumeChat: ve, isSessionRestoring: ye, openToChatCounter: be, voiceEndCounter: xe } = Cn();
14395
+ let { status: e, runtimeConfig: t, resolvedConfig: n, chatHistory: r, isOpen: i, activeScreen: a, isHumanHandled: s, agentName: l, agentHeadshot: u, visitorEmail: h, isAgentTyping: v, isAiTyping: y, isLoading: b, isRateLimited: x, rateLimitMessage: S, isConversationEnded: C, incomingCall: w, activeCallId: T, callConnectionState: E, callConnectedAt: D, isCallMuted: O, webRTCError: k, language: A, chatId: ee, historyRef: te, onMessageSync: ne, sendMessage: j, uploadChatFile: re, openWidget: ie, captureVisitorEmail: M, setVoiceMode: ae, endConversation: oe, startNewChat: le, acceptCall: ue, rejectCall: de, endWebRTCCall: fe, toggleCallMute: pe, dismissCallError: me, startTyping: he, stopTyping: N, updateTypingDraft: ge, getVisitorChatHistory: _e, resumeChat: ve, isSessionRestoring: ye, openToChatCounter: be, voiceEndCounter: xe } = Cn();
14390
14396
  c(() => {
14391
14397
  try {
14392
14398
  or();
@@ -14465,11 +14471,11 @@ function Ng() {
14465
14471
  } catch {}
14466
14472
  let n = De(), r = z ? we(z) : null, i = n || !!r?.transcript;
14467
14473
  if (t) {
14468
- re?.({ notifyChatInitiated: !0 }), ae?.(!0), H("voice_mode");
14474
+ ie?.({ notifyChatInitiated: !0 }), ae?.(!0), H("voice_mode");
14469
14475
  return;
14470
14476
  }
14471
14477
  if (ke()) {
14472
- re?.({ notifyChatInitiated: !1 }), H("text_chat");
14478
+ ie?.({ notifyChatInitiated: !1 }), H("text_chat");
14473
14479
  return;
14474
14480
  }
14475
14481
  if (i) {
@@ -14477,7 +14483,7 @@ function Ng() {
14477
14483
  H("minimized_orb");
14478
14484
  return;
14479
14485
  }
14480
- re?.({ notifyChatInitiated: !0 }), ae?.(!0), H("voice_mode");
14486
+ ie?.({ notifyChatInitiated: !0 }), ae?.(!0), H("voice_mode");
14481
14487
  return;
14482
14488
  }
14483
14489
  if (z) try {
@@ -14541,7 +14547,7 @@ function Ng() {
14541
14547
  hasIncomingCall: !!w?.callId,
14542
14548
  activeCallId: T,
14543
14549
  callConnectionState: E
14544
- }), wt.current = e, V === "voice_mode" && ae?.(!1), re?.(), At());
14550
+ }), wt.current = e, V === "voice_mode" && ae?.(!1), ie?.(), At());
14545
14551
  }
14546
14552
  }, [
14547
14553
  T,
@@ -14549,7 +14555,7 @@ function Ng() {
14549
14555
  At,
14550
14556
  w?.callId,
14551
14557
  i,
14552
- re,
14558
+ ie,
14553
14559
  ae,
14554
14560
  V
14555
14561
  ]), c(() => {
@@ -14596,7 +14602,7 @@ function Ng() {
14596
14602
  st("Please enter a valid email so we can continue helping you.");
14597
14603
  return;
14598
14604
  }
14599
- await ie(e), st(""), lt(!0), setTimeout(() => lt(!1), 3e3);
14605
+ await M(e), st(""), lt(!0), setTimeout(() => lt(!1), 3e3);
14600
14606
  return;
14601
14607
  }
14602
14608
  let t = Mt(it);
@@ -14604,7 +14610,7 @@ function Ng() {
14604
14610
  if (mt) {
14605
14611
  try {
14606
14612
  yt(!0), _t("");
14607
- let e = await M(mt), n = e?.data || e, r = nt.trim() || `Shared file: ${ah(mt)}`;
14613
+ let e = await re(mt), n = e?.data || e, r = nt.trim() || `Shared file: ${ah(mt)}`;
14608
14614
  rt(""), U(null), Ot(), await j(r, "", t, {
14609
14615
  type: "file",
14610
14616
  metadata: {
@@ -14681,9 +14687,9 @@ function Ng() {
14681
14687
  t.resume().catch(() => {}), setTimeout(() => t.close().catch(() => {}), 3e3);
14682
14688
  }
14683
14689
  } catch {}
14684
- re({ notifyChatInitiated: !0 }), ae?.(!0), H("voice_mode");
14690
+ ie({ notifyChatInitiated: !0 }), ae?.(!0), H("voice_mode");
14685
14691
  }, Vt = () => {
14686
- re({ notifyChatInitiated: !0 }), ae?.(!1), H("text_chat");
14692
+ ie({ notifyChatInitiated: !0 }), ae?.(!1), H("text_chat");
14687
14693
  }, Ht = () => {
14688
14694
  ae?.(!1), Rt();
14689
14695
  };
@@ -14809,7 +14815,7 @@ function Ng() {
14809
14815
  voiceEndCounter: xe,
14810
14816
  websiteName: t?.websiteName,
14811
14817
  voiceFirstMessage: Se.voiceFirstMessage || null,
14812
- captureVisitorEmail: ie,
14818
+ captureVisitorEmail: M,
14813
14819
  emailRequired: !h,
14814
14820
  emailCaptureEnabled: P.disableEmailCapture !== !0,
14815
14821
  listeningLabel: P.voiceListeningLabel || "Listening...",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowengage/react-chatbot",
3
- "version": "8.0.63",
3
+ "version": "8.0.68",
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",