@paymanai/payman-typescript-ask-sdk 1.2.4 → 1.2.6
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 +186 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +187 -8
- package/dist/index.mjs.map +1 -1
- package/dist/index.native.js +191 -7
- package/dist/index.native.js.map +1 -1
- package/package.json +1 -1
package/dist/index.native.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var react = require('react');
|
|
4
|
+
var reactNativeMmkv = require('react-native-mmkv');
|
|
4
5
|
var expoSpeechRecognition = require('expo-speech-recognition');
|
|
5
6
|
|
|
6
7
|
// src/hooks/useChat.ts
|
|
@@ -187,6 +188,8 @@ function getEventMessage(event) {
|
|
|
187
188
|
return event.workerName ? `${event.workerName} thinking...` : "Thinking...";
|
|
188
189
|
case "INTENT_THINKING_CONT":
|
|
189
190
|
return event.message || "";
|
|
191
|
+
case "KEEP_ALIVE":
|
|
192
|
+
return "";
|
|
190
193
|
default:
|
|
191
194
|
return eventType;
|
|
192
195
|
}
|
|
@@ -223,6 +226,9 @@ function completeLastInProgressStep(steps) {
|
|
|
223
226
|
}
|
|
224
227
|
function processStreamEvent(event, state) {
|
|
225
228
|
const eventType = event.eventType;
|
|
229
|
+
if (typeof eventType === "string" && eventType.toUpperCase() === "KEEP_ALIVE") {
|
|
230
|
+
return state;
|
|
231
|
+
}
|
|
226
232
|
const message = getEventMessage(event);
|
|
227
233
|
if (eventType !== "INTENT_THINKING" && eventType !== "INTENT_THINKING_CONT") {
|
|
228
234
|
if (state.currentThinkingStepId) {
|
|
@@ -639,6 +645,88 @@ async function cancelUserAction(config, userActionId) {
|
|
|
639
645
|
async function resendUserAction(config, userActionId) {
|
|
640
646
|
return sendUserActionRequest(config, userActionId, "resend");
|
|
641
647
|
}
|
|
648
|
+
var storage = reactNativeMmkv.createMMKV({ id: "payman-chat-store" });
|
|
649
|
+
var chatStore = {
|
|
650
|
+
get(key) {
|
|
651
|
+
const raw = storage.getString(key);
|
|
652
|
+
if (!raw) return [];
|
|
653
|
+
try {
|
|
654
|
+
return JSON.parse(raw);
|
|
655
|
+
} catch {
|
|
656
|
+
return [];
|
|
657
|
+
}
|
|
658
|
+
},
|
|
659
|
+
set(key, messages) {
|
|
660
|
+
storage.set(key, JSON.stringify(messages));
|
|
661
|
+
},
|
|
662
|
+
delete(key) {
|
|
663
|
+
storage.delete(key);
|
|
664
|
+
}
|
|
665
|
+
};
|
|
666
|
+
|
|
667
|
+
// src/utils/activeStreamStore.ts
|
|
668
|
+
var streams = /* @__PURE__ */ new Map();
|
|
669
|
+
var activeStreamStore = {
|
|
670
|
+
has(key) {
|
|
671
|
+
return streams.has(key);
|
|
672
|
+
},
|
|
673
|
+
get(key) {
|
|
674
|
+
const entry = streams.get(key);
|
|
675
|
+
if (!entry) return null;
|
|
676
|
+
return { messages: entry.messages, isWaiting: entry.isWaiting };
|
|
677
|
+
},
|
|
678
|
+
// Called before startStream — registers the controller and initial messages
|
|
679
|
+
start(key, abortController, initialMessages) {
|
|
680
|
+
const existing = streams.get(key);
|
|
681
|
+
streams.set(key, {
|
|
682
|
+
messages: initialMessages,
|
|
683
|
+
isWaiting: true,
|
|
684
|
+
abortController,
|
|
685
|
+
listeners: existing?.listeners ?? /* @__PURE__ */ new Set()
|
|
686
|
+
});
|
|
687
|
+
},
|
|
688
|
+
// Called by the stream on every event — applies the same updater pattern React uses
|
|
689
|
+
applyMessages(key, updater) {
|
|
690
|
+
const entry = streams.get(key);
|
|
691
|
+
if (!entry) return;
|
|
692
|
+
const next = typeof updater === "function" ? updater(entry.messages) : updater;
|
|
693
|
+
entry.messages = next;
|
|
694
|
+
entry.listeners.forEach((l) => l(next, entry.isWaiting));
|
|
695
|
+
},
|
|
696
|
+
setWaiting(key, waiting) {
|
|
697
|
+
const entry = streams.get(key);
|
|
698
|
+
if (!entry) return;
|
|
699
|
+
entry.isWaiting = waiting;
|
|
700
|
+
entry.listeners.forEach((l) => l(entry.messages, waiting));
|
|
701
|
+
},
|
|
702
|
+
// Called when stream completes — persists to chatStore and cleans up
|
|
703
|
+
complete(key) {
|
|
704
|
+
const entry = streams.get(key);
|
|
705
|
+
if (!entry) return;
|
|
706
|
+
entry.isWaiting = false;
|
|
707
|
+
entry.listeners.forEach((l) => l(entry.messages, false));
|
|
708
|
+
const toSave = entry.messages.filter((m) => !m.isStreaming);
|
|
709
|
+
if (toSave.length > 0) chatStore.set(key, toSave);
|
|
710
|
+
streams.delete(key);
|
|
711
|
+
},
|
|
712
|
+
// Subscribe — returns unsubscribe fn. Component calls this on mount, cleanup on unmount.
|
|
713
|
+
subscribe(key, listener) {
|
|
714
|
+
const entry = streams.get(key);
|
|
715
|
+
if (!entry) return () => {
|
|
716
|
+
};
|
|
717
|
+
entry.listeners.add(listener);
|
|
718
|
+
return () => {
|
|
719
|
+
streams.get(key)?.listeners.delete(listener);
|
|
720
|
+
};
|
|
721
|
+
},
|
|
722
|
+
// Explicit user cancel — aborts the controller and removes the entry
|
|
723
|
+
abort(key) {
|
|
724
|
+
const entry = streams.get(key);
|
|
725
|
+
if (!entry) return;
|
|
726
|
+
entry.abortController.abort();
|
|
727
|
+
streams.delete(key);
|
|
728
|
+
}
|
|
729
|
+
};
|
|
642
730
|
function useStreamManager(config, callbacks, setMessages, setIsWaitingForResponse) {
|
|
643
731
|
const abortControllerRef = react.useRef(null);
|
|
644
732
|
const configRef = react.useRef(config);
|
|
@@ -646,9 +734,9 @@ function useStreamManager(config, callbacks, setMessages, setIsWaitingForRespons
|
|
|
646
734
|
const callbacksRef = react.useRef(callbacks);
|
|
647
735
|
callbacksRef.current = callbacks;
|
|
648
736
|
const startStream = react.useCallback(
|
|
649
|
-
async (userMessage, streamingId, sessionId) => {
|
|
737
|
+
async (userMessage, streamingId, sessionId, externalAbortController) => {
|
|
650
738
|
abortControllerRef.current?.abort();
|
|
651
|
-
const abortController = new AbortController();
|
|
739
|
+
const abortController = externalAbortController ?? new AbortController();
|
|
652
740
|
abortControllerRef.current = abortController;
|
|
653
741
|
const state = {
|
|
654
742
|
accumulatedContent: "",
|
|
@@ -727,6 +815,11 @@ function useStreamManager(config, callbacks, setMessages, setIsWaitingForRespons
|
|
|
727
815
|
if (abortController.signal.aborted) {
|
|
728
816
|
return;
|
|
729
817
|
}
|
|
818
|
+
if (typeof event.eventType === "string" && event.eventType.toUpperCase() === "KEEP_ALIVE") {
|
|
819
|
+
if (event.executionId) state.executionId = event.executionId;
|
|
820
|
+
if (event.sessionId) state.currentSessionId = event.sessionId;
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
730
823
|
if (event.executionId) state.executionId = event.executionId;
|
|
731
824
|
if (event.sessionId) state.currentSessionId = event.sessionId;
|
|
732
825
|
const activeThinkingLengthBeforeProcess = state.activeThinkingText?.length ?? 0;
|
|
@@ -852,13 +945,43 @@ function useStreamManager(config, callbacks, setMessages, setIsWaitingForRespons
|
|
|
852
945
|
|
|
853
946
|
// src/hooks/useChat.ts
|
|
854
947
|
function useChat(config, callbacks = {}) {
|
|
855
|
-
const [messages, setMessages] = react.useState(
|
|
948
|
+
const [messages, setMessages] = react.useState(() => {
|
|
949
|
+
if (config.userId) return chatStore.get(config.userId);
|
|
950
|
+
return config.initialMessages ?? [];
|
|
951
|
+
});
|
|
856
952
|
const [isWaitingForResponse, setIsWaitingForResponse] = react.useState(false);
|
|
857
|
-
const sessionIdRef = react.useRef(
|
|
953
|
+
const sessionIdRef = react.useRef(
|
|
954
|
+
config.userId ? chatStore.get(config.userId).find((m) => m.sessionId)?.sessionId ?? config.initialSessionId ?? void 0 : config.initialSessionId ?? void 0
|
|
955
|
+
);
|
|
956
|
+
const prevUserIdRef = react.useRef(config.userId);
|
|
858
957
|
const callbacksRef = react.useRef(callbacks);
|
|
859
958
|
callbacksRef.current = callbacks;
|
|
860
959
|
const configRef = react.useRef(config);
|
|
861
960
|
configRef.current = config;
|
|
961
|
+
const messagesRef = react.useRef(messages);
|
|
962
|
+
messagesRef.current = messages;
|
|
963
|
+
const storeAwareSetMessages = react.useCallback(
|
|
964
|
+
(updater) => {
|
|
965
|
+
const { userId } = configRef.current;
|
|
966
|
+
if (userId && activeStreamStore.has(userId)) {
|
|
967
|
+
activeStreamStore.applyMessages(userId, updater);
|
|
968
|
+
}
|
|
969
|
+
setMessages(updater);
|
|
970
|
+
},
|
|
971
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
972
|
+
[]
|
|
973
|
+
);
|
|
974
|
+
const storeAwareSetIsWaiting = react.useCallback(
|
|
975
|
+
(waiting) => {
|
|
976
|
+
const { userId } = configRef.current;
|
|
977
|
+
if (userId && activeStreamStore.has(userId)) {
|
|
978
|
+
activeStreamStore.setWaiting(userId, waiting);
|
|
979
|
+
}
|
|
980
|
+
setIsWaitingForResponse(waiting);
|
|
981
|
+
},
|
|
982
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
983
|
+
[]
|
|
984
|
+
);
|
|
862
985
|
const [userActionState, setUserActionState] = react.useState({
|
|
863
986
|
request: null,
|
|
864
987
|
result: null,
|
|
@@ -901,8 +1024,8 @@ function useChat(config, callbacks = {}) {
|
|
|
901
1024
|
const { startStream, cancelStream: cancelStreamManager, abortControllerRef } = useStreamManager(
|
|
902
1025
|
config,
|
|
903
1026
|
wrappedCallbacks,
|
|
904
|
-
|
|
905
|
-
|
|
1027
|
+
storeAwareSetMessages,
|
|
1028
|
+
storeAwareSetIsWaiting
|
|
906
1029
|
);
|
|
907
1030
|
const sendMessage = react.useCallback(
|
|
908
1031
|
async (userMessage) => {
|
|
@@ -939,11 +1062,21 @@ function useChat(config, callbacks = {}) {
|
|
|
939
1062
|
currentMessage: void 0
|
|
940
1063
|
};
|
|
941
1064
|
setMessages((prev) => [...prev, streamingMsg]);
|
|
1065
|
+
const abortController = new AbortController();
|
|
1066
|
+
const { userId } = configRef.current;
|
|
1067
|
+
if (userId) {
|
|
1068
|
+
const initialMessages = [...messagesRef.current, userMsg, streamingMsg];
|
|
1069
|
+
activeStreamStore.start(userId, abortController, initialMessages);
|
|
1070
|
+
}
|
|
942
1071
|
const newSessionId = await startStream(
|
|
943
1072
|
userMessage,
|
|
944
1073
|
streamingId,
|
|
945
|
-
sessionIdRef.current
|
|
1074
|
+
sessionIdRef.current,
|
|
1075
|
+
abortController
|
|
946
1076
|
);
|
|
1077
|
+
if (userId) {
|
|
1078
|
+
activeStreamStore.complete(userId);
|
|
1079
|
+
}
|
|
947
1080
|
if (newSessionId && newSessionId !== sessionIdRef.current) {
|
|
948
1081
|
sessionIdRef.current = newSessionId;
|
|
949
1082
|
}
|
|
@@ -951,9 +1084,18 @@ function useChat(config, callbacks = {}) {
|
|
|
951
1084
|
[startStream]
|
|
952
1085
|
);
|
|
953
1086
|
const clearMessages = react.useCallback(() => {
|
|
1087
|
+
if (configRef.current.userId) {
|
|
1088
|
+
chatStore.delete(configRef.current.userId);
|
|
1089
|
+
}
|
|
954
1090
|
setMessages([]);
|
|
955
1091
|
}, []);
|
|
1092
|
+
const prependMessages = react.useCallback((msgs) => {
|
|
1093
|
+
setMessages((prev) => [...msgs, ...prev]);
|
|
1094
|
+
}, []);
|
|
956
1095
|
const cancelStream = react.useCallback(() => {
|
|
1096
|
+
if (configRef.current.userId) {
|
|
1097
|
+
activeStreamStore.abort(configRef.current.userId);
|
|
1098
|
+
}
|
|
957
1099
|
cancelStreamManager();
|
|
958
1100
|
setIsWaitingForResponse(false);
|
|
959
1101
|
setUserActionState((prev) => ({ ...prev, request: null, result: null }));
|
|
@@ -973,6 +1115,10 @@ function useChat(config, callbacks = {}) {
|
|
|
973
1115
|
);
|
|
974
1116
|
}, [cancelStreamManager]);
|
|
975
1117
|
const resetSession = react.useCallback(() => {
|
|
1118
|
+
if (configRef.current.userId) {
|
|
1119
|
+
activeStreamStore.abort(configRef.current.userId);
|
|
1120
|
+
chatStore.delete(configRef.current.userId);
|
|
1121
|
+
}
|
|
976
1122
|
setMessages([]);
|
|
977
1123
|
sessionIdRef.current = void 0;
|
|
978
1124
|
abortControllerRef.current?.abort();
|
|
@@ -1035,10 +1181,48 @@ function useChat(config, callbacks = {}) {
|
|
|
1035
1181
|
throw error;
|
|
1036
1182
|
}
|
|
1037
1183
|
}, []);
|
|
1184
|
+
react.useEffect(() => {
|
|
1185
|
+
const { userId } = config;
|
|
1186
|
+
if (!userId) return;
|
|
1187
|
+
const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting) => {
|
|
1188
|
+
setMessages(msgs);
|
|
1189
|
+
setIsWaitingForResponse(isWaiting);
|
|
1190
|
+
});
|
|
1191
|
+
const active = activeStreamStore.get(userId);
|
|
1192
|
+
if (active) {
|
|
1193
|
+
setMessages(active.messages);
|
|
1194
|
+
setIsWaitingForResponse(active.isWaiting);
|
|
1195
|
+
}
|
|
1196
|
+
return unsubscribe;
|
|
1197
|
+
}, []);
|
|
1198
|
+
react.useEffect(() => {
|
|
1199
|
+
if (!config.userId) return;
|
|
1200
|
+
const toSave = messages.filter((m) => !m.isStreaming);
|
|
1201
|
+
if (toSave.length > 0) {
|
|
1202
|
+
chatStore.set(config.userId, toSave);
|
|
1203
|
+
}
|
|
1204
|
+
}, [messages, config.userId]);
|
|
1205
|
+
react.useEffect(() => {
|
|
1206
|
+
const prevUserId = prevUserIdRef.current;
|
|
1207
|
+
prevUserIdRef.current = config.userId;
|
|
1208
|
+
if (prevUserId === config.userId) return;
|
|
1209
|
+
if (prevUserId && !config.userId) {
|
|
1210
|
+
chatStore.delete(prevUserId);
|
|
1211
|
+
setMessages([]);
|
|
1212
|
+
sessionIdRef.current = void 0;
|
|
1213
|
+
setIsWaitingForResponse(false);
|
|
1214
|
+
setUserActionState({ request: null, result: null, clearOtpTrigger: 0 });
|
|
1215
|
+
} else if (config.userId) {
|
|
1216
|
+
const stored = chatStore.get(config.userId);
|
|
1217
|
+
setMessages(stored);
|
|
1218
|
+
sessionIdRef.current = stored.find((m) => m.sessionId)?.sessionId;
|
|
1219
|
+
}
|
|
1220
|
+
}, [config.userId]);
|
|
1038
1221
|
return {
|
|
1039
1222
|
messages,
|
|
1040
1223
|
sendMessage,
|
|
1041
1224
|
clearMessages,
|
|
1225
|
+
prependMessages,
|
|
1042
1226
|
cancelStream,
|
|
1043
1227
|
resetSession,
|
|
1044
1228
|
getSessionId,
|