@microsoft/omnichannel-chat-sdk 2.0.2 → 2.1.0-main.8f375cf

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.
@@ -67,6 +67,7 @@ var locale_1 = require("./utils/locale");
67
67
  var exceptionThrowers_1 = require("./utils/exceptionThrowers");
68
68
  var errorClassifier_1 = require("./utils/errorClassifier");
69
69
  var utilities_1 = require("./utils/utilities");
70
+ var messageUpdates_1 = require("./utils/messageUpdates");
70
71
  var WebUtils_1 = require("./utils/WebUtils");
71
72
  var AMSClientUtils_1 = require("./utils/AMSClientUtils");
72
73
  var SDKConfigValidators_1 = require("./validators/SDKConfigValidators");
@@ -86,6 +87,7 @@ var MessageContentType_1 = require("@microsoft/omnichannel-ic3core/lib/model/Mes
86
87
  var MessageSource_1 = require("./telemetry/MessageSource");
87
88
  var MessageType_1 = require("@microsoft/omnichannel-ic3core/lib/model/MessageType");
88
89
  var OmnichannelErrorCodes_1 = require("./core/OmnichannelErrorCodes");
90
+ var OmnichannelMessage_1 = require("./core/messaging/OmnichannelMessage");
89
91
  var PersonType_1 = require("@microsoft/omnichannel-ic3core/lib/model/PersonType");
90
92
  var ProtocoleType_1 = require("@microsoft/omnichannel-ic3core/lib/interfaces/ProtocoleType");
91
93
  var ScenarioMarker_1 = require("./telemetry/ScenarioMarker");
@@ -103,6 +105,8 @@ var location_1 = require("./utils/location");
103
105
  var internalUtils_1 = require("./utils/internalUtils");
104
106
  var loggerUtils_1 = require("./utils/loggerUtils");
105
107
  var parsers_1 = require("./utils/parsers");
108
+ var chatTokenUnauthorizedRecovery_1 = require("./utils/chatTokenUnauthorizedRecovery");
109
+ var chatTokenRenewal_1 = require("./utils/chatTokenRenewal");
106
110
  var platform_1 = require("./utils/platform");
107
111
  var retrieveCollectorUri_1 = require("./telemetry/retrieveCollectorUri");
108
112
  var startPolling_1 = require("./commands/startPolling");
@@ -125,6 +129,8 @@ var OmnichannelChatSDK = /** @class */ (function () {
125
129
  this.unqServicesOrgUrl = null;
126
130
  this.coreServicesOrgUrl = null;
127
131
  this.dynamicsLocationCode = null;
132
+ this.chatTokenUnauthorizedRecovery = null;
133
+ this.chatTokenRenewedListeners = new Set();
128
134
  this.widgetSnippetBaseUrl = '';
129
135
  this.dataMaskingRules = { rules: [] };
130
136
  this.authSettings = null;
@@ -141,6 +147,8 @@ var OmnichannelChatSDK = /** @class */ (function () {
141
147
  this.isPersistentChat = false;
142
148
  this.isChatReconnect = false;
143
149
  this.reconnectId = null;
150
+ // Session key of the most recently ended chat. MRT validates it on transcript calls made after endChat.
151
+ this.endedChatSessionKey = null;
144
152
  this.refreshTokenTimer = null;
145
153
  this.AMSClientLoadCurrentState = AMSClientLoadStates_1.AMSClientLoadStates.NOT_LOADED;
146
154
  this.isMaskingDisabled = false;
@@ -876,6 +884,7 @@ var OmnichannelChatSDK = /** @class */ (function () {
876
884
  switch (_u.label) {
877
885
  case 0:
878
886
  this.isEndingChat = false;
887
+ this.endedChatSessionKey = null;
879
888
  this.scenarioMarker.startScenario(TelemetryEvent_1.default.StartChat, {
880
889
  RequestId: this.requestId
881
890
  });
@@ -957,7 +966,7 @@ var OmnichannelChatSDK = /** @class */ (function () {
957
966
  hasAuthToken: String(!!this.authenticatedUserToken)
958
967
  })
959
968
  });
960
- if (!this.authSettings) return [3 /*break*/, 15];
969
+ if (!this.authSettings) return [3 /*break*/, 16];
961
970
  if (!(isMidAuthEnabled && (deferInitialAuth || !this.authenticatedUserToken))) return [3 /*break*/, 9];
962
971
  this.scenarioMarker.singleRecord(TelemetryEvent_1.default.StartChat, {
963
972
  RequestId: this.requestId || "",
@@ -968,7 +977,7 @@ var OmnichannelChatSDK = /** @class */ (function () {
968
977
  hasAuthToken: String(!!this.authenticatedUserToken)
969
978
  })
970
979
  });
971
- return [3 /*break*/, 15];
980
+ return [3 /*break*/, 16];
972
981
  case 9:
973
982
  if (!!this.authenticatedUserToken) return [3 /*break*/, 11];
974
983
  return [4 /*yield*/, this.setAuthTokenProvider(this.chatSDKConfig.getAuthToken, { throwError: true })];
@@ -976,7 +985,7 @@ var OmnichannelChatSDK = /** @class */ (function () {
976
985
  _u.sent();
977
986
  _u.label = 11;
978
987
  case 11:
979
- if (!(optionalParams.liveChatContext && Object.keys(optionalParams.liveChatContext).length > 0)) return [3 /*break*/, 15];
988
+ if (!(optionalParams.liveChatContext && Object.keys(optionalParams.liveChatContext).length > 0)) return [3 /*break*/, 16];
980
989
  this.chatToken = optionalParams.liveChatContext.chatToken || {};
981
990
  this.requestId = optionalParams.liveChatContext.requestId || (0, ocsdk_1.uuidv4)();
982
991
  _u.label = 12;
@@ -998,12 +1007,21 @@ var OmnichannelChatSDK = /** @class */ (function () {
998
1007
  exceptionThrowers_1.default.throwAuthenticatedChatConversationRetrievalFailure(e_7, this.scenarioMarker, TelemetryEvent_1.default.StartChat, telemetryData);
999
1008
  return [3 /*break*/, 15];
1000
1009
  case 15:
1001
- if (!(((_k = this.chatSDKConfig.useCreateConversation) === null || _k === void 0 ? void 0 : _k.disable) && this.chatToken && Object.keys(this.chatToken).length === 0)) return [3 /*break*/, 17];
1002
- return [4 /*yield*/, this.getChatToken(false)];
1010
+ // A persistent chat restore has a reconnectId, so the restore above skipped the key. Without it,
1011
+ // calls the service validates against the chat's session key (transcripts) return 401. Apply it
1012
+ // only after the chat is confirmed to belong to the signed-in user.
1013
+ this.sessionId = optionalParams.liveChatContext.sessionId || null;
1014
+ if (this.sessionId) {
1015
+ this.OCClient.sessionId = this.sessionId;
1016
+ }
1017
+ _u.label = 16;
1003
1018
  case 16:
1004
- _u.sent();
1005
- _u.label = 17;
1019
+ if (!(((_k = this.chatSDKConfig.useCreateConversation) === null || _k === void 0 ? void 0 : _k.disable) && this.chatToken && Object.keys(this.chatToken).length === 0)) return [3 /*break*/, 18];
1020
+ return [4 /*yield*/, this.getChatToken(false)];
1006
1021
  case 17:
1022
+ _u.sent();
1023
+ _u.label = 18;
1024
+ case 18:
1007
1025
  if ((_l = this.chatToken) === null || _l === void 0 ? void 0 : _l.chatId) {
1008
1026
  loggerUtils_1.default.setChatId(this.chatToken.chatId || '', this.ocSdkLogger, this.acsClientLogger, this.acsAdapterLogger, this.callingSdkLogger, this.amsClientLogger, this.ic3ClientLogger);
1009
1027
  }
@@ -1024,14 +1042,14 @@ var OmnichannelChatSDK = /** @class */ (function () {
1024
1042
  else if (this.isChatReconnect && !((_o = this.chatSDKConfig.chatReconnect) === null || _o === void 0 ? void 0 : _o.disable) && !this.isPersistentChat) {
1025
1043
  sessionInitOptionalParams.reconnectId = this.reconnectId;
1026
1044
  }
1027
- if (!((0, parsers_1.parseLowerCaseString)((_q = (_p = this.liveChatConfig) === null || _p === void 0 ? void 0 : _p.LiveWSAndLiveChatEngJoin) === null || _q === void 0 ? void 0 : _q.msdyn_requestvisitorlocation) === "true")) return [3 /*break*/, 19];
1045
+ if (!((0, parsers_1.parseLowerCaseString)((_q = (_p = this.liveChatConfig) === null || _p === void 0 ? void 0 : _p.LiveWSAndLiveChatEngJoin) === null || _q === void 0 ? void 0 : _q.msdyn_requestvisitorlocation) === "true")) return [3 /*break*/, 20];
1028
1046
  return [4 /*yield*/, (0, location_1.getLocationInfo)(this.scenarioMarker, this.chatToken.chatId, this.requestId)];
1029
- case 18:
1047
+ case 19:
1030
1048
  location_2 = _u.sent();
1031
1049
  sessionInitOptionalParams.initContext.latitude = location_2.latitude;
1032
1050
  sessionInitOptionalParams.initContext.longitude = location_2.longitude;
1033
- _u.label = 19;
1034
- case 19:
1051
+ _u.label = 20;
1052
+ case 20:
1035
1053
  sessionInitPromise = function () { return __awaiter(_this, void 0, void 0, function () {
1036
1054
  var error_6, telemetryData;
1037
1055
  var _a, _b, _c;
@@ -1097,10 +1115,10 @@ var OmnichannelChatSDK = /** @class */ (function () {
1097
1115
  });
1098
1116
  }); };
1099
1117
  messagingClientPromise = function () { return __awaiter(_this, void 0, void 0, function () {
1100
- var chatAdapterConfig, error_8, telemetryData, _a, error_9, telemetryData, error_10, telemetryData, _b, error_11, telemetryData;
1101
- var _c, _d;
1102
- return __generator(this, function (_e) {
1103
- switch (_e.label) {
1118
+ var chatAdapterConfig, tokenRefresher, error_8, telemetryData, _a, error_9, telemetryData, error_10, telemetryData, _b, error_11, telemetryData;
1119
+ var _c, _d, _e;
1120
+ return __generator(this, function (_f) {
1121
+ switch (_f.label) {
1104
1122
  case 0:
1105
1123
  if (!(this.liveChatVersion === LiveChatVersion_1.default.V2)) return [3 /*break*/, 8];
1106
1124
  chatAdapterConfig = {
@@ -1110,18 +1128,22 @@ var OmnichannelChatSDK = /** @class */ (function () {
1110
1128
  environmentUrl: this.chatToken.acsEndpoint,
1111
1129
  pollingInterval: 30000
1112
1130
  };
1113
- _e.label = 1;
1131
+ _f.label = 1;
1114
1132
  case 1:
1115
- _e.trys.push([1, 3, , 4]);
1133
+ _f.trys.push([1, 3, , 4]);
1134
+ tokenRefresher = this.createChatTokenRefresher(chatAdapterConfig.token);
1135
+ this.chatTokenUnauthorizedRecovery = this.createChatTokenUnauthorizedRecovery(chatAdapterConfig.token, tokenRefresher);
1116
1136
  return [4 /*yield*/, ((_c = this.ACSClient) === null || _c === void 0 ? void 0 : _c.initialize({
1117
1137
  token: chatAdapterConfig.token,
1118
1138
  environmentUrl: chatAdapterConfig.environmentUrl,
1139
+ tokenRefresher: tokenRefresher,
1140
+ unauthorizedRecovery: (_d = this.chatTokenUnauthorizedRecovery) !== null && _d !== void 0 ? _d : undefined
1119
1141
  }))];
1120
1142
  case 2:
1121
- _e.sent();
1143
+ _f.sent();
1122
1144
  return [3 /*break*/, 4];
1123
1145
  case 3:
1124
- error_8 = _e.sent();
1146
+ error_8 = _f.sent();
1125
1147
  telemetryData = {
1126
1148
  RequestId: this.requestId,
1127
1149
  ChatId: this.chatToken.chatId,
@@ -1129,22 +1151,22 @@ var OmnichannelChatSDK = /** @class */ (function () {
1129
1151
  exceptionThrowers_1.default.throwMessagingClientInitializationFailure(error_8, this.scenarioMarker, TelemetryEvent_1.default.StartChat, telemetryData);
1130
1152
  return [3 /*break*/, 4];
1131
1153
  case 4:
1132
- _e.trys.push([4, 6, , 7]);
1154
+ _f.trys.push([4, 6, , 7]);
1133
1155
  _a = this;
1134
- return [4 /*yield*/, ((_d = this.ACSClient) === null || _d === void 0 ? void 0 : _d.joinConversation({
1156
+ return [4 /*yield*/, ((_e = this.ACSClient) === null || _e === void 0 ? void 0 : _e.joinConversation({
1135
1157
  id: chatAdapterConfig.id,
1136
1158
  threadId: chatAdapterConfig.threadId,
1137
1159
  pollingInterval: chatAdapterConfig.pollingInterval
1138
1160
  }))];
1139
1161
  case 5:
1140
- _a.conversation = (_e.sent());
1162
+ _a.conversation = (_f.sent());
1141
1163
  this.scenarioMarker.completeScenario(TelemetryEvent_1.default.StartChat, {
1142
1164
  RequestId: this.requestId,
1143
1165
  ChatId: this.chatToken.chatId
1144
1166
  });
1145
1167
  return [3 /*break*/, 7];
1146
1168
  case 6:
1147
- error_9 = _e.sent();
1169
+ error_9 = _f.sent();
1148
1170
  telemetryData = {
1149
1171
  RequestId: this.requestId,
1150
1172
  ChatId: this.chatToken.chatId,
@@ -1153,17 +1175,17 @@ var OmnichannelChatSDK = /** @class */ (function () {
1153
1175
  return [3 /*break*/, 7];
1154
1176
  case 7: return [3 /*break*/, 14];
1155
1177
  case 8:
1156
- _e.trys.push([8, 10, , 11]);
1178
+ _f.trys.push([8, 10, , 11]);
1157
1179
  return [4 /*yield*/, this.IC3Client.initialize({
1158
1180
  token: this.chatToken.token,
1159
1181
  regionGtms: this.chatToken.regionGTMS,
1160
1182
  visitor: true
1161
1183
  })];
1162
1184
  case 9:
1163
- _e.sent();
1185
+ _f.sent();
1164
1186
  return [3 /*break*/, 11];
1165
1187
  case 10:
1166
- error_10 = _e.sent();
1188
+ error_10 = _f.sent();
1167
1189
  telemetryData = {
1168
1190
  RequestId: this.requestId,
1169
1191
  ChatId: this.chatToken.chatId,
@@ -1171,18 +1193,18 @@ var OmnichannelChatSDK = /** @class */ (function () {
1171
1193
  exceptionThrowers_1.default.throwMessagingClientInitializationFailure(error_10, this.scenarioMarker, TelemetryEvent_1.default.StartChat, telemetryData);
1172
1194
  return [3 /*break*/, 11];
1173
1195
  case 11:
1174
- _e.trys.push([11, 13, , 14]);
1196
+ _f.trys.push([11, 13, , 14]);
1175
1197
  _b = this;
1176
1198
  return [4 /*yield*/, this.IC3Client.joinConversation(this.chatToken.chatId)];
1177
1199
  case 12:
1178
- _b.conversation = _e.sent();
1200
+ _b.conversation = _f.sent();
1179
1201
  this.scenarioMarker.completeScenario(TelemetryEvent_1.default.StartChat, {
1180
1202
  RequestId: this.requestId,
1181
1203
  ChatId: this.chatToken.chatId
1182
1204
  });
1183
1205
  return [3 /*break*/, 14];
1184
1206
  case 13:
1185
- error_11 = _e.sent();
1207
+ error_11 = _f.sent();
1186
1208
  telemetryData = {
1187
1209
  RequestId: this.requestId,
1188
1210
  ChatId: this.chatToken.chatId,
@@ -1225,32 +1247,32 @@ var OmnichannelChatSDK = /** @class */ (function () {
1225
1247
  }
1226
1248
  });
1227
1249
  }); };
1228
- if (!!((_r = this.chatSDKConfig.useCreateConversation) === null || _r === void 0 ? void 0 : _r.disable)) return [3 /*break*/, 21];
1250
+ if (!!((_r = this.chatSDKConfig.useCreateConversation) === null || _r === void 0 ? void 0 : _r.disable)) return [3 /*break*/, 22];
1229
1251
  return [4 /*yield*/, createConversationPromise()];
1230
- case 20:
1252
+ case 21:
1231
1253
  _u.sent();
1232
- return [3 /*break*/, 23];
1233
- case 21: return [4 /*yield*/, sessionInitPromise()];
1234
- case 22:
1235
- _u.sent(); // Await the session initialization
1236
- _u.label = 23;
1254
+ return [3 /*break*/, 24];
1255
+ case 22: return [4 /*yield*/, sessionInitPromise()];
1237
1256
  case 23:
1238
- _u.trys.push([23, 25, , 27]);
1239
- return [4 /*yield*/, Promise.all([messagingClientPromise(), attachmentClientPromise()])];
1257
+ _u.sent(); // Await the session initialization
1258
+ _u.label = 24;
1240
1259
  case 24:
1241
- _u.sent();
1242
- return [3 /*break*/, 27];
1260
+ _u.trys.push([24, 26, , 28]);
1261
+ return [4 /*yield*/, Promise.all([messagingClientPromise(), attachmentClientPromise()])];
1243
1262
  case 25:
1263
+ _u.sent();
1264
+ return [3 /*break*/, 28];
1265
+ case 26:
1244
1266
  error_5 = _u.sent();
1245
1267
  // If conversation joining fails after conversation was created, clean up the conversation
1246
1268
  // Only cleanup conversations that were freshly created (not existing ones being reconnected to)
1247
1269
  return [4 /*yield*/, this.handleConversationJoinFailure(error_5, optionalParams)];
1248
- case 26:
1270
+ case 27:
1249
1271
  // If conversation joining fails after conversation was created, clean up the conversation
1250
1272
  // Only cleanup conversations that were freshly created (not existing ones being reconnected to)
1251
1273
  _u.sent();
1252
1274
  throw error_5; // Re-throw the original error
1253
- case 27:
1275
+ case 28:
1254
1276
  if (this.isPersistentChat && !((_s = this.chatSDKConfig.persistentChat) === null || _s === void 0 ? void 0 : _s.disable)) {
1255
1277
  this.refreshTokenTimer = setInterval(function () { return __awaiter(_this, void 0, void 0, function () {
1256
1278
  var error_13;
@@ -1360,7 +1382,7 @@ var OmnichannelChatSDK = /** @class */ (function () {
1360
1382
  };
1361
1383
  OmnichannelChatSDK.prototype.internalEndChat = function () {
1362
1384
  return __awaiter(this, arguments, void 0, function (endChatOptionalParams) {
1363
- var cleanupMetadata, isReactNative, isConversationalSurveyEnabled, shouldWaitForSurvey, telemetryData, surveyStarted, error_15, error_16, telemetryData;
1385
+ var cleanupMetadata, isReactNative, isConversationalSurveyEnabled, shouldWaitForSurvey, telemetryData, surveyStarted, error_15, error_16, telemetryData, endedChatId, endedSessionId;
1364
1386
  var _a, _b, _c;
1365
1387
  if (endChatOptionalParams === void 0) { endChatOptionalParams = {}; }
1366
1388
  return __generator(this, function (_d) {
@@ -1419,12 +1441,17 @@ var OmnichannelChatSDK = /** @class */ (function () {
1419
1441
  exceptionThrowers_1.default.throwConversationClosureFailure(error_16, this.scenarioMarker, TelemetryEvent_1.default.EndChat, telemetryData);
1420
1442
  return [3 /*break*/, 11];
1421
1443
  case 10:
1422
- // Cleanup always runs, regardless of success or failure
1423
- // This ensures resources are released even if closeChat or survey waiting throws
1444
+ endedChatId = this.chatToken.chatId;
1445
+ endedSessionId = this.OCClient.sessionId || this.sessionId;
1446
+ // Keep the previous chat's key when this call had no chat to end (for example a second endChat).
1447
+ if (endedChatId && endedSessionId) {
1448
+ this.endedChatSessionKey = { chatId: endedChatId, sessionId: endedSessionId };
1449
+ }
1424
1450
  (_c = this.conversation) === null || _c === void 0 ? void 0 : _c.disconnect();
1425
1451
  this.conversation = null;
1426
1452
  this.requestId = (0, ocsdk_1.uuidv4)();
1427
1453
  this.chatToken = {};
1454
+ this.chatTokenUnauthorizedRecovery = null;
1428
1455
  this.reconnectId = null;
1429
1456
  if (this.IC3Client) {
1430
1457
  this.IC3Client.dispose();
@@ -1543,6 +1570,20 @@ var OmnichannelChatSDK = /** @class */ (function () {
1543
1570
  });
1544
1571
  });
1545
1572
  };
1573
+ /**
1574
+ * Subscribes to usable chat token renewals after the current SDK context has been updated.
1575
+ * No token or other payload is passed. Read getCurrentLiveChatContext() to persist the updated context.
1576
+ * Returns an idempotent unsubscribe function. Listener failures never affect renewal.
1577
+ * Subscriptions belong to this SDK instance and survive endChat()/startChat().
1578
+ * Subscribe before startChat() to observe restoration renewals; past notifications are not replayed.
1579
+ * Unsubscribe on host teardown or before replacing a per-chat subscription.
1580
+ */
1581
+ OmnichannelChatSDK.prototype.onChatTokenRenewed = function (listener) {
1582
+ var _this = this;
1583
+ var subscription = function () { return listener(); };
1584
+ this.chatTokenRenewedListeners.add(subscription);
1585
+ return function () { _this.chatTokenRenewedListeners.delete(subscription); };
1586
+ };
1546
1587
  OmnichannelChatSDK.prototype.getCurrentLiveChatContext = function () {
1547
1588
  return __awaiter(this, void 0, void 0, function () {
1548
1589
  var chatToken, requestId, chatSession;
@@ -1790,6 +1831,208 @@ var OmnichannelChatSDK = /** @class */ (function () {
1790
1831
  this.sessionId = this.OCClient.sessionId;
1791
1832
  }
1792
1833
  };
1834
+ /**
1835
+ * Creates the ACS token refresher used to renew the chat token before it expires. Returns undefined, which keeps
1836
+ * the existing behavior, unless renewal is enabled in the chat config, not disabled in the SDK config and
1837
+ * supported by the installed OCSDK. The refresher never throws and falls back to the current token on failure.
1838
+ */
1839
+ OmnichannelChatSDK.prototype.createChatTokenRefresher = function (initialToken) {
1840
+ var _this = this;
1841
+ var _a, _b, _c, _d, _e, _f;
1842
+ try {
1843
+ if (this.liveChatVersion !== LiveChatVersion_1.default.V2
1844
+ || ((_b = (_a = this.chatSDKConfig) === null || _a === void 0 ? void 0 : _a.chatTokenRenewal) === null || _b === void 0 ? void 0 : _b.disable) === true
1845
+ || (0, parsers_1.parseLowerCaseString)((_d = (_c = this.liveChatConfig) === null || _c === void 0 ? void 0 : _c.LcwFcbConfiguration) === null || _d === void 0 ? void 0 : _d.lcwChatTokenRenewalEnabled) !== "true"
1846
+ || typeof ((_e = this.OCClient) === null || _e === void 0 ? void 0 : _e.renewChatToken) !== "function"
1847
+ || !initialToken
1848
+ || !((_f = this.chatToken) === null || _f === void 0 ? void 0 : _f.chatId)
1849
+ || !this.requestId) {
1850
+ return undefined;
1851
+ }
1852
+ var chatId_1 = this.chatToken.chatId;
1853
+ var requestId_1 = this.requestId;
1854
+ // A reconnected chat is found by its reconnect id, not by the new request id
1855
+ var renewalId_1 = this.reconnectId || requestId_1;
1856
+ var telemetryData_1 = {
1857
+ RequestId: requestId_1,
1858
+ ChatId: chatId_1
1859
+ };
1860
+ return (0, chatTokenRenewal_1.createChatTokenRefresher)({
1861
+ initialToken: initialToken,
1862
+ chatId: chatId_1,
1863
+ isChatActive: function () { var _a; return !_this.isEndingChat && _this.requestId === requestId_1 && ((_a = _this.chatToken) === null || _a === void 0 ? void 0 : _a.chatId) === chatId_1; },
1864
+ renewChatToken: function () { return __awaiter(_this, void 0, void 0, function () {
1865
+ var renewChatTokenOptionalParams, authenticatedUserToken;
1866
+ return __generator(this, function (_a) {
1867
+ switch (_a.label) {
1868
+ case 0:
1869
+ renewChatTokenOptionalParams = {};
1870
+ return [4 /*yield*/, this.getAuthenticatedUserTokenForChatTokenRenewal()];
1871
+ case 1:
1872
+ authenticatedUserToken = _a.sent();
1873
+ if (authenticatedUserToken) {
1874
+ renewChatTokenOptionalParams.authenticatedUserToken = authenticatedUserToken;
1875
+ }
1876
+ return [2 /*return*/, this.OCClient.renewChatToken(renewalId_1, renewChatTokenOptionalParams)];
1877
+ }
1878
+ });
1879
+ }); },
1880
+ isNonRetriableStatus: function (statusCode) { return (_this.authenticatedUserToken ? chatTokenRenewal_1.authenticatedNonRetriableStatusCodes : chatTokenRenewal_1.defaultNonRetriableStatusCodes).includes(statusCode); },
1881
+ onRenewed: function (renewed) {
1882
+ var _a;
1883
+ _this.chatToken = __assign(__assign({}, _this.chatToken), { token: renewed.Token, expiresIn: renewed.ExpiresIn !== undefined && renewed.ExpiresIn !== null ? String(renewed.ExpiresIn) : _this.chatToken.expiresIn, voiceVideoCallToken: (_a = renewed.VoiceVideoCallToken) !== null && _a !== void 0 ? _a : _this.chatToken.voiceVideoCallToken });
1884
+ _this.refreshAttachmentClientToken(chatId_1);
1885
+ _this.notifyChatTokenRenewed(requestId_1, chatId_1);
1886
+ },
1887
+ onStart: function () { return _this.scenarioMarker.startScenario(TelemetryEvent_1.default.RenewChatToken, telemetryData_1); },
1888
+ onSuccess: function () { return _this.scenarioMarker.completeScenario(TelemetryEvent_1.default.RenewChatToken, telemetryData_1); },
1889
+ onFailure: function (reason, error) {
1890
+ var exceptionDetails = {
1891
+ response: reason,
1892
+ errorObject: error !== undefined ? "".concat(error) : undefined
1893
+ };
1894
+ _this.scenarioMarker.failScenario(TelemetryEvent_1.default.RenewChatToken, __assign(__assign({}, telemetryData_1), { ExceptionDetails: JSON.stringify(exceptionDetails) }));
1895
+ }
1896
+ });
1897
+ }
1898
+ catch (_g) {
1899
+ return undefined;
1900
+ }
1901
+ };
1902
+ OmnichannelChatSDK.prototype.notifyChatTokenRenewed = function (requestId, chatId) {
1903
+ var _this = this;
1904
+ var reportFailure = function (response) {
1905
+ try {
1906
+ var telemetryData = { RequestId: requestId, ChatId: chatId };
1907
+ _this.scenarioMarker.startScenario(TelemetryEvent_1.default.ChatTokenRenewedListener, telemetryData);
1908
+ _this.scenarioMarker.failScenario(TelemetryEvent_1.default.ChatTokenRenewedListener, __assign(__assign({}, telemetryData), { ExceptionDetails: JSON.stringify({ response: response }) }));
1909
+ }
1910
+ catch (_a) {
1911
+ // Subscriber telemetry must not affect renewal or become an unhandled rejection.
1912
+ }
1913
+ };
1914
+ Array.from(this.chatTokenRenewedListeners).forEach(function (listener) {
1915
+ var _a;
1916
+ if (_this.isEndingChat || _this.requestId !== requestId || ((_a = _this.chatToken) === null || _a === void 0 ? void 0 : _a.chatId) !== chatId
1917
+ || !_this.chatTokenRenewedListeners.has(listener)) {
1918
+ return;
1919
+ }
1920
+ try {
1921
+ Promise.resolve(listener()).catch(function () { return reportFailure("ListenerRejected"); });
1922
+ }
1923
+ catch (_b) {
1924
+ reportFailure("ListenerThrew");
1925
+ }
1926
+ });
1927
+ };
1928
+ /**
1929
+ * Gives the renewed chat token to the attachment client, which keeps the token it was initialized with and uses
1930
+ * it for every upload and download. Runs in the background and never throws: on failure, attachments keep using
1931
+ * the previous token as they did before renewal existed.
1932
+ */
1933
+ OmnichannelChatSDK.prototype.refreshAttachmentClientToken = function (chatId) {
1934
+ var _this = this;
1935
+ try {
1936
+ var amsClient_1 = this.AMSClient;
1937
+ var chatToken_1 = this.chatToken;
1938
+ if (!this.isAMSClientAllowed
1939
+ || this.AMSClientLoadCurrentState !== AMSClientLoadStates_1.AMSClientLoadStates.LOADED
1940
+ || !amsClient_1
1941
+ || typeof amsClient_1.initialize !== "function"
1942
+ || (chatToken_1 === null || chatToken_1 === void 0 ? void 0 : chatToken_1.chatId) !== chatId
1943
+ || !chatToken_1.token) {
1944
+ return;
1945
+ }
1946
+ var telemetryData_2 = {
1947
+ RequestId: this.requestId,
1948
+ ChatId: chatId
1949
+ };
1950
+ this.scenarioMarker.startScenario(TelemetryEvent_1.default.RefreshAttachmentClientToken, telemetryData_2);
1951
+ Promise.resolve()
1952
+ .then(function () { return amsClient_1.initialize({ chatToken: chatToken_1 }); })
1953
+ .then(function () {
1954
+ _this.scenarioMarker.completeScenario(TelemetryEvent_1.default.RefreshAttachmentClientToken, telemetryData_2);
1955
+ }, function (error) {
1956
+ _this.scenarioMarker.failScenario(TelemetryEvent_1.default.RefreshAttachmentClientToken, __assign(__assign({}, telemetryData_2), { ExceptionDetails: JSON.stringify({ errorObject: "".concat(error) }) }));
1957
+ })
1958
+ .catch(function () {
1959
+ // Telemetry failures must not surface
1960
+ });
1961
+ }
1962
+ catch (_a) {
1963
+ // Attachments keep using the previous token
1964
+ }
1965
+ };
1966
+ /**
1967
+ * Creates the recovery for chat requests that fail with 401 while the chat token has not
1968
+ * expired. Returns null, which keeps the existing behavior, unless chat token renewal is enabled and recovery is
1969
+ * not disabled in the SDK config.
1970
+ */
1971
+ OmnichannelChatSDK.prototype.createChatTokenUnauthorizedRecovery = function (initialToken, tokenRefresher) {
1972
+ var _this = this;
1973
+ var _a, _b, _c;
1974
+ try {
1975
+ if (!tokenRefresher
1976
+ || ((_b = (_a = this.chatSDKConfig) === null || _a === void 0 ? void 0 : _a.chatTokenRenewal) === null || _b === void 0 ? void 0 : _b.disableUnauthorizedRecovery) === true
1977
+ || !initialToken) {
1978
+ return null;
1979
+ }
1980
+ var telemetryData_3 = {
1981
+ RequestId: this.requestId,
1982
+ ChatId: (_c = this.chatToken) === null || _c === void 0 ? void 0 : _c.chatId
1983
+ };
1984
+ return (0, chatTokenUnauthorizedRecovery_1.createChatTokenUnauthorizedRecovery)({
1985
+ initialToken: initialToken,
1986
+ refreshToken: tokenRefresher,
1987
+ onStart: function () { return _this.scenarioMarker.startScenario(TelemetryEvent_1.default.ChatTokenUnauthorizedRecovery, telemetryData_3); },
1988
+ onSuccess: function (_source, usedExistingToken) {
1989
+ if (!usedExistingToken) {
1990
+ _this.scenarioMarker.completeScenario(TelemetryEvent_1.default.ChatTokenUnauthorizedRecovery, telemetryData_3);
1991
+ }
1992
+ },
1993
+ onFailure: function (source, reason) {
1994
+ _this.scenarioMarker.failScenario(TelemetryEvent_1.default.ChatTokenUnauthorizedRecovery, __assign(__assign({}, telemetryData_3), { ExceptionDetails: JSON.stringify({ response: reason, source: source }) }));
1995
+ }
1996
+ });
1997
+ }
1998
+ catch (_d) {
1999
+ return null;
2000
+ }
2001
+ };
2002
+ /**
2003
+ * Returns the token of the authenticated user to renew the chat token with, refreshed from the auth token
2004
+ * provider when possible because the token used to start the chat may have expired. Returns undefined for
2005
+ * unauthenticated chats.
2006
+ */
2007
+ OmnichannelChatSDK.prototype.getAuthenticatedUserTokenForChatTokenRenewal = function () {
2008
+ return __awaiter(this, void 0, void 0, function () {
2009
+ var token, _a;
2010
+ var _b;
2011
+ return __generator(this, function (_c) {
2012
+ switch (_c.label) {
2013
+ case 0:
2014
+ if (!this.authenticatedUserToken) {
2015
+ return [2 /*return*/, undefined];
2016
+ }
2017
+ if (!(typeof ((_b = this.chatSDKConfig) === null || _b === void 0 ? void 0 : _b.getAuthToken) === "function")) return [3 /*break*/, 4];
2018
+ _c.label = 1;
2019
+ case 1:
2020
+ _c.trys.push([1, 3, , 4]);
2021
+ return [4 /*yield*/, this.chatSDKConfig.getAuthToken()];
2022
+ case 2:
2023
+ token = _c.sent();
2024
+ if (typeof token === "string" && token.trim().length > 0) {
2025
+ return [2 /*return*/, token];
2026
+ }
2027
+ return [3 /*break*/, 4];
2028
+ case 3:
2029
+ _a = _c.sent();
2030
+ return [3 /*break*/, 4];
2031
+ case 4: return [2 /*return*/, this.authenticatedUserToken];
2032
+ }
2033
+ });
2034
+ });
2035
+ };
1793
2036
  OmnichannelChatSDK.prototype.getCallingToken = function () {
1794
2037
  return __awaiter(this, void 0, void 0, function () {
1795
2038
  return __generator(this, function (_a) {
@@ -1971,7 +2214,7 @@ var OmnichannelChatSDK = /** @class */ (function () {
1971
2214
  };
1972
2215
  OmnichannelChatSDK.prototype.onNewMessage = function (onNewMessageCallback_1) {
1973
2216
  return __awaiter(this, arguments, void 0, function (onNewMessageCallback, optionalParams) {
1974
- var postedMessages_1, messages, _i, _a, message, id, registerOnNewMessageOptionalParams;
2217
+ var postedMessages_1, customerMessageUpdates_1, getNewCustomerVersion_1, messages, _i, _a, message, id, customerMessage, customerVersion, registerOnNewMessageOptionalParams;
1975
2218
  var _this = this;
1976
2219
  var _b;
1977
2220
  if (optionalParams === void 0) { optionalParams = {}; }
@@ -1987,6 +2230,20 @@ var OmnichannelChatSDK = /** @class */ (function () {
1987
2230
  }
1988
2231
  if (!(this.liveChatVersion === LiveChatVersion_1.default.V2)) return [3 /*break*/, 3];
1989
2232
  postedMessages_1 = new Set();
2233
+ customerMessageUpdates_1 = new messageUpdates_1.MessageUpdateTracker();
2234
+ getNewCustomerVersion_1 = function (message) {
2235
+ var version = (0, messageUpdates_1.getMessageVersion)(message);
2236
+ if (version === undefined) {
2237
+ _this.scenarioMarker.singleRecord(TelemetryEvent_1.default.OnNewMessage, {
2238
+ RequestId: _this.requestId,
2239
+ ChatId: _this.chatToken.chatId,
2240
+ ExceptionDetails: "InvalidCustomerMessageVersion"
2241
+ });
2242
+ console.warn("[OmnichannelChatSDK][onNewMessage] Invalid customer message version");
2243
+ return undefined;
2244
+ }
2245
+ return customerMessageUpdates_1.shouldDeliver(message.id, version) ? version : undefined;
2246
+ };
1990
2247
  if (!(optionalParams === null || optionalParams === void 0 ? void 0 : optionalParams.rehydrate)) return [3 /*break*/, 2];
1991
2248
  this.debug && console.log('[OmnichannelChatSDK][onNewMessage] rehydrate');
1992
2249
  return [4 /*yield*/, this.getMessages()];
@@ -1998,8 +2255,16 @@ var OmnichannelChatSDK = /** @class */ (function () {
1998
2255
  if (postedMessages_1.has(id)) {
1999
2256
  continue;
2000
2257
  }
2258
+ customerMessage = (0, utilities_1.isCustomerMessage)(message);
2259
+ customerVersion = customerMessage ? (0, messageUpdates_1.getMessageVersion)(message) : undefined;
2260
+ if (customerMessage) {
2261
+ message.role = OmnichannelMessage_1.Role.User;
2262
+ }
2001
2263
  postedMessages_1.add(id);
2002
2264
  onNewMessageCallback(message);
2265
+ if (customerVersion !== undefined) {
2266
+ customerMessageUpdates_1.markDelivered(id, customerVersion);
2267
+ }
2003
2268
  }
2004
2269
  _c.label = 2;
2005
2270
  case 2:
@@ -2016,7 +2281,7 @@ var OmnichannelChatSDK = /** @class */ (function () {
2016
2281
  (_b = this.conversation) === null || _b === void 0 ? void 0 : _b.registerOnNewMessage(function (event) {
2017
2282
  var id = event.id;
2018
2283
  var isChatMessageEditedEvent = Object.keys(event).includes("editedOn");
2019
- console.log("[OmnichannelChatSDK][onNewMessage] New message received", event);
2284
+ console.log("[OmnichannelChatSDK][onNewMessage] New message received");
2020
2285
  console.log("[OmnichannelChatSDK][onNewMessage] isChatMessageEditedEvent=>", isChatMessageEditedEvent);
2021
2286
  // Guard message transformation: createOmnichannelMessage() can throw
2022
2287
  // (e.g. unexpected event shape). Without this, the throw became an
@@ -2044,9 +2309,23 @@ var OmnichannelChatSDK = /** @class */ (function () {
2044
2309
  });
2045
2310
  return;
2046
2311
  }
2312
+ var customerMessage = (0, utilities_1.isCustomerMessage)(omnichannelMessage);
2313
+ if (customerMessage && !(0, messageUpdates_1.isMessageEdited)(event)) {
2314
+ return;
2315
+ }
2316
+ var customerVersion = customerMessage ? getNewCustomerVersion_1(event) : undefined;
2317
+ if (customerMessage && customerVersion === undefined) {
2318
+ return;
2319
+ }
2320
+ if (customerMessage) {
2321
+ omnichannelMessage.role = OmnichannelMessage_1.Role.User;
2322
+ }
2047
2323
  // send callback for new messages or edited existent messages
2048
- if (!postedMessages_1.has(id) || isChatMessageEditedEvent) {
2324
+ if (customerMessage || !postedMessages_1.has(id) || isChatMessageEditedEvent) {
2049
2325
  onNewMessageCallback(omnichannelMessage);
2326
+ if (customerVersion !== undefined) {
2327
+ customerMessageUpdates_1.markDelivered(id, customerVersion);
2328
+ }
2050
2329
  console.log("[OmnichannelChatSDK][onNewMessage] Message posted");
2051
2330
  postedMessages_1.add(id);
2052
2331
  }
@@ -2628,7 +2907,8 @@ var OmnichannelChatSDK = /** @class */ (function () {
2628
2907
  };
2629
2908
  OmnichannelChatSDK.prototype.emailLiveChatTranscript = function (body_1) {
2630
2909
  return __awaiter(this, arguments, void 0, function (body, optionalParams) {
2631
- var emailTranscriptOptionalParams, requestId, chatToken, chatId, sessionId, emailRequestBody, error_27;
2910
+ var emailTranscriptOptionalParams, requestId, chatToken, chatId, requestSessionKey, emailRequestBody_1, error_27;
2911
+ var _this = this;
2632
2912
  var _a;
2633
2913
  if (optionalParams === void 0) { optionalParams = {}; }
2634
2914
  return __generator(this, function (_b) {
@@ -2638,16 +2918,12 @@ var OmnichannelChatSDK = /** @class */ (function () {
2638
2918
  requestId = this.requestId;
2639
2919
  chatToken = this.chatToken;
2640
2920
  chatId = chatToken.chatId;
2641
- sessionId = this.sessionId;
2642
2921
  if (optionalParams.liveChatContext) {
2643
2922
  requestId = optionalParams.liveChatContext.requestId;
2644
2923
  chatToken = optionalParams.liveChatContext.chatToken;
2645
2924
  chatId = chatToken.chatId;
2646
2925
  }
2647
- if ((_a = optionalParams.liveChatContext) === null || _a === void 0 ? void 0 : _a.sessionId) {
2648
- sessionId = optionalParams.liveChatContext.sessionId;
2649
- this.OCClient.sessionId = sessionId;
2650
- }
2926
+ requestSessionKey = ((_a = optionalParams.liveChatContext) === null || _a === void 0 ? void 0 : _a.sessionId) || this.getEndedChatSessionKey(chatId);
2651
2927
  this.scenarioMarker.startScenario(TelemetryEvent_1.default.EmailLiveChatTranscript, {
2652
2928
  RequestId: requestId,
2653
2929
  ChatId: chatId
@@ -2661,18 +2937,15 @@ var OmnichannelChatSDK = /** @class */ (function () {
2661
2937
  if (this.authenticatedUserToken) {
2662
2938
  emailTranscriptOptionalParams.authenticatedUserToken = this.authenticatedUserToken;
2663
2939
  }
2664
- emailRequestBody = {
2940
+ emailRequestBody_1 = {
2665
2941
  ChatId: chatId,
2666
2942
  EmailAddress: body.emailAddress,
2667
2943
  DefaultAttachmentMessage: body.attachmentMessage,
2668
2944
  CustomerLocale: body.locale || (0, locale_1.getLocaleStringFromId)(this.localeId)
2669
2945
  };
2670
- return [4 /*yield*/, this.OCClient.emailTranscript(requestId, chatToken.token, emailRequestBody, emailTranscriptOptionalParams)];
2946
+ return [4 /*yield*/, this.withRequestSessionKey(requestSessionKey, function () { return _this.OCClient.emailTranscript(requestId, chatToken.token, emailRequestBody_1, emailTranscriptOptionalParams); })];
2671
2947
  case 2:
2672
2948
  _b.sent();
2673
- if (this.sessionId) {
2674
- this.OCClient.sessionId = this.sessionId;
2675
- }
2676
2949
  this.scenarioMarker.completeScenario(TelemetryEvent_1.default.EmailLiveChatTranscript, {
2677
2950
  RequestId: requestId,
2678
2951
  ChatId: chatId
@@ -2693,7 +2966,8 @@ var OmnichannelChatSDK = /** @class */ (function () {
2693
2966
  };
2694
2967
  OmnichannelChatSDK.prototype.getLiveChatTranscript = function () {
2695
2968
  return __awaiter(this, arguments, void 0, function (optionalParams) {
2696
- var getChatTranscriptOptionalParams, requestId, chatToken, chatId, sessionId, transcriptResponse, error_28, telemetryData;
2969
+ var getChatTranscriptOptionalParams, requestId, chatToken, chatId, requestSessionKey, transcriptResponse, error_28, telemetryData;
2970
+ var _this = this;
2697
2971
  var _a, _b;
2698
2972
  if (optionalParams === void 0) { optionalParams = {}; }
2699
2973
  return __generator(this, function (_c) {
@@ -2703,7 +2977,6 @@ var OmnichannelChatSDK = /** @class */ (function () {
2703
2977
  requestId = this.requestId;
2704
2978
  chatToken = this.chatToken;
2705
2979
  chatId = chatToken.chatId;
2706
- sessionId = this.sessionId;
2707
2980
  if (optionalParams.liveChatContext) {
2708
2981
  if (this.isPersistentChat && !((_a = this.chatSDKConfig.persistentChat) === null || _a === void 0 ? void 0 : _a.disable)) {
2709
2982
  requestId = this.requestId || optionalParams.liveChatContext.requestId;
@@ -2715,10 +2988,6 @@ var OmnichannelChatSDK = /** @class */ (function () {
2715
2988
  }
2716
2989
  chatId = chatToken.chatId;
2717
2990
  }
2718
- if ((_b = optionalParams.liveChatContext) === null || _b === void 0 ? void 0 : _b.sessionId) {
2719
- sessionId = optionalParams.liveChatContext.sessionId;
2720
- this.OCClient.sessionId = sessionId;
2721
- }
2722
2991
  if (!chatId) {
2723
2992
  throw new ChatSDKError_1.ChatSDKError(ChatSDKError_1.ChatSDKErrorName.LiveChatTranscriptRetrievalFailure, undefined, {
2724
2993
  response: ChatSDKError_1.ChatSDKErrorName.LiveChatTranscriptRetrievalFailure,
@@ -2732,18 +3001,16 @@ var OmnichannelChatSDK = /** @class */ (function () {
2732
3001
  if (!this.isInitialized) {
2733
3002
  exceptionThrowers_1.default.throwUninitializedChatSDK(this.scenarioMarker, TelemetryEvent_1.default.GetLiveChatTranscript);
2734
3003
  }
3004
+ requestSessionKey = ((_b = optionalParams.liveChatContext) === null || _b === void 0 ? void 0 : _b.sessionId) || this.getEndedChatSessionKey(chatId);
2735
3005
  _c.label = 1;
2736
3006
  case 1:
2737
3007
  _c.trys.push([1, 3, , 4]);
2738
3008
  if (this.authenticatedUserToken) {
2739
3009
  getChatTranscriptOptionalParams.authenticatedUserToken = this.authenticatedUserToken;
2740
3010
  }
2741
- return [4 /*yield*/, this.OCClient.getChatTranscripts(requestId, chatToken.chatId, chatToken.token, getChatTranscriptOptionalParams)];
3011
+ return [4 /*yield*/, this.withRequestSessionKey(requestSessionKey, function () { return _this.OCClient.getChatTranscripts(requestId, chatToken.chatId, chatToken.token, getChatTranscriptOptionalParams); })];
2742
3012
  case 2:
2743
3013
  transcriptResponse = _c.sent();
2744
- if (this.sessionId) {
2745
- this.OCClient.sessionId = this.sessionId;
2746
- }
2747
3014
  this.scenarioMarker.completeScenario(TelemetryEvent_1.default.GetLiveChatTranscript, {
2748
3015
  RequestId: requestId,
2749
3016
  ChatId: chatId
@@ -2762,6 +3029,30 @@ var OmnichannelChatSDK = /** @class */ (function () {
2762
3029
  });
2763
3030
  });
2764
3031
  };
3032
+ /**
3033
+ * Returns the ended chat's session key when the call targets that chat, or null.
3034
+ */
3035
+ OmnichannelChatSDK.prototype.getEndedChatSessionKey = function (chatId) {
3036
+ var _a;
3037
+ return chatId && ((_a = this.endedChatSessionKey) === null || _a === void 0 ? void 0 : _a.chatId) === chatId ? this.endedChatSessionKey.sessionId : null;
3038
+ };
3039
+ /**
3040
+ * Sends the session key on one OCSDK request without leaving it on the shared client. OCSDK copies the
3041
+ * key into the request headers before its first await, so the previous key is restored before the HTTP wait.
3042
+ */
3043
+ OmnichannelChatSDK.prototype.withRequestSessionKey = function (sessionKey, request) {
3044
+ if (!sessionKey) {
3045
+ return request();
3046
+ }
3047
+ var previousSessionKey = this.OCClient.sessionId;
3048
+ this.OCClient.sessionId = sessionKey;
3049
+ try {
3050
+ return request();
3051
+ }
3052
+ finally {
3053
+ this.OCClient.sessionId = previousSessionKey;
3054
+ }
3055
+ };
2765
3056
  OmnichannelChatSDK.prototype.createChatAdapter = function () {
2766
3057
  return __awaiter(this, arguments, void 0, function (optionalParams) {
2767
3058
  var protocol, supportedChatAdapterProtocols, options, fileManager;