@microsoft/omnichannel-chat-sdk 2.0.1 → 2.0.2-main.8b19159

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.
package/README.md CHANGED
@@ -113,10 +113,14 @@ For a detailed tracking of the releases, please refer to the [Changelog document
113
113
 
114
114
  _**Important Note:**_ Versions below 1.11.0 are no longer supported after November 1st, 2025. Please update to recent versions to ensure you have the latest features and bug fixes.
115
115
 
116
+ _**Known issue:**_ Versions earlier than 1.11.6 can start duplicate conversations when an application calls `startChat()` again before the previous call is complete. Upgrade to 1.11.8 or later. See [Concurrent `startChat()` calls in versions before 1.11.6](docs/KNOWN_ISSUE_CONCURRENT_STARTCHAT.md).
117
+
116
118
  | Version | Docs | Release Date | End of Support | Deprecated |
117
119
  | -- | -- | -- | -- | -- |
120
+ | 2.0.2 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v2.0.2) | Oct 20th 2026 | Oct 20th 2027 | |
118
121
  | 2.0.1 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v2.0.1) | Oct 1st 2026 | Oct 1st 2027 | |
119
122
  | 2.0.0 | [Migration Guide](docs/MIGRATION_2.0.md) / [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v2.0.0) | Aug 13th 2026 | Aug 13th 2027 | |
123
+ | 1.11.8 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.11.8) | Feb 2nd 2026 | Feb 2nd 2027 | |
120
124
  | 1.11.4 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.11.4) | Jul 17th 2025 | Jul 17th 2026 | |
121
125
  | 1.11.3 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.11.3) | Jul 14th 2025 | Jul 14th 2026 | |
122
126
  | 1.11.2 | [Release Notes](https://github.com/microsoft/omnichannel-chat-sdk/releases/tag/v1.11.2) | Jun 24th 2025 | Jun 24th 2026 | |
@@ -57,6 +57,7 @@ declare class OmnichannelChatSDK {
57
57
  private coreServicesOrgUrl;
58
58
  private dynamicsLocationCode;
59
59
  private chatToken;
60
+ private chatTokenUnauthorizedRecovery;
60
61
  private liveChatConfig;
61
62
  private widgetSnippetBaseUrl;
62
63
  private liveChatVersion;
@@ -77,6 +78,7 @@ declare class OmnichannelChatSDK {
77
78
  private isPersistentChat;
78
79
  private isChatReconnect;
79
80
  private reconnectId;
81
+ private endedChatSessionKey;
80
82
  private refreshTokenTimer;
81
83
  private AMSClientLoadCurrentState;
82
84
  private isMaskingDisabled;
@@ -165,6 +167,30 @@ declare class OmnichannelChatSDK {
165
167
  getLiveChatConfig(optionalParams?: GetLiveChatConfigOptionalParams): Promise<ChatConfig>;
166
168
  getChatToken(cached?: boolean, optionalParams?: GetChatTokenOptionalParams): Promise<IChatToken>;
167
169
  setChatToken(chatToken: FetchChatTokenResponse): void;
170
+ /**
171
+ * Creates the ACS token refresher used to renew the chat token before it expires. Returns undefined, which keeps
172
+ * the existing behavior, unless renewal is enabled in the chat config, not disabled in the SDK config and
173
+ * supported by the installed OCSDK. The refresher never throws and falls back to the current token on failure.
174
+ */
175
+ private createChatTokenRefresher;
176
+ /**
177
+ * Gives the renewed chat token to the attachment client, which keeps the token it was initialized with and uses
178
+ * it for every upload and download. Runs in the background and never throws: on failure, attachments keep using
179
+ * the previous token as they did before renewal existed.
180
+ */
181
+ private refreshAttachmentClientToken;
182
+ /**
183
+ * Creates the recovery for chat requests that fail with 401 while the chat token has not
184
+ * expired. Returns null, which keeps the existing behavior, unless chat token renewal is enabled and recovery is
185
+ * not disabled in the SDK config.
186
+ */
187
+ private createChatTokenUnauthorizedRecovery;
188
+ /**
189
+ * Returns the token of the authenticated user to renew the chat token with, refreshed from the auth token
190
+ * provider when possible because the token used to start the chat may have expired. Returns undefined for
191
+ * unauthenticated chats.
192
+ */
193
+ private getAuthenticatedUserTokenForChatTokenRenewal;
168
194
  getCallingToken(): Promise<string>;
169
195
  private recordMessages;
170
196
  getMessages(): Promise<GetMessagesResponse>;
@@ -208,6 +234,15 @@ declare class OmnichannelChatSDK {
208
234
  downloadFileAttachment(fileMetadata: FileMetadata | IFileMetadata): Promise<Blob>;
209
235
  emailLiveChatTranscript(body: ChatTranscriptBody, optionalParams?: EmailLiveChatTranscriptOptionaParams): Promise<void>;
210
236
  getLiveChatTranscript(optionalParams?: GetLiveChatTranscriptOptionalParams): Promise<GetLiveChatTranscriptResponse>;
237
+ /**
238
+ * Returns the ended chat's session key when the call targets that chat, or null.
239
+ */
240
+ private getEndedChatSessionKey;
241
+ /**
242
+ * Sends the session key on one OCSDK request without leaving it on the shared client. OCSDK copies the
243
+ * key into the request headers before its first await, so the previous key is restored before the HTTP wait.
244
+ */
245
+ private withRequestSessionKey;
211
246
  createChatAdapter(optionalParams?: ChatAdapterOptionalParams): Promise<ChatAdapter>;
212
247
  isVoiceVideoCallingEnabled(): boolean;
213
248
  getVoiceVideoCalling(voiceVideoCallingOptionalParams?: VoiceVideoCallingOptionalParams): Promise<GetVoiceVideoCallingResponse>;
@@ -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
  });
@@ -1097,10 +1103,10 @@ var OmnichannelChatSDK = /** @class */ (function () {
1097
1103
  });
1098
1104
  }); };
1099
1105
  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) {
1106
+ var chatAdapterConfig, tokenRefresher, error_8, telemetryData, _a, error_9, telemetryData, error_10, telemetryData, _b, error_11, telemetryData;
1107
+ var _c, _d, _e;
1108
+ return __generator(this, function (_f) {
1109
+ switch (_f.label) {
1104
1110
  case 0:
1105
1111
  if (!(this.liveChatVersion === LiveChatVersion_1.default.V2)) return [3 /*break*/, 8];
1106
1112
  chatAdapterConfig = {
@@ -1110,18 +1116,22 @@ var OmnichannelChatSDK = /** @class */ (function () {
1110
1116
  environmentUrl: this.chatToken.acsEndpoint,
1111
1117
  pollingInterval: 30000
1112
1118
  };
1113
- _e.label = 1;
1119
+ _f.label = 1;
1114
1120
  case 1:
1115
- _e.trys.push([1, 3, , 4]);
1121
+ _f.trys.push([1, 3, , 4]);
1122
+ tokenRefresher = this.createChatTokenRefresher(chatAdapterConfig.token);
1123
+ this.chatTokenUnauthorizedRecovery = this.createChatTokenUnauthorizedRecovery(chatAdapterConfig.token, tokenRefresher);
1116
1124
  return [4 /*yield*/, ((_c = this.ACSClient) === null || _c === void 0 ? void 0 : _c.initialize({
1117
1125
  token: chatAdapterConfig.token,
1118
1126
  environmentUrl: chatAdapterConfig.environmentUrl,
1127
+ tokenRefresher: tokenRefresher,
1128
+ unauthorizedRecovery: (_d = this.chatTokenUnauthorizedRecovery) !== null && _d !== void 0 ? _d : undefined
1119
1129
  }))];
1120
1130
  case 2:
1121
- _e.sent();
1131
+ _f.sent();
1122
1132
  return [3 /*break*/, 4];
1123
1133
  case 3:
1124
- error_8 = _e.sent();
1134
+ error_8 = _f.sent();
1125
1135
  telemetryData = {
1126
1136
  RequestId: this.requestId,
1127
1137
  ChatId: this.chatToken.chatId,
@@ -1129,22 +1139,22 @@ var OmnichannelChatSDK = /** @class */ (function () {
1129
1139
  exceptionThrowers_1.default.throwMessagingClientInitializationFailure(error_8, this.scenarioMarker, TelemetryEvent_1.default.StartChat, telemetryData);
1130
1140
  return [3 /*break*/, 4];
1131
1141
  case 4:
1132
- _e.trys.push([4, 6, , 7]);
1142
+ _f.trys.push([4, 6, , 7]);
1133
1143
  _a = this;
1134
- return [4 /*yield*/, ((_d = this.ACSClient) === null || _d === void 0 ? void 0 : _d.joinConversation({
1144
+ return [4 /*yield*/, ((_e = this.ACSClient) === null || _e === void 0 ? void 0 : _e.joinConversation({
1135
1145
  id: chatAdapterConfig.id,
1136
1146
  threadId: chatAdapterConfig.threadId,
1137
1147
  pollingInterval: chatAdapterConfig.pollingInterval
1138
1148
  }))];
1139
1149
  case 5:
1140
- _a.conversation = (_e.sent());
1150
+ _a.conversation = (_f.sent());
1141
1151
  this.scenarioMarker.completeScenario(TelemetryEvent_1.default.StartChat, {
1142
1152
  RequestId: this.requestId,
1143
1153
  ChatId: this.chatToken.chatId
1144
1154
  });
1145
1155
  return [3 /*break*/, 7];
1146
1156
  case 6:
1147
- error_9 = _e.sent();
1157
+ error_9 = _f.sent();
1148
1158
  telemetryData = {
1149
1159
  RequestId: this.requestId,
1150
1160
  ChatId: this.chatToken.chatId,
@@ -1153,17 +1163,17 @@ var OmnichannelChatSDK = /** @class */ (function () {
1153
1163
  return [3 /*break*/, 7];
1154
1164
  case 7: return [3 /*break*/, 14];
1155
1165
  case 8:
1156
- _e.trys.push([8, 10, , 11]);
1166
+ _f.trys.push([8, 10, , 11]);
1157
1167
  return [4 /*yield*/, this.IC3Client.initialize({
1158
1168
  token: this.chatToken.token,
1159
1169
  regionGtms: this.chatToken.regionGTMS,
1160
1170
  visitor: true
1161
1171
  })];
1162
1172
  case 9:
1163
- _e.sent();
1173
+ _f.sent();
1164
1174
  return [3 /*break*/, 11];
1165
1175
  case 10:
1166
- error_10 = _e.sent();
1176
+ error_10 = _f.sent();
1167
1177
  telemetryData = {
1168
1178
  RequestId: this.requestId,
1169
1179
  ChatId: this.chatToken.chatId,
@@ -1171,18 +1181,18 @@ var OmnichannelChatSDK = /** @class */ (function () {
1171
1181
  exceptionThrowers_1.default.throwMessagingClientInitializationFailure(error_10, this.scenarioMarker, TelemetryEvent_1.default.StartChat, telemetryData);
1172
1182
  return [3 /*break*/, 11];
1173
1183
  case 11:
1174
- _e.trys.push([11, 13, , 14]);
1184
+ _f.trys.push([11, 13, , 14]);
1175
1185
  _b = this;
1176
1186
  return [4 /*yield*/, this.IC3Client.joinConversation(this.chatToken.chatId)];
1177
1187
  case 12:
1178
- _b.conversation = _e.sent();
1188
+ _b.conversation = _f.sent();
1179
1189
  this.scenarioMarker.completeScenario(TelemetryEvent_1.default.StartChat, {
1180
1190
  RequestId: this.requestId,
1181
1191
  ChatId: this.chatToken.chatId
1182
1192
  });
1183
1193
  return [3 /*break*/, 14];
1184
1194
  case 13:
1185
- error_11 = _e.sent();
1195
+ error_11 = _f.sent();
1186
1196
  telemetryData = {
1187
1197
  RequestId: this.requestId,
1188
1198
  ChatId: this.chatToken.chatId,
@@ -1360,7 +1370,7 @@ var OmnichannelChatSDK = /** @class */ (function () {
1360
1370
  };
1361
1371
  OmnichannelChatSDK.prototype.internalEndChat = function () {
1362
1372
  return __awaiter(this, arguments, void 0, function (endChatOptionalParams) {
1363
- var cleanupMetadata, isReactNative, isConversationalSurveyEnabled, shouldWaitForSurvey, telemetryData, surveyStarted, error_15, error_16, telemetryData;
1373
+ var cleanupMetadata, isReactNative, isConversationalSurveyEnabled, shouldWaitForSurvey, telemetryData, surveyStarted, error_15, error_16, telemetryData, endedChatId, endedSessionId;
1364
1374
  var _a, _b, _c;
1365
1375
  if (endChatOptionalParams === void 0) { endChatOptionalParams = {}; }
1366
1376
  return __generator(this, function (_d) {
@@ -1419,12 +1429,17 @@ var OmnichannelChatSDK = /** @class */ (function () {
1419
1429
  exceptionThrowers_1.default.throwConversationClosureFailure(error_16, this.scenarioMarker, TelemetryEvent_1.default.EndChat, telemetryData);
1420
1430
  return [3 /*break*/, 11];
1421
1431
  case 10:
1422
- // Cleanup always runs, regardless of success or failure
1423
- // This ensures resources are released even if closeChat or survey waiting throws
1432
+ endedChatId = this.chatToken.chatId;
1433
+ endedSessionId = this.OCClient.sessionId || this.sessionId;
1434
+ // Keep the previous chat's key when this call had no chat to end (for example a second endChat).
1435
+ if (endedChatId && endedSessionId) {
1436
+ this.endedChatSessionKey = { chatId: endedChatId, sessionId: endedSessionId };
1437
+ }
1424
1438
  (_c = this.conversation) === null || _c === void 0 ? void 0 : _c.disconnect();
1425
1439
  this.conversation = null;
1426
1440
  this.requestId = (0, ocsdk_1.uuidv4)();
1427
1441
  this.chatToken = {};
1442
+ this.chatTokenUnauthorizedRecovery = null;
1428
1443
  this.reconnectId = null;
1429
1444
  if (this.IC3Client) {
1430
1445
  this.IC3Client.dispose();
@@ -1790,6 +1805,181 @@ var OmnichannelChatSDK = /** @class */ (function () {
1790
1805
  this.sessionId = this.OCClient.sessionId;
1791
1806
  }
1792
1807
  };
1808
+ /**
1809
+ * Creates the ACS token refresher used to renew the chat token before it expires. Returns undefined, which keeps
1810
+ * the existing behavior, unless renewal is enabled in the chat config, not disabled in the SDK config and
1811
+ * supported by the installed OCSDK. The refresher never throws and falls back to the current token on failure.
1812
+ */
1813
+ OmnichannelChatSDK.prototype.createChatTokenRefresher = function (initialToken) {
1814
+ var _this = this;
1815
+ var _a, _b, _c, _d, _e, _f;
1816
+ try {
1817
+ if (this.liveChatVersion !== LiveChatVersion_1.default.V2
1818
+ || ((_b = (_a = this.chatSDKConfig) === null || _a === void 0 ? void 0 : _a.chatTokenRenewal) === null || _b === void 0 ? void 0 : _b.disable) === true
1819
+ || (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"
1820
+ || typeof ((_e = this.OCClient) === null || _e === void 0 ? void 0 : _e.renewChatToken) !== "function"
1821
+ || !initialToken
1822
+ || !((_f = this.chatToken) === null || _f === void 0 ? void 0 : _f.chatId)
1823
+ || !this.requestId) {
1824
+ return undefined;
1825
+ }
1826
+ var chatId_1 = this.chatToken.chatId;
1827
+ var requestId_1 = this.requestId;
1828
+ // A reconnected chat is found by its reconnect id, not by the new request id
1829
+ var renewalId_1 = this.reconnectId || requestId_1;
1830
+ var telemetryData_1 = {
1831
+ RequestId: requestId_1,
1832
+ ChatId: chatId_1
1833
+ };
1834
+ return (0, chatTokenRenewal_1.createChatTokenRefresher)({
1835
+ initialToken: initialToken,
1836
+ chatId: chatId_1,
1837
+ isChatActive: function () { var _a; return !_this.isEndingChat && _this.requestId === requestId_1 && ((_a = _this.chatToken) === null || _a === void 0 ? void 0 : _a.chatId) === chatId_1; },
1838
+ renewChatToken: function () { return __awaiter(_this, void 0, void 0, function () {
1839
+ var renewChatTokenOptionalParams, authenticatedUserToken;
1840
+ return __generator(this, function (_a) {
1841
+ switch (_a.label) {
1842
+ case 0:
1843
+ renewChatTokenOptionalParams = {};
1844
+ return [4 /*yield*/, this.getAuthenticatedUserTokenForChatTokenRenewal()];
1845
+ case 1:
1846
+ authenticatedUserToken = _a.sent();
1847
+ if (authenticatedUserToken) {
1848
+ renewChatTokenOptionalParams.authenticatedUserToken = authenticatedUserToken;
1849
+ }
1850
+ return [2 /*return*/, this.OCClient.renewChatToken(renewalId_1, renewChatTokenOptionalParams)];
1851
+ }
1852
+ });
1853
+ }); },
1854
+ isNonRetriableStatus: function (statusCode) { return (_this.authenticatedUserToken ? chatTokenRenewal_1.authenticatedNonRetriableStatusCodes : chatTokenRenewal_1.defaultNonRetriableStatusCodes).includes(statusCode); },
1855
+ onRenewed: function (renewed) {
1856
+ var _a;
1857
+ _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 });
1858
+ _this.refreshAttachmentClientToken(chatId_1);
1859
+ },
1860
+ onStart: function () { return _this.scenarioMarker.startScenario(TelemetryEvent_1.default.RenewChatToken, telemetryData_1); },
1861
+ onSuccess: function () { return _this.scenarioMarker.completeScenario(TelemetryEvent_1.default.RenewChatToken, telemetryData_1); },
1862
+ onFailure: function (reason, error) {
1863
+ var exceptionDetails = {
1864
+ response: reason,
1865
+ errorObject: error !== undefined ? "".concat(error) : undefined
1866
+ };
1867
+ _this.scenarioMarker.failScenario(TelemetryEvent_1.default.RenewChatToken, __assign(__assign({}, telemetryData_1), { ExceptionDetails: JSON.stringify(exceptionDetails) }));
1868
+ }
1869
+ });
1870
+ }
1871
+ catch (_g) {
1872
+ return undefined;
1873
+ }
1874
+ };
1875
+ /**
1876
+ * Gives the renewed chat token to the attachment client, which keeps the token it was initialized with and uses
1877
+ * it for every upload and download. Runs in the background and never throws: on failure, attachments keep using
1878
+ * the previous token as they did before renewal existed.
1879
+ */
1880
+ OmnichannelChatSDK.prototype.refreshAttachmentClientToken = function (chatId) {
1881
+ var _this = this;
1882
+ try {
1883
+ var amsClient_1 = this.AMSClient;
1884
+ var chatToken_1 = this.chatToken;
1885
+ if (!this.isAMSClientAllowed
1886
+ || this.AMSClientLoadCurrentState !== AMSClientLoadStates_1.AMSClientLoadStates.LOADED
1887
+ || !amsClient_1
1888
+ || typeof amsClient_1.initialize !== "function"
1889
+ || (chatToken_1 === null || chatToken_1 === void 0 ? void 0 : chatToken_1.chatId) !== chatId
1890
+ || !chatToken_1.token) {
1891
+ return;
1892
+ }
1893
+ var telemetryData_2 = {
1894
+ RequestId: this.requestId,
1895
+ ChatId: chatId
1896
+ };
1897
+ this.scenarioMarker.startScenario(TelemetryEvent_1.default.RefreshAttachmentClientToken, telemetryData_2);
1898
+ Promise.resolve()
1899
+ .then(function () { return amsClient_1.initialize({ chatToken: chatToken_1 }); })
1900
+ .then(function () {
1901
+ _this.scenarioMarker.completeScenario(TelemetryEvent_1.default.RefreshAttachmentClientToken, telemetryData_2);
1902
+ }, function (error) {
1903
+ _this.scenarioMarker.failScenario(TelemetryEvent_1.default.RefreshAttachmentClientToken, __assign(__assign({}, telemetryData_2), { ExceptionDetails: JSON.stringify({ errorObject: "".concat(error) }) }));
1904
+ })
1905
+ .catch(function () {
1906
+ // Telemetry failures must not surface
1907
+ });
1908
+ }
1909
+ catch (_a) {
1910
+ // Attachments keep using the previous token
1911
+ }
1912
+ };
1913
+ /**
1914
+ * Creates the recovery for chat requests that fail with 401 while the chat token has not
1915
+ * expired. Returns null, which keeps the existing behavior, unless chat token renewal is enabled and recovery is
1916
+ * not disabled in the SDK config.
1917
+ */
1918
+ OmnichannelChatSDK.prototype.createChatTokenUnauthorizedRecovery = function (initialToken, tokenRefresher) {
1919
+ var _this = this;
1920
+ var _a, _b, _c;
1921
+ try {
1922
+ if (!tokenRefresher
1923
+ || ((_b = (_a = this.chatSDKConfig) === null || _a === void 0 ? void 0 : _a.chatTokenRenewal) === null || _b === void 0 ? void 0 : _b.disableUnauthorizedRecovery) === true
1924
+ || !initialToken) {
1925
+ return null;
1926
+ }
1927
+ var telemetryData_3 = {
1928
+ RequestId: this.requestId,
1929
+ ChatId: (_c = this.chatToken) === null || _c === void 0 ? void 0 : _c.chatId
1930
+ };
1931
+ return (0, chatTokenUnauthorizedRecovery_1.createChatTokenUnauthorizedRecovery)({
1932
+ initialToken: initialToken,
1933
+ refreshToken: tokenRefresher,
1934
+ onStart: function () { return _this.scenarioMarker.startScenario(TelemetryEvent_1.default.ChatTokenUnauthorizedRecovery, telemetryData_3); },
1935
+ onSuccess: function (_source, usedExistingToken) {
1936
+ if (!usedExistingToken) {
1937
+ _this.scenarioMarker.completeScenario(TelemetryEvent_1.default.ChatTokenUnauthorizedRecovery, telemetryData_3);
1938
+ }
1939
+ },
1940
+ onFailure: function (source, reason) {
1941
+ _this.scenarioMarker.failScenario(TelemetryEvent_1.default.ChatTokenUnauthorizedRecovery, __assign(__assign({}, telemetryData_3), { ExceptionDetails: JSON.stringify({ response: reason, source: source }) }));
1942
+ }
1943
+ });
1944
+ }
1945
+ catch (_d) {
1946
+ return null;
1947
+ }
1948
+ };
1949
+ /**
1950
+ * Returns the token of the authenticated user to renew the chat token with, refreshed from the auth token
1951
+ * provider when possible because the token used to start the chat may have expired. Returns undefined for
1952
+ * unauthenticated chats.
1953
+ */
1954
+ OmnichannelChatSDK.prototype.getAuthenticatedUserTokenForChatTokenRenewal = function () {
1955
+ return __awaiter(this, void 0, void 0, function () {
1956
+ var token, _a;
1957
+ var _b;
1958
+ return __generator(this, function (_c) {
1959
+ switch (_c.label) {
1960
+ case 0:
1961
+ if (!this.authenticatedUserToken) {
1962
+ return [2 /*return*/, undefined];
1963
+ }
1964
+ if (!(typeof ((_b = this.chatSDKConfig) === null || _b === void 0 ? void 0 : _b.getAuthToken) === "function")) return [3 /*break*/, 4];
1965
+ _c.label = 1;
1966
+ case 1:
1967
+ _c.trys.push([1, 3, , 4]);
1968
+ return [4 /*yield*/, this.chatSDKConfig.getAuthToken()];
1969
+ case 2:
1970
+ token = _c.sent();
1971
+ if (typeof token === "string" && token.trim().length > 0) {
1972
+ return [2 /*return*/, token];
1973
+ }
1974
+ return [3 /*break*/, 4];
1975
+ case 3:
1976
+ _a = _c.sent();
1977
+ return [3 /*break*/, 4];
1978
+ case 4: return [2 /*return*/, this.authenticatedUserToken];
1979
+ }
1980
+ });
1981
+ });
1982
+ };
1793
1983
  OmnichannelChatSDK.prototype.getCallingToken = function () {
1794
1984
  return __awaiter(this, void 0, void 0, function () {
1795
1985
  return __generator(this, function (_a) {
@@ -2628,7 +2818,8 @@ var OmnichannelChatSDK = /** @class */ (function () {
2628
2818
  };
2629
2819
  OmnichannelChatSDK.prototype.emailLiveChatTranscript = function (body_1) {
2630
2820
  return __awaiter(this, arguments, void 0, function (body, optionalParams) {
2631
- var emailTranscriptOptionalParams, requestId, chatToken, chatId, sessionId, emailRequestBody, error_27;
2821
+ var emailTranscriptOptionalParams, requestId, chatToken, chatId, requestSessionKey, emailRequestBody_1, error_27;
2822
+ var _this = this;
2632
2823
  var _a;
2633
2824
  if (optionalParams === void 0) { optionalParams = {}; }
2634
2825
  return __generator(this, function (_b) {
@@ -2638,16 +2829,12 @@ var OmnichannelChatSDK = /** @class */ (function () {
2638
2829
  requestId = this.requestId;
2639
2830
  chatToken = this.chatToken;
2640
2831
  chatId = chatToken.chatId;
2641
- sessionId = this.sessionId;
2642
2832
  if (optionalParams.liveChatContext) {
2643
2833
  requestId = optionalParams.liveChatContext.requestId;
2644
2834
  chatToken = optionalParams.liveChatContext.chatToken;
2645
2835
  chatId = chatToken.chatId;
2646
2836
  }
2647
- if ((_a = optionalParams.liveChatContext) === null || _a === void 0 ? void 0 : _a.sessionId) {
2648
- sessionId = optionalParams.liveChatContext.sessionId;
2649
- this.OCClient.sessionId = sessionId;
2650
- }
2837
+ requestSessionKey = ((_a = optionalParams.liveChatContext) === null || _a === void 0 ? void 0 : _a.sessionId) || this.getEndedChatSessionKey(chatId);
2651
2838
  this.scenarioMarker.startScenario(TelemetryEvent_1.default.EmailLiveChatTranscript, {
2652
2839
  RequestId: requestId,
2653
2840
  ChatId: chatId
@@ -2661,18 +2848,15 @@ var OmnichannelChatSDK = /** @class */ (function () {
2661
2848
  if (this.authenticatedUserToken) {
2662
2849
  emailTranscriptOptionalParams.authenticatedUserToken = this.authenticatedUserToken;
2663
2850
  }
2664
- emailRequestBody = {
2851
+ emailRequestBody_1 = {
2665
2852
  ChatId: chatId,
2666
2853
  EmailAddress: body.emailAddress,
2667
2854
  DefaultAttachmentMessage: body.attachmentMessage,
2668
2855
  CustomerLocale: body.locale || (0, locale_1.getLocaleStringFromId)(this.localeId)
2669
2856
  };
2670
- return [4 /*yield*/, this.OCClient.emailTranscript(requestId, chatToken.token, emailRequestBody, emailTranscriptOptionalParams)];
2857
+ return [4 /*yield*/, this.withRequestSessionKey(requestSessionKey, function () { return _this.OCClient.emailTranscript(requestId, chatToken.token, emailRequestBody_1, emailTranscriptOptionalParams); })];
2671
2858
  case 2:
2672
2859
  _b.sent();
2673
- if (this.sessionId) {
2674
- this.OCClient.sessionId = this.sessionId;
2675
- }
2676
2860
  this.scenarioMarker.completeScenario(TelemetryEvent_1.default.EmailLiveChatTranscript, {
2677
2861
  RequestId: requestId,
2678
2862
  ChatId: chatId
@@ -2693,7 +2877,8 @@ var OmnichannelChatSDK = /** @class */ (function () {
2693
2877
  };
2694
2878
  OmnichannelChatSDK.prototype.getLiveChatTranscript = function () {
2695
2879
  return __awaiter(this, arguments, void 0, function (optionalParams) {
2696
- var getChatTranscriptOptionalParams, requestId, chatToken, chatId, sessionId, transcriptResponse, error_28, telemetryData;
2880
+ var getChatTranscriptOptionalParams, requestId, chatToken, chatId, requestSessionKey, transcriptResponse, error_28, telemetryData;
2881
+ var _this = this;
2697
2882
  var _a, _b;
2698
2883
  if (optionalParams === void 0) { optionalParams = {}; }
2699
2884
  return __generator(this, function (_c) {
@@ -2703,7 +2888,6 @@ var OmnichannelChatSDK = /** @class */ (function () {
2703
2888
  requestId = this.requestId;
2704
2889
  chatToken = this.chatToken;
2705
2890
  chatId = chatToken.chatId;
2706
- sessionId = this.sessionId;
2707
2891
  if (optionalParams.liveChatContext) {
2708
2892
  if (this.isPersistentChat && !((_a = this.chatSDKConfig.persistentChat) === null || _a === void 0 ? void 0 : _a.disable)) {
2709
2893
  requestId = this.requestId || optionalParams.liveChatContext.requestId;
@@ -2715,10 +2899,6 @@ var OmnichannelChatSDK = /** @class */ (function () {
2715
2899
  }
2716
2900
  chatId = chatToken.chatId;
2717
2901
  }
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
2902
  if (!chatId) {
2723
2903
  throw new ChatSDKError_1.ChatSDKError(ChatSDKError_1.ChatSDKErrorName.LiveChatTranscriptRetrievalFailure, undefined, {
2724
2904
  response: ChatSDKError_1.ChatSDKErrorName.LiveChatTranscriptRetrievalFailure,
@@ -2732,18 +2912,16 @@ var OmnichannelChatSDK = /** @class */ (function () {
2732
2912
  if (!this.isInitialized) {
2733
2913
  exceptionThrowers_1.default.throwUninitializedChatSDK(this.scenarioMarker, TelemetryEvent_1.default.GetLiveChatTranscript);
2734
2914
  }
2915
+ requestSessionKey = ((_b = optionalParams.liveChatContext) === null || _b === void 0 ? void 0 : _b.sessionId) || this.getEndedChatSessionKey(chatId);
2735
2916
  _c.label = 1;
2736
2917
  case 1:
2737
2918
  _c.trys.push([1, 3, , 4]);
2738
2919
  if (this.authenticatedUserToken) {
2739
2920
  getChatTranscriptOptionalParams.authenticatedUserToken = this.authenticatedUserToken;
2740
2921
  }
2741
- return [4 /*yield*/, this.OCClient.getChatTranscripts(requestId, chatToken.chatId, chatToken.token, getChatTranscriptOptionalParams)];
2922
+ return [4 /*yield*/, this.withRequestSessionKey(requestSessionKey, function () { return _this.OCClient.getChatTranscripts(requestId, chatToken.chatId, chatToken.token, getChatTranscriptOptionalParams); })];
2742
2923
  case 2:
2743
2924
  transcriptResponse = _c.sent();
2744
- if (this.sessionId) {
2745
- this.OCClient.sessionId = this.sessionId;
2746
- }
2747
2925
  this.scenarioMarker.completeScenario(TelemetryEvent_1.default.GetLiveChatTranscript, {
2748
2926
  RequestId: requestId,
2749
2927
  ChatId: chatId
@@ -2762,6 +2940,30 @@ var OmnichannelChatSDK = /** @class */ (function () {
2762
2940
  });
2763
2941
  });
2764
2942
  };
2943
+ /**
2944
+ * Returns the ended chat's session key when the call targets that chat, or null.
2945
+ */
2946
+ OmnichannelChatSDK.prototype.getEndedChatSessionKey = function (chatId) {
2947
+ var _a;
2948
+ return chatId && ((_a = this.endedChatSessionKey) === null || _a === void 0 ? void 0 : _a.chatId) === chatId ? this.endedChatSessionKey.sessionId : null;
2949
+ };
2950
+ /**
2951
+ * Sends the session key on one OCSDK request without leaving it on the shared client. OCSDK copies the
2952
+ * key into the request headers before its first await, so the previous key is restored before the HTTP wait.
2953
+ */
2954
+ OmnichannelChatSDK.prototype.withRequestSessionKey = function (sessionKey, request) {
2955
+ if (!sessionKey) {
2956
+ return request();
2957
+ }
2958
+ var previousSessionKey = this.OCClient.sessionId;
2959
+ this.OCClient.sessionId = sessionKey;
2960
+ try {
2961
+ return request();
2962
+ }
2963
+ finally {
2964
+ this.OCClient.sessionId = previousSessionKey;
2965
+ }
2966
+ };
2765
2967
  OmnichannelChatSDK.prototype.createChatAdapter = function () {
2766
2968
  return __awaiter(this, arguments, void 0, function (optionalParams) {
2767
2969
  var protocol, supportedChatAdapterProtocols, options, fileManager;