@microsoft/omnichannel-chat-sdk 1.11.9-main.b0a2bb8 → 1.11.9-main.c03be93
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 +214 -0
- package/lib/OmnichannelChatSDK.d.ts +22 -0
- package/lib/OmnichannelChatSDK.js +330 -89
- package/lib/OmnichannelChatSDK.js.map +1 -1
- package/lib/core/ChatSDKError.d.ts +9 -1
- package/lib/core/ChatSDKError.js +8 -0
- package/lib/core/ChatSDKError.js.map +1 -1
- package/lib/core/ChatSDKExceptionDetails.d.ts +6 -0
- package/lib/core/StartChatOptionalParams.d.ts +1 -0
- package/lib/core/messaging/ACSClient.d.ts +1 -0
- package/lib/core/messaging/ACSClient.js +32 -0
- package/lib/core/messaging/ACSClient.js.map +1 -1
- package/lib/telemetry/TelemetryEvent.d.ts +4 -1
- package/lib/telemetry/TelemetryEvent.js +3 -0
- package/lib/telemetry/TelemetryEvent.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/utils/createOmnichannelMessage.js +18 -0
- package/lib/utils/createOmnichannelMessage.js.map +1 -1
- package/lib/utils/errorClassifier.d.ts +25 -0
- package/lib/utils/errorClassifier.js +75 -0
- package/lib/utils/errorClassifier.js.map +1 -0
- package/lib/utils/exceptionThrowers.d.ts +38 -4
- package/lib/utils/exceptionThrowers.js +25 -8
- package/lib/utils/exceptionThrowers.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -44,6 +44,7 @@ Please make sure you have a chat widget configured before using this package or
|
|
|
44
44
|
- [Create Chat Adapter](#create-chat-adapter)
|
|
45
45
|
- [Get Voice & Video Calling](#get-voice--video-calling)
|
|
46
46
|
- [Get Post Chat Survey Context](#get-post-chat-survey-context)
|
|
47
|
+
- [Get Persistent Chat History](#get-persistent-chat-history)
|
|
47
48
|
- [Common Scenarios](#common-scenarios)
|
|
48
49
|
- [Using BotFramework-WebChat](#using-botframework-webchat)
|
|
49
50
|
- [Escalation to Voice & Video](#escalation-to-voice--video)
|
|
@@ -52,6 +53,7 @@ Please make sure you have a chat widget configured before using this package or
|
|
|
52
53
|
- [Reconnect to existing Chat](#reconnect-to-existing-chat)
|
|
53
54
|
- [Authenticated Chat](#authenticated-chat)
|
|
54
55
|
- [Persistent Chat](#persistent-chat)
|
|
56
|
+
- [Persistent Chat History](#persistent-chat-history)
|
|
55
57
|
- [Chat Reconnect with Authenticated User](#chat-reconnect-with-authenticated-user)
|
|
56
58
|
- [Chat Reconnect with Unauthenticated User](#chat-reconnect-with-unauthenticated-user)
|
|
57
59
|
- [Best Practices for Chat Session Management: Handling Disconnections and Network Instabilit(#best-practices-for-chat-session-management:-handling-disconnections-and-network-instability)
|
|
@@ -579,6 +581,24 @@ It gets the participant type that should be used for the survey and both the def
|
|
|
579
581
|
const postChatSurveyContext = await chatSDK.getPostChatSurveyContext();
|
|
580
582
|
```
|
|
581
583
|
|
|
584
|
+
### Get Persistent Chat History
|
|
585
|
+
|
|
586
|
+
It fetches paginated chat history from previous persistent chat conversations for authenticated users. Returns messages in chronological order along with a pagination token to fetch the next page.
|
|
587
|
+
|
|
588
|
+
> :warning: Requires **persistent chat** to be enabled and the user must be **authenticated**.
|
|
589
|
+
|
|
590
|
+
```ts
|
|
591
|
+
const optionalParams = {
|
|
592
|
+
pageSize: 25, // Number of messages per page (optional)
|
|
593
|
+
pageToken: '' // Token from a previous response to fetch the next page (optional, omit for first call)
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
const response = await chatSDK.getPersistentChatHistory(optionalParams);
|
|
597
|
+
|
|
598
|
+
// response.chatMessages: PersistentChatHistoryMessage[] — Array of chat messages
|
|
599
|
+
// response.nextPageToken: string | null — Token to pass in the next call; null means no more history
|
|
600
|
+
```
|
|
601
|
+
|
|
582
602
|
### Get Agent Availability
|
|
583
603
|
|
|
584
604
|
It gets information on whether a queue is available, and whether there are agents available in that queue, as well as queue position and average wait time. This call only supports authenticated chat.
|
|
@@ -735,6 +755,200 @@ await chatSDK.initialize();
|
|
|
735
755
|
// from this point, this acts like a persistent chat
|
|
736
756
|
```
|
|
737
757
|
|
|
758
|
+
### Persistent Chat History
|
|
759
|
+
|
|
760
|
+
> See <https://docs.microsoft.com/en-us/dynamics365/customer-service/persistent-chat> on how to set up persistent chat
|
|
761
|
+
|
|
762
|
+
When persistent chat is enabled, you can retrieve the chat history from previous conversations using `getPersistentChatHistory()`. This method returns paginated results, allowing you to load history incrementally (e.g., as the user scrolls up).
|
|
763
|
+
|
|
764
|
+
> :warning: **Prerequisites:**
|
|
765
|
+
> - Persistent chat must be **enabled** in the admin portal (conversation mode set to Persistent Chat) and in the SDK config (`persistentChat.disable: false`)
|
|
766
|
+
> - The user must be **authenticated** (`getAuthToken` must be configured)
|
|
767
|
+
> - `chatSDK.initialize()` and `chatSDK.startChat()` must be called before fetching history
|
|
768
|
+
> - Chat history is available for up to **12 months**
|
|
769
|
+
|
|
770
|
+
#### Page Size
|
|
771
|
+
|
|
772
|
+
The `pageSize` parameter controls how many messages are returned per call.
|
|
773
|
+
|
|
774
|
+
| | Value |
|
|
775
|
+
| --- | --- |
|
|
776
|
+
| **Default** | `50` (used when `pageSize` is omitted) |
|
|
777
|
+
| **Minimum** | `1` |
|
|
778
|
+
| **Maximum** | `100` |
|
|
779
|
+
|
|
780
|
+
If `pageSize` is not provided, the backend defaults to **50**. Values outside the 1–100 range will be rejected with an error.
|
|
781
|
+
|
|
782
|
+
#### How Pagination Works
|
|
783
|
+
|
|
784
|
+
| Call | `pageToken` param | What happens |
|
|
785
|
+
| --- | --- | --- |
|
|
786
|
+
| **First call** | Omit or `undefined` | Fetches the most recent page of messages. The response includes `nextPageToken` if older messages exist. |
|
|
787
|
+
| **Subsequent calls** | Pass the `nextPageToken` from the previous response | Fetches the next (older) page. Again returns `nextPageToken` if more messages remain. |
|
|
788
|
+
| **Last page** | Pass the `nextPageToken` from the previous response | Returns the remaining messages. `nextPageToken` is `null`, indicating there are no more messages in the history. |
|
|
789
|
+
|
|
790
|
+
In short: keep passing the `nextPageToken` from each response into the next call until the backend returns `nextPageToken: null` — that signals the entire history has been retrieved.
|
|
791
|
+
|
|
792
|
+
#### Basic Usage
|
|
793
|
+
|
|
794
|
+
```ts
|
|
795
|
+
const chatSDKConfig = {
|
|
796
|
+
persistentChat: {
|
|
797
|
+
disable: false,
|
|
798
|
+
tokenUpdateTime: 21600000
|
|
799
|
+
},
|
|
800
|
+
getAuthToken: async () => {
|
|
801
|
+
const response = await fetch("http://contosohelp.com/token");
|
|
802
|
+
if (response.ok) {
|
|
803
|
+
return await response.text();
|
|
804
|
+
}
|
|
805
|
+
else {
|
|
806
|
+
return null
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
|
|
812
|
+
await chatSDK.initialize();
|
|
813
|
+
|
|
814
|
+
await chatSDK.startChat();
|
|
815
|
+
|
|
816
|
+
// Fetch the first page of chat history
|
|
817
|
+
const history = await chatSDK.getPersistentChatHistory({
|
|
818
|
+
pageSize: 25
|
|
819
|
+
});
|
|
820
|
+
|
|
821
|
+
if (history) {
|
|
822
|
+
// Render messages
|
|
823
|
+
history.chatMessages.forEach((message) => {
|
|
824
|
+
console.log(`[${message.createdDateTime}] ${message.content}`);
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
// Check if more history is available
|
|
828
|
+
if (history.nextPageToken) {
|
|
829
|
+
console.log("More history available");
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
```
|
|
833
|
+
|
|
834
|
+
#### Pagination — Loading More History on Scroll Up
|
|
835
|
+
|
|
836
|
+
After the first call returns a `nextPageToken`, you can fetch older pages on demand — for example, each time the customer scrolls up in the chat window. The loop below shows fetching all remaining history, but in practice you would call `getPersistentChatHistory` once per scroll-up action, passing the `nextPageToken` from the previous response.
|
|
837
|
+
|
|
838
|
+
```ts
|
|
839
|
+
// After the first call (Basic Usage above), save the nextPageToken
|
|
840
|
+
let pageToken: string | undefined = history?.nextPageToken ?? undefined;
|
|
841
|
+
|
|
842
|
+
// Example: fetch the next page when the customer scrolls up
|
|
843
|
+
const loadMoreHistory = async () => {
|
|
844
|
+
if (!pageToken) {
|
|
845
|
+
console.log("No more history to load");
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
const response = await chatSDK.getPersistentChatHistory({
|
|
850
|
+
pageSize: 25,
|
|
851
|
+
pageToken
|
|
852
|
+
});
|
|
853
|
+
|
|
854
|
+
if (response && response.chatMessages.length > 0) {
|
|
855
|
+
// Render the older messages in the chat UI
|
|
856
|
+
response.chatMessages.forEach((message) => {
|
|
857
|
+
console.log(`[${message.createdDateTime}] ${message.content}`);
|
|
858
|
+
});
|
|
859
|
+
|
|
860
|
+
// Update the token for the next scroll-up action
|
|
861
|
+
pageToken = response.nextPageToken ?? undefined;
|
|
862
|
+
}
|
|
863
|
+
};
|
|
864
|
+
|
|
865
|
+
// Bind to your scroll-up event (e.g., user reaches the top of the chat container)
|
|
866
|
+
chatContainer.addEventListener('scroll', () => {
|
|
867
|
+
if (chatContainer.scrollTop === 0) {
|
|
868
|
+
loadMoreHistory();
|
|
869
|
+
}
|
|
870
|
+
});
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
Alternatively, to fetch all history at once in a loop:
|
|
874
|
+
|
|
875
|
+
```ts
|
|
876
|
+
let token: string | undefined = history?.nextPageToken ?? undefined;
|
|
877
|
+
let allMessages = [...(history?.chatMessages ?? [])];
|
|
878
|
+
|
|
879
|
+
while (token) {
|
|
880
|
+
const response = await chatSDK.getPersistentChatHistory({
|
|
881
|
+
pageSize: 25,
|
|
882
|
+
pageToken: token
|
|
883
|
+
});
|
|
884
|
+
|
|
885
|
+
if (response && response.chatMessages.length > 0) {
|
|
886
|
+
allMessages = [...allMessages, ...response.chatMessages];
|
|
887
|
+
token = response.nextPageToken ?? undefined;
|
|
888
|
+
} else {
|
|
889
|
+
break;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
console.log(`Total messages retrieved: ${allMessages.length}`);
|
|
894
|
+
```
|
|
895
|
+
|
|
896
|
+
#### Response Shape
|
|
897
|
+
|
|
898
|
+
The response type is exported from the SDK and can be imported for TypeScript usage:
|
|
899
|
+
|
|
900
|
+
```ts
|
|
901
|
+
import { GetPersistentChatHistoryResponse } from '@microsoft/omnichannel-chat-sdk';
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
```ts
|
|
905
|
+
type GetPersistentChatHistoryResponse = {
|
|
906
|
+
chatMessages: PersistentChatHistoryMessage[];
|
|
907
|
+
nextPageToken: string | null; // null when no more pages
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
type PersistentChatHistoryMessage = {
|
|
911
|
+
content: string; // Message text
|
|
912
|
+
contentType: number; // Content type identifier
|
|
913
|
+
createdDateTime: string; // ISO 8601 timestamp
|
|
914
|
+
from: {
|
|
915
|
+
application: { // Sender application info
|
|
916
|
+
displayName: string; // e.g., agent name or bot name
|
|
917
|
+
id: string;
|
|
918
|
+
} | null;
|
|
919
|
+
};
|
|
920
|
+
id: string; // Unique message identifier
|
|
921
|
+
attachments: unknown[]; // File attachments if any
|
|
922
|
+
additionalData: {
|
|
923
|
+
deliveryMode: string; // Delivery channel
|
|
924
|
+
ConversationId: string; // Conversation the message belongs to
|
|
925
|
+
tags: string; // Message tags
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
```
|
|
929
|
+
|
|
930
|
+
#### Error Handling
|
|
931
|
+
|
|
932
|
+
```ts
|
|
933
|
+
try {
|
|
934
|
+
const history = await chatSDK.getPersistentChatHistory({ pageSize: 25 });
|
|
935
|
+
// Process messages...
|
|
936
|
+
} catch (error) {
|
|
937
|
+
if (error.message === 'ChatSDKNotInitialized') {
|
|
938
|
+
// SDK not initialized — call chatSDK.initialize() first
|
|
939
|
+
}
|
|
940
|
+
if (error.message === 'PersistentChatNotEnabled') {
|
|
941
|
+
// Persistent chat is not enabled for this widget
|
|
942
|
+
}
|
|
943
|
+
if (error.message === 'AuthenticatedUserTokenNotFound') {
|
|
944
|
+
// User is not authenticated — configure getAuthToken
|
|
945
|
+
}
|
|
946
|
+
if (error.message === 'PersistentChatConversationRetrievalFailure') {
|
|
947
|
+
// Server error fetching history — retry or handle gracefully
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
```
|
|
951
|
+
|
|
738
952
|
### Chat Reconnect with Authenticated User
|
|
739
953
|
|
|
740
954
|
> See <https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-reconnect-chat?tabs=customerserviceadmincenter#enable-reconnection-to-a-previous-chat-session> on how to set up chat reconnect
|
|
@@ -50,6 +50,7 @@ declare class OmnichannelChatSDK {
|
|
|
50
50
|
sessionId: string | null;
|
|
51
51
|
private chatOperationInProgress;
|
|
52
52
|
private pendingOperations;
|
|
53
|
+
private deferInitialAuth;
|
|
53
54
|
private unqServicesOrgUrl;
|
|
54
55
|
private coreServicesOrgUrl;
|
|
55
56
|
private dynamicsLocationCode;
|
|
@@ -170,6 +171,17 @@ declare class OmnichannelChatSDK {
|
|
|
170
171
|
sendMessage(message: ChatSDKMessage): Promise<OmnichannelMessage | void>;
|
|
171
172
|
onNewMessage(onNewMessageCallback: CallableFunction, optionalParams?: OnNewMessageOptionalParams): Promise<void>;
|
|
172
173
|
sendTypingEvent(): Promise<void>;
|
|
174
|
+
/**
|
|
175
|
+
* Fetches unread message count for the authenticated user.
|
|
176
|
+
* Auth-only — does not require an active chat session.
|
|
177
|
+
*/
|
|
178
|
+
getUnreadMessageCount(): Promise<object>;
|
|
179
|
+
/**
|
|
180
|
+
* Sends a read receipt for a specific message.
|
|
181
|
+
* Authenticated: calls MRT (updates NRD + forwards to ACS).
|
|
182
|
+
* Unauthenticated: calls ACS directly.
|
|
183
|
+
*/
|
|
184
|
+
sendReadReceipt(messageId: string): Promise<void>;
|
|
173
185
|
onTypingEvent(onTypingEventCallback: CallableFunction): Promise<void>;
|
|
174
186
|
onAgentEndSession(onAgentEndSessionCallback: (message: IRawThread | ParticipantsRemovedEvent) => void): Promise<void>;
|
|
175
187
|
uploadFileAttachment(fileInfo: IFileInfo | File): Promise<UploadFileAttachmentResponse>;
|
|
@@ -181,6 +193,9 @@ declare class OmnichannelChatSDK {
|
|
|
181
193
|
getVoiceVideoCalling(voiceVideoCallingOptionalParams?: VoiceVideoCallingOptionalParams): Promise<GetVoiceVideoCallingResponse>;
|
|
182
194
|
getPostChatSurveyContext(): Promise<PostChatContext>;
|
|
183
195
|
getAgentAvailability(optionalParams?: GetAgentAvailabilityOptionalParams): Promise<GetAgentAvailabilityResponse>;
|
|
196
|
+
authenticateChat(tokenOrProvider: string | (() => Promise<string>), optionalParams?: {
|
|
197
|
+
refreshChatToken?: boolean;
|
|
198
|
+
}): Promise<void>;
|
|
184
199
|
startPolling(): Promise<void>;
|
|
185
200
|
stopPolling(): Promise<void>;
|
|
186
201
|
private populateInitChatOptionalParam;
|
|
@@ -194,6 +209,13 @@ declare class OmnichannelChatSDK {
|
|
|
194
209
|
private setCallingOptionConfiguration;
|
|
195
210
|
private setLiveChatVersionConfiguration;
|
|
196
211
|
private setWidgetSnippetBaseUrl;
|
|
212
|
+
/**
|
|
213
|
+
* Creates diagnostic data for getChatConfig errors using the error classifier
|
|
214
|
+
* @param e The error object
|
|
215
|
+
* @param clientElapsedMs Optional elapsed time in milliseconds from client's perspective
|
|
216
|
+
* @returns Diagnostic data with clientElapsedMs, online status, and cancellation reason
|
|
217
|
+
*/
|
|
218
|
+
private createGetChatConfigDiagnosticData;
|
|
197
219
|
private getChatConfig;
|
|
198
220
|
private buildConfigurations;
|
|
199
221
|
private resolveIC3ClientUrl;
|