@eshal-bot/chat-widget 0.2.16 → 0.2.17

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.
@@ -1 +1 @@
1
- export{S as default}from"./chat-widget-index-DxXf_IzK.esm.js";import"react";import"react-dom/client";import"react/jsx-runtime";import"react-dom";
1
+ export{e as default}from"./chat-widget-index-CNSzbZUh.esm.js";import"react";import"react-dom/client";import"react/jsx-runtime";import"react-dom";
@@ -12197,6 +12197,28 @@
12197
12197
  const speechGateRef = reactExports.useRef(null);
12198
12198
  // The single pending voice reconnect, so stop/unmount can cancel it.
12199
12199
  const reconnectTimerRef = reactExports.useRef(null);
12200
+ // EV-4552 (19): the org's fallback message from an out-of-credits refusal
12201
+ // frame, shown to the customer when the socket then closes 1008.
12202
+ const voiceFallbackRef = reactExports.useRef(null);
12203
+ // EV-4552 (19): show the org's fallback message from an out-of-credits
12204
+ // refusal in the chat, once. A mid-session refusal already spoke and
12205
+ // streamed it, so skip it when it is already the last assistant message.
12206
+ const showVoiceFallback = () => {
12207
+ const fallbackText = voiceFallbackRef.current;
12208
+ voiceFallbackRef.current = null;
12209
+ if (!fallbackText) return;
12210
+ setMessages(prev => {
12211
+ const last = [...prev].reverse().find(m => m.role === "assistant");
12212
+ if (last && typeof last.content === "string" && last.content.trim() === fallbackText) {
12213
+ return prev;
12214
+ }
12215
+ return [...prev, createMessage({
12216
+ id: getNextMessageId(),
12217
+ role: "assistant",
12218
+ content: fallbackText
12219
+ })];
12220
+ });
12221
+ };
12200
12222
  const currentInputMessageIdRef = reactExports.useRef(null);
12201
12223
  const currentAssistantMessageIdRef = reactExports.useRef(null);
12202
12224
  const isAudioReadyRef = reactExports.useRef(false);
@@ -14280,6 +14302,9 @@
14280
14302
  hasContentParts: !!payload.content?.parts,
14281
14303
  payload
14282
14304
  });
14305
+ if (payload && payload.code === "AI_CREDITS_EXHAUSTED" && typeof payload.fallbackMessage === "string" && payload.fallbackMessage.trim()) {
14306
+ voiceFallbackRef.current = payload.fallbackMessage.trim();
14307
+ }
14283
14308
  handleBidiEvent(payload);
14284
14309
  } catch (error) {
14285
14310
  console.error("[BIDI] Failed to parse WebSocket event", {
@@ -14315,6 +14340,8 @@
14315
14340
  setIsVoiceSessionActive(false);
14316
14341
  setVoiceStatus("error");
14317
14342
  setVoiceError("voiceUnavailable");
14343
+ // EV-4552 (19): show the org's fallback message in the chat, once.
14344
+ showVoiceFallback();
14318
14345
  return;
14319
14346
  }
14320
14347
  if (isVoiceSessionActiveRef.current) {
@@ -21629,7 +21656,7 @@
21629
21656
  * value by its own test (that constant sat at 0.1.113 while this package was
21630
21657
  * at 0.2.2 precisely because nothing enforced it - EV-2431).
21631
21658
  */
21632
- const WIDGET_VERSION = '0.2.16';
21659
+ const WIDGET_VERSION = '0.2.17';
21633
21660
 
21634
21661
  /**
21635
21662
  * API utility functions
@@ -21716,6 +21743,24 @@
21716
21743
  }
21717
21744
  };
21718
21745
 
21746
+ /** Called once with the fetched agent config; no policy means off. */
21747
+ function setChatImagePolicy(policy, apiBaseUrl) {
21748
+ if (!policy || policy.mode !== "report" && policy.mode !== "enforce") {
21749
+ return;
21750
+ }
21751
+ let apiOrigin = "";
21752
+ try {
21753
+ apiOrigin = new URL(apiBaseUrl).origin;
21754
+ } catch {
21755
+ apiOrigin = "";
21756
+ }
21757
+ ({
21758
+ mode: policy.mode,
21759
+ hosts: new Set((Array.isArray(policy.hosts) ? policy.hosts : []).map(h => String(h).toLowerCase())),
21760
+ apiOrigin
21761
+ });
21762
+ }
21763
+
21719
21764
  const ChatWidget = ({
21720
21765
  /**
21721
21766
  * @param {Function|undefined} getAuthToken - async fn returning a Keycloak Bearer token (in-app JWT path)
@@ -21805,6 +21850,8 @@
21805
21850
  setConfigError(null);
21806
21851
  return;
21807
21852
  }
21853
+ // Absent unless WIDGET_IMAGE_POLICY is on server-side: then a no-op.
21854
+ setChatImagePolicy(config.chatImagePolicy, apiBaseUrl);
21808
21855
  setAgentConfig(config);
21809
21856
  setConfigError(null);
21810
21857
  } catch (error) {