@eshal-bot/chat-widget 0.2.37 → 0.2.39

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-Byr1aRO0.esm.js";import"react";import"react-dom/client";import"react/jsx-runtime";import"react-dom";
1
+ export{S as default}from"./chat-widget-index--xs5FWxs.esm.js";import"react";import"react-dom/client";import"react/jsx-runtime";import"react-dom";
@@ -8099,6 +8099,12 @@
8099
8099
  /** @param {{ conversationId: string, code: string }} payload */
8100
8100
  const verifyVisitorCode = (payload, apiBaseUrl, getAuthToken) => postIdentity('verify', payload, apiBaseUrl, getAuthToken);
8101
8101
 
8102
+ /** EV-4942: the visitor closed the card; the agent sees the cancel. */
8103
+ const cancelVisitorVerification = (payload, apiBaseUrl, getAuthToken) => postIdentity('cancel', payload, apiBaseUrl, getAuthToken);
8104
+
8105
+ /** EV-4939: the method's settings; for SMS, the calling codes allowed. */
8106
+ const visitorIdentityConfig = (payload, apiBaseUrl, getAuthToken) => postIdentity('config', payload, apiBaseUrl, getAuthToken);
8107
+
8102
8108
  /** Delivery of the pending code ("sent", "delivered", "failed" or null). */
8103
8109
  const visitorCodeStatus = (payload, apiBaseUrl, getAuthToken) => postIdentity('status', payload, apiBaseUrl, getAuthToken);
8104
8110
 
@@ -9301,6 +9307,9 @@
9301
9307
  verifyResendIn: "Resend in {seconds} s",
9302
9308
  verifyResend: "Send a new code",
9303
9309
  verifyDifferent: "Use a different address",
9310
+ verifyDifferentNumber: "Use a different number",
9311
+ verifyCountryNotAllowed: "We can't send codes to numbers in this country. Try another number.",
9312
+ verifyLockedFor: "Try again in {time}",
9304
9313
  verifyDone: "Verified as {target}",
9305
9314
  verifyResumeMessage: "I've confirmed it's me.",
9306
9315
  verifyTriesLeft: "That code doesn't match. {count} tries left.",
@@ -10809,46 +10818,46 @@
10809
10818
  },
10810
10819
  sr: {
10811
10820
  agentJoinedConversation: "{name} se pridružio/la razgovoru",
10812
- connectionError: "Извините, тренутно имам проблема са повезивањем. Пробајте поново.",
10813
- micDenied: "Нисмо могли да приступимо вашем микрофону. Дозволите приступ и пробајте поново.",
10814
- micNotFound: "Микрофон није пронађен. Прикључите микрофон и пробајте поново.",
10815
- voiceUnavailable: "Гласовна функција тренутно није доступна. Пробајте поново.",
10821
+ connectionError: "Izvinite, trenutno imam problema sa povezivanjem. Probajte ponovo.",
10822
+ micDenied: "Nismo mogli da pristupimo vašem mikrofonu. Dozvolite pristup i probajte ponovo.",
10823
+ micNotFound: "Mikrofon nije pronađen. Priključite mikrofon i probajte ponovo.",
10824
+ voiceUnavailable: "Glasovna funkcija trenutno nije dostupna. Probajte ponovo.",
10816
10825
  // Topic-picker + quick-questions surface strings. {category} is
10817
10826
  // substituted verbatim at the call site and rendered through
10818
10827
  // ReactMarkdown - keep the **{category}** bold wrapper.
10819
- chooseTopicLabel: "Изаберите тему да бисте започели:",
10820
- categoryTopicsHeading: "Молимо поставите своје питање о **{category}** испод.",
10821
- quickQuestionsHeadingLabel: "Или поставите брзо питање:",
10822
- typeYourMessage: "Укуцајте вашу поруку...",
10823
- agentIsLoading: "Агент се учитава...",
10824
- conversationResolved: "Разговор је завршен",
10825
- howWasYourExperience: "Какво је било ваше искуство?",
10826
- feedbackPrompt: "Молимо оцените нашу подршку да бисмо се побољшали.",
10827
- feedbackPlaceholder: "Реците нам више о свом искуству...",
10828
- submitFeedback: "Пошаљи повратне информације",
10829
- submitting: "Слање...",
10830
- selectRatingFirst: "Прво одаберите оцену",
10831
- pleaseSubmitRatingFirst: "Молимо прво пошаљите оцену.",
10832
- completeOnboardingToEnableVoice: "Завршите увод да омогућите глас",
10833
- sendMessageToCompleteOnboarding: "Пошаљите поруку да завршите увод и омогућите глас.",
10834
- resolve: "Заврши",
10835
- scrollLeft: "Скроловати лево",
10836
- scrollRight: "Скроловати десно",
10837
- sendMessage: "Пошаљи поруку",
10838
- voiceSessionLive: "Гласовна сесија активна - говорите или куцајте.",
10839
- connectingVoice: "Повезивање са гласовном сесијом...",
10840
- poweredBy: "Покреће",
10841
- menu: "Мени",
10842
- close: "Затвори",
10843
- openChat: "Отвори ћаскање",
10844
- closeChat: "Затвори ћаскање",
10845
- lightMode: "Светли режим",
10846
- nightMode: "Тамни режим",
10847
- refreshChat: "Освежи ћаскање",
10848
- copyChat: "Копирај ћаскање",
10849
- startChat: "Започни ћаскање",
10850
- startingVoiceSession: "Покретање гласовне сесије...",
10851
- allowMicAccess: "Дозволи приступ микрофону"
10828
+ chooseTopicLabel: "Izaberite temu da biste započeli:",
10829
+ categoryTopicsHeading: "Molimo postavite svoje pitanje o **{category}** ispod.",
10830
+ quickQuestionsHeadingLabel: "Ili postavite brzo pitanje:",
10831
+ typeYourMessage: "Ukucajte vašu poruku...",
10832
+ agentIsLoading: "Agent se učitava...",
10833
+ conversationResolved: "Razgovor je završen",
10834
+ howWasYourExperience: "Kakvo je bilo vaše iskustvo?",
10835
+ feedbackPrompt: "Molimo ocenite našu podršku da bismo se poboljšali.",
10836
+ feedbackPlaceholder: "Recite nam više o svom iskustvu...",
10837
+ submitFeedback: "Pošalji povratne informacije",
10838
+ submitting: "Slanje...",
10839
+ selectRatingFirst: "Prvo odaberite ocenu",
10840
+ pleaseSubmitRatingFirst: "Molimo prvo pošaljite ocenu.",
10841
+ completeOnboardingToEnableVoice: "Završite uvod da omogućite glas",
10842
+ sendMessageToCompleteOnboarding: "Pošaljite poruku da završite uvod i omogućite glas.",
10843
+ resolve: "Završi",
10844
+ scrollLeft: "Skrolovati levo",
10845
+ scrollRight: "Skrolovati desno",
10846
+ sendMessage: "Pošalji poruku",
10847
+ voiceSessionLive: "Glasovna sesija aktivna - govorite ili kucajte.",
10848
+ connectingVoice: "Povezivanje sa glasovnom sesijom...",
10849
+ poweredBy: "Pokreće",
10850
+ menu: "Meni",
10851
+ close: "Zatvori",
10852
+ openChat: "Otvori ćaskanje",
10853
+ closeChat: "Zatvori ćaskanje",
10854
+ lightMode: "Svetli režim",
10855
+ nightMode: "Tamni režim",
10856
+ refreshChat: "Osveži ćaskanje",
10857
+ copyChat: "Kopiraj ćaskanje",
10858
+ startChat: "Započni ćaskanje",
10859
+ startingVoiceSession: "Pokretanje glasovne sesije...",
10860
+ allowMicAccess: "Dozvoli pristup mikrofonu"
10852
10861
  },
10853
10862
  sk: {
10854
10863
  connectionError: "Ľutujeme, momentálne mám problém s pripojením. Skúste to znova.",
@@ -11735,19 +11744,19 @@
11735
11744
  moreSources: "+{count} ещё"
11736
11745
  },
11737
11746
  sr: {
11738
- removeAttachment: "Уклони прилог",
11739
- categoryFilter: "Филтер категорија",
11740
- filterByCategory: "Филтрирај по категорији",
11741
- scrollCategoriesLeft: "Скролуј категорије лево",
11742
- scrollCategoriesRight: "Скролуј категорије десно",
11743
- scrollTagsLeft: "Скролуј ознаке лево",
11744
- scrollTagsRight: "Скролуј ознаке десно",
11745
- copyMessage: "Копирај поруку",
11746
- copied: "Копирано",
11747
- like: "Свиђа ми се",
11748
- dislike: "Не свиђа ми се",
11749
- sourcesCited: "Цитирани извори: {count}",
11750
- moreSources: "+{count} још"
11747
+ removeAttachment: "Ukloni prilog",
11748
+ categoryFilter: "Filter kategorija",
11749
+ filterByCategory: "Filtriraj po kategoriji",
11750
+ scrollCategoriesLeft: "Skroluj kategorije levo",
11751
+ scrollCategoriesRight: "Skroluj kategorije desno",
11752
+ scrollTagsLeft: "Skroluj oznake levo",
11753
+ scrollTagsRight: "Skroluj oznake desno",
11754
+ copyMessage: "Kopiraj poruku",
11755
+ copied: "Kopirano",
11756
+ like: "Sviđa mi se",
11757
+ dislike: "Ne sviđa mi se",
11758
+ sourcesCited: "Citirani izvori: {count}",
11759
+ moreSources: "+{count} još"
11751
11760
  },
11752
11761
  sk: {
11753
11762
  removeAttachment: "Odstrániť prílohu",
@@ -12052,9 +12061,9 @@
12052
12061
  onboardingPhonePlaceholder: "Введите номер телефона"
12053
12062
  },
12054
12063
  sr: {
12055
- onboardingNamePlaceholder: "Унесите своје име",
12056
- onboardingEmailPlaceholder: "Унесите своју адресу е-поште",
12057
- onboardingPhonePlaceholder: "Унесите свој број телефона"
12064
+ onboardingNamePlaceholder: "Unesite svoje ime",
12065
+ onboardingEmailPlaceholder: "Unesite svoju adresu e-pošte",
12066
+ onboardingPhonePlaceholder: "Unesite svoj broj telefona"
12058
12067
  },
12059
12068
  sk: {
12060
12069
  onboardingNamePlaceholder: "Zadajte svoje meno",
@@ -13223,6 +13232,10 @@
13223
13232
  // EV-4552 (19): the org's fallback message from an out-of-credits refusal
13224
13233
  // frame, shown to the customer when the socket then closes 1008.
13225
13234
  const voiceFallbackRef = reactExports.useRef(null);
13235
+ // EV-4901 (5): the server refused this voice session because the org is out
13236
+ // of AI credits. The org's own message says so, so the generic "voice isn't
13237
+ // available" error must not appear under it.
13238
+ const voiceCreditsExhaustedRef = reactExports.useRef(false);
13226
13239
  // EV-4552 (19): show the org's fallback message from an out-of-credits
13227
13240
  // refusal in the chat, once. A mid-session refusal already spoke and
13228
13241
  // streamed it, so skip it when it is already the last assistant message.
@@ -15068,7 +15081,8 @@
15068
15081
  // the text fallback when STT/TTS fails mid-session (e.g. no credits /
15069
15082
  // invalid key). Previously the widget ignored it - matching the Testing
15070
15083
  // Lab fix. Do NOT return; let the rest of the handler still render text.
15071
- if (event.error) {
15084
+ // EV-4901 (5): an out-of-credits refusal is told by the org's message.
15085
+ if (event.error && event.code !== "AI_CREDITS_EXHAUSTED") {
15072
15086
  // EV-3813: the backend error text is diagnostic, not customer copy.
15073
15087
  console.warn("[BIDI] voice error from backend", event.error);
15074
15088
  setVoiceError("voiceUnavailable");
@@ -15369,6 +15383,7 @@
15369
15383
  }
15370
15384
  setVoiceStatus("connecting");
15371
15385
  setVoiceError(null);
15386
+ voiceCreditsExhaustedRef.current = false;
15372
15387
 
15373
15388
  // EV-4119: the voice socket now requires a ticket minted by the backend
15374
15389
  // behind verified widget auth. Previously the org id in the URL path WAS
@@ -15432,6 +15447,9 @@
15432
15447
  if (payload && payload.code === "AI_CREDITS_EXHAUSTED" && typeof payload.fallbackMessage === "string" && payload.fallbackMessage.trim()) {
15433
15448
  voiceFallbackRef.current = payload.fallbackMessage.trim();
15434
15449
  }
15450
+ if (payload && payload.code === "AI_CREDITS_EXHAUSTED") {
15451
+ voiceCreditsExhaustedRef.current = true;
15452
+ }
15435
15453
  handleBidiEvent(payload);
15436
15454
  } catch (error) {
15437
15455
  console.error("[BIDI] Failed to parse WebSocket event", {
@@ -15442,7 +15460,7 @@
15442
15460
  };
15443
15461
  ws.onerror = () => {
15444
15462
  setVoiceStatus("error");
15445
- setVoiceError("voiceUnavailable");
15463
+ if (!voiceCreditsExhaustedRef.current) setVoiceError("voiceUnavailable");
15446
15464
  setIsLoading(false);
15447
15465
  };
15448
15466
  ws.onclose = event => {
@@ -15466,7 +15484,12 @@
15466
15484
  isVoiceSessionActiveRef.current = false;
15467
15485
  setIsVoiceSessionActive(false);
15468
15486
  setVoiceStatus("error");
15469
- setVoiceError("voiceUnavailable");
15487
+ // EV-4901 (5): out of credits with the org's message to show, show
15488
+ // only that. Any other refusal, or no message, keeps the generic one.
15489
+ const creditLimit = voiceCreditsExhaustedRef.current || String(event.reason || "").startsWith("AI_CREDITS_EXHAUSTED");
15490
+ if (!creditLimit || !voiceFallbackRef.current) {
15491
+ setVoiceError("voiceUnavailable");
15492
+ }
15470
15493
  // EV-4552 (19): show the org's fallback message in the chat, once.
15471
15494
  showVoiceFallback();
15472
15495
  return;
@@ -15550,7 +15573,7 @@
15550
15573
  userHasSpokenRef.current = true;
15551
15574
  const ws = websocketRef.current;
15552
15575
  if (!ws || ws.readyState !== WebSocket.OPEN) {
15553
- setVoiceError("voiceUnavailable");
15576
+ if (!voiceCreditsExhaustedRef.current) setVoiceError("voiceUnavailable");
15554
15577
  return;
15555
15578
  }
15556
15579
  ws.send(JSON.stringify({
@@ -22001,6 +22024,12 @@
22001
22024
  }, apiBaseUrl, getAuthToken),
22002
22025
  status: () => visitorCodeStatus({
22003
22026
  conversationId
22027
+ }, apiBaseUrl, getAuthToken),
22028
+ cancel: () => cancelVisitorVerification({
22029
+ conversationId
22030
+ }, apiBaseUrl, getAuthToken),
22031
+ config: () => visitorIdentityConfig({
22032
+ conversationId
22004
22033
  }, apiBaseUrl, getAuthToken)
22005
22034
  } : null, [t, apiBaseUrl, conversationId, getAuthToken, setVerificationPending]);
22006
22035
 
@@ -22046,8 +22075,12 @@
22046
22075
  const verificationComplete = index && typeof index === "object" && index.verificationComplete ? index.verificationComplete : null;
22047
22076
  if (onPromptSuggestionClick) onPromptSuggestionClick(text);else if (toolConfirmation) onDirectSend?.(text, undefined, {
22048
22077
  toolConfirmation
22049
- });else if (verificationComplete) onDirectSend?.(text, undefined, {
22050
- verificationComplete
22078
+ });
22079
+ // EV-4942: the resume is sent for the held turn but not drawn as a
22080
+ // visitor bubble: the card already says "Verified as...".
22081
+ else if (verificationComplete) onDirectSend?.(text, undefined, {
22082
+ verificationComplete,
22083
+ skipUserAppend: true
22051
22084
  });else onDirectSend?.(text);
22052
22085
  }, [onPromptSuggestionClick, onDirectSend, reportChipClick]);
22053
22086
 
@@ -23205,7 +23238,7 @@
23205
23238
  * value by its own test (that constant sat at 0.1.113 while this package was
23206
23239
  * at 0.2.2 precisely because nothing enforced it - EV-2431).
23207
23240
  */
23208
- const WIDGET_VERSION = '0.2.37';
23241
+ const WIDGET_VERSION = '0.2.39';
23209
23242
 
23210
23243
  /**
23211
23244
  * API utility functions