@flowengage/react-chatbot 8.0.35 → 8.0.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8876,30 +8876,30 @@ async function Tm(e, t, n) {
8876
8876
  async function Em(e) {
8877
8877
  let { apiBaseUrl: t, siteId: n, chatId: r, clientTools: i = {}, onConnect: a, onDisconnect: o, onMessage: s, onModeChange: c, onError: l, onUnhandledClientToolCall: u } = e, d = await Tm(t, n, r);
8878
8878
  e.greeting !== void 0 && (e.greeting ? d.settings.agent.greeting = e.greeting : delete d.settings.agent.greeting);
8879
- let f = d.settings?.agent?.think?.prompt || "", p = "", m = await navigator.mediaDevices.getUserMedia({ audio: {
8879
+ let f = await navigator.mediaDevices.getUserMedia({ audio: {
8880
8880
  channelCount: 1,
8881
8881
  echoCancellation: !0,
8882
8882
  noiseSuppression: !0,
8883
8883
  autoGainControl: !0
8884
- } }), h = new (window.AudioContext || window.webkitAudioContext)({ sampleRate: bm });
8885
- h.state === "suspended" && await h.resume();
8886
- let g = new WebSocket(d.wsUrl, ["token", d.token]);
8887
- g.binaryType = "arraybuffer";
8888
- let _ = !1, v = !1, y = !1, b = wm(h, () => {
8889
- y && (y = !1, c?.({ mode: "listening" }));
8890
- }), x = h.createMediaStreamSource(m), S = h.createScriptProcessor(xm, 1, 1);
8891
- S.onaudioprocess = (e) => {
8892
- _ || v || g.readyState !== WebSocket.OPEN || g.send(Sm(e.inputBuffer.getChannelData(0)).buffer);
8893
- }, x.connect(S), S.connect(h.destination);
8894
- let C = () => {
8895
- if (!_) {
8896
- _ = !0, b.stop();
8884
+ } }), p = new (window.AudioContext || window.webkitAudioContext)({ sampleRate: bm });
8885
+ p.state === "suspended" && await p.resume();
8886
+ let m = new WebSocket(d.wsUrl, ["token", d.token]);
8887
+ m.binaryType = "arraybuffer";
8888
+ let h = !1, g = !1, _ = !1, v = wm(p, () => {
8889
+ _ && (_ = !1, c?.({ mode: "listening" }));
8890
+ }), y = p.createMediaStreamSource(f), b = p.createScriptProcessor(xm, 1, 1);
8891
+ b.onaudioprocess = (e) => {
8892
+ h || g || m.readyState !== WebSocket.OPEN || m.send(Sm(e.inputBuffer.getChannelData(0)).buffer);
8893
+ }, y.connect(b), b.connect(p.destination);
8894
+ let x = () => {
8895
+ if (!h) {
8896
+ h = !0, v.stop();
8897
8897
  try {
8898
- S.disconnect(), x.disconnect();
8898
+ b.disconnect(), y.disconnect();
8899
8899
  } catch {}
8900
- m.getTracks().forEach((e) => e.stop()), h.close().catch(() => {}), (g.readyState === WebSocket.OPEN || g.readyState === WebSocket.CONNECTING) && g.close();
8900
+ f.getTracks().forEach((e) => e.stop()), p.close().catch(() => {}), (m.readyState === WebSocket.OPEN || m.readyState === WebSocket.CONNECTING) && m.close();
8901
8901
  }
8902
- }, w = async (e) => {
8902
+ }, S = async (e) => {
8903
8903
  let t = i[e.name];
8904
8904
  if (!t) return u?.({ tool_name: e.name }), { error: `Unknown tool ${e.name}` };
8905
8905
  let n = {};
@@ -8911,19 +8911,19 @@ async function Em(e) {
8911
8911
  } catch (e) {
8912
8912
  return { error: e?.message || "Tool execution failed" };
8913
8913
  }
8914
- }, T = async (e) => {
8914
+ }, C = async (e) => {
8915
8915
  for (let t of e.functions || []) {
8916
8916
  if (!t.client_side) continue;
8917
- let e = await w(t);
8918
- if (_ || g.readyState !== WebSocket.OPEN) return;
8919
- g.send(JSON.stringify({
8917
+ let e = await S(t);
8918
+ if (h || m.readyState !== WebSocket.OPEN) return;
8919
+ m.send(JSON.stringify({
8920
8920
  type: "FunctionCallResponse",
8921
8921
  id: t.id,
8922
8922
  name: t.name,
8923
8923
  content: typeof e == "string" ? e : JSON.stringify(e ?? {})
8924
8924
  }));
8925
8925
  }
8926
- }, E = (e) => {
8926
+ }, w = (e) => {
8927
8927
  switch (e.type) {
8928
8928
  case "Welcome":
8929
8929
  a?.({ conversationId: e.request_id || d.token.slice(0, 12) });
@@ -8935,46 +8935,64 @@ async function Em(e) {
8935
8935
  });
8936
8936
  break;
8937
8937
  case "UserStartedSpeaking":
8938
- b.stop(), y = !1, c?.({ mode: "listening" });
8938
+ v.stop(), _ = !1, c?.({ mode: "listening" });
8939
8939
  break;
8940
8940
  case "AgentStartedSpeaking":
8941
- y = !0, c?.({ mode: "speaking" });
8941
+ _ = !0, c?.({ mode: "speaking" });
8942
8942
  break;
8943
8943
  case "AgentAudioDone":
8944
- b.isPlaying() || (y = !1, c?.({ mode: "listening" }));
8944
+ v.isPlaying() || (_ = !1, c?.({ mode: "listening" }));
8945
8945
  break;
8946
8946
  case "FunctionCallRequest":
8947
- T(e);
8947
+ C(e);
8948
8948
  break;
8949
+ case "PromptUpdated":
8950
+ case "AgentThinking": break;
8949
8951
  case "Error":
8950
- l?.(Error(e.description || "Voice service error"));
8952
+ console.error("[FlowEngage:Deepgram]", e.code || "", e.description || e), l?.(Error(e.description || "Voice service error"));
8953
+ break;
8954
+ case "Warning":
8955
+ console.warn("[FlowEngage:Deepgram]", e.code || "", e.description || "");
8951
8956
  break;
8952
8957
  default: break;
8953
8958
  }
8954
8959
  };
8955
- return g.onopen = () => g.send(JSON.stringify(d.settings)), g.onmessage = (e) => {
8960
+ return m.onopen = () => m.send(JSON.stringify(d.settings)), m.onmessage = (e) => {
8956
8961
  if (e.data instanceof ArrayBuffer) {
8957
- b.enqueue(new Int16Array(e.data));
8962
+ v.enqueue(new Int16Array(e.data));
8958
8963
  return;
8959
8964
  }
8960
8965
  try {
8961
- E(JSON.parse(e.data));
8966
+ w(JSON.parse(e.data));
8962
8967
  } catch {}
8963
- }, g.onerror = () => l?.(/* @__PURE__ */ Error("Voice connection failed")), g.onclose = () => {
8964
- C(), o?.();
8968
+ }, m.onerror = () => l?.(/* @__PURE__ */ Error("Voice connection failed")), m.onclose = () => {
8969
+ x(), o?.();
8965
8970
  }, {
8966
- endSession: async () => C(),
8971
+ endSession: async () => x(),
8967
8972
  sendContextualUpdate: (e) => {
8968
- _ || g.readyState !== WebSocket.OPEN || !e || (p += `\n\n${e}`, g.send(JSON.stringify({
8973
+ h || m.readyState !== WebSocket.OPEN || !e || m.send(JSON.stringify({
8969
8974
  type: "UpdatePrompt",
8970
- prompt: `${f}${p}`
8971
- })));
8975
+ prompt: e
8976
+ }));
8977
+ },
8978
+ sendUserMessage: (e) => {
8979
+ h || m.readyState !== WebSocket.OPEN || !e || m.send(JSON.stringify({
8980
+ type: "InjectUserMessage",
8981
+ content: e
8982
+ }));
8983
+ },
8984
+ injectAgentSpeech: (e, t = "interrupt") => {
8985
+ h || m.readyState !== WebSocket.OPEN || !e || m.send(JSON.stringify({
8986
+ type: "InjectAgentMessage",
8987
+ message: e,
8988
+ behavior: t
8989
+ }));
8972
8990
  },
8973
8991
  setMicMuted: (e) => {
8974
- v = !!e;
8992
+ g = !!e;
8975
8993
  },
8976
8994
  get status() {
8977
- return _ ? "disconnected" : "connected";
8995
+ return h ? "disconnected" : "connected";
8978
8996
  }
8979
8997
  };
8980
8998
  }
@@ -12657,17 +12675,21 @@ function yg({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
12657
12675
  });
12658
12676
  }, [l]), F = o(() => {
12659
12677
  se.current &&= (clearTimeout(se.current), null);
12660
- }, []), Ae = o(() => {
12678
+ }, []);
12679
+ c(() => {
12680
+ y || (ae.current = !0, oe.current = !1, te(!1), F());
12681
+ }, [y, F]);
12682
+ let Ae = o(() => {
12661
12683
  F(), se.current = setTimeout(() => {
12662
12684
  if (!(!oe.current || ae.current)) if (ce.current < 3) {
12663
12685
  ce.current += 1;
12664
12686
  try {
12665
- j.current?.sendUserMessage?.("[SYSTEM: The visitor still has NOT entered their email in the text box. Remind them once, briefly and warmly: 'I still need your email in the box below to continue — could you enter it, please?' Then stay completely silent again. Do NOT answer any other question until the email is provided.]");
12687
+ j.current?.injectAgentSpeech?.("I still need your email in the box below to continue — could you enter it, please?", "queue");
12666
12688
  } catch {}
12667
12689
  Ae();
12668
12690
  } else {
12669
12691
  try {
12670
- j.current?.sendUserMessage?.("[SYSTEM: The visitor did not provide their email after multiple reminders. Say a brief, warm goodbye EXACTLY like: 'Since I haven't received your email, I'll close this session for now. Feel free to come back anytime — take care!' Then stop talking. Do NOT ask for the email again.]");
12692
+ j.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");
12671
12693
  } catch {}
12672
12694
  oe.current = !1, te(!1), F(), xe.current = !0;
12673
12695
  }
@@ -12788,7 +12810,7 @@ function yg({ orbColors: e, onEnterChat: t, onEndChat: n, agentId: r, siteId: i,
12788
12810
  xe.current = !1, ke();
12789
12811
  return;
12790
12812
  }
12791
- if (de && !se) {
12813
+ if (de && !se && !ae.current) {
12792
12814
  se = !0, E = !0, O = !0;
12793
12815
  try {
12794
12816
  j.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.");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowengage/react-chatbot",
3
- "version": "8.0.35",
3
+ "version": "8.0.36",
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",