@microsoft/omnichannel-chat-widget 1.7.8-main.9e74278 → 1.7.8-main.bd4de53

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.
Files changed (43) hide show
  1. package/lib/cjs/common/telemetry/TelemetryConstants.js +5 -0
  2. package/lib/cjs/components/chatbuttonstateful/ChatButtonStateful.js +4 -5
  3. package/lib/cjs/components/headerstateful/HeaderStateful.js +3 -5
  4. package/lib/cjs/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +4 -1
  5. package/lib/cjs/components/livechatwidget/common/chatDisconnectHelper.js +3 -1
  6. package/lib/cjs/components/livechatwidget/common/endChat.js +4 -18
  7. package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +17 -11
  8. package/lib/cjs/components/ooohpanestateful/OOOHPaneStateful.js +9 -3
  9. package/lib/cjs/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +22 -6
  10. package/lib/cjs/components/postchatsurveypanestateful/common/isValidSurveyUrl.js +28 -0
  11. package/lib/cjs/components/webchatcontainerstateful/WebChatContainerStateful.js +4 -3
  12. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/DeliveredTimestamp.js +4 -0
  13. package/lib/cjs/contexts/common/LiveChatWidgetContextInitialState.js +18 -6
  14. package/lib/cjs/firstresponselatency/Constants.js +13 -0
  15. package/lib/cjs/firstresponselatency/FirstResponseLatencyTracker.js +152 -0
  16. package/lib/cjs/firstresponselatency/util.js +85 -0
  17. package/lib/cjs/plugins/createChatTranscript.js +4 -4
  18. package/lib/cjs/plugins/newMessageEventHandler.js +102 -88
  19. package/lib/esm/common/telemetry/TelemetryConstants.js +5 -0
  20. package/lib/esm/components/chatbuttonstateful/ChatButtonStateful.js +4 -5
  21. package/lib/esm/components/headerstateful/HeaderStateful.js +3 -5
  22. package/lib/esm/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +4 -1
  23. package/lib/esm/components/livechatwidget/common/chatDisconnectHelper.js +3 -1
  24. package/lib/esm/components/livechatwidget/common/endChat.js +4 -18
  25. package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +17 -11
  26. package/lib/esm/components/ooohpanestateful/OOOHPaneStateful.js +9 -3
  27. package/lib/esm/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +22 -6
  28. package/lib/esm/components/postchatsurveypanestateful/common/isValidSurveyUrl.js +21 -0
  29. package/lib/esm/components/webchatcontainerstateful/WebChatContainerStateful.js +4 -3
  30. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/DeliveredTimestamp.js +4 -0
  31. package/lib/esm/contexts/common/LiveChatWidgetContextInitialState.js +18 -6
  32. package/lib/esm/firstresponselatency/Constants.js +6 -0
  33. package/lib/esm/firstresponselatency/FirstResponseLatencyTracker.js +145 -0
  34. package/lib/esm/firstresponselatency/util.js +75 -0
  35. package/lib/esm/plugins/createChatTranscript.js +4 -4
  36. package/lib/esm/plugins/newMessageEventHandler.js +100 -86
  37. package/lib/types/common/telemetry/TelemetryConstants.d.ts +5 -0
  38. package/lib/types/components/postchatsurveypanestateful/common/isValidSurveyUrl.d.ts +2 -0
  39. package/lib/types/contexts/common/ILiveChatWidgetContext.d.ts +1 -1
  40. package/lib/types/firstresponselatency/Constants.d.ts +30 -0
  41. package/lib/types/firstresponselatency/FirstResponseLatencyTracker.d.ts +17 -0
  42. package/lib/types/firstresponselatency/util.d.ts +6 -0
  43. package/package.json +1 -1
@@ -203,7 +203,7 @@ const endChat = async (props, facadeChatSDK, state, dispatch, setAdapter, setWeb
203
203
  payload: undefined
204
204
  });
205
205
  // Always allow to close the chat for embedded mode irrespective of end chat errors
206
- closeChatWidget(dispatch, props, state);
206
+ closeChatWidget(dispatch);
207
207
  facadeChatSDK.destroy();
208
208
  }
209
209
  }
@@ -327,21 +327,7 @@ export const endVoiceVideoCallIfOngoing = async (facadeChatSDK, dispatch) => {
327
327
  }, callId);
328
328
  }
329
329
  };
330
- const closeChatWidget = (dispatch, props, state) => {
331
- var _state$appStates5;
332
- if (state !== null && state !== void 0 && (_state$appStates5 = state.appStates) !== null && _state$appStates5 !== void 0 && _state$appStates5.hideStartChatButton) {
333
- var _props$controlProps2, _props$controlProps3;
334
- // Only close chat if header is enabled for popout
335
- // TODO : This condition needs to be removed eventually when the filler UX is ready for popout, removing this condition would show a blank screen for OOB Widget
336
- if ((props === null || props === void 0 ? void 0 : (_props$controlProps2 = props.controlProps) === null || _props$controlProps2 === void 0 ? void 0 : _props$controlProps2.hideHeader) === undefined || (props === null || props === void 0 ? void 0 : (_props$controlProps3 = props.controlProps) === null || _props$controlProps3 === void 0 ? void 0 : _props$controlProps3.hideHeader) === false) {
337
- dispatch({
338
- type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
339
- payload: ConversationState.Closed
340
- });
341
- }
342
- return;
343
- }
344
-
330
+ const closeChatWidget = dispatch => {
345
331
  // Embedded chat
346
332
  dispatch({
347
333
  type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
@@ -361,7 +347,7 @@ const chatTokenCleanUp = async dispatch => {
361
347
  };
362
348
 
363
349
  const getEndChatEventName = async (facadeChatSDK, props) => {
364
- var _facadeChatSDK$getCha2, _facadeChatSDK$getCha3, _facadeChatSDK$getCha4, _facadeChatSDK$getCha5, _props$controlProps4;
365
- return getWidgetEndChatEventName((_facadeChatSDK$getCha2 = facadeChatSDK.getChatSDK()) === null || _facadeChatSDK$getCha2 === void 0 ? void 0 : (_facadeChatSDK$getCha3 = _facadeChatSDK$getCha2.omnichannelConfig) === null || _facadeChatSDK$getCha3 === void 0 ? void 0 : _facadeChatSDK$getCha3.orgId, (_facadeChatSDK$getCha4 = facadeChatSDK.getChatSDK()) === null || _facadeChatSDK$getCha4 === void 0 ? void 0 : (_facadeChatSDK$getCha5 = _facadeChatSDK$getCha4.omnichannelConfig) === null || _facadeChatSDK$getCha5 === void 0 ? void 0 : _facadeChatSDK$getCha5.widgetId, (props === null || props === void 0 ? void 0 : (_props$controlProps4 = props.controlProps) === null || _props$controlProps4 === void 0 ? void 0 : _props$controlProps4.widgetInstanceId) ?? "");
350
+ var _facadeChatSDK$getCha2, _facadeChatSDK$getCha3, _facadeChatSDK$getCha4, _facadeChatSDK$getCha5, _props$controlProps2;
351
+ return getWidgetEndChatEventName((_facadeChatSDK$getCha2 = facadeChatSDK.getChatSDK()) === null || _facadeChatSDK$getCha2 === void 0 ? void 0 : (_facadeChatSDK$getCha3 = _facadeChatSDK$getCha2.omnichannelConfig) === null || _facadeChatSDK$getCha3 === void 0 ? void 0 : _facadeChatSDK$getCha3.orgId, (_facadeChatSDK$getCha4 = facadeChatSDK.getChatSDK()) === null || _facadeChatSDK$getCha4 === void 0 ? void 0 : (_facadeChatSDK$getCha5 = _facadeChatSDK$getCha4.omnichannelConfig) === null || _facadeChatSDK$getCha5 === void 0 ? void 0 : _facadeChatSDK$getCha5.widgetId, (props === null || props === void 0 ? void 0 : (_props$controlProps2 = props.controlProps) === null || _props$controlProps2 === void 0 ? void 0 : _props$controlProps2.widgetInstanceId) ?? "");
366
352
  };
367
353
  export { prepareEndChat, endChat };
@@ -56,7 +56,7 @@ import useChatContextStore from "../../../hooks/useChatContextStore";
56
56
  import useFacadeSDKStore from "../../../hooks/useFacadeChatSDKStore";
57
57
  let uiTimer;
58
58
  export const LiveChatWidgetStateful = props => {
59
- var _props$webChatContain, _props$styleProps, _props$webChatContain2, _props$webChatContain3, _props$controlProps, _props$controlProps3, _state$appStates7, _props$webChatContain7, _state$appStates14, _props$webChatContain9, _props$webChatContain10, _props$controlProps12, _props$draggableChatW, _props$draggableChatW2, _props$draggableChatW3, _props$draggableChatW4, _props$draggableChatW5, _livechatProps$webCha, _props$webChatContain11, _props$webChatContain12, _props$webChatContain13, _props$webChatContain14, _livechatProps$styleP, _livechatProps$contro, _livechatProps$contro2, _livechatProps$compon, _livechatProps$contro3, _livechatProps$compon2, _livechatProps$contro4, _livechatProps$compon3, _livechatProps$contro5, _livechatProps$compon4, _livechatProps$contro6, _livechatProps$compon5, _livechatProps$contro7, _livechatProps$compon6, _livechatProps$contro8, _livechatProps$compon7, _livechatProps$contro9, _livechatProps$compon8, _livechatProps$contro10, _livechatProps$contro11, _livechatProps$compon9, _livechatProps$contro12, _livechatProps$compon10, _livechatProps$contro13, _livechatProps$compon11, _livechatProps$compon12, _livechatProps$compon13;
59
+ var _props$webChatContain, _props$styleProps, _props$webChatContain2, _props$webChatContain3, _props$controlProps, _props$controlProps3, _state$appStates7, _props$webChatContain7, _state$appStates14, _props$webChatContain9, _props$webChatContain10, _props$controlProps12, _props$draggableChatW, _props$draggableChatW2, _props$draggableChatW3, _props$draggableChatW4, _props$draggableChatW5, _livechatProps$webCha, _props$webChatContain11, _props$webChatContain12, _props$webChatContain13, _props$webChatContain14, _props$webChatContain15, _props$webChatContain16, _props$webChatContain17, _props$webChatContain18, _livechatProps$styleP, _livechatProps$contro, _livechatProps$contro2, _livechatProps$compon, _livechatProps$contro3, _livechatProps$compon2, _livechatProps$contro4, _livechatProps$compon3, _livechatProps$contro5, _livechatProps$compon4, _livechatProps$contro6, _livechatProps$compon5, _livechatProps$contro7, _livechatProps$compon6, _livechatProps$contro8, _livechatProps$compon7, _livechatProps$contro9, _livechatProps$compon8, _livechatProps$contro10, _livechatProps$contro11, _livechatProps$compon9, _livechatProps$contro12, _livechatProps$compon10, _livechatProps$contro13, _livechatProps$compon11, _livechatProps$compon12, _livechatProps$compon13;
60
60
  useEffect(() => {
61
61
  uiTimer = createTimer();
62
62
  TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
@@ -409,7 +409,7 @@ export const LiveChatWidgetStateful = props => {
409
409
 
410
410
  // Start chat from SDK Event
411
411
  BroadcastService.getMessageByEventName(BroadcastEvent.StartChat).subscribe(msg => {
412
- var _props$chatConfig5, _props$chatConfig5$Li, _props$chatConfig6, _props$chatConfig6$Li, _msg$payload5, _msg$payload6, _msg$payload7, _msg$payload9, _inMemoryState$appSta2, _inMemoryState$appSta3, _inMemoryState$appSta4, _inMemoryState$appSta5;
412
+ var _props$chatConfig5, _props$chatConfig5$Li, _props$chatConfig6, _props$chatConfig6$Li, _msg$payload5, _msg$payload6, _msg$payload7, _msg$payload9, _inMemoryState$appSta2, _inMemoryState$appSta3;
413
413
  // If chat is out of operating hours chat widget sets the conversation state to OutOfOffice.
414
414
  if (typeof (props === null || props === void 0 ? void 0 : (_props$chatConfig5 = props.chatConfig) === null || _props$chatConfig5 === void 0 ? void 0 : (_props$chatConfig5$Li = _props$chatConfig5.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig5$Li === void 0 ? void 0 : _props$chatConfig5$Li.OutOfOperatingHours) === "string" && (props === null || props === void 0 ? void 0 : (_props$chatConfig6 = props.chatConfig) === null || _props$chatConfig6 === void 0 ? void 0 : (_props$chatConfig6$Li = _props$chatConfig6.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig6$Li === void 0 ? void 0 : _props$chatConfig6$Li.OutOfOperatingHours.toLowerCase()) === "true") {
415
415
  (state === null || state === void 0 ? void 0 : state.appStates.isMinimized) && dispatch({
@@ -447,8 +447,14 @@ export const LiveChatWidgetStateful = props => {
447
447
  });
448
448
  inMemoryState.domainStates.customContext = msg === null || msg === void 0 ? void 0 : (_msg$payload9 = msg.payload) === null || _msg$payload9 === void 0 ? void 0 : _msg$payload9.customContext;
449
449
 
450
- // Only initiate new chat if widget runtime state is one of the followings
451
- if (((_inMemoryState$appSta2 = inMemoryState.appStates) === null || _inMemoryState$appSta2 === void 0 ? void 0 : _inMemoryState$appSta2.conversationState) === ConversationState.Closed || ((_inMemoryState$appSta3 = inMemoryState.appStates) === null || _inMemoryState$appSta3 === void 0 ? void 0 : _inMemoryState$appSta3.conversationState) === ConversationState.InActive || ((_inMemoryState$appSta4 = inMemoryState.appStates) === null || _inMemoryState$appSta4 === void 0 ? void 0 : _inMemoryState$appSta4.conversationState) === ConversationState.Postchat) {
450
+ /*
451
+ * If the conversation is in closed state then we start a new chat,
452
+ * else if the conversation is in active state then we maximize the chat
453
+ * If the conversation is in inactive or postchat state then we maximize the chat.
454
+ *
455
+ * To start a new chat, it needs to be called via the close button or close chat via SDK.
456
+ **/
457
+ if (((_inMemoryState$appSta2 = inMemoryState.appStates) === null || _inMemoryState$appSta2 === void 0 ? void 0 : _inMemoryState$appSta2.conversationState) === ConversationState.Closed) {
452
458
  BroadcastService.postMessage({
453
459
  eventName: BroadcastEvent.ChatInitiated
454
460
  });
@@ -457,7 +463,7 @@ export const LiveChatWidgetStateful = props => {
457
463
  }
458
464
 
459
465
  // If minimized, maximize the chat
460
- if ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta5 = inMemoryState.appStates) === null || _inMemoryState$appSta5 === void 0 ? void 0 : _inMemoryState$appSta5.isMinimized) === true) {
466
+ if ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta3 = inMemoryState.appStates) === null || _inMemoryState$appSta3 === void 0 ? void 0 : _inMemoryState$appSta3.isMinimized) === true) {
461
467
  var _inMemoryState$domain, _inMemoryState$domain2, _inMemoryState$domain3, _inMemoryState$domain4;
462
468
  dispatch({
463
469
  type: LiveChatWidgetActionType.SET_MINIMIZED,
@@ -585,12 +591,12 @@ export const LiveChatWidgetStateful = props => {
585
591
  disablePolling: true
586
592
  });
587
593
  facadeChatSDK === null || facadeChatSDK === void 0 ? void 0 : facadeChatSDK.onAgentEndSession(event => {
588
- var _inMemoryState$appSta6;
594
+ var _inMemoryState$appSta4;
589
595
  const inMemoryState = executeReducer(state, {
590
596
  type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
591
597
  payload: null
592
598
  });
593
- if ("participantsRemoved" in event && (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta6 = inMemoryState.appStates) === null || _inMemoryState$appSta6 === void 0 ? void 0 : _inMemoryState$appSta6.conversationState) === ConversationState.Active) {
599
+ if ("participantsRemoved" in event && (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta4 = inMemoryState.appStates) === null || _inMemoryState$appSta4 === void 0 ? void 0 : _inMemoryState$appSta4.conversationState) === ConversationState.Active) {
594
600
  setWebChatStyles(styles => {
595
601
  return {
596
602
  ...styles,
@@ -733,13 +739,13 @@ export const LiveChatWidgetStateful = props => {
733
739
 
734
740
  // Handle Chat disconnect cases
735
741
  useEffect(() => {
736
- var _inMemoryState$appSta7;
742
+ var _inMemoryState$appSta5;
737
743
  const inMemoryState = executeReducer(state, {
738
744
  type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
739
745
  payload: null
740
746
  });
741
747
  handleChatDisconnect(props, inMemoryState, setWebChatStyles);
742
- const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta7 = inMemoryState.appStates) === null || _inMemoryState$appSta7 === void 0 ? void 0 : _inMemoryState$appSta7.chatDisconnectEventReceived;
748
+ const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta5 = inMemoryState.appStates) === null || _inMemoryState$appSta5 === void 0 ? void 0 : _inMemoryState$appSta5.chatDisconnectEventReceived;
743
749
  if (chatDisconnectState && adapter) {
744
750
  try {
745
751
  adapter.end();
@@ -868,8 +874,8 @@ export const LiveChatWidgetStateful = props => {
868
874
  userID: userID,
869
875
  styleOptions: {
870
876
  ...webChatStyles,
871
- bubbleBackground: ((_props$webChatContain11 = props.webChatContainerProps) === null || _props$webChatContain11 === void 0 ? void 0 : (_props$webChatContain12 = _props$webChatContain11.adaptiveCardStyles) === null || _props$webChatContain12 === void 0 ? void 0 : _props$webChatContain12.background) ?? defaultAdaptiveCardStyles.background,
872
- bubbleTextColor: ((_props$webChatContain13 = props.webChatContainerProps) === null || _props$webChatContain13 === void 0 ? void 0 : (_props$webChatContain14 = _props$webChatContain13.adaptiveCardStyles) === null || _props$webChatContain14 === void 0 ? void 0 : _props$webChatContain14.color) ?? defaultAdaptiveCardStyles.color
877
+ bubbleBackground: ((_props$webChatContain11 = props.webChatContainerProps) === null || _props$webChatContain11 === void 0 ? void 0 : (_props$webChatContain12 = _props$webChatContain11.webChatStyles) === null || _props$webChatContain12 === void 0 ? void 0 : _props$webChatContain12.bubbleBackground) ?? ((_props$webChatContain13 = props.webChatContainerProps) === null || _props$webChatContain13 === void 0 ? void 0 : (_props$webChatContain14 = _props$webChatContain13.adaptiveCardStyles) === null || _props$webChatContain14 === void 0 ? void 0 : _props$webChatContain14.background) ?? defaultAdaptiveCardStyles.background,
878
+ bubbleTextColor: ((_props$webChatContain15 = props.webChatContainerProps) === null || _props$webChatContain15 === void 0 ? void 0 : (_props$webChatContain16 = _props$webChatContain15.webChatStyles) === null || _props$webChatContain16 === void 0 ? void 0 : _props$webChatContain16.bubbleTextColor) ?? ((_props$webChatContain17 = props.webChatContainerProps) === null || _props$webChatContain17 === void 0 ? void 0 : (_props$webChatContain18 = _props$webChatContain17.adaptiveCardStyles) === null || _props$webChatContain18 === void 0 ? void 0 : _props$webChatContain18.color) ?? defaultAdaptiveCardStyles.color
873
879
  },
874
880
  directLine: directLine
875
881
  }), /*#__PURE__*/React.createElement(Stack, {
@@ -1,6 +1,7 @@
1
1
  import { LogLevel, TelemetryEvent } from "../../common/telemetry/TelemetryConstants";
2
2
  import React, { useEffect } from "react";
3
3
  import { createTimer, findAllFocusableElement } from "../../common/utils";
4
+ import DOMPurify from "dompurify";
4
5
  import { OutOfOfficeHoursPane } from "@microsoft/omnichannel-chat-components";
5
6
  import { TelemetryHelper } from "../../common/telemetry/TelemetryHelper";
6
7
  import { defaultGeneralStyleProps } from "./common/defaultStyleProps/defaultgeneralOOOHPaneStyleProps";
@@ -28,9 +29,11 @@ export const OutOfOfficeHoursPaneStateful = props => {
28
29
 
29
30
  // Move focus to the first button
30
31
  useEffect(() => {
31
- const firstElement = findAllFocusableElement(`#${state.domainStates.widgetElementId}`);
32
- if (firstElement && firstElement[0]) {
33
- firstElement[0].focus();
32
+ if (state.domainStates.widgetElementId !== null && state.domainStates.widgetElementId !== undefined && state.domainStates.widgetElementId.trim() !== "") {
33
+ const firstElement = findAllFocusableElement(`#${state.domainStates.widgetElementId}`);
34
+ if (firstElement && firstElement[0]) {
35
+ firstElement[0].focus();
36
+ }
34
37
  }
35
38
  TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
36
39
  Event: TelemetryEvent.OutOfOfficePaneLoaded
@@ -40,6 +43,9 @@ export const OutOfOfficeHoursPaneStateful = props => {
40
43
  ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
41
44
  });
42
45
  }, []);
46
+ if (controlProps !== null && controlProps !== void 0 && controlProps.titleText) {
47
+ controlProps.titleText = DOMPurify.sanitize(controlProps.titleText);
48
+ }
43
49
  return /*#__PURE__*/React.createElement(OutOfOfficeHoursPane, {
44
50
  componentOverrides: props.componentOverrides,
45
51
  controlProps: controlProps,
@@ -8,14 +8,16 @@ import { TelemetryHelper } from "../../common/telemetry/TelemetryHelper";
8
8
  import { defaultGeneralPostChatSurveyPaneStyleProps } from "./common/defaultStyleProps/defaultgeneralPostChatSurveyPaneStyleProps";
9
9
  import { findAllFocusableElement } from "../../common/utils";
10
10
  import useChatContextStore from "../../hooks/useChatContextStore";
11
+ import isValidSurveyUrl from "./common/isValidSurveyUrl";
11
12
  const generateSurveyInviteLink = function (surveyInviteLink, isEmbed, locale, compact) {
12
13
  let showMultiLingual = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
13
- const surveyLink = `${surveyInviteLink}
14
- &embed=${isEmbed.toString()}
15
- &compact=${compact.toString() ?? "true"}
16
- &lang=${locale ?? "en-us"}
17
- &showmultilingual=${showMultiLingual.toString() ?? "false"}`;
18
- return surveyLink;
14
+ const surveyLinkParams = new URLSearchParams({
15
+ embed: isEmbed.toString(),
16
+ compact: (compact ?? true).toString(),
17
+ lang: locale ?? "en-us",
18
+ showmultilingual: (showMultiLingual ?? false).toString()
19
+ });
20
+ return `${surveyInviteLink}&${surveyLinkParams.toString()}`;
19
21
  };
20
22
  export const PostChatSurveyPaneStateful = props => {
21
23
  var _props$styleProps, _state$appStates, _props$controlProps;
@@ -45,6 +47,20 @@ export const PostChatSurveyPaneStateful = props => {
45
47
  surveyURL: ((_props$controlProps = props.controlProps) === null || _props$controlProps === void 0 ? void 0 : _props$controlProps.surveyURL) ?? surveyInviteLink,
46
48
  ...props.controlProps
47
49
  };
50
+ if (controlProps.surveyURL) {
51
+ if (!isValidSurveyUrl(controlProps.surveyURL)) {
52
+ TelemetryHelper.logLoadingEvent(LogLevel.ERROR, {
53
+ Event: TelemetryEvent.PostChatSurveyUrlValidationFailed,
54
+ Description: `${controlProps.surveyURL} is not a valid Survey URL`
55
+ });
56
+ controlProps.surveyURL = "";
57
+ } else {
58
+ TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
59
+ Event: TelemetryEvent.PostChatSurveyUrlValidationCompleted,
60
+ Description: `${controlProps.surveyURL} is a valid Survey URL`
61
+ });
62
+ }
63
+ }
48
64
 
49
65
  // Move focus to the first button
50
66
  useEffect(() => {
@@ -0,0 +1,21 @@
1
+ import { isNullOrEmptyString } from "../../../common/utils";
2
+ const validRootDomains = ["microsoft.com", "microsoft.us", "appsplatform.us", "powervirtualagents.cn"];
3
+ const isValidSurveyUrl = url => {
4
+ if (isNullOrEmptyString(url)) {
5
+ return false;
6
+ }
7
+ try {
8
+ const objectUrl = new URL(url);
9
+ if (!objectUrl.origin || objectUrl.origin === "null") {
10
+ return false;
11
+ }
12
+ const validDomain = validRootDomains.find(domain => objectUrl.origin.endsWith(domain));
13
+ if (validDomain) {
14
+ return true;
15
+ }
16
+ } catch (error) {
17
+ return false;
18
+ }
19
+ return false;
20
+ };
21
+ export default isValidSurveyUrl;
@@ -1,12 +1,12 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
 
3
+ import { Constants, HtmlAttributeNames, HtmlClassNames } from "../../common/Constants";
3
4
  import { Stack } from "@fluentui/react";
4
5
  import { LogLevel, TelemetryEvent } from "../../common/telemetry/TelemetryConstants";
5
6
  import React, { useEffect } from "react";
6
7
  import { createTimer, getDeviceType, setFocusOnSendBox } from "../../common/utils";
7
8
  import { BotMagicCodeStore } from "./webchatcontroller/BotMagicCodeStore";
8
9
  import { Components } from "botframework-webchat";
9
- import { Constants, HtmlAttributeNames, HtmlClassNames } from "../../common/Constants";
10
10
  import { LiveChatWidgetActionType } from "../../contexts/common/LiveChatWidgetActionType";
11
11
  import { NotificationHandler } from "./webchatcontroller/notification/NotificationHandler";
12
12
  import { NotificationScenarios } from "./webchatcontroller/enums/NotificationScenarios";
@@ -48,7 +48,7 @@ const createMagicCodeSuccessResponse = signin => {
48
48
  };
49
49
  };
50
50
  export const WebChatContainerStateful = props => {
51
- var _webChatContainerProp, _webChatContainerProp2, _webChatContainerProp3, _webChatContainerProp4, _webChatContainerProp5, _webChatContainerProp6, _webChatContainerProp7, _props$webChatContain5, _props$webChatContain6, _defaultWebChatContai, _props$webChatContain7, _props$webChatContain8, _defaultWebChatContai2, _webChatContainerProp8, _webChatContainerProp9, _webChatContainerProp10, _webChatContainerProp11, _webChatContainerProp12, _webChatContainerProp13, _webChatContainerProp14, _webChatContainerProp15, _props$webChatContain9, _props$webChatContain10;
51
+ var _webChatContainerProp, _webChatContainerProp2, _webChatContainerProp3, _webChatContainerProp4, _webChatContainerProp5, _webChatContainerProp6, _webChatContainerProp7, _props$webChatContain5, _props$webChatContain6, _defaultWebChatContai, _props$webChatContain7, _props$webChatContain8, _defaultWebChatContai2, _webChatContainerProp8, _webChatContainerProp9, _webChatContainerProp10, _webChatContainerProp11, _webChatContainerProp12, _webChatContainerProp13, _webChatContainerProp14, _webChatContainerProp15, _webChatContainerProp16, _props$webChatContain9, _props$webChatContain10;
52
52
  useEffect(() => {
53
53
  uiTimer = createTimer();
54
54
  TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
@@ -233,8 +233,9 @@ export const WebChatContainerStateful = props => {
233
233
  color: ${(webChatContainerProps === null || webChatContainerProps === void 0 ? void 0 : (_webChatContainerProp14 = webChatContainerProps.renderingMiddlewareProps) === null || _webChatContainerProp14 === void 0 ? void 0 : (_webChatContainerProp15 = _webChatContainerProp14.sentMessageAnchorStyles) === null || _webChatContainerProp15 === void 0 ? void 0 : _webChatContainerProp15.color) ?? (defaultSentMessageAnchorStyles === null || defaultSentMessageAnchorStyles === void 0 ? void 0 : defaultSentMessageAnchorStyles.color)};
234
234
  }
235
235
 
236
+ // we had a nasty bug long time ago with crashing borders messing with the sendbox, so if customer adds this value, they need to deal with that
236
237
  .webchat__bubble:not(.webchat__bubble--from-user) .webchat__bubble__content {
237
- border-radius: 0 !important; /* Override border-radius */
238
+ border-radius: ${(webChatContainerProps === null || webChatContainerProps === void 0 ? void 0 : (_webChatContainerProp16 = webChatContainerProps.webChatStyles) === null || _webChatContainerProp16 === void 0 ? void 0 : _webChatContainerProp16.bubbleBorderRadius) ?? 0} !important; /* Override border-radius */
238
239
  }
239
240
 
240
241
  .webchat__stacked-layout_container>div {
@@ -35,6 +35,10 @@ export const DeliveredTimestamp = _ref => {
35
35
  return /*#__PURE__*/React.createElement("span", {
36
36
  dir: "ltr"
37
37
  }, getTimestampHourMinute(timestamp));
38
+ } else {
39
+ return /*#__PURE__*/React.createElement("span", {
40
+ dir: dir
41
+ }, getTimestampHourMinute(timestamp));
38
42
  }
39
43
  return timeString;
40
44
  };
@@ -1,11 +1,15 @@
1
- import { ConversationState } from "./ConversationState";
2
- import { defaultMiddlewareLocalizedTexts } from "../../components/webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts";
3
- import { getWidgetCacheIdfromProps, isNullOrUndefined } from "../../common/utils";
4
- import { defaultClientDataStoreProvider } from "../../common/storage/default/defaultClientDataStoreProvider";
5
1
  import { ConfirmationState, Constants, ConversationEndEntity, StorageType } from "../../common/Constants";
2
+ import { getWidgetCacheIdfromProps, isNullOrUndefined } from "../../common/utils";
3
+ import { ConversationState } from "./ConversationState";
6
4
  import { StartChatFailureType } from "./StartChatFailureType";
5
+ import { defaultClientDataStoreProvider } from "../../common/storage/default/defaultClientDataStoreProvider";
6
+ import { defaultMiddlewareLocalizedTexts } from "../../components/webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts";
7
7
  export const getLiveChatWidgetContextInitialState = props => {
8
8
  var _props$controlProps, _props$webChatContain;
9
+ const isOutsideOperatingHours = () => {
10
+ var _props$chatConfig, _props$chatConfig$Liv, _props$chatConfig$Liv2;
11
+ return ((_props$chatConfig = props.chatConfig) === null || _props$chatConfig === void 0 ? void 0 : (_props$chatConfig$Liv = _props$chatConfig.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig$Liv === void 0 ? void 0 : (_props$chatConfig$Liv2 = _props$chatConfig$Liv.OutOfOperatingHours) === null || _props$chatConfig$Liv2 === void 0 ? void 0 : _props$chatConfig$Liv2.toString().toLowerCase()) === "true";
12
+ };
9
13
  const widgetCacheId = getWidgetCacheIdfromProps(props);
10
14
  const cacheTtlInMins = (props === null || props === void 0 ? void 0 : (_props$controlProps = props.controlProps) === null || _props$controlProps === void 0 ? void 0 : _props$controlProps.cacheTtlInMins) ?? Constants.CacheTtlInMinutes;
11
15
  const storageType = (props === null || props === void 0 ? void 0 : props.useSessionStorage) === true ? StorageType.sessionStorage : StorageType.localStorage;
@@ -22,6 +26,14 @@ export const getLiveChatWidgetContextInitialState = props => {
22
26
  if (initialStateFromCache.appStates.conversationState === ConversationState.Prechat) {
23
27
  initialStateFromCache.appStates.conversationState = ConversationState.Closed;
24
28
  }
29
+
30
+ // we are always setting the chatConfig from the props to avoid any issues with the cache
31
+ initialStateFromCache.domainStates.liveChatConfig = props.chatConfig;
32
+
33
+ // Cache the result of isOutsideOperatingHours() to ensure consistency
34
+ const outsideOperatingHours = isOutsideOperatingHours();
35
+ initialStateFromCache.appStates.outsideOperatingHours = outsideOperatingHours;
36
+ initialStateFromCache.appStates.conversationState = outsideOperatingHours ? ConversationState.OutOfOffice : initialStateFromCache.appStates.conversationState;
25
37
  return initialStateFromCache;
26
38
  }
27
39
  const LiveChatWidgetContextInitialState = {
@@ -46,11 +58,11 @@ export const getLiveChatWidgetContextInitialState = props => {
46
58
  startChatFailureType: StartChatFailureType.Generic
47
59
  },
48
60
  appStates: {
49
- conversationState: ConversationState.Closed,
61
+ conversationState: isOutsideOperatingHours() ? ConversationState.OutOfOffice : ConversationState.Closed,
50
62
  isMinimized: undefined,
51
63
  previousElementIdOnFocusBeforeModalOpen: null,
52
64
  startChatFailed: false,
53
- outsideOperatingHours: false,
65
+ outsideOperatingHours: isOutsideOperatingHours(),
54
66
  preChatResponseEmail: "",
55
67
  isAudioMuted: null,
56
68
  newMessage: false,
@@ -0,0 +1,6 @@
1
+ export let ScenarioType;
2
+ (function (ScenarioType) {
3
+ ScenarioType["UserSendMessageStrategy"] = "UserSendMessageStrategy";
4
+ ScenarioType["SystemMessageStrategy"] = "SystemMessageStrategy";
5
+ ScenarioType["ReceivedMessageStrategy"] = "ReceivedMessageStrategy";
6
+ })(ScenarioType || (ScenarioType = {}));
@@ -0,0 +1,145 @@
1
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
2
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
3
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
4
+ import { LogLevel, TelemetryEvent } from "../common/telemetry/TelemetryConstants";
5
+ import { TelemetryHelper } from "../common/telemetry/TelemetryHelper";
6
+ export class FirstResponseLatencyTracker {
7
+ constructor() {
8
+ _defineProperty(this, "isABotConversation", false);
9
+ _defineProperty(this, "isStarted", false);
10
+ _defineProperty(this, "isEnded", false);
11
+ _defineProperty(this, "startTrackingMessage", void 0);
12
+ _defineProperty(this, "stopTrackingMessage", void 0);
13
+ // this is a workaround to ensure in reload we track effectively the messages
14
+ // we do have a mechanism in place to prevent log agent messages.
15
+ this.isABotConversation = true;
16
+ }
17
+ createTrackingMessage(payload, type) {
18
+ return {
19
+ Id: payload.Id,
20
+ role: payload.role,
21
+ timestamp: payload === null || payload === void 0 ? void 0 : payload.timestamp,
22
+ tags: payload.tags,
23
+ messageType: payload.messageType,
24
+ text: payload.text,
25
+ type: type,
26
+ checkTime: new Date().getTime()
27
+ };
28
+ }
29
+
30
+ // Tracking Functions
31
+ startTracking(payload) {
32
+ // this prevents to initiate tracking for multiple incoming messages
33
+ if (this.isStarted) {
34
+ return;
35
+ }
36
+ // this is to ensure we track only messages where bot is engaged
37
+ if (!this.isABotConversation) {
38
+ return;
39
+ }
40
+
41
+ // control of states to prevent clashing of messages
42
+ this.isStarted = true;
43
+ this.isEnded = false;
44
+
45
+ // The idea of using types is to enrich telemetry data
46
+ this.startTrackingMessage = this.createTrackingMessage(payload, "userMessage");
47
+ }
48
+ handleAgentMessage(payload) {
49
+ var _payload$tags;
50
+ // this tag so far is only present in agent messages
51
+ if (payload !== null && payload !== void 0 && (_payload$tags = payload.tags) !== null && _payload$tags !== void 0 && _payload$tags.includes("public")) {
52
+ this.deregister();
53
+ }
54
+ }
55
+ stopTracking(payload) {
56
+ var _this$stopTrackingMes, _this$startTrackingMe;
57
+ // this prevents execution for multiple incoming messages from the bot.
58
+ if (this.isEnded && !this.isStarted) {
59
+ return;
60
+ }
61
+
62
+ // control of states to prevent clashing of messages
63
+ this.isEnded = true;
64
+ this.isStarted = false;
65
+
66
+ // The idea of using types is to enrich telemetry data
67
+ this.stopTrackingMessage = this.createTrackingMessage(payload, "botMessage");
68
+ // calculating elapsed time
69
+ const elapsedTime = (((_this$stopTrackingMes = this.stopTrackingMessage) === null || _this$stopTrackingMes === void 0 ? void 0 : _this$stopTrackingMes.checkTime) ?? 0) - (((_this$startTrackingMe = this.startTrackingMessage) === null || _this$startTrackingMe === void 0 ? void 0 : _this$startTrackingMe.checkTime) ?? 0);
70
+ TelemetryHelper.logActionEvent(LogLevel.INFO, {
71
+ Event: TelemetryEvent.MessageLapTrack,
72
+ Description: "First response latency tracking",
73
+ CustomProperties: {
74
+ elapsedTime,
75
+ userMessage: this.startTrackingMessage,
76
+ botMessage: this.stopTrackingMessage
77
+ }
78
+ });
79
+ }
80
+
81
+ // mechanism to ensure we track only allowed conversations
82
+ isMessageFromValidSender(payload) {
83
+ var _payload$tags2;
84
+ // agent scenario
85
+ if (payload !== null && payload !== void 0 && (_payload$tags2 = payload.tags) !== null && _payload$tags2 !== void 0 && _payload$tags2.includes("public")) {
86
+ this.handleAgentMessage(payload);
87
+ return false;
88
+ }
89
+ return true;
90
+ }
91
+ startClock(payload) {
92
+ try {
93
+ if (!payload || !payload.Id) {
94
+ throw new Error("Invalid payload");
95
+ }
96
+ // in the case of a reload, tracker will be paused, until last history message is received
97
+ // this is because we dont have a way to identidy send messages as part of the history
98
+ //if (this.inPause) return;
99
+ this.startTracking(payload);
100
+ } catch (e) {
101
+ TelemetryHelper.logActionEvent(LogLevel.ERROR, {
102
+ Event: TelemetryEvent.MessageStartLapTrackError,
103
+ Description: "Error while starting the clock",
104
+ ExceptionDetails: e,
105
+ CustomProperties: {
106
+ payload: payload
107
+ }
108
+ });
109
+ }
110
+ }
111
+ stopClock(payload) {
112
+ try {
113
+ if (!payload || !payload.Id) {
114
+ throw new Error("Invalid payload");
115
+ }
116
+ if (!this.isMessageFromValidSender(payload)) return;
117
+ if (this.isABotConversation && this.isStarted) {
118
+ this.stopTracking(payload);
119
+ }
120
+ } catch (e) {
121
+ console.error("FRL : error while trying to stop the tracker", e);
122
+ TelemetryHelper.logActionEvent(LogLevel.ERROR, {
123
+ Event: TelemetryEvent.MessageStopLapTrackError,
124
+ Description: "Error while stopping the clock",
125
+ ExceptionDetails: e,
126
+ CustomProperties: {
127
+ payload: payload
128
+ }
129
+ });
130
+ //reset state
131
+ this.startTrackingMessage = undefined;
132
+ this.stopTrackingMessage = undefined;
133
+ this.isStarted = false;
134
+ this.isEnded = false;
135
+ }
136
+ }
137
+ deregister() {
138
+ // Reset State
139
+ this.isABotConversation = false;
140
+ this.isStarted = false;
141
+ this.isEnded = false;
142
+ this.startTrackingMessage = undefined;
143
+ this.stopTrackingMessage = undefined;
144
+ }
145
+ }
@@ -0,0 +1,75 @@
1
+ import { ScenarioType } from "./Constants";
2
+ import { Constants } from "../common/Constants";
3
+ export const isHistoryMessage = (activity, startTime) => {
4
+ try {
5
+ if ((activity === null || activity === void 0 ? void 0 : activity.type) === Constants.message) {
6
+ var _activity$channelData, _activity$channelData2;
7
+ // this is an old piece of code, probably no longer relevant
8
+ if (activity !== null && activity !== void 0 && (_activity$channelData = activity.channelData) !== null && _activity$channelData !== void 0 && (_activity$channelData2 = _activity$channelData.tags) !== null && _activity$channelData2 !== void 0 && _activity$channelData2.includes(Constants.historyMessageTag)) return true;
9
+
10
+ // Id is an epoch time in milliseconds , in utc format, for some reason is in a string format
11
+ if (activity !== null && activity !== void 0 && activity.id) {
12
+ /// activity.id is an string that contains epoch time in milliseconds
13
+ const activityId = parseInt(activity === null || activity === void 0 ? void 0 : activity.id);
14
+
15
+ // if the activity id is not a number, we default to new message
16
+ if (isNaN(activityId)) {
17
+ return false;
18
+ }
19
+
20
+ // if the activity id is less than the start time, it means that the message is a history message
21
+ if (activityId < startTime) {
22
+ return true;
23
+ }
24
+ }
25
+ // anything else will be considered a new message
26
+ return false;
27
+ }
28
+ } catch (e) {
29
+ // if there is an error in parsing the activity id, we will consider it a new message
30
+ console.error("Error in parsing activity id: ", e);
31
+ }
32
+ return false;
33
+ };
34
+ export const buildMessagePayload = (activity, userId) => {
35
+ var _text, _text2, _activity$channelData3, _activity$from;
36
+ return {
37
+ // To identify hidden contents vs empty content
38
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
+ text: (activity === null || activity === void 0 ? void 0 : (_text = activity.text) === null || _text === void 0 ? void 0 : _text.length) >= 1 ? `*contents hidden (${activity === null || activity === void 0 ? void 0 : (_text2 = activity.text) === null || _text2 === void 0 ? void 0 : _text2.length} chars)*` : "",
40
+ type: activity === null || activity === void 0 ? void 0 : activity.type,
41
+ timestamp: activity === null || activity === void 0 ? void 0 : activity.timestamp,
42
+ userId: userId,
43
+ tags: activity === null || activity === void 0 ? void 0 : (_activity$channelData3 = activity.channelData) === null || _activity$channelData3 === void 0 ? void 0 : _activity$channelData3.tags,
44
+ messageType: "",
45
+ Id: activity === null || activity === void 0 ? void 0 : activity.id,
46
+ role: activity === null || activity === void 0 ? void 0 : (_activity$from = activity.from) === null || _activity$from === void 0 ? void 0 : _activity$from.role,
47
+ isChatComplete: false
48
+ };
49
+ };
50
+ export const polyfillMessagePayloadForEvent = (activity, payload, conversationId) => {
51
+ var _activity$conversatio, _attachments, _activity$from2;
52
+ return {
53
+ ...payload,
54
+ channelData: activity === null || activity === void 0 ? void 0 : activity.channelData,
55
+ chatId: activity === null || activity === void 0 ? void 0 : (_activity$conversatio = activity.conversation) === null || _activity$conversatio === void 0 ? void 0 : _activity$conversatio.id,
56
+ conversationId: conversationId,
57
+ Id: activity === null || activity === void 0 ? void 0 : activity.id,
58
+ isChatComplete: false,
59
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
60
+ text: activity === null || activity === void 0 ? void 0 : activity.text,
61
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
62
+ attachment: (activity === null || activity === void 0 ? void 0 : (_attachments = activity.attachments) === null || _attachments === void 0 ? void 0 : _attachments.length) >= 1 ? activity === null || activity === void 0 ? void 0 : activity.attachments : [],
63
+ role: activity === null || activity === void 0 ? void 0 : (_activity$from2 = activity.from) === null || _activity$from2 === void 0 ? void 0 : _activity$from2.role
64
+ };
65
+ };
66
+ export const getScenarioType = activity => {
67
+ var _activity$from3, _activity$channelData4, _activity$channelData5;
68
+ if ((activity === null || activity === void 0 ? void 0 : (_activity$from3 = activity.from) === null || _activity$from3 === void 0 ? void 0 : _activity$from3.role) === Constants.userMessageTag) {
69
+ return ScenarioType.UserSendMessageStrategy;
70
+ }
71
+ if (activity !== null && activity !== void 0 && (_activity$channelData4 = activity.channelData) !== null && _activity$channelData4 !== void 0 && (_activity$channelData5 = _activity$channelData4.tags) !== null && _activity$channelData5 !== void 0 && _activity$channelData5.includes(Constants.systemMessageTag)) {
72
+ return ScenarioType.SystemMessageStrategy;
73
+ }
74
+ return ScenarioType.ReceivedMessageStrategy;
75
+ };
@@ -168,7 +168,7 @@ class TranscriptHTMLBuilder {
168
168
  <script>
169
169
  class Translator {
170
170
  static convertTranscriptMessageToActivity(message) {
171
- const {created, OriginalMessageId, id, isControlMessage, content, tags, from, attachments, amsMetadata, amsReferences} = message;
171
+ const {created, OriginalMessageId, id, isControlMessage, content, tags, from, attachments, amsMetadata, amsReferences, amsreferences} = message;
172
172
 
173
173
  //it's required to convert the id to a number, otherwise the webchat will not render the messages in the correct order
174
174
  // if the OrginalMessageId is not present, we can use the id as the sequence id, which is always present.
@@ -215,7 +215,7 @@ class TranscriptHTMLBuilder {
215
215
  }
216
216
 
217
217
  // Attachments
218
- if (amsReferences && amsMetadata) {
218
+ if ((amsReferences || amsreferences) && amsMetadata) {
219
219
  const metadata = JSON.parse(amsMetadata);
220
220
  const { fileName } = metadata[0];
221
221
  const text = \`${this.attachmentMessage}\${fileName}\`;
@@ -239,7 +239,7 @@ class TranscriptHTMLBuilder {
239
239
  // Message
240
240
  if (content) {
241
241
  // Adaptive card formatting
242
- if (content.includes('"text"') && content.includes('"attachments"') && content.includes('"suggestedActions"')) {
242
+ if (content.includes('"attachments"') || content.includes('"suggestedActions"')) {
243
243
  try {
244
244
  const partialActivity = JSON.parse(content);
245
245
  return {
@@ -678,7 +678,7 @@ const createChatTranscript = async function (transcript, facadeChatSDK) {
678
678
  messages = await Promise.all(transcriptMessages.map(async message => {
679
679
  // eslint-disable-line @typescript-eslint/no-explicit-any
680
680
  const {
681
- amsReferences,
681
+ amsReferences = message.amsreferences,
682
682
  amsMetadata
683
683
  } = message;
684
684
  if (amsReferences && amsMetadata) {