@eshal-bot/chat-widget 0.2.51 → 0.2.53

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-NZXHxR3K.esm.js";import"react";import"react-dom/client";import"react/jsx-runtime";import"react-dom";
1
+ export{S as default}from"./chat-widget-index-bgKYLm2D.esm.js";import"react";import"react-dom/client";import"react/jsx-runtime";import"react-dom";
@@ -13398,10 +13398,35 @@
13398
13398
  const line = lines[i];
13399
13399
  if (line.role !== "assistant") continue;
13400
13400
  if (line.a2ui) return line.a2ui;
13401
- if (!line.isProcessing && (line.content || "").trim()) return "";
13401
+ if (!line.isProcessing && (line.content || "").trim()) {
13402
+ // A verify card still waiting for its code stays (dev, 12 Nov 2026: the caller said "Hello" while
13403
+ // the code box was up and heard "please confirm the box on your screen", with the box gone).
13404
+ const older = lines.slice(0, i).reverse().find(l => l.role === "assistant" && l.a2ui);
13405
+ return older && waitsForCode(older) ? older.a2ui || "" : "";
13406
+ }
13402
13407
  }
13403
13408
  return "";
13404
13409
  }
13410
+ const VERIFY_CARD = /"type"\s*:\s*"verification"/;
13411
+
13412
+ /** A verification code card (VerifyCard) whose code is not confirmed yet. */
13413
+ function waitsForCode(line) {
13414
+ return Boolean(line?.a2ui && VERIFY_CARD.test(line.a2ui) && !line.cardDone);
13415
+ }
13416
+
13417
+ /**
13418
+ * The lines with the verify card of this held call marked done, once its code is confirmed: the card
13419
+ * then goes like any other, when a newer answer has words of its own.
13420
+ * Mirrors packages/frontend/src/components/chatbot-preview/voiceCard.ts.
13421
+ */
13422
+ function markCodeConfirmed(lines, card) {
13423
+ const id = String(card?.tool_call_id || "").trim();
13424
+ if (!id) return lines;
13425
+ return lines.map(l => l.a2ui && VERIFY_CARD.test(l.a2ui) && l.a2ui.includes(id) ? {
13426
+ ...l,
13427
+ cardDone: true
13428
+ } : l);
13429
+ }
13405
13430
  const CARD_FENCE = /```[ \t]*(?:eshal-ui|eshal-chart|chart)\b[^\n]*\n[\s\S]*?(?:```|$)/g;
13406
13431
 
13407
13432
  /**
@@ -13444,6 +13469,40 @@
13444
13469
  return true;
13445
13470
  }
13446
13471
 
13472
+ /**
13473
+ * The call socket message a verify card sends once the caller's code checked
13474
+ * out: voice-runtime (serializer.verification_turn) makes it the caller's
13475
+ * next turn and resumes the held call with it. The code itself went from the
13476
+ * card to the server's identity route, never over the call. Null when the
13477
+ * card names no held call, so nothing half-formed is sent.
13478
+ * Mirrors packages/frontend/src/components/chatbot-preview/voiceCard.ts.
13479
+ */
13480
+ function verificationResumeMessage(text, card) {
13481
+ const toolCallId = String(card?.tool_call_id || "").trim();
13482
+ if (!toolCallId) return null;
13483
+ const verificationComplete = {
13484
+ tool_call_id: toolCallId
13485
+ };
13486
+ const invocationId = String(card?.invocation_id || "").trim();
13487
+ if (invocationId) verificationComplete.invocation_id = invocationId;
13488
+ return JSON.stringify({
13489
+ type: "verification_complete",
13490
+ text: String(text || "").trim(),
13491
+ verificationComplete
13492
+ });
13493
+ }
13494
+
13495
+ /**
13496
+ * A click on the call screen's card: a verify card whose code checked out
13497
+ * resumes the held call (never typed as the caller's words), a web address
13498
+ * opens in a new tab, anything else is the caller's next turn.
13499
+ * `send` is { resume(text, card), say(text) }.
13500
+ * Mirrors packages/frontend/src/components/chatbot-preview/voiceCard.ts.
13501
+ */
13502
+ function routeCallCardAction(text, extra, send, open) {
13503
+ if (extra?.verificationComplete) send.resume?.(text, extra.verificationComplete);else if (!openCardLink(text, open)) send.say?.(text);
13504
+ }
13505
+
13447
13506
  /**
13448
13507
  * Replies the widget never streamed itself.
13449
13508
  *
@@ -16987,6 +17046,25 @@
16987
17046
  setInputValue("");
16988
17047
  }, []);
16989
17048
 
17049
+ // A verify card on the call screen whose code checked out: the held call
17050
+ // resumes over the call socket. Not drawn as the caller's words, as in the
17051
+ // chat (EV-4942): the caller entered a code, they did not say this.
17052
+ const sendBidiVerificationComplete = reactExports.useCallback((text, card) => {
17053
+ const message = verificationResumeMessage(text, card);
17054
+ if (!message) return;
17055
+ const ws = websocketRef.current;
17056
+ if (!ws || ws.readyState !== WebSocket.OPEN) {
17057
+ if (!voiceCreditsExhaustedRef.current) setVoiceError("voiceUnavailable");
17058
+ return;
17059
+ }
17060
+ userHasSpokenRef.current = true;
17061
+ ws.send(message);
17062
+ updateActivity(organizationId);
17063
+ setIsLoading(true);
17064
+ // The card's code is confirmed: it may go once the resumed answer speaks.
17065
+ setBidiMessages(prev => markCodeConfirmed(prev, card));
17066
+ }, []);
17067
+
16990
17068
  // Cleanup on unmount
16991
17069
  reactExports.useEffect(() => {
16992
17070
  isVoiceSessionActiveRef.current = isVoiceSessionActive;
@@ -17311,6 +17389,7 @@
17311
17389
  handleVoiceToggle,
17312
17390
  toggleVoicePause,
17313
17391
  sendBidiTextMessage,
17392
+ sendBidiVerificationComplete,
17314
17393
  // Session lifecycle
17315
17394
  sessionExpiringSoon,
17316
17395
  resetConversation,
@@ -23423,7 +23502,7 @@
23423
23502
  isRtl: isRtl,
23424
23503
  fontFamily: fontFamily,
23425
23504
  provideCitations: false,
23426
- onButtonClick: value => onCardAction?.(String(value ?? ""))
23505
+ onButtonClick: (value, _label, extra) => onCardAction?.(String(value ?? ""), extra)
23427
23506
  })
23428
23507
  })
23429
23508
  }, card)
@@ -23999,6 +24078,7 @@
23999
24078
  onToggleVoicePause,
24000
24079
  voiceLevelSource,
24001
24080
  onBidiTextMessage,
24081
+ onBidiVerificationComplete,
24002
24082
  disclaimerEnabled = false,
24003
24083
  disclaimerText,
24004
24084
  disclaimerPosition = "top",
@@ -24294,11 +24374,13 @@
24294
24374
  // While a voice call is live the body becomes the call screen; when it
24295
24375
  // ends the chat returns with the call's lines kept as messages.
24296
24376
  const showCallView = isVoiceSessionActive;
24297
- // A card button on the call screen: a web address (a payment or check-in
24298
- // link) opens in a new tab, anything else is the caller's next turn.
24299
- const handleVoiceCardAction = reactExports.useCallback(value => {
24300
- if (!openCardLink(value)) onBidiTextMessage?.(value);
24301
- }, [onBidiTextMessage]);
24377
+ // A card button on the call screen: a verify card's confirmed code resumes
24378
+ // the held call over the call, a web address (a payment or check-in link)
24379
+ // opens in a new tab, anything else is the caller's next turn.
24380
+ const handleVoiceCardAction = reactExports.useCallback((value, extra) => routeCallCardAction(value, extra, {
24381
+ resume: onBidiVerificationComplete,
24382
+ say: onBidiTextMessage
24383
+ }), [onBidiTextMessage, onBidiVerificationComplete]);
24302
24384
  // EV-3813: voiceError is an i18n code (lib/voiceErrors.js), resolved the
24303
24385
  // way ChatInput resolves it.
24304
24386
  const voiceErrorText = voiceError ? t(voiceError) === voiceError ? t("voiceUnavailable") : t(voiceError) : null;
@@ -25342,7 +25424,7 @@
25342
25424
  * value by its own test (that constant sat at 0.1.113 while this package was
25343
25425
  * at 0.2.2 precisely because nothing enforced it - EV-2431).
25344
25426
  */
25345
- const WIDGET_VERSION = '0.2.51';
25427
+ const WIDGET_VERSION = '0.2.53';
25346
25428
 
25347
25429
  /**
25348
25430
  * API utility functions
@@ -25768,6 +25850,7 @@
25768
25850
  voiceConclusionForCsat,
25769
25851
  handleVoiceToggle,
25770
25852
  sendBidiTextMessage,
25853
+ sendBidiVerificationComplete,
25771
25854
  bidiMessages,
25772
25855
  isVoicePaused,
25773
25856
  toggleVoicePause,
@@ -25996,6 +26079,7 @@
25996
26079
  onToggleVoicePause: toggleVoicePause,
25997
26080
  voiceLevelSource: voiceLevelSource,
25998
26081
  onBidiTextMessage: sendBidiTextMessage,
26082
+ onBidiVerificationComplete: sendBidiVerificationComplete,
25999
26083
  disclaimerEnabled: widgetConfig.disclaimerEnabled,
26000
26084
  disclaimerText: widgetConfig.disclaimerText,
26001
26085
  disclaimerPosition: widgetConfig.disclaimerPosition,