@eshal-bot/chat-widget 0.2.36 → 0.2.38

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-CudNa4lx.esm.js";import"react";import"react-dom/client";import"react/jsx-runtime";import"react-dom";
1
+ export{S as default}from"./chat-widget-index-nFrn-Uh5.esm.js";import"react";import"react-dom/client";import"react/jsx-runtime";import"react-dom";
@@ -10809,46 +10809,46 @@
10809
10809
  },
10810
10810
  sr: {
10811
10811
  agentJoinedConversation: "{name} se pridružio/la razgovoru",
10812
- connectionError: "Извините, тренутно имам проблема са повезивањем. Пробајте поново.",
10813
- micDenied: "Нисмо могли да приступимо вашем микрофону. Дозволите приступ и пробајте поново.",
10814
- micNotFound: "Микрофон није пронађен. Прикључите микрофон и пробајте поново.",
10815
- voiceUnavailable: "Гласовна функција тренутно није доступна. Пробајте поново.",
10812
+ connectionError: "Izvinite, trenutno imam problema sa povezivanjem. Probajte ponovo.",
10813
+ micDenied: "Nismo mogli da pristupimo vašem mikrofonu. Dozvolite pristup i probajte ponovo.",
10814
+ micNotFound: "Mikrofon nije pronađen. Priključite mikrofon i probajte ponovo.",
10815
+ voiceUnavailable: "Glasovna funkcija trenutno nije dostupna. Probajte ponovo.",
10816
10816
  // Topic-picker + quick-questions surface strings. {category} is
10817
10817
  // substituted verbatim at the call site and rendered through
10818
10818
  // 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: "Дозволи приступ микрофону"
10819
+ chooseTopicLabel: "Izaberite temu da biste započeli:",
10820
+ categoryTopicsHeading: "Molimo postavite svoje pitanje o **{category}** ispod.",
10821
+ quickQuestionsHeadingLabel: "Ili postavite brzo pitanje:",
10822
+ typeYourMessage: "Ukucajte vašu poruku...",
10823
+ agentIsLoading: "Agent se učitava...",
10824
+ conversationResolved: "Razgovor je završen",
10825
+ howWasYourExperience: "Kakvo je bilo vaše iskustvo?",
10826
+ feedbackPrompt: "Molimo ocenite našu podršku da bismo se poboljšali.",
10827
+ feedbackPlaceholder: "Recite nam više o svom iskustvu...",
10828
+ submitFeedback: "Pošalji povratne informacije",
10829
+ submitting: "Slanje...",
10830
+ selectRatingFirst: "Prvo odaberite ocenu",
10831
+ pleaseSubmitRatingFirst: "Molimo prvo pošaljite ocenu.",
10832
+ completeOnboardingToEnableVoice: "Završite uvod da omogućite glas",
10833
+ sendMessageToCompleteOnboarding: "Pošaljite poruku da završite uvod i omogućite glas.",
10834
+ resolve: "Završi",
10835
+ scrollLeft: "Skrolovati levo",
10836
+ scrollRight: "Skrolovati desno",
10837
+ sendMessage: "Pošalji poruku",
10838
+ voiceSessionLive: "Glasovna sesija aktivna - govorite ili kucajte.",
10839
+ connectingVoice: "Povezivanje sa glasovnom sesijom...",
10840
+ poweredBy: "Pokreće",
10841
+ menu: "Meni",
10842
+ close: "Zatvori",
10843
+ openChat: "Otvori ćaskanje",
10844
+ closeChat: "Zatvori ćaskanje",
10845
+ lightMode: "Svetli režim",
10846
+ nightMode: "Tamni režim",
10847
+ refreshChat: "Osveži ćaskanje",
10848
+ copyChat: "Kopiraj ćaskanje",
10849
+ startChat: "Započni ćaskanje",
10850
+ startingVoiceSession: "Pokretanje glasovne sesije...",
10851
+ allowMicAccess: "Dozvoli pristup mikrofonu"
10852
10852
  },
10853
10853
  sk: {
10854
10854
  connectionError: "Ľutujeme, momentálne mám problém s pripojením. Skúste to znova.",
@@ -11735,19 +11735,19 @@
11735
11735
  moreSources: "+{count} ещё"
11736
11736
  },
11737
11737
  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} још"
11738
+ removeAttachment: "Ukloni prilog",
11739
+ categoryFilter: "Filter kategorija",
11740
+ filterByCategory: "Filtriraj po kategoriji",
11741
+ scrollCategoriesLeft: "Skroluj kategorije levo",
11742
+ scrollCategoriesRight: "Skroluj kategorije desno",
11743
+ scrollTagsLeft: "Skroluj oznake levo",
11744
+ scrollTagsRight: "Skroluj oznake desno",
11745
+ copyMessage: "Kopiraj poruku",
11746
+ copied: "Kopirano",
11747
+ like: "Sviđa mi se",
11748
+ dislike: "Ne sviđa mi se",
11749
+ sourcesCited: "Citirani izvori: {count}",
11750
+ moreSources: "+{count} još"
11751
11751
  },
11752
11752
  sk: {
11753
11753
  removeAttachment: "Odstrániť prílohu",
@@ -12052,9 +12052,9 @@
12052
12052
  onboardingPhonePlaceholder: "Введите номер телефона"
12053
12053
  },
12054
12054
  sr: {
12055
- onboardingNamePlaceholder: "Унесите своје име",
12056
- onboardingEmailPlaceholder: "Унесите своју адресу е-поште",
12057
- onboardingPhonePlaceholder: "Унесите свој број телефона"
12055
+ onboardingNamePlaceholder: "Unesite svoje ime",
12056
+ onboardingEmailPlaceholder: "Unesite svoju adresu e-pošte",
12057
+ onboardingPhonePlaceholder: "Unesite svoj broj telefona"
12058
12058
  },
12059
12059
  sk: {
12060
12060
  onboardingNamePlaceholder: "Zadajte svoje meno",
@@ -12276,14 +12276,16 @@
12276
12276
  * only what reached the conversation another way: what a person sent from the
12277
12277
  * Inbox (contentType human_reply, handoff_ack), the away and holding lines
12278
12278
  * sent while the visitor waits for a person (handoff_wait, EV-4803; backend
12279
- * services/widgetHandoffLines.ts) and a Skill's reply to a staff
12279
+ * services/widgetHandoffLines.ts), the code card an agent sends with Request
12280
+ * verification (verification_request; backend services/verificationRequest.ts)
12281
+ * and a Skill's reply to a staff
12280
12282
  * turn (staffTurn: Instruct Skill, or a hand-back that resumes the Skill;
12281
12283
  * backend services/staffTurn.ts). Dev, 15 Oct 2026: a Skill reply sent while
12282
12284
  * the Testing lab was closed never showed there, because only a person's
12283
12285
  * replies were merged. Mirrors packages/frontend/src/lib/messages/repliedOutsideStream.ts.
12284
12286
  */
12285
12287
  function isRepliedOutsideStream(m) {
12286
- return m?.contentType === 'human_reply' || m?.contentType === 'handoff_ack' || m?.contentType === 'handoff_wait' || m?.staffTurn === true;
12288
+ return m?.contentType === 'human_reply' || m?.contentType === 'handoff_ack' || m?.contentType === 'handoff_wait' || m?.contentType === 'verification_request' || m?.staffTurn === true;
12287
12289
  }
12288
12290
 
12289
12291
  /**
@@ -13221,6 +13223,10 @@
13221
13223
  // EV-4552 (19): the org's fallback message from an out-of-credits refusal
13222
13224
  // frame, shown to the customer when the socket then closes 1008.
13223
13225
  const voiceFallbackRef = reactExports.useRef(null);
13226
+ // EV-4901 (5): the server refused this voice session because the org is out
13227
+ // of AI credits. The org's own message says so, so the generic "voice isn't
13228
+ // available" error must not appear under it.
13229
+ const voiceCreditsExhaustedRef = reactExports.useRef(false);
13224
13230
  // EV-4552 (19): show the org's fallback message from an out-of-credits
13225
13231
  // refusal in the chat, once. A mid-session refusal already spoke and
13226
13232
  // streamed it, so skip it when it is already the last assistant message.
@@ -15066,7 +15072,8 @@
15066
15072
  // the text fallback when STT/TTS fails mid-session (e.g. no credits /
15067
15073
  // invalid key). Previously the widget ignored it - matching the Testing
15068
15074
  // Lab fix. Do NOT return; let the rest of the handler still render text.
15069
- if (event.error) {
15075
+ // EV-4901 (5): an out-of-credits refusal is told by the org's message.
15076
+ if (event.error && event.code !== "AI_CREDITS_EXHAUSTED") {
15070
15077
  // EV-3813: the backend error text is diagnostic, not customer copy.
15071
15078
  console.warn("[BIDI] voice error from backend", event.error);
15072
15079
  setVoiceError("voiceUnavailable");
@@ -15367,6 +15374,7 @@
15367
15374
  }
15368
15375
  setVoiceStatus("connecting");
15369
15376
  setVoiceError(null);
15377
+ voiceCreditsExhaustedRef.current = false;
15370
15378
 
15371
15379
  // EV-4119: the voice socket now requires a ticket minted by the backend
15372
15380
  // behind verified widget auth. Previously the org id in the URL path WAS
@@ -15430,6 +15438,9 @@
15430
15438
  if (payload && payload.code === "AI_CREDITS_EXHAUSTED" && typeof payload.fallbackMessage === "string" && payload.fallbackMessage.trim()) {
15431
15439
  voiceFallbackRef.current = payload.fallbackMessage.trim();
15432
15440
  }
15441
+ if (payload && payload.code === "AI_CREDITS_EXHAUSTED") {
15442
+ voiceCreditsExhaustedRef.current = true;
15443
+ }
15433
15444
  handleBidiEvent(payload);
15434
15445
  } catch (error) {
15435
15446
  console.error("[BIDI] Failed to parse WebSocket event", {
@@ -15440,7 +15451,7 @@
15440
15451
  };
15441
15452
  ws.onerror = () => {
15442
15453
  setVoiceStatus("error");
15443
- setVoiceError("voiceUnavailable");
15454
+ if (!voiceCreditsExhaustedRef.current) setVoiceError("voiceUnavailable");
15444
15455
  setIsLoading(false);
15445
15456
  };
15446
15457
  ws.onclose = event => {
@@ -15464,7 +15475,12 @@
15464
15475
  isVoiceSessionActiveRef.current = false;
15465
15476
  setIsVoiceSessionActive(false);
15466
15477
  setVoiceStatus("error");
15467
- setVoiceError("voiceUnavailable");
15478
+ // EV-4901 (5): out of credits with the org's message to show, show
15479
+ // only that. Any other refusal, or no message, keeps the generic one.
15480
+ const creditLimit = voiceCreditsExhaustedRef.current || String(event.reason || "").startsWith("AI_CREDITS_EXHAUSTED");
15481
+ if (!creditLimit || !voiceFallbackRef.current) {
15482
+ setVoiceError("voiceUnavailable");
15483
+ }
15468
15484
  // EV-4552 (19): show the org's fallback message in the chat, once.
15469
15485
  showVoiceFallback();
15470
15486
  return;
@@ -15548,7 +15564,7 @@
15548
15564
  userHasSpokenRef.current = true;
15549
15565
  const ws = websocketRef.current;
15550
15566
  if (!ws || ws.readyState !== WebSocket.OPEN) {
15551
- setVoiceError("voiceUnavailable");
15567
+ if (!voiceCreditsExhaustedRef.current) setVoiceError("voiceUnavailable");
15552
15568
  return;
15553
15569
  }
15554
15570
  ws.send(JSON.stringify({
@@ -20157,7 +20173,9 @@
20157
20173
  // Check if onboarding flow exists and is not completed
20158
20174
  const hasOnboardingQuestions = onboardingQuestions && onboardingQuestions.length > 0;
20159
20175
  const isOnboardingIncomplete = hasOnboardingQuestions && !onboardingCompleted;
20160
- const isVoiceButtonDisabled = csatVisible || isConversationLoading || onboardingEnabled && isOnboardingIncomplete || voiceStatus === "connecting";
20176
+ // A pending code card blocks starting voice; a live session can still be
20177
+ // stopped.
20178
+ const isVoiceButtonDisabled = csatVisible || isConversationLoading || onboardingEnabled && isOnboardingIncomplete || voiceStatus === "connecting" || verificationPending && !isVoiceSessionActive;
20161
20179
 
20162
20180
  // Determine tooltip message
20163
20181
  const getTooltipMessage = () => {
@@ -20357,7 +20375,7 @@
20357
20375
  children: [/*#__PURE__*/jsxRuntimeExports.jsx("button", {
20358
20376
  type: "button",
20359
20377
  onClick: () => fileInputRef.current && fileInputRef.current.click(),
20360
- disabled: csatVisible || isConversationLoading || isLoading || attachmentsAtLimit,
20378
+ disabled: csatVisible || isConversationLoading || isLoading || attachmentsAtLimit || verificationPending,
20361
20379
  "aria-label": attachmentsAtLimit ? paperclipLimitTooltip : "Attach file",
20362
20380
  title: attachmentsAtLimit ? paperclipLimitTooltip : "Attach file",
20363
20381
  className: `h-8 w-8 rounded-lg flex items-center justify-center transition-colors duration-200 ${isDark ? "text-gray-300 hover:bg-gray-700" : "text-gray-500 hover:bg-gray-200"} disabled:opacity-40 disabled:cursor-not-allowed`,
@@ -23201,7 +23219,7 @@
23201
23219
  * value by its own test (that constant sat at 0.1.113 while this package was
23202
23220
  * at 0.2.2 precisely because nothing enforced it - EV-2431).
23203
23221
  */
23204
- const WIDGET_VERSION = '0.2.36';
23222
+ const WIDGET_VERSION = '0.2.38';
23205
23223
 
23206
23224
  /**
23207
23225
  * API utility functions