@microsoft/omnichannel-chat-sdk 2.0.1 → 2.0.2-main.07ad838

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.
@@ -103,6 +103,8 @@ var location_1 = require("./utils/location");
103
103
  var internalUtils_1 = require("./utils/internalUtils");
104
104
  var loggerUtils_1 = require("./utils/loggerUtils");
105
105
  var parsers_1 = require("./utils/parsers");
106
+ var chatTokenUnauthorizedRecovery_1 = require("./utils/chatTokenUnauthorizedRecovery");
107
+ var chatTokenRenewal_1 = require("./utils/chatTokenRenewal");
106
108
  var platform_1 = require("./utils/platform");
107
109
  var retrieveCollectorUri_1 = require("./telemetry/retrieveCollectorUri");
108
110
  var startPolling_1 = require("./commands/startPolling");
@@ -125,6 +127,7 @@ var OmnichannelChatSDK = /** @class */ (function () {
125
127
  this.unqServicesOrgUrl = null;
126
128
  this.coreServicesOrgUrl = null;
127
129
  this.dynamicsLocationCode = null;
130
+ this.chatTokenUnauthorizedRecovery = null;
128
131
  this.widgetSnippetBaseUrl = '';
129
132
  this.dataMaskingRules = { rules: [] };
130
133
  this.authSettings = null;
@@ -141,6 +144,8 @@ var OmnichannelChatSDK = /** @class */ (function () {
141
144
  this.isPersistentChat = false;
142
145
  this.isChatReconnect = false;
143
146
  this.reconnectId = null;
147
+ // Session key of the most recently ended chat. MRT validates it on transcript calls made after endChat.
148
+ this.endedChatSessionKey = null;
144
149
  this.refreshTokenTimer = null;
145
150
  this.AMSClientLoadCurrentState = AMSClientLoadStates_1.AMSClientLoadStates.NOT_LOADED;
146
151
  this.isMaskingDisabled = false;
@@ -876,6 +881,7 @@ var OmnichannelChatSDK = /** @class */ (function () {
876
881
  switch (_u.label) {
877
882
  case 0:
878
883
  this.isEndingChat = false;
884
+ this.endedChatSessionKey = null;
879
885
  this.scenarioMarker.startScenario(TelemetryEvent_1.default.StartChat, {
880
886
  RequestId: this.requestId
881
887
  });
@@ -957,7 +963,7 @@ var OmnichannelChatSDK = /** @class */ (function () {
957
963
  hasAuthToken: String(!!this.authenticatedUserToken)
958
964
  })
959
965
  });
960
- if (!this.authSettings) return [3 /*break*/, 15];
966
+ if (!this.authSettings) return [3 /*break*/, 16];
961
967
  if (!(isMidAuthEnabled && (deferInitialAuth || !this.authenticatedUserToken))) return [3 /*break*/, 9];
962
968
  this.scenarioMarker.singleRecord(TelemetryEvent_1.default.StartChat, {
963
969
  RequestId: this.requestId || "",
@@ -968,7 +974,7 @@ var OmnichannelChatSDK = /** @class */ (function () {
968
974
  hasAuthToken: String(!!this.authenticatedUserToken)
969
975
  })
970
976
  });
971
- return [3 /*break*/, 15];
977
+ return [3 /*break*/, 16];
972
978
  case 9:
973
979
  if (!!this.authenticatedUserToken) return [3 /*break*/, 11];
974
980
  return [4 /*yield*/, this.setAuthTokenProvider(this.chatSDKConfig.getAuthToken, { throwError: true })];
@@ -976,7 +982,7 @@ var OmnichannelChatSDK = /** @class */ (function () {
976
982
  _u.sent();
977
983
  _u.label = 11;
978
984
  case 11:
979
- if (!(optionalParams.liveChatContext && Object.keys(optionalParams.liveChatContext).length > 0)) return [3 /*break*/, 15];
985
+ if (!(optionalParams.liveChatContext && Object.keys(optionalParams.liveChatContext).length > 0)) return [3 /*break*/, 16];
980
986
  this.chatToken = optionalParams.liveChatContext.chatToken || {};
981
987
  this.requestId = optionalParams.liveChatContext.requestId || (0, ocsdk_1.uuidv4)();
982
988
  _u.label = 12;
@@ -998,12 +1004,21 @@ var OmnichannelChatSDK = /** @class */ (function () {
998
1004
  exceptionThrowers_1.default.throwAuthenticatedChatConversationRetrievalFailure(e_7, this.scenarioMarker, TelemetryEvent_1.default.StartChat, telemetryData);
999
1005
  return [3 /*break*/, 15];
1000
1006
  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)];
1007
+ // A persistent chat restore has a reconnectId, so the restore above skipped the key. Without it,
1008
+ // calls the service validates against the chat's session key (transcripts) return 401. Apply it
1009
+ // only after the chat is confirmed to belong to the signed-in user.
1010
+ this.sessionId = optionalParams.liveChatContext.sessionId || null;
1011
+ if (this.sessionId) {
1012
+ this.OCClient.sessionId = this.sessionId;
1013
+ }
1014
+ _u.label = 16;
1003
1015
  case 16:
1004
- _u.sent();
1005
- _u.label = 17;
1016
+ 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];
1017
+ return [4 /*yield*/, this.getChatToken(false)];
1006
1018
  case 17:
1019
+ _u.sent();
1020
+ _u.label = 18;
1021
+ case 18:
1007
1022
  if ((_l = this.chatToken) === null || _l === void 0 ? void 0 : _l.chatId) {
1008
1023
  loggerUtils_1.default.setChatId(this.chatToken.chatId || '', this.ocSdkLogger, this.acsClientLogger, this.acsAdapterLogger, this.callingSdkLogger, this.amsClientLogger, this.ic3ClientLogger);
1009
1024
  }
@@ -1024,14 +1039,14 @@ var OmnichannelChatSDK = /** @class */ (function () {
1024
1039
  else if (this.isChatReconnect && !((_o = this.chatSDKConfig.chatReconnect) === null || _o === void 0 ? void 0 : _o.disable) && !this.isPersistentChat) {
1025
1040
  sessionInitOptionalParams.reconnectId = this.reconnectId;
1026
1041
  }
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];
1042
+ 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
1043
  return [4 /*yield*/, (0, location_1.getLocationInfo)(this.scenarioMarker, this.chatToken.chatId, this.requestId)];
1029
- case 18:
1044
+ case 19:
1030
1045
  location_2 = _u.sent();
1031
1046
  sessionInitOptionalParams.initContext.latitude = location_2.latitude;
1032
1047
  sessionInitOptionalParams.initContext.longitude = location_2.longitude;
1033
- _u.label = 19;
1034
- case 19:
1048
+ _u.label = 20;
1049
+ case 20:
1035
1050
  sessionInitPromise = function () { return __awaiter(_this, void 0, void 0, function () {
1036
1051
  var error_6, telemetryData;
1037
1052
  var _a, _b, _c;
@@ -1097,10 +1112,10 @@ var OmnichannelChatSDK = /** @class */ (function () {
1097
1112
  });
1098
1113
  }); };
1099
1114
  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) {
1115
+ var chatAdapterConfig, tokenRefresher, error_8, telemetryData, _a, error_9, telemetryData, error_10, telemetryData, _b, error_11, telemetryData;
1116
+ var _c, _d, _e;
1117
+ return __generator(this, function (_f) {
1118
+ switch (_f.label) {
1104
1119
  case 0:
1105
1120
  if (!(this.liveChatVersion === LiveChatVersion_1.default.V2)) return [3 /*break*/, 8];
1106
1121
  chatAdapterConfig = {
@@ -1110,18 +1125,22 @@ var OmnichannelChatSDK = /** @class */ (function () {
1110
1125
  environmentUrl: this.chatToken.acsEndpoint,
1111
1126
  pollingInterval: 30000
1112
1127
  };
1113
- _e.label = 1;
1128
+ _f.label = 1;
1114
1129
  case 1:
1115
- _e.trys.push([1, 3, , 4]);
1130
+ _f.trys.push([1, 3, , 4]);
1131
+ tokenRefresher = this.createChatTokenRefresher(chatAdapterConfig.token);
1132
+ this.chatTokenUnauthorizedRecovery = this.createChatTokenUnauthorizedRecovery(chatAdapterConfig.token, tokenRefresher);
1116
1133
  return [4 /*yield*/, ((_c = this.ACSClient) === null || _c === void 0 ? void 0 : _c.initialize({
1117
1134
  token: chatAdapterConfig.token,
1118
1135
  environmentUrl: chatAdapterConfig.environmentUrl,
1136
+ tokenRefresher: tokenRefresher,
1137
+ unauthorizedRecovery: (_d = this.chatTokenUnauthorizedRecovery) !== null && _d !== void 0 ? _d : undefined
1119
1138
  }))];
1120
1139
  case 2:
1121
- _e.sent();
1140
+ _f.sent();
1122
1141
  return [3 /*break*/, 4];
1123
1142
  case 3:
1124
- error_8 = _e.sent();
1143
+ error_8 = _f.sent();
1125
1144
  telemetryData = {
1126
1145
  RequestId: this.requestId,
1127
1146
  ChatId: this.chatToken.chatId,
@@ -1129,22 +1148,22 @@ var OmnichannelChatSDK = /** @class */ (function () {
1129
1148
  exceptionThrowers_1.default.throwMessagingClientInitializationFailure(error_8, this.scenarioMarker, TelemetryEvent_1.default.StartChat, telemetryData);
1130
1149
  return [3 /*break*/, 4];
1131
1150
  case 4:
1132
- _e.trys.push([4, 6, , 7]);
1151
+ _f.trys.push([4, 6, , 7]);
1133
1152
  _a = this;
1134
- return [4 /*yield*/, ((_d = this.ACSClient) === null || _d === void 0 ? void 0 : _d.joinConversation({
1153
+ return [4 /*yield*/, ((_e = this.ACSClient) === null || _e === void 0 ? void 0 : _e.joinConversation({
1135
1154
  id: chatAdapterConfig.id,
1136
1155
  threadId: chatAdapterConfig.threadId,
1137
1156
  pollingInterval: chatAdapterConfig.pollingInterval
1138
1157
  }))];
1139
1158
  case 5:
1140
- _a.conversation = (_e.sent());
1159
+ _a.conversation = (_f.sent());
1141
1160
  this.scenarioMarker.completeScenario(TelemetryEvent_1.default.StartChat, {
1142
1161
  RequestId: this.requestId,
1143
1162
  ChatId: this.chatToken.chatId
1144
1163
  });
1145
1164
  return [3 /*break*/, 7];
1146
1165
  case 6:
1147
- error_9 = _e.sent();
1166
+ error_9 = _f.sent();
1148
1167
  telemetryData = {
1149
1168
  RequestId: this.requestId,
1150
1169
  ChatId: this.chatToken.chatId,
@@ -1153,17 +1172,17 @@ var OmnichannelChatSDK = /** @class */ (function () {
1153
1172
  return [3 /*break*/, 7];
1154
1173
  case 7: return [3 /*break*/, 14];
1155
1174
  case 8:
1156
- _e.trys.push([8, 10, , 11]);
1175
+ _f.trys.push([8, 10, , 11]);
1157
1176
  return [4 /*yield*/, this.IC3Client.initialize({
1158
1177
  token: this.chatToken.token,
1159
1178
  regionGtms: this.chatToken.regionGTMS,
1160
1179
  visitor: true
1161
1180
  })];
1162
1181
  case 9:
1163
- _e.sent();
1182
+ _f.sent();
1164
1183
  return [3 /*break*/, 11];
1165
1184
  case 10:
1166
- error_10 = _e.sent();
1185
+ error_10 = _f.sent();
1167
1186
  telemetryData = {
1168
1187
  RequestId: this.requestId,
1169
1188
  ChatId: this.chatToken.chatId,
@@ -1171,18 +1190,18 @@ var OmnichannelChatSDK = /** @class */ (function () {
1171
1190
  exceptionThrowers_1.default.throwMessagingClientInitializationFailure(error_10, this.scenarioMarker, TelemetryEvent_1.default.StartChat, telemetryData);
1172
1191
  return [3 /*break*/, 11];
1173
1192
  case 11:
1174
- _e.trys.push([11, 13, , 14]);
1193
+ _f.trys.push([11, 13, , 14]);
1175
1194
  _b = this;
1176
1195
  return [4 /*yield*/, this.IC3Client.joinConversation(this.chatToken.chatId)];
1177
1196
  case 12:
1178
- _b.conversation = _e.sent();
1197
+ _b.conversation = _f.sent();
1179
1198
  this.scenarioMarker.completeScenario(TelemetryEvent_1.default.StartChat, {
1180
1199
  RequestId: this.requestId,
1181
1200
  ChatId: this.chatToken.chatId
1182
1201
  });
1183
1202
  return [3 /*break*/, 14];
1184
1203
  case 13:
1185
- error_11 = _e.sent();
1204
+ error_11 = _f.sent();
1186
1205
  telemetryData = {
1187
1206
  RequestId: this.requestId,
1188
1207
  ChatId: this.chatToken.chatId,
@@ -1225,32 +1244,32 @@ var OmnichannelChatSDK = /** @class */ (function () {
1225
1244
  }
1226
1245
  });
1227
1246
  }); };
1228
- if (!!((_r = this.chatSDKConfig.useCreateConversation) === null || _r === void 0 ? void 0 : _r.disable)) return [3 /*break*/, 21];
1247
+ if (!!((_r = this.chatSDKConfig.useCreateConversation) === null || _r === void 0 ? void 0 : _r.disable)) return [3 /*break*/, 22];
1229
1248
  return [4 /*yield*/, createConversationPromise()];
1230
- case 20:
1249
+ case 21:
1231
1250
  _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;
1251
+ return [3 /*break*/, 24];
1252
+ case 22: return [4 /*yield*/, sessionInitPromise()];
1237
1253
  case 23:
1238
- _u.trys.push([23, 25, , 27]);
1239
- return [4 /*yield*/, Promise.all([messagingClientPromise(), attachmentClientPromise()])];
1254
+ _u.sent(); // Await the session initialization
1255
+ _u.label = 24;
1240
1256
  case 24:
1241
- _u.sent();
1242
- return [3 /*break*/, 27];
1257
+ _u.trys.push([24, 26, , 28]);
1258
+ return [4 /*yield*/, Promise.all([messagingClientPromise(), attachmentClientPromise()])];
1243
1259
  case 25:
1260
+ _u.sent();
1261
+ return [3 /*break*/, 28];
1262
+ case 26:
1244
1263
  error_5 = _u.sent();
1245
1264
  // If conversation joining fails after conversation was created, clean up the conversation
1246
1265
  // Only cleanup conversations that were freshly created (not existing ones being reconnected to)
1247
1266
  return [4 /*yield*/, this.handleConversationJoinFailure(error_5, optionalParams)];
1248
- case 26:
1267
+ case 27:
1249
1268
  // If conversation joining fails after conversation was created, clean up the conversation
1250
1269
  // Only cleanup conversations that were freshly created (not existing ones being reconnected to)
1251
1270
  _u.sent();
1252
1271
  throw error_5; // Re-throw the original error
1253
- case 27:
1272
+ case 28:
1254
1273
  if (this.isPersistentChat && !((_s = this.chatSDKConfig.persistentChat) === null || _s === void 0 ? void 0 : _s.disable)) {
1255
1274
  this.refreshTokenTimer = setInterval(function () { return __awaiter(_this, void 0, void 0, function () {
1256
1275
  var error_13;
@@ -1360,7 +1379,7 @@ var OmnichannelChatSDK = /** @class */ (function () {
1360
1379
  };
1361
1380
  OmnichannelChatSDK.prototype.internalEndChat = function () {
1362
1381
  return __awaiter(this, arguments, void 0, function (endChatOptionalParams) {
1363
- var cleanupMetadata, isReactNative, isConversationalSurveyEnabled, shouldWaitForSurvey, telemetryData, surveyStarted, error_15, error_16, telemetryData;
1382
+ var cleanupMetadata, isReactNative, isConversationalSurveyEnabled, shouldWaitForSurvey, telemetryData, surveyStarted, error_15, error_16, telemetryData, endedChatId, endedSessionId;
1364
1383
  var _a, _b, _c;
1365
1384
  if (endChatOptionalParams === void 0) { endChatOptionalParams = {}; }
1366
1385
  return __generator(this, function (_d) {
@@ -1419,12 +1438,17 @@ var OmnichannelChatSDK = /** @class */ (function () {
1419
1438
  exceptionThrowers_1.default.throwConversationClosureFailure(error_16, this.scenarioMarker, TelemetryEvent_1.default.EndChat, telemetryData);
1420
1439
  return [3 /*break*/, 11];
1421
1440
  case 10:
1422
- // Cleanup always runs, regardless of success or failure
1423
- // This ensures resources are released even if closeChat or survey waiting throws
1441
+ endedChatId = this.chatToken.chatId;
1442
+ endedSessionId = this.OCClient.sessionId || this.sessionId;
1443
+ // Keep the previous chat's key when this call had no chat to end (for example a second endChat).
1444
+ if (endedChatId && endedSessionId) {
1445
+ this.endedChatSessionKey = { chatId: endedChatId, sessionId: endedSessionId };
1446
+ }
1424
1447
  (_c = this.conversation) === null || _c === void 0 ? void 0 : _c.disconnect();
1425
1448
  this.conversation = null;
1426
1449
  this.requestId = (0, ocsdk_1.uuidv4)();
1427
1450
  this.chatToken = {};
1451
+ this.chatTokenUnauthorizedRecovery = null;
1428
1452
  this.reconnectId = null;
1429
1453
  if (this.IC3Client) {
1430
1454
  this.IC3Client.dispose();
@@ -1790,6 +1814,181 @@ var OmnichannelChatSDK = /** @class */ (function () {
1790
1814
  this.sessionId = this.OCClient.sessionId;
1791
1815
  }
1792
1816
  };
1817
+ /**
1818
+ * Creates the ACS token refresher used to renew the chat token before it expires. Returns undefined, which keeps
1819
+ * the existing behavior, unless renewal is enabled in the chat config, not disabled in the SDK config and
1820
+ * supported by the installed OCSDK. The refresher never throws and falls back to the current token on failure.
1821
+ */
1822
+ OmnichannelChatSDK.prototype.createChatTokenRefresher = function (initialToken) {
1823
+ var _this = this;
1824
+ var _a, _b, _c, _d, _e, _f;
1825
+ try {
1826
+ if (this.liveChatVersion !== LiveChatVersion_1.default.V2
1827
+ || ((_b = (_a = this.chatSDKConfig) === null || _a === void 0 ? void 0 : _a.chatTokenRenewal) === null || _b === void 0 ? void 0 : _b.disable) === true
1828
+ || (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"
1829
+ || typeof ((_e = this.OCClient) === null || _e === void 0 ? void 0 : _e.renewChatToken) !== "function"
1830
+ || !initialToken
1831
+ || !((_f = this.chatToken) === null || _f === void 0 ? void 0 : _f.chatId)
1832
+ || !this.requestId) {
1833
+ return undefined;
1834
+ }
1835
+ var chatId_1 = this.chatToken.chatId;
1836
+ var requestId_1 = this.requestId;
1837
+ // A reconnected chat is found by its reconnect id, not by the new request id
1838
+ var renewalId_1 = this.reconnectId || requestId_1;
1839
+ var telemetryData_1 = {
1840
+ RequestId: requestId_1,
1841
+ ChatId: chatId_1
1842
+ };
1843
+ return (0, chatTokenRenewal_1.createChatTokenRefresher)({
1844
+ initialToken: initialToken,
1845
+ chatId: chatId_1,
1846
+ isChatActive: function () { var _a; return !_this.isEndingChat && _this.requestId === requestId_1 && ((_a = _this.chatToken) === null || _a === void 0 ? void 0 : _a.chatId) === chatId_1; },
1847
+ renewChatToken: function () { return __awaiter(_this, void 0, void 0, function () {
1848
+ var renewChatTokenOptionalParams, authenticatedUserToken;
1849
+ return __generator(this, function (_a) {
1850
+ switch (_a.label) {
1851
+ case 0:
1852
+ renewChatTokenOptionalParams = {};
1853
+ return [4 /*yield*/, this.getAuthenticatedUserTokenForChatTokenRenewal()];
1854
+ case 1:
1855
+ authenticatedUserToken = _a.sent();
1856
+ if (authenticatedUserToken) {
1857
+ renewChatTokenOptionalParams.authenticatedUserToken = authenticatedUserToken;
1858
+ }
1859
+ return [2 /*return*/, this.OCClient.renewChatToken(renewalId_1, renewChatTokenOptionalParams)];
1860
+ }
1861
+ });
1862
+ }); },
1863
+ isNonRetriableStatus: function (statusCode) { return (_this.authenticatedUserToken ? chatTokenRenewal_1.authenticatedNonRetriableStatusCodes : chatTokenRenewal_1.defaultNonRetriableStatusCodes).includes(statusCode); },
1864
+ onRenewed: function (renewed) {
1865
+ var _a;
1866
+ _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 });
1867
+ _this.refreshAttachmentClientToken(chatId_1);
1868
+ },
1869
+ onStart: function () { return _this.scenarioMarker.startScenario(TelemetryEvent_1.default.RenewChatToken, telemetryData_1); },
1870
+ onSuccess: function () { return _this.scenarioMarker.completeScenario(TelemetryEvent_1.default.RenewChatToken, telemetryData_1); },
1871
+ onFailure: function (reason, error) {
1872
+ var exceptionDetails = {
1873
+ response: reason,
1874
+ errorObject: error !== undefined ? "".concat(error) : undefined
1875
+ };
1876
+ _this.scenarioMarker.failScenario(TelemetryEvent_1.default.RenewChatToken, __assign(__assign({}, telemetryData_1), { ExceptionDetails: JSON.stringify(exceptionDetails) }));
1877
+ }
1878
+ });
1879
+ }
1880
+ catch (_g) {
1881
+ return undefined;
1882
+ }
1883
+ };
1884
+ /**
1885
+ * Gives the renewed chat token to the attachment client, which keeps the token it was initialized with and uses
1886
+ * it for every upload and download. Runs in the background and never throws: on failure, attachments keep using
1887
+ * the previous token as they did before renewal existed.
1888
+ */
1889
+ OmnichannelChatSDK.prototype.refreshAttachmentClientToken = function (chatId) {
1890
+ var _this = this;
1891
+ try {
1892
+ var amsClient_1 = this.AMSClient;
1893
+ var chatToken_1 = this.chatToken;
1894
+ if (!this.isAMSClientAllowed
1895
+ || this.AMSClientLoadCurrentState !== AMSClientLoadStates_1.AMSClientLoadStates.LOADED
1896
+ || !amsClient_1
1897
+ || typeof amsClient_1.initialize !== "function"
1898
+ || (chatToken_1 === null || chatToken_1 === void 0 ? void 0 : chatToken_1.chatId) !== chatId
1899
+ || !chatToken_1.token) {
1900
+ return;
1901
+ }
1902
+ var telemetryData_2 = {
1903
+ RequestId: this.requestId,
1904
+ ChatId: chatId
1905
+ };
1906
+ this.scenarioMarker.startScenario(TelemetryEvent_1.default.RefreshAttachmentClientToken, telemetryData_2);
1907
+ Promise.resolve()
1908
+ .then(function () { return amsClient_1.initialize({ chatToken: chatToken_1 }); })
1909
+ .then(function () {
1910
+ _this.scenarioMarker.completeScenario(TelemetryEvent_1.default.RefreshAttachmentClientToken, telemetryData_2);
1911
+ }, function (error) {
1912
+ _this.scenarioMarker.failScenario(TelemetryEvent_1.default.RefreshAttachmentClientToken, __assign(__assign({}, telemetryData_2), { ExceptionDetails: JSON.stringify({ errorObject: "".concat(error) }) }));
1913
+ })
1914
+ .catch(function () {
1915
+ // Telemetry failures must not surface
1916
+ });
1917
+ }
1918
+ catch (_a) {
1919
+ // Attachments keep using the previous token
1920
+ }
1921
+ };
1922
+ /**
1923
+ * Creates the recovery for chat requests that fail with 401 while the chat token has not
1924
+ * expired. Returns null, which keeps the existing behavior, unless chat token renewal is enabled and recovery is
1925
+ * not disabled in the SDK config.
1926
+ */
1927
+ OmnichannelChatSDK.prototype.createChatTokenUnauthorizedRecovery = function (initialToken, tokenRefresher) {
1928
+ var _this = this;
1929
+ var _a, _b, _c;
1930
+ try {
1931
+ if (!tokenRefresher
1932
+ || ((_b = (_a = this.chatSDKConfig) === null || _a === void 0 ? void 0 : _a.chatTokenRenewal) === null || _b === void 0 ? void 0 : _b.disableUnauthorizedRecovery) === true
1933
+ || !initialToken) {
1934
+ return null;
1935
+ }
1936
+ var telemetryData_3 = {
1937
+ RequestId: this.requestId,
1938
+ ChatId: (_c = this.chatToken) === null || _c === void 0 ? void 0 : _c.chatId
1939
+ };
1940
+ return (0, chatTokenUnauthorizedRecovery_1.createChatTokenUnauthorizedRecovery)({
1941
+ initialToken: initialToken,
1942
+ refreshToken: tokenRefresher,
1943
+ onStart: function () { return _this.scenarioMarker.startScenario(TelemetryEvent_1.default.ChatTokenUnauthorizedRecovery, telemetryData_3); },
1944
+ onSuccess: function (_source, usedExistingToken) {
1945
+ if (!usedExistingToken) {
1946
+ _this.scenarioMarker.completeScenario(TelemetryEvent_1.default.ChatTokenUnauthorizedRecovery, telemetryData_3);
1947
+ }
1948
+ },
1949
+ onFailure: function (source, reason) {
1950
+ _this.scenarioMarker.failScenario(TelemetryEvent_1.default.ChatTokenUnauthorizedRecovery, __assign(__assign({}, telemetryData_3), { ExceptionDetails: JSON.stringify({ response: reason, source: source }) }));
1951
+ }
1952
+ });
1953
+ }
1954
+ catch (_d) {
1955
+ return null;
1956
+ }
1957
+ };
1958
+ /**
1959
+ * Returns the token of the authenticated user to renew the chat token with, refreshed from the auth token
1960
+ * provider when possible because the token used to start the chat may have expired. Returns undefined for
1961
+ * unauthenticated chats.
1962
+ */
1963
+ OmnichannelChatSDK.prototype.getAuthenticatedUserTokenForChatTokenRenewal = function () {
1964
+ return __awaiter(this, void 0, void 0, function () {
1965
+ var token, _a;
1966
+ var _b;
1967
+ return __generator(this, function (_c) {
1968
+ switch (_c.label) {
1969
+ case 0:
1970
+ if (!this.authenticatedUserToken) {
1971
+ return [2 /*return*/, undefined];
1972
+ }
1973
+ if (!(typeof ((_b = this.chatSDKConfig) === null || _b === void 0 ? void 0 : _b.getAuthToken) === "function")) return [3 /*break*/, 4];
1974
+ _c.label = 1;
1975
+ case 1:
1976
+ _c.trys.push([1, 3, , 4]);
1977
+ return [4 /*yield*/, this.chatSDKConfig.getAuthToken()];
1978
+ case 2:
1979
+ token = _c.sent();
1980
+ if (typeof token === "string" && token.trim().length > 0) {
1981
+ return [2 /*return*/, token];
1982
+ }
1983
+ return [3 /*break*/, 4];
1984
+ case 3:
1985
+ _a = _c.sent();
1986
+ return [3 /*break*/, 4];
1987
+ case 4: return [2 /*return*/, this.authenticatedUserToken];
1988
+ }
1989
+ });
1990
+ });
1991
+ };
1793
1992
  OmnichannelChatSDK.prototype.getCallingToken = function () {
1794
1993
  return __awaiter(this, void 0, void 0, function () {
1795
1994
  return __generator(this, function (_a) {
@@ -2628,7 +2827,8 @@ var OmnichannelChatSDK = /** @class */ (function () {
2628
2827
  };
2629
2828
  OmnichannelChatSDK.prototype.emailLiveChatTranscript = function (body_1) {
2630
2829
  return __awaiter(this, arguments, void 0, function (body, optionalParams) {
2631
- var emailTranscriptOptionalParams, requestId, chatToken, chatId, sessionId, emailRequestBody, error_27;
2830
+ var emailTranscriptOptionalParams, requestId, chatToken, chatId, requestSessionKey, emailRequestBody_1, error_27;
2831
+ var _this = this;
2632
2832
  var _a;
2633
2833
  if (optionalParams === void 0) { optionalParams = {}; }
2634
2834
  return __generator(this, function (_b) {
@@ -2638,16 +2838,12 @@ var OmnichannelChatSDK = /** @class */ (function () {
2638
2838
  requestId = this.requestId;
2639
2839
  chatToken = this.chatToken;
2640
2840
  chatId = chatToken.chatId;
2641
- sessionId = this.sessionId;
2642
2841
  if (optionalParams.liveChatContext) {
2643
2842
  requestId = optionalParams.liveChatContext.requestId;
2644
2843
  chatToken = optionalParams.liveChatContext.chatToken;
2645
2844
  chatId = chatToken.chatId;
2646
2845
  }
2647
- if ((_a = optionalParams.liveChatContext) === null || _a === void 0 ? void 0 : _a.sessionId) {
2648
- sessionId = optionalParams.liveChatContext.sessionId;
2649
- this.OCClient.sessionId = sessionId;
2650
- }
2846
+ requestSessionKey = ((_a = optionalParams.liveChatContext) === null || _a === void 0 ? void 0 : _a.sessionId) || this.getEndedChatSessionKey(chatId);
2651
2847
  this.scenarioMarker.startScenario(TelemetryEvent_1.default.EmailLiveChatTranscript, {
2652
2848
  RequestId: requestId,
2653
2849
  ChatId: chatId
@@ -2661,18 +2857,15 @@ var OmnichannelChatSDK = /** @class */ (function () {
2661
2857
  if (this.authenticatedUserToken) {
2662
2858
  emailTranscriptOptionalParams.authenticatedUserToken = this.authenticatedUserToken;
2663
2859
  }
2664
- emailRequestBody = {
2860
+ emailRequestBody_1 = {
2665
2861
  ChatId: chatId,
2666
2862
  EmailAddress: body.emailAddress,
2667
2863
  DefaultAttachmentMessage: body.attachmentMessage,
2668
2864
  CustomerLocale: body.locale || (0, locale_1.getLocaleStringFromId)(this.localeId)
2669
2865
  };
2670
- return [4 /*yield*/, this.OCClient.emailTranscript(requestId, chatToken.token, emailRequestBody, emailTranscriptOptionalParams)];
2866
+ return [4 /*yield*/, this.withRequestSessionKey(requestSessionKey, function () { return _this.OCClient.emailTranscript(requestId, chatToken.token, emailRequestBody_1, emailTranscriptOptionalParams); })];
2671
2867
  case 2:
2672
2868
  _b.sent();
2673
- if (this.sessionId) {
2674
- this.OCClient.sessionId = this.sessionId;
2675
- }
2676
2869
  this.scenarioMarker.completeScenario(TelemetryEvent_1.default.EmailLiveChatTranscript, {
2677
2870
  RequestId: requestId,
2678
2871
  ChatId: chatId
@@ -2693,7 +2886,8 @@ var OmnichannelChatSDK = /** @class */ (function () {
2693
2886
  };
2694
2887
  OmnichannelChatSDK.prototype.getLiveChatTranscript = function () {
2695
2888
  return __awaiter(this, arguments, void 0, function (optionalParams) {
2696
- var getChatTranscriptOptionalParams, requestId, chatToken, chatId, sessionId, transcriptResponse, error_28, telemetryData;
2889
+ var getChatTranscriptOptionalParams, requestId, chatToken, chatId, requestSessionKey, transcriptResponse, error_28, telemetryData;
2890
+ var _this = this;
2697
2891
  var _a, _b;
2698
2892
  if (optionalParams === void 0) { optionalParams = {}; }
2699
2893
  return __generator(this, function (_c) {
@@ -2703,7 +2897,6 @@ var OmnichannelChatSDK = /** @class */ (function () {
2703
2897
  requestId = this.requestId;
2704
2898
  chatToken = this.chatToken;
2705
2899
  chatId = chatToken.chatId;
2706
- sessionId = this.sessionId;
2707
2900
  if (optionalParams.liveChatContext) {
2708
2901
  if (this.isPersistentChat && !((_a = this.chatSDKConfig.persistentChat) === null || _a === void 0 ? void 0 : _a.disable)) {
2709
2902
  requestId = this.requestId || optionalParams.liveChatContext.requestId;
@@ -2715,10 +2908,6 @@ var OmnichannelChatSDK = /** @class */ (function () {
2715
2908
  }
2716
2909
  chatId = chatToken.chatId;
2717
2910
  }
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
2911
  if (!chatId) {
2723
2912
  throw new ChatSDKError_1.ChatSDKError(ChatSDKError_1.ChatSDKErrorName.LiveChatTranscriptRetrievalFailure, undefined, {
2724
2913
  response: ChatSDKError_1.ChatSDKErrorName.LiveChatTranscriptRetrievalFailure,
@@ -2732,18 +2921,16 @@ var OmnichannelChatSDK = /** @class */ (function () {
2732
2921
  if (!this.isInitialized) {
2733
2922
  exceptionThrowers_1.default.throwUninitializedChatSDK(this.scenarioMarker, TelemetryEvent_1.default.GetLiveChatTranscript);
2734
2923
  }
2924
+ requestSessionKey = ((_b = optionalParams.liveChatContext) === null || _b === void 0 ? void 0 : _b.sessionId) || this.getEndedChatSessionKey(chatId);
2735
2925
  _c.label = 1;
2736
2926
  case 1:
2737
2927
  _c.trys.push([1, 3, , 4]);
2738
2928
  if (this.authenticatedUserToken) {
2739
2929
  getChatTranscriptOptionalParams.authenticatedUserToken = this.authenticatedUserToken;
2740
2930
  }
2741
- return [4 /*yield*/, this.OCClient.getChatTranscripts(requestId, chatToken.chatId, chatToken.token, getChatTranscriptOptionalParams)];
2931
+ return [4 /*yield*/, this.withRequestSessionKey(requestSessionKey, function () { return _this.OCClient.getChatTranscripts(requestId, chatToken.chatId, chatToken.token, getChatTranscriptOptionalParams); })];
2742
2932
  case 2:
2743
2933
  transcriptResponse = _c.sent();
2744
- if (this.sessionId) {
2745
- this.OCClient.sessionId = this.sessionId;
2746
- }
2747
2934
  this.scenarioMarker.completeScenario(TelemetryEvent_1.default.GetLiveChatTranscript, {
2748
2935
  RequestId: requestId,
2749
2936
  ChatId: chatId
@@ -2762,6 +2949,30 @@ var OmnichannelChatSDK = /** @class */ (function () {
2762
2949
  });
2763
2950
  });
2764
2951
  };
2952
+ /**
2953
+ * Returns the ended chat's session key when the call targets that chat, or null.
2954
+ */
2955
+ OmnichannelChatSDK.prototype.getEndedChatSessionKey = function (chatId) {
2956
+ var _a;
2957
+ return chatId && ((_a = this.endedChatSessionKey) === null || _a === void 0 ? void 0 : _a.chatId) === chatId ? this.endedChatSessionKey.sessionId : null;
2958
+ };
2959
+ /**
2960
+ * Sends the session key on one OCSDK request without leaving it on the shared client. OCSDK copies the
2961
+ * key into the request headers before its first await, so the previous key is restored before the HTTP wait.
2962
+ */
2963
+ OmnichannelChatSDK.prototype.withRequestSessionKey = function (sessionKey, request) {
2964
+ if (!sessionKey) {
2965
+ return request();
2966
+ }
2967
+ var previousSessionKey = this.OCClient.sessionId;
2968
+ this.OCClient.sessionId = sessionKey;
2969
+ try {
2970
+ return request();
2971
+ }
2972
+ finally {
2973
+ this.OCClient.sessionId = previousSessionKey;
2974
+ }
2975
+ };
2765
2976
  OmnichannelChatSDK.prototype.createChatAdapter = function () {
2766
2977
  return __awaiter(this, arguments, void 0, function (optionalParams) {
2767
2978
  var protocol, supportedChatAdapterProtocols, options, fileManager;