@paymanai/payman-typescript-ask-sdk 1.2.4 → 1.2.5
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/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +176 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +177 -8
- package/dist/index.mjs.map +1 -1
- package/dist/index.native.js +181 -7
- package/dist/index.native.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -144,6 +144,8 @@ type ChatConfig = {
|
|
|
144
144
|
api: APIConfig;
|
|
145
145
|
/** Workflow name */
|
|
146
146
|
workflowName: string;
|
|
147
|
+
/** User ID for chatStore and activeStreamStore — required for context store messages management. Set to undefined on logout to clear stored messages. */
|
|
148
|
+
userId?: string;
|
|
147
149
|
/** Workflow version */
|
|
148
150
|
workflowVersion?: number;
|
|
149
151
|
/** Stage/Environment */
|
|
@@ -194,6 +196,10 @@ type ChatConfig = {
|
|
|
194
196
|
isChatDisabled?: boolean;
|
|
195
197
|
/** Custom component to render when chat is disabled. If not provided, default disabled UI will be shown */
|
|
196
198
|
disabledComponent?: React.ReactNode;
|
|
199
|
+
/** Pre-populate the chat with messages (e.g. loaded conversation history) */
|
|
200
|
+
initialMessages?: MessageDisplay[];
|
|
201
|
+
/** Resume an existing session by providing its ID */
|
|
202
|
+
initialSessionId?: string;
|
|
197
203
|
};
|
|
198
204
|
type ChatCallbacks = {
|
|
199
205
|
/** Called when a message is sent (before API call) */
|
|
@@ -222,6 +228,8 @@ type UseChatReturn = {
|
|
|
222
228
|
messages: MessageDisplay[];
|
|
223
229
|
sendMessage: (userMessage: string) => Promise<void>;
|
|
224
230
|
clearMessages: () => void;
|
|
231
|
+
/** Prepend older messages to the top of the list (e.g. loaded from history pagination) */
|
|
232
|
+
prependMessages: (messages: MessageDisplay[]) => void;
|
|
225
233
|
cancelStream: () => void;
|
|
226
234
|
resetSession: () => void;
|
|
227
235
|
getSessionId: () => string | undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -144,6 +144,8 @@ type ChatConfig = {
|
|
|
144
144
|
api: APIConfig;
|
|
145
145
|
/** Workflow name */
|
|
146
146
|
workflowName: string;
|
|
147
|
+
/** User ID for chatStore and activeStreamStore — required for context store messages management. Set to undefined on logout to clear stored messages. */
|
|
148
|
+
userId?: string;
|
|
147
149
|
/** Workflow version */
|
|
148
150
|
workflowVersion?: number;
|
|
149
151
|
/** Stage/Environment */
|
|
@@ -194,6 +196,10 @@ type ChatConfig = {
|
|
|
194
196
|
isChatDisabled?: boolean;
|
|
195
197
|
/** Custom component to render when chat is disabled. If not provided, default disabled UI will be shown */
|
|
196
198
|
disabledComponent?: React.ReactNode;
|
|
199
|
+
/** Pre-populate the chat with messages (e.g. loaded conversation history) */
|
|
200
|
+
initialMessages?: MessageDisplay[];
|
|
201
|
+
/** Resume an existing session by providing its ID */
|
|
202
|
+
initialSessionId?: string;
|
|
197
203
|
};
|
|
198
204
|
type ChatCallbacks = {
|
|
199
205
|
/** Called when a message is sent (before API call) */
|
|
@@ -222,6 +228,8 @@ type UseChatReturn = {
|
|
|
222
228
|
messages: MessageDisplay[];
|
|
223
229
|
sendMessage: (userMessage: string) => Promise<void>;
|
|
224
230
|
clearMessages: () => void;
|
|
231
|
+
/** Prepend older messages to the top of the list (e.g. loaded from history pagination) */
|
|
232
|
+
prependMessages: (messages: MessageDisplay[]) => void;
|
|
225
233
|
cancelStream: () => void;
|
|
226
234
|
resetSession: () => void;
|
|
227
235
|
getSessionId: () => string | undefined;
|
package/dist/index.js
CHANGED
|
@@ -614,6 +614,84 @@ async function cancelUserAction(config, userActionId) {
|
|
|
614
614
|
async function resendUserAction(config, userActionId) {
|
|
615
615
|
return sendUserActionRequest(config, userActionId, "resend");
|
|
616
616
|
}
|
|
617
|
+
|
|
618
|
+
// src/utils/chatStore.ts
|
|
619
|
+
var memoryStore = /* @__PURE__ */ new Map();
|
|
620
|
+
var chatStore = {
|
|
621
|
+
get(key) {
|
|
622
|
+
return memoryStore.get(key) ?? [];
|
|
623
|
+
},
|
|
624
|
+
set(key, messages) {
|
|
625
|
+
memoryStore.set(key, messages);
|
|
626
|
+
},
|
|
627
|
+
delete(key) {
|
|
628
|
+
memoryStore.delete(key);
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
|
|
632
|
+
// src/utils/activeStreamStore.ts
|
|
633
|
+
var streams = /* @__PURE__ */ new Map();
|
|
634
|
+
var activeStreamStore = {
|
|
635
|
+
has(key) {
|
|
636
|
+
return streams.has(key);
|
|
637
|
+
},
|
|
638
|
+
get(key) {
|
|
639
|
+
const entry = streams.get(key);
|
|
640
|
+
if (!entry) return null;
|
|
641
|
+
return { messages: entry.messages, isWaiting: entry.isWaiting };
|
|
642
|
+
},
|
|
643
|
+
// Called before startStream — registers the controller and initial messages
|
|
644
|
+
start(key, abortController, initialMessages) {
|
|
645
|
+
const existing = streams.get(key);
|
|
646
|
+
streams.set(key, {
|
|
647
|
+
messages: initialMessages,
|
|
648
|
+
isWaiting: true,
|
|
649
|
+
abortController,
|
|
650
|
+
listeners: existing?.listeners ?? /* @__PURE__ */ new Set()
|
|
651
|
+
});
|
|
652
|
+
},
|
|
653
|
+
// Called by the stream on every event — applies the same updater pattern React uses
|
|
654
|
+
applyMessages(key, updater) {
|
|
655
|
+
const entry = streams.get(key);
|
|
656
|
+
if (!entry) return;
|
|
657
|
+
const next = typeof updater === "function" ? updater(entry.messages) : updater;
|
|
658
|
+
entry.messages = next;
|
|
659
|
+
entry.listeners.forEach((l) => l(next, entry.isWaiting));
|
|
660
|
+
},
|
|
661
|
+
setWaiting(key, waiting) {
|
|
662
|
+
const entry = streams.get(key);
|
|
663
|
+
if (!entry) return;
|
|
664
|
+
entry.isWaiting = waiting;
|
|
665
|
+
entry.listeners.forEach((l) => l(entry.messages, waiting));
|
|
666
|
+
},
|
|
667
|
+
// Called when stream completes — persists to chatStore and cleans up
|
|
668
|
+
complete(key) {
|
|
669
|
+
const entry = streams.get(key);
|
|
670
|
+
if (!entry) return;
|
|
671
|
+
entry.isWaiting = false;
|
|
672
|
+
entry.listeners.forEach((l) => l(entry.messages, false));
|
|
673
|
+
const toSave = entry.messages.filter((m) => !m.isStreaming);
|
|
674
|
+
if (toSave.length > 0) chatStore.set(key, toSave);
|
|
675
|
+
streams.delete(key);
|
|
676
|
+
},
|
|
677
|
+
// Subscribe — returns unsubscribe fn. Component calls this on mount, cleanup on unmount.
|
|
678
|
+
subscribe(key, listener) {
|
|
679
|
+
const entry = streams.get(key);
|
|
680
|
+
if (!entry) return () => {
|
|
681
|
+
};
|
|
682
|
+
entry.listeners.add(listener);
|
|
683
|
+
return () => {
|
|
684
|
+
streams.get(key)?.listeners.delete(listener);
|
|
685
|
+
};
|
|
686
|
+
},
|
|
687
|
+
// Explicit user cancel — aborts the controller and removes the entry
|
|
688
|
+
abort(key) {
|
|
689
|
+
const entry = streams.get(key);
|
|
690
|
+
if (!entry) return;
|
|
691
|
+
entry.abortController.abort();
|
|
692
|
+
streams.delete(key);
|
|
693
|
+
}
|
|
694
|
+
};
|
|
617
695
|
function useStreamManager(config, callbacks, setMessages, setIsWaitingForResponse) {
|
|
618
696
|
const abortControllerRef = react.useRef(null);
|
|
619
697
|
const configRef = react.useRef(config);
|
|
@@ -621,9 +699,9 @@ function useStreamManager(config, callbacks, setMessages, setIsWaitingForRespons
|
|
|
621
699
|
const callbacksRef = react.useRef(callbacks);
|
|
622
700
|
callbacksRef.current = callbacks;
|
|
623
701
|
const startStream = react.useCallback(
|
|
624
|
-
async (userMessage, streamingId, sessionId) => {
|
|
702
|
+
async (userMessage, streamingId, sessionId, externalAbortController) => {
|
|
625
703
|
abortControllerRef.current?.abort();
|
|
626
|
-
const abortController = new AbortController();
|
|
704
|
+
const abortController = externalAbortController ?? new AbortController();
|
|
627
705
|
abortControllerRef.current = abortController;
|
|
628
706
|
const state = {
|
|
629
707
|
accumulatedContent: "",
|
|
@@ -827,13 +905,43 @@ function useStreamManager(config, callbacks, setMessages, setIsWaitingForRespons
|
|
|
827
905
|
|
|
828
906
|
// src/hooks/useChat.ts
|
|
829
907
|
function useChat(config, callbacks = {}) {
|
|
830
|
-
const [messages, setMessages] = react.useState(
|
|
908
|
+
const [messages, setMessages] = react.useState(() => {
|
|
909
|
+
if (config.userId) return chatStore.get(config.userId);
|
|
910
|
+
return config.initialMessages ?? [];
|
|
911
|
+
});
|
|
831
912
|
const [isWaitingForResponse, setIsWaitingForResponse] = react.useState(false);
|
|
832
|
-
const sessionIdRef = react.useRef(
|
|
913
|
+
const sessionIdRef = react.useRef(
|
|
914
|
+
config.userId ? chatStore.get(config.userId).find((m) => m.sessionId)?.sessionId ?? config.initialSessionId ?? void 0 : config.initialSessionId ?? void 0
|
|
915
|
+
);
|
|
916
|
+
const prevUserIdRef = react.useRef(config.userId);
|
|
833
917
|
const callbacksRef = react.useRef(callbacks);
|
|
834
918
|
callbacksRef.current = callbacks;
|
|
835
919
|
const configRef = react.useRef(config);
|
|
836
920
|
configRef.current = config;
|
|
921
|
+
const messagesRef = react.useRef(messages);
|
|
922
|
+
messagesRef.current = messages;
|
|
923
|
+
const storeAwareSetMessages = react.useCallback(
|
|
924
|
+
(updater) => {
|
|
925
|
+
const { userId } = configRef.current;
|
|
926
|
+
if (userId && activeStreamStore.has(userId)) {
|
|
927
|
+
activeStreamStore.applyMessages(userId, updater);
|
|
928
|
+
}
|
|
929
|
+
setMessages(updater);
|
|
930
|
+
},
|
|
931
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
932
|
+
[]
|
|
933
|
+
);
|
|
934
|
+
const storeAwareSetIsWaiting = react.useCallback(
|
|
935
|
+
(waiting) => {
|
|
936
|
+
const { userId } = configRef.current;
|
|
937
|
+
if (userId && activeStreamStore.has(userId)) {
|
|
938
|
+
activeStreamStore.setWaiting(userId, waiting);
|
|
939
|
+
}
|
|
940
|
+
setIsWaitingForResponse(waiting);
|
|
941
|
+
},
|
|
942
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
943
|
+
[]
|
|
944
|
+
);
|
|
837
945
|
const [userActionState, setUserActionState] = react.useState({
|
|
838
946
|
request: null,
|
|
839
947
|
result: null,
|
|
@@ -876,8 +984,8 @@ function useChat(config, callbacks = {}) {
|
|
|
876
984
|
const { startStream, cancelStream: cancelStreamManager, abortControllerRef } = useStreamManager(
|
|
877
985
|
config,
|
|
878
986
|
wrappedCallbacks,
|
|
879
|
-
|
|
880
|
-
|
|
987
|
+
storeAwareSetMessages,
|
|
988
|
+
storeAwareSetIsWaiting
|
|
881
989
|
);
|
|
882
990
|
const sendMessage = react.useCallback(
|
|
883
991
|
async (userMessage) => {
|
|
@@ -914,11 +1022,21 @@ function useChat(config, callbacks = {}) {
|
|
|
914
1022
|
currentMessage: void 0
|
|
915
1023
|
};
|
|
916
1024
|
setMessages((prev) => [...prev, streamingMsg]);
|
|
1025
|
+
const abortController = new AbortController();
|
|
1026
|
+
const { userId } = configRef.current;
|
|
1027
|
+
if (userId) {
|
|
1028
|
+
const initialMessages = [...messagesRef.current, userMsg, streamingMsg];
|
|
1029
|
+
activeStreamStore.start(userId, abortController, initialMessages);
|
|
1030
|
+
}
|
|
917
1031
|
const newSessionId = await startStream(
|
|
918
1032
|
userMessage,
|
|
919
1033
|
streamingId,
|
|
920
|
-
sessionIdRef.current
|
|
1034
|
+
sessionIdRef.current,
|
|
1035
|
+
abortController
|
|
921
1036
|
);
|
|
1037
|
+
if (userId) {
|
|
1038
|
+
activeStreamStore.complete(userId);
|
|
1039
|
+
}
|
|
922
1040
|
if (newSessionId && newSessionId !== sessionIdRef.current) {
|
|
923
1041
|
sessionIdRef.current = newSessionId;
|
|
924
1042
|
}
|
|
@@ -926,9 +1044,18 @@ function useChat(config, callbacks = {}) {
|
|
|
926
1044
|
[startStream]
|
|
927
1045
|
);
|
|
928
1046
|
const clearMessages = react.useCallback(() => {
|
|
1047
|
+
if (configRef.current.userId) {
|
|
1048
|
+
chatStore.delete(configRef.current.userId);
|
|
1049
|
+
}
|
|
929
1050
|
setMessages([]);
|
|
930
1051
|
}, []);
|
|
1052
|
+
const prependMessages = react.useCallback((msgs) => {
|
|
1053
|
+
setMessages((prev) => [...msgs, ...prev]);
|
|
1054
|
+
}, []);
|
|
931
1055
|
const cancelStream = react.useCallback(() => {
|
|
1056
|
+
if (configRef.current.userId) {
|
|
1057
|
+
activeStreamStore.abort(configRef.current.userId);
|
|
1058
|
+
}
|
|
932
1059
|
cancelStreamManager();
|
|
933
1060
|
setIsWaitingForResponse(false);
|
|
934
1061
|
setUserActionState((prev) => ({ ...prev, request: null, result: null }));
|
|
@@ -948,6 +1075,10 @@ function useChat(config, callbacks = {}) {
|
|
|
948
1075
|
);
|
|
949
1076
|
}, [cancelStreamManager]);
|
|
950
1077
|
const resetSession = react.useCallback(() => {
|
|
1078
|
+
if (configRef.current.userId) {
|
|
1079
|
+
activeStreamStore.abort(configRef.current.userId);
|
|
1080
|
+
chatStore.delete(configRef.current.userId);
|
|
1081
|
+
}
|
|
951
1082
|
setMessages([]);
|
|
952
1083
|
sessionIdRef.current = void 0;
|
|
953
1084
|
abortControllerRef.current?.abort();
|
|
@@ -1010,10 +1141,48 @@ function useChat(config, callbacks = {}) {
|
|
|
1010
1141
|
throw error;
|
|
1011
1142
|
}
|
|
1012
1143
|
}, []);
|
|
1144
|
+
react.useEffect(() => {
|
|
1145
|
+
const { userId } = config;
|
|
1146
|
+
if (!userId) return;
|
|
1147
|
+
const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting) => {
|
|
1148
|
+
setMessages(msgs);
|
|
1149
|
+
setIsWaitingForResponse(isWaiting);
|
|
1150
|
+
});
|
|
1151
|
+
const active = activeStreamStore.get(userId);
|
|
1152
|
+
if (active) {
|
|
1153
|
+
setMessages(active.messages);
|
|
1154
|
+
setIsWaitingForResponse(active.isWaiting);
|
|
1155
|
+
}
|
|
1156
|
+
return unsubscribe;
|
|
1157
|
+
}, []);
|
|
1158
|
+
react.useEffect(() => {
|
|
1159
|
+
if (!config.userId) return;
|
|
1160
|
+
const toSave = messages.filter((m) => !m.isStreaming);
|
|
1161
|
+
if (toSave.length > 0) {
|
|
1162
|
+
chatStore.set(config.userId, toSave);
|
|
1163
|
+
}
|
|
1164
|
+
}, [messages, config.userId]);
|
|
1165
|
+
react.useEffect(() => {
|
|
1166
|
+
const prevUserId = prevUserIdRef.current;
|
|
1167
|
+
prevUserIdRef.current = config.userId;
|
|
1168
|
+
if (prevUserId === config.userId) return;
|
|
1169
|
+
if (prevUserId && !config.userId) {
|
|
1170
|
+
chatStore.delete(prevUserId);
|
|
1171
|
+
setMessages([]);
|
|
1172
|
+
sessionIdRef.current = void 0;
|
|
1173
|
+
setIsWaitingForResponse(false);
|
|
1174
|
+
setUserActionState({ request: null, result: null, clearOtpTrigger: 0 });
|
|
1175
|
+
} else if (config.userId) {
|
|
1176
|
+
const stored = chatStore.get(config.userId);
|
|
1177
|
+
setMessages(stored);
|
|
1178
|
+
sessionIdRef.current = stored.find((m) => m.sessionId)?.sessionId;
|
|
1179
|
+
}
|
|
1180
|
+
}, [config.userId]);
|
|
1013
1181
|
return {
|
|
1014
1182
|
messages,
|
|
1015
1183
|
sendMessage,
|
|
1016
1184
|
clearMessages,
|
|
1185
|
+
prependMessages,
|
|
1017
1186
|
cancelStream,
|
|
1018
1187
|
resetSession,
|
|
1019
1188
|
getSessionId,
|