@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.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
|
@@ -162,6 +162,8 @@ function getEventMessage(event) {
|
|
|
162
162
|
return event.workerName ? `${event.workerName} thinking...` : "Thinking...";
|
|
163
163
|
case "INTENT_THINKING_CONT":
|
|
164
164
|
return event.message || "";
|
|
165
|
+
case "KEEP_ALIVE":
|
|
166
|
+
return "";
|
|
165
167
|
default:
|
|
166
168
|
return eventType;
|
|
167
169
|
}
|
|
@@ -198,6 +200,9 @@ function completeLastInProgressStep(steps) {
|
|
|
198
200
|
}
|
|
199
201
|
function processStreamEvent(event, state) {
|
|
200
202
|
const eventType = event.eventType;
|
|
203
|
+
if (typeof eventType === "string" && eventType.toUpperCase() === "KEEP_ALIVE") {
|
|
204
|
+
return state;
|
|
205
|
+
}
|
|
201
206
|
const message = getEventMessage(event);
|
|
202
207
|
if (eventType !== "INTENT_THINKING" && eventType !== "INTENT_THINKING_CONT") {
|
|
203
208
|
if (state.currentThinkingStepId) {
|
|
@@ -614,6 +619,84 @@ async function cancelUserAction(config, userActionId) {
|
|
|
614
619
|
async function resendUserAction(config, userActionId) {
|
|
615
620
|
return sendUserActionRequest(config, userActionId, "resend");
|
|
616
621
|
}
|
|
622
|
+
|
|
623
|
+
// src/utils/chatStore.ts
|
|
624
|
+
var memoryStore = /* @__PURE__ */ new Map();
|
|
625
|
+
var chatStore = {
|
|
626
|
+
get(key) {
|
|
627
|
+
return memoryStore.get(key) ?? [];
|
|
628
|
+
},
|
|
629
|
+
set(key, messages) {
|
|
630
|
+
memoryStore.set(key, messages);
|
|
631
|
+
},
|
|
632
|
+
delete(key) {
|
|
633
|
+
memoryStore.delete(key);
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
|
|
637
|
+
// src/utils/activeStreamStore.ts
|
|
638
|
+
var streams = /* @__PURE__ */ new Map();
|
|
639
|
+
var activeStreamStore = {
|
|
640
|
+
has(key) {
|
|
641
|
+
return streams.has(key);
|
|
642
|
+
},
|
|
643
|
+
get(key) {
|
|
644
|
+
const entry = streams.get(key);
|
|
645
|
+
if (!entry) return null;
|
|
646
|
+
return { messages: entry.messages, isWaiting: entry.isWaiting };
|
|
647
|
+
},
|
|
648
|
+
// Called before startStream — registers the controller and initial messages
|
|
649
|
+
start(key, abortController, initialMessages) {
|
|
650
|
+
const existing = streams.get(key);
|
|
651
|
+
streams.set(key, {
|
|
652
|
+
messages: initialMessages,
|
|
653
|
+
isWaiting: true,
|
|
654
|
+
abortController,
|
|
655
|
+
listeners: existing?.listeners ?? /* @__PURE__ */ new Set()
|
|
656
|
+
});
|
|
657
|
+
},
|
|
658
|
+
// Called by the stream on every event — applies the same updater pattern React uses
|
|
659
|
+
applyMessages(key, updater) {
|
|
660
|
+
const entry = streams.get(key);
|
|
661
|
+
if (!entry) return;
|
|
662
|
+
const next = typeof updater === "function" ? updater(entry.messages) : updater;
|
|
663
|
+
entry.messages = next;
|
|
664
|
+
entry.listeners.forEach((l) => l(next, entry.isWaiting));
|
|
665
|
+
},
|
|
666
|
+
setWaiting(key, waiting) {
|
|
667
|
+
const entry = streams.get(key);
|
|
668
|
+
if (!entry) return;
|
|
669
|
+
entry.isWaiting = waiting;
|
|
670
|
+
entry.listeners.forEach((l) => l(entry.messages, waiting));
|
|
671
|
+
},
|
|
672
|
+
// Called when stream completes — persists to chatStore and cleans up
|
|
673
|
+
complete(key) {
|
|
674
|
+
const entry = streams.get(key);
|
|
675
|
+
if (!entry) return;
|
|
676
|
+
entry.isWaiting = false;
|
|
677
|
+
entry.listeners.forEach((l) => l(entry.messages, false));
|
|
678
|
+
const toSave = entry.messages.filter((m) => !m.isStreaming);
|
|
679
|
+
if (toSave.length > 0) chatStore.set(key, toSave);
|
|
680
|
+
streams.delete(key);
|
|
681
|
+
},
|
|
682
|
+
// Subscribe — returns unsubscribe fn. Component calls this on mount, cleanup on unmount.
|
|
683
|
+
subscribe(key, listener) {
|
|
684
|
+
const entry = streams.get(key);
|
|
685
|
+
if (!entry) return () => {
|
|
686
|
+
};
|
|
687
|
+
entry.listeners.add(listener);
|
|
688
|
+
return () => {
|
|
689
|
+
streams.get(key)?.listeners.delete(listener);
|
|
690
|
+
};
|
|
691
|
+
},
|
|
692
|
+
// Explicit user cancel — aborts the controller and removes the entry
|
|
693
|
+
abort(key) {
|
|
694
|
+
const entry = streams.get(key);
|
|
695
|
+
if (!entry) return;
|
|
696
|
+
entry.abortController.abort();
|
|
697
|
+
streams.delete(key);
|
|
698
|
+
}
|
|
699
|
+
};
|
|
617
700
|
function useStreamManager(config, callbacks, setMessages, setIsWaitingForResponse) {
|
|
618
701
|
const abortControllerRef = react.useRef(null);
|
|
619
702
|
const configRef = react.useRef(config);
|
|
@@ -621,9 +704,9 @@ function useStreamManager(config, callbacks, setMessages, setIsWaitingForRespons
|
|
|
621
704
|
const callbacksRef = react.useRef(callbacks);
|
|
622
705
|
callbacksRef.current = callbacks;
|
|
623
706
|
const startStream = react.useCallback(
|
|
624
|
-
async (userMessage, streamingId, sessionId) => {
|
|
707
|
+
async (userMessage, streamingId, sessionId, externalAbortController) => {
|
|
625
708
|
abortControllerRef.current?.abort();
|
|
626
|
-
const abortController = new AbortController();
|
|
709
|
+
const abortController = externalAbortController ?? new AbortController();
|
|
627
710
|
abortControllerRef.current = abortController;
|
|
628
711
|
const state = {
|
|
629
712
|
accumulatedContent: "",
|
|
@@ -702,6 +785,11 @@ function useStreamManager(config, callbacks, setMessages, setIsWaitingForRespons
|
|
|
702
785
|
if (abortController.signal.aborted) {
|
|
703
786
|
return;
|
|
704
787
|
}
|
|
788
|
+
if (typeof event.eventType === "string" && event.eventType.toUpperCase() === "KEEP_ALIVE") {
|
|
789
|
+
if (event.executionId) state.executionId = event.executionId;
|
|
790
|
+
if (event.sessionId) state.currentSessionId = event.sessionId;
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
705
793
|
if (event.executionId) state.executionId = event.executionId;
|
|
706
794
|
if (event.sessionId) state.currentSessionId = event.sessionId;
|
|
707
795
|
const activeThinkingLengthBeforeProcess = state.activeThinkingText?.length ?? 0;
|
|
@@ -827,13 +915,43 @@ function useStreamManager(config, callbacks, setMessages, setIsWaitingForRespons
|
|
|
827
915
|
|
|
828
916
|
// src/hooks/useChat.ts
|
|
829
917
|
function useChat(config, callbacks = {}) {
|
|
830
|
-
const [messages, setMessages] = react.useState(
|
|
918
|
+
const [messages, setMessages] = react.useState(() => {
|
|
919
|
+
if (config.userId) return chatStore.get(config.userId);
|
|
920
|
+
return config.initialMessages ?? [];
|
|
921
|
+
});
|
|
831
922
|
const [isWaitingForResponse, setIsWaitingForResponse] = react.useState(false);
|
|
832
|
-
const sessionIdRef = react.useRef(
|
|
923
|
+
const sessionIdRef = react.useRef(
|
|
924
|
+
config.userId ? chatStore.get(config.userId).find((m) => m.sessionId)?.sessionId ?? config.initialSessionId ?? void 0 : config.initialSessionId ?? void 0
|
|
925
|
+
);
|
|
926
|
+
const prevUserIdRef = react.useRef(config.userId);
|
|
833
927
|
const callbacksRef = react.useRef(callbacks);
|
|
834
928
|
callbacksRef.current = callbacks;
|
|
835
929
|
const configRef = react.useRef(config);
|
|
836
930
|
configRef.current = config;
|
|
931
|
+
const messagesRef = react.useRef(messages);
|
|
932
|
+
messagesRef.current = messages;
|
|
933
|
+
const storeAwareSetMessages = react.useCallback(
|
|
934
|
+
(updater) => {
|
|
935
|
+
const { userId } = configRef.current;
|
|
936
|
+
if (userId && activeStreamStore.has(userId)) {
|
|
937
|
+
activeStreamStore.applyMessages(userId, updater);
|
|
938
|
+
}
|
|
939
|
+
setMessages(updater);
|
|
940
|
+
},
|
|
941
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
942
|
+
[]
|
|
943
|
+
);
|
|
944
|
+
const storeAwareSetIsWaiting = react.useCallback(
|
|
945
|
+
(waiting) => {
|
|
946
|
+
const { userId } = configRef.current;
|
|
947
|
+
if (userId && activeStreamStore.has(userId)) {
|
|
948
|
+
activeStreamStore.setWaiting(userId, waiting);
|
|
949
|
+
}
|
|
950
|
+
setIsWaitingForResponse(waiting);
|
|
951
|
+
},
|
|
952
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
953
|
+
[]
|
|
954
|
+
);
|
|
837
955
|
const [userActionState, setUserActionState] = react.useState({
|
|
838
956
|
request: null,
|
|
839
957
|
result: null,
|
|
@@ -876,8 +994,8 @@ function useChat(config, callbacks = {}) {
|
|
|
876
994
|
const { startStream, cancelStream: cancelStreamManager, abortControllerRef } = useStreamManager(
|
|
877
995
|
config,
|
|
878
996
|
wrappedCallbacks,
|
|
879
|
-
|
|
880
|
-
|
|
997
|
+
storeAwareSetMessages,
|
|
998
|
+
storeAwareSetIsWaiting
|
|
881
999
|
);
|
|
882
1000
|
const sendMessage = react.useCallback(
|
|
883
1001
|
async (userMessage) => {
|
|
@@ -914,11 +1032,21 @@ function useChat(config, callbacks = {}) {
|
|
|
914
1032
|
currentMessage: void 0
|
|
915
1033
|
};
|
|
916
1034
|
setMessages((prev) => [...prev, streamingMsg]);
|
|
1035
|
+
const abortController = new AbortController();
|
|
1036
|
+
const { userId } = configRef.current;
|
|
1037
|
+
if (userId) {
|
|
1038
|
+
const initialMessages = [...messagesRef.current, userMsg, streamingMsg];
|
|
1039
|
+
activeStreamStore.start(userId, abortController, initialMessages);
|
|
1040
|
+
}
|
|
917
1041
|
const newSessionId = await startStream(
|
|
918
1042
|
userMessage,
|
|
919
1043
|
streamingId,
|
|
920
|
-
sessionIdRef.current
|
|
1044
|
+
sessionIdRef.current,
|
|
1045
|
+
abortController
|
|
921
1046
|
);
|
|
1047
|
+
if (userId) {
|
|
1048
|
+
activeStreamStore.complete(userId);
|
|
1049
|
+
}
|
|
922
1050
|
if (newSessionId && newSessionId !== sessionIdRef.current) {
|
|
923
1051
|
sessionIdRef.current = newSessionId;
|
|
924
1052
|
}
|
|
@@ -926,9 +1054,18 @@ function useChat(config, callbacks = {}) {
|
|
|
926
1054
|
[startStream]
|
|
927
1055
|
);
|
|
928
1056
|
const clearMessages = react.useCallback(() => {
|
|
1057
|
+
if (configRef.current.userId) {
|
|
1058
|
+
chatStore.delete(configRef.current.userId);
|
|
1059
|
+
}
|
|
929
1060
|
setMessages([]);
|
|
930
1061
|
}, []);
|
|
1062
|
+
const prependMessages = react.useCallback((msgs) => {
|
|
1063
|
+
setMessages((prev) => [...msgs, ...prev]);
|
|
1064
|
+
}, []);
|
|
931
1065
|
const cancelStream = react.useCallback(() => {
|
|
1066
|
+
if (configRef.current.userId) {
|
|
1067
|
+
activeStreamStore.abort(configRef.current.userId);
|
|
1068
|
+
}
|
|
932
1069
|
cancelStreamManager();
|
|
933
1070
|
setIsWaitingForResponse(false);
|
|
934
1071
|
setUserActionState((prev) => ({ ...prev, request: null, result: null }));
|
|
@@ -948,6 +1085,10 @@ function useChat(config, callbacks = {}) {
|
|
|
948
1085
|
);
|
|
949
1086
|
}, [cancelStreamManager]);
|
|
950
1087
|
const resetSession = react.useCallback(() => {
|
|
1088
|
+
if (configRef.current.userId) {
|
|
1089
|
+
activeStreamStore.abort(configRef.current.userId);
|
|
1090
|
+
chatStore.delete(configRef.current.userId);
|
|
1091
|
+
}
|
|
951
1092
|
setMessages([]);
|
|
952
1093
|
sessionIdRef.current = void 0;
|
|
953
1094
|
abortControllerRef.current?.abort();
|
|
@@ -1010,10 +1151,48 @@ function useChat(config, callbacks = {}) {
|
|
|
1010
1151
|
throw error;
|
|
1011
1152
|
}
|
|
1012
1153
|
}, []);
|
|
1154
|
+
react.useEffect(() => {
|
|
1155
|
+
const { userId } = config;
|
|
1156
|
+
if (!userId) return;
|
|
1157
|
+
const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting) => {
|
|
1158
|
+
setMessages(msgs);
|
|
1159
|
+
setIsWaitingForResponse(isWaiting);
|
|
1160
|
+
});
|
|
1161
|
+
const active = activeStreamStore.get(userId);
|
|
1162
|
+
if (active) {
|
|
1163
|
+
setMessages(active.messages);
|
|
1164
|
+
setIsWaitingForResponse(active.isWaiting);
|
|
1165
|
+
}
|
|
1166
|
+
return unsubscribe;
|
|
1167
|
+
}, []);
|
|
1168
|
+
react.useEffect(() => {
|
|
1169
|
+
if (!config.userId) return;
|
|
1170
|
+
const toSave = messages.filter((m) => !m.isStreaming);
|
|
1171
|
+
if (toSave.length > 0) {
|
|
1172
|
+
chatStore.set(config.userId, toSave);
|
|
1173
|
+
}
|
|
1174
|
+
}, [messages, config.userId]);
|
|
1175
|
+
react.useEffect(() => {
|
|
1176
|
+
const prevUserId = prevUserIdRef.current;
|
|
1177
|
+
prevUserIdRef.current = config.userId;
|
|
1178
|
+
if (prevUserId === config.userId) return;
|
|
1179
|
+
if (prevUserId && !config.userId) {
|
|
1180
|
+
chatStore.delete(prevUserId);
|
|
1181
|
+
setMessages([]);
|
|
1182
|
+
sessionIdRef.current = void 0;
|
|
1183
|
+
setIsWaitingForResponse(false);
|
|
1184
|
+
setUserActionState({ request: null, result: null, clearOtpTrigger: 0 });
|
|
1185
|
+
} else if (config.userId) {
|
|
1186
|
+
const stored = chatStore.get(config.userId);
|
|
1187
|
+
setMessages(stored);
|
|
1188
|
+
sessionIdRef.current = stored.find((m) => m.sessionId)?.sessionId;
|
|
1189
|
+
}
|
|
1190
|
+
}, [config.userId]);
|
|
1013
1191
|
return {
|
|
1014
1192
|
messages,
|
|
1015
1193
|
sendMessage,
|
|
1016
1194
|
clearMessages,
|
|
1195
|
+
prependMessages,
|
|
1017
1196
|
cancelStream,
|
|
1018
1197
|
resetSession,
|
|
1019
1198
|
getSessionId,
|