@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.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { useState, useRef, useMemo, useCallback, useEffect } from 'react';
1
+ import { useState, useRef, useCallback, useMemo, useEffect } from 'react';
2
2
 
3
3
  // src/hooks/useChat.ts
4
4
 
@@ -612,6 +612,84 @@ async function cancelUserAction(config, userActionId) {
612
612
  async function resendUserAction(config, userActionId) {
613
613
  return sendUserActionRequest(config, userActionId, "resend");
614
614
  }
615
+
616
+ // src/utils/chatStore.ts
617
+ var memoryStore = /* @__PURE__ */ new Map();
618
+ var chatStore = {
619
+ get(key) {
620
+ return memoryStore.get(key) ?? [];
621
+ },
622
+ set(key, messages) {
623
+ memoryStore.set(key, messages);
624
+ },
625
+ delete(key) {
626
+ memoryStore.delete(key);
627
+ }
628
+ };
629
+
630
+ // src/utils/activeStreamStore.ts
631
+ var streams = /* @__PURE__ */ new Map();
632
+ var activeStreamStore = {
633
+ has(key) {
634
+ return streams.has(key);
635
+ },
636
+ get(key) {
637
+ const entry = streams.get(key);
638
+ if (!entry) return null;
639
+ return { messages: entry.messages, isWaiting: entry.isWaiting };
640
+ },
641
+ // Called before startStream — registers the controller and initial messages
642
+ start(key, abortController, initialMessages) {
643
+ const existing = streams.get(key);
644
+ streams.set(key, {
645
+ messages: initialMessages,
646
+ isWaiting: true,
647
+ abortController,
648
+ listeners: existing?.listeners ?? /* @__PURE__ */ new Set()
649
+ });
650
+ },
651
+ // Called by the stream on every event — applies the same updater pattern React uses
652
+ applyMessages(key, updater) {
653
+ const entry = streams.get(key);
654
+ if (!entry) return;
655
+ const next = typeof updater === "function" ? updater(entry.messages) : updater;
656
+ entry.messages = next;
657
+ entry.listeners.forEach((l) => l(next, entry.isWaiting));
658
+ },
659
+ setWaiting(key, waiting) {
660
+ const entry = streams.get(key);
661
+ if (!entry) return;
662
+ entry.isWaiting = waiting;
663
+ entry.listeners.forEach((l) => l(entry.messages, waiting));
664
+ },
665
+ // Called when stream completes — persists to chatStore and cleans up
666
+ complete(key) {
667
+ const entry = streams.get(key);
668
+ if (!entry) return;
669
+ entry.isWaiting = false;
670
+ entry.listeners.forEach((l) => l(entry.messages, false));
671
+ const toSave = entry.messages.filter((m) => !m.isStreaming);
672
+ if (toSave.length > 0) chatStore.set(key, toSave);
673
+ streams.delete(key);
674
+ },
675
+ // Subscribe — returns unsubscribe fn. Component calls this on mount, cleanup on unmount.
676
+ subscribe(key, listener) {
677
+ const entry = streams.get(key);
678
+ if (!entry) return () => {
679
+ };
680
+ entry.listeners.add(listener);
681
+ return () => {
682
+ streams.get(key)?.listeners.delete(listener);
683
+ };
684
+ },
685
+ // Explicit user cancel — aborts the controller and removes the entry
686
+ abort(key) {
687
+ const entry = streams.get(key);
688
+ if (!entry) return;
689
+ entry.abortController.abort();
690
+ streams.delete(key);
691
+ }
692
+ };
615
693
  function useStreamManager(config, callbacks, setMessages, setIsWaitingForResponse) {
616
694
  const abortControllerRef = useRef(null);
617
695
  const configRef = useRef(config);
@@ -619,9 +697,9 @@ function useStreamManager(config, callbacks, setMessages, setIsWaitingForRespons
619
697
  const callbacksRef = useRef(callbacks);
620
698
  callbacksRef.current = callbacks;
621
699
  const startStream = useCallback(
622
- async (userMessage, streamingId, sessionId) => {
700
+ async (userMessage, streamingId, sessionId, externalAbortController) => {
623
701
  abortControllerRef.current?.abort();
624
- const abortController = new AbortController();
702
+ const abortController = externalAbortController ?? new AbortController();
625
703
  abortControllerRef.current = abortController;
626
704
  const state = {
627
705
  accumulatedContent: "",
@@ -825,13 +903,43 @@ function useStreamManager(config, callbacks, setMessages, setIsWaitingForRespons
825
903
 
826
904
  // src/hooks/useChat.ts
827
905
  function useChat(config, callbacks = {}) {
828
- const [messages, setMessages] = useState([]);
906
+ const [messages, setMessages] = useState(() => {
907
+ if (config.userId) return chatStore.get(config.userId);
908
+ return config.initialMessages ?? [];
909
+ });
829
910
  const [isWaitingForResponse, setIsWaitingForResponse] = useState(false);
830
- const sessionIdRef = useRef(void 0);
911
+ const sessionIdRef = useRef(
912
+ config.userId ? chatStore.get(config.userId).find((m) => m.sessionId)?.sessionId ?? config.initialSessionId ?? void 0 : config.initialSessionId ?? void 0
913
+ );
914
+ const prevUserIdRef = useRef(config.userId);
831
915
  const callbacksRef = useRef(callbacks);
832
916
  callbacksRef.current = callbacks;
833
917
  const configRef = useRef(config);
834
918
  configRef.current = config;
919
+ const messagesRef = useRef(messages);
920
+ messagesRef.current = messages;
921
+ const storeAwareSetMessages = useCallback(
922
+ (updater) => {
923
+ const { userId } = configRef.current;
924
+ if (userId && activeStreamStore.has(userId)) {
925
+ activeStreamStore.applyMessages(userId, updater);
926
+ }
927
+ setMessages(updater);
928
+ },
929
+ // eslint-disable-next-line react-hooks/exhaustive-deps
930
+ []
931
+ );
932
+ const storeAwareSetIsWaiting = useCallback(
933
+ (waiting) => {
934
+ const { userId } = configRef.current;
935
+ if (userId && activeStreamStore.has(userId)) {
936
+ activeStreamStore.setWaiting(userId, waiting);
937
+ }
938
+ setIsWaitingForResponse(waiting);
939
+ },
940
+ // eslint-disable-next-line react-hooks/exhaustive-deps
941
+ []
942
+ );
835
943
  const [userActionState, setUserActionState] = useState({
836
944
  request: null,
837
945
  result: null,
@@ -874,8 +982,8 @@ function useChat(config, callbacks = {}) {
874
982
  const { startStream, cancelStream: cancelStreamManager, abortControllerRef } = useStreamManager(
875
983
  config,
876
984
  wrappedCallbacks,
877
- setMessages,
878
- setIsWaitingForResponse
985
+ storeAwareSetMessages,
986
+ storeAwareSetIsWaiting
879
987
  );
880
988
  const sendMessage = useCallback(
881
989
  async (userMessage) => {
@@ -912,11 +1020,21 @@ function useChat(config, callbacks = {}) {
912
1020
  currentMessage: void 0
913
1021
  };
914
1022
  setMessages((prev) => [...prev, streamingMsg]);
1023
+ const abortController = new AbortController();
1024
+ const { userId } = configRef.current;
1025
+ if (userId) {
1026
+ const initialMessages = [...messagesRef.current, userMsg, streamingMsg];
1027
+ activeStreamStore.start(userId, abortController, initialMessages);
1028
+ }
915
1029
  const newSessionId = await startStream(
916
1030
  userMessage,
917
1031
  streamingId,
918
- sessionIdRef.current
1032
+ sessionIdRef.current,
1033
+ abortController
919
1034
  );
1035
+ if (userId) {
1036
+ activeStreamStore.complete(userId);
1037
+ }
920
1038
  if (newSessionId && newSessionId !== sessionIdRef.current) {
921
1039
  sessionIdRef.current = newSessionId;
922
1040
  }
@@ -924,9 +1042,18 @@ function useChat(config, callbacks = {}) {
924
1042
  [startStream]
925
1043
  );
926
1044
  const clearMessages = useCallback(() => {
1045
+ if (configRef.current.userId) {
1046
+ chatStore.delete(configRef.current.userId);
1047
+ }
927
1048
  setMessages([]);
928
1049
  }, []);
1050
+ const prependMessages = useCallback((msgs) => {
1051
+ setMessages((prev) => [...msgs, ...prev]);
1052
+ }, []);
929
1053
  const cancelStream = useCallback(() => {
1054
+ if (configRef.current.userId) {
1055
+ activeStreamStore.abort(configRef.current.userId);
1056
+ }
930
1057
  cancelStreamManager();
931
1058
  setIsWaitingForResponse(false);
932
1059
  setUserActionState((prev) => ({ ...prev, request: null, result: null }));
@@ -946,6 +1073,10 @@ function useChat(config, callbacks = {}) {
946
1073
  );
947
1074
  }, [cancelStreamManager]);
948
1075
  const resetSession = useCallback(() => {
1076
+ if (configRef.current.userId) {
1077
+ activeStreamStore.abort(configRef.current.userId);
1078
+ chatStore.delete(configRef.current.userId);
1079
+ }
949
1080
  setMessages([]);
950
1081
  sessionIdRef.current = void 0;
951
1082
  abortControllerRef.current?.abort();
@@ -1008,10 +1139,48 @@ function useChat(config, callbacks = {}) {
1008
1139
  throw error;
1009
1140
  }
1010
1141
  }, []);
1142
+ useEffect(() => {
1143
+ const { userId } = config;
1144
+ if (!userId) return;
1145
+ const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting) => {
1146
+ setMessages(msgs);
1147
+ setIsWaitingForResponse(isWaiting);
1148
+ });
1149
+ const active = activeStreamStore.get(userId);
1150
+ if (active) {
1151
+ setMessages(active.messages);
1152
+ setIsWaitingForResponse(active.isWaiting);
1153
+ }
1154
+ return unsubscribe;
1155
+ }, []);
1156
+ useEffect(() => {
1157
+ if (!config.userId) return;
1158
+ const toSave = messages.filter((m) => !m.isStreaming);
1159
+ if (toSave.length > 0) {
1160
+ chatStore.set(config.userId, toSave);
1161
+ }
1162
+ }, [messages, config.userId]);
1163
+ useEffect(() => {
1164
+ const prevUserId = prevUserIdRef.current;
1165
+ prevUserIdRef.current = config.userId;
1166
+ if (prevUserId === config.userId) return;
1167
+ if (prevUserId && !config.userId) {
1168
+ chatStore.delete(prevUserId);
1169
+ setMessages([]);
1170
+ sessionIdRef.current = void 0;
1171
+ setIsWaitingForResponse(false);
1172
+ setUserActionState({ request: null, result: null, clearOtpTrigger: 0 });
1173
+ } else if (config.userId) {
1174
+ const stored = chatStore.get(config.userId);
1175
+ setMessages(stored);
1176
+ sessionIdRef.current = stored.find((m) => m.sessionId)?.sessionId;
1177
+ }
1178
+ }, [config.userId]);
1011
1179
  return {
1012
1180
  messages,
1013
1181
  sendMessage,
1014
1182
  clearMessages,
1183
+ prependMessages,
1015
1184
  cancelStream,
1016
1185
  resetSession,
1017
1186
  getSessionId,