@antdv-next/x-sdk 0.0.1
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/_util/types.d.ts +1 -0
- package/dist/chat-providers/AbstractChatProvider.d.ts +42 -0
- package/dist/chat-providers/DeepSeekChatProvider.d.ts +15 -0
- package/dist/chat-providers/DefaultChatProvider.d.ts +8 -0
- package/dist/chat-providers/OpenAIChatProvider.d.ts +15 -0
- package/dist/chat-providers/index.d.ts +5 -0
- package/dist/chat-providers/index.js +2 -0
- package/dist/chat-providers/types/model.d.ts +108 -0
- package/dist/chat-providers/types/model.js +0 -0
- package/dist/chat-providers-5x9Va7p5.js +167 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +26 -0
- package/dist/store-C1diHqNH.js +145 -0
- package/dist/x-chat/index.d.ts +86 -0
- package/dist/x-chat/index.js +292 -0
- package/dist/x-chat/store.d.ts +38 -0
- package/dist/x-conversations/index.d.ts +20 -0
- package/dist/x-conversations/index.js +2 -0
- package/dist/x-conversations/store.d.ts +26 -0
- package/dist/x-conversations-BrKWhj5r.js +122 -0
- package/dist/x-request/index.d.ts +74 -0
- package/dist/x-request/index.js +2 -0
- package/dist/x-request/x-fetch.d.ts +8 -0
- package/dist/x-request-BSFGaKND.js +234 -0
- package/dist/x-stream/index.d.ts +49 -0
- package/dist/x-stream/index.js +114 -0
- package/package.json +52 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { n as chatMessagesStoreHelper, t as ChatMessagesStore } from "../store-C1diHqNH.js";
|
|
2
|
+
import { computed, isRef, onScopeDispose, reactive, ref, shallowRef, watch } from "vue";
|
|
3
|
+
//#region src/x-chat/index.ts
|
|
4
|
+
function toArray(item) {
|
|
5
|
+
return Array.isArray(item) ? item : [item];
|
|
6
|
+
}
|
|
7
|
+
function resolveMaybeRef(value) {
|
|
8
|
+
return isRef(value) ? value.value : value;
|
|
9
|
+
}
|
|
10
|
+
var IsRequestingMap = reactive(/* @__PURE__ */ new Map());
|
|
11
|
+
var generateConversationKey = () => Symbol("ConversationKey");
|
|
12
|
+
function useXChat(config) {
|
|
13
|
+
const { defaultMessages, requestFallback, requestPlaceholder, parser, provider } = config;
|
|
14
|
+
const idRef = ref(0);
|
|
15
|
+
const requestHandlerRef = shallowRef();
|
|
16
|
+
const conversationKey = ref((config.conversationKey ? resolveMaybeRef(config.conversationKey) : void 0) ?? generateConversationKey());
|
|
17
|
+
if (config.conversationKey && isRef(config.conversationKey)) watch(config.conversationKey, (value) => {
|
|
18
|
+
if (value !== void 0 && value !== null) conversationKey.value = value;
|
|
19
|
+
});
|
|
20
|
+
const messageQueueMap = /* @__PURE__ */ new Map();
|
|
21
|
+
const activeStore = shallowRef();
|
|
22
|
+
const messages = ref([]);
|
|
23
|
+
const isDefaultMessagesRequesting = ref(false);
|
|
24
|
+
let unsubscribeStore = null;
|
|
25
|
+
const resolveDefaultMessages = async (currentConversationKey) => {
|
|
26
|
+
return ((typeof defaultMessages === "function" ? await defaultMessages({ conversationKey: currentConversationKey }) : defaultMessages) || []).map((info, index) => ({
|
|
27
|
+
id: `default_${index}`,
|
|
28
|
+
status: "local",
|
|
29
|
+
...info
|
|
30
|
+
}));
|
|
31
|
+
};
|
|
32
|
+
const createStore = (currentConversationKey) => {
|
|
33
|
+
const existingStore = chatMessagesStoreHelper.get(currentConversationKey);
|
|
34
|
+
if (existingStore) return existingStore;
|
|
35
|
+
return new ChatMessagesStore(() => resolveDefaultMessages(currentConversationKey), currentConversationKey);
|
|
36
|
+
};
|
|
37
|
+
const syncStoreSnapshot = () => {
|
|
38
|
+
if (!activeStore.value) {
|
|
39
|
+
messages.value = [];
|
|
40
|
+
isDefaultMessagesRequesting.value = false;
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const snapshot = activeStore.value.getSnapshot();
|
|
44
|
+
messages.value = snapshot.messages;
|
|
45
|
+
isDefaultMessagesRequesting.value = snapshot.isDefaultMessagesRequesting;
|
|
46
|
+
};
|
|
47
|
+
const bindStore = (currentConversationKey) => {
|
|
48
|
+
if (unsubscribeStore) {
|
|
49
|
+
unsubscribeStore();
|
|
50
|
+
unsubscribeStore = null;
|
|
51
|
+
}
|
|
52
|
+
activeStore.value = createStore(currentConversationKey);
|
|
53
|
+
syncStoreSnapshot();
|
|
54
|
+
unsubscribeStore = activeStore.value.subscribe(syncStoreSnapshot);
|
|
55
|
+
};
|
|
56
|
+
bindStore(conversationKey.value);
|
|
57
|
+
watch(conversationKey, (nextConversationKey) => {
|
|
58
|
+
bindStore(nextConversationKey);
|
|
59
|
+
});
|
|
60
|
+
onScopeDispose(() => {
|
|
61
|
+
if (unsubscribeStore) {
|
|
62
|
+
unsubscribeStore();
|
|
63
|
+
unsubscribeStore = null;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
const setMessages = (updater) => {
|
|
67
|
+
return activeStore.value?.setMessages(updater) ?? false;
|
|
68
|
+
};
|
|
69
|
+
const getMessages = () => {
|
|
70
|
+
return activeStore.value?.getMessages() ?? [];
|
|
71
|
+
};
|
|
72
|
+
const setMessage = (id, message) => {
|
|
73
|
+
return activeStore.value?.setMessage(id, message) ?? false;
|
|
74
|
+
};
|
|
75
|
+
const removeMessage = (id) => {
|
|
76
|
+
return activeStore.value?.removeMessage(id) ?? false;
|
|
77
|
+
};
|
|
78
|
+
const createMessage = (message, status, extraInfo) => {
|
|
79
|
+
const msg = {
|
|
80
|
+
id: `msg_${idRef.value}`,
|
|
81
|
+
message,
|
|
82
|
+
status
|
|
83
|
+
};
|
|
84
|
+
if (extraInfo) msg.extraInfo = extraInfo;
|
|
85
|
+
idRef.value += 1;
|
|
86
|
+
return msg;
|
|
87
|
+
};
|
|
88
|
+
const parsedMessages = computed(() => {
|
|
89
|
+
const list = [];
|
|
90
|
+
messages.value.forEach((agentMsg) => {
|
|
91
|
+
const sourceMessage = agentMsg.message;
|
|
92
|
+
const bubbleMsgs = toArray(parser ? parser(sourceMessage) : sourceMessage);
|
|
93
|
+
bubbleMsgs.forEach((bubbleMsg, bubbleMsgIndex) => {
|
|
94
|
+
let key = agentMsg.id;
|
|
95
|
+
if (bubbleMsgs.length > 1) key = `${key}_${bubbleMsgIndex}`;
|
|
96
|
+
list.push({
|
|
97
|
+
id: key,
|
|
98
|
+
message: bubbleMsg,
|
|
99
|
+
status: agentMsg.status
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
return list;
|
|
104
|
+
});
|
|
105
|
+
const getFilteredMessages = (msgs) => msgs.filter((info) => info.status !== "loading").map((info) => info.message);
|
|
106
|
+
provider?.injectGetMessages(() => {
|
|
107
|
+
return getFilteredMessages(getMessages());
|
|
108
|
+
});
|
|
109
|
+
requestHandlerRef.value = provider?.request;
|
|
110
|
+
const getRequestMessages = () => getFilteredMessages(getMessages());
|
|
111
|
+
const innerOnRequest = (requestParams, opts) => {
|
|
112
|
+
if (!provider) return;
|
|
113
|
+
const { updatingId, reload } = opts || {};
|
|
114
|
+
let loadingMsgId = null;
|
|
115
|
+
const localMessage = provider.transformLocalMessage(requestParams);
|
|
116
|
+
const localMessages = (Array.isArray(localMessage) ? localMessage : [localMessage]).map((message) => createMessage(message, "local", opts?.extraInfo));
|
|
117
|
+
if (reload) {
|
|
118
|
+
loadingMsgId = updatingId;
|
|
119
|
+
setMessages((ori) => {
|
|
120
|
+
const nextMessages = [...ori];
|
|
121
|
+
if (requestPlaceholder) {
|
|
122
|
+
let placeholderMsg;
|
|
123
|
+
if (typeof requestPlaceholder === "function") placeholderMsg = requestPlaceholder(requestParams, { messages: getFilteredMessages(nextMessages) });
|
|
124
|
+
else placeholderMsg = requestPlaceholder;
|
|
125
|
+
nextMessages.forEach((info) => {
|
|
126
|
+
if (info.id === updatingId) {
|
|
127
|
+
info.status = "loading";
|
|
128
|
+
info.message = placeholderMsg;
|
|
129
|
+
if (opts?.extraInfo) info.extraInfo = opts?.extraInfo;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
return nextMessages;
|
|
134
|
+
});
|
|
135
|
+
} else setMessages((ori) => {
|
|
136
|
+
let nextMessages = [...ori, ...localMessages];
|
|
137
|
+
if (requestPlaceholder) {
|
|
138
|
+
let placeholderMsg;
|
|
139
|
+
if (typeof requestPlaceholder === "function") placeholderMsg = requestPlaceholder(requestParams, { messages: getFilteredMessages(nextMessages) });
|
|
140
|
+
else placeholderMsg = requestPlaceholder;
|
|
141
|
+
const loadingMsg = createMessage(placeholderMsg, "loading");
|
|
142
|
+
loadingMsgId = loadingMsg.id;
|
|
143
|
+
nextMessages = [...nextMessages, loadingMsg];
|
|
144
|
+
}
|
|
145
|
+
return nextMessages;
|
|
146
|
+
});
|
|
147
|
+
let updatingMsgId = null;
|
|
148
|
+
const updateMessage = (status, chunk, chunks, responseHeaders) => {
|
|
149
|
+
let msg = getMessages().find((info) => info.id === updatingMsgId);
|
|
150
|
+
if (!msg) if (reload && updatingId) {
|
|
151
|
+
msg = getMessages().find((info) => info.id === updatingId);
|
|
152
|
+
if (msg) {
|
|
153
|
+
msg.status = status;
|
|
154
|
+
msg.message = provider.transformMessage({
|
|
155
|
+
chunk,
|
|
156
|
+
status,
|
|
157
|
+
chunks,
|
|
158
|
+
responseHeaders
|
|
159
|
+
});
|
|
160
|
+
setMessages((ori) => {
|
|
161
|
+
return [...ori];
|
|
162
|
+
});
|
|
163
|
+
updatingMsgId = msg.id;
|
|
164
|
+
}
|
|
165
|
+
} else {
|
|
166
|
+
msg = createMessage(provider.transformMessage({
|
|
167
|
+
chunk,
|
|
168
|
+
status,
|
|
169
|
+
chunks,
|
|
170
|
+
responseHeaders
|
|
171
|
+
}), status);
|
|
172
|
+
setMessages((ori) => {
|
|
173
|
+
return [...ori.filter((info) => info.id !== loadingMsgId), msg];
|
|
174
|
+
});
|
|
175
|
+
updatingMsgId = msg.id;
|
|
176
|
+
}
|
|
177
|
+
else setMessages((ori) => {
|
|
178
|
+
return ori.map((info) => {
|
|
179
|
+
if (info.id === updatingMsgId) {
|
|
180
|
+
const transformData = provider.transformMessage({
|
|
181
|
+
originMessage: info.message,
|
|
182
|
+
chunk,
|
|
183
|
+
chunks,
|
|
184
|
+
status,
|
|
185
|
+
responseHeaders
|
|
186
|
+
});
|
|
187
|
+
return {
|
|
188
|
+
...info,
|
|
189
|
+
message: transformData,
|
|
190
|
+
status
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
return info;
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
msg = getMessages().find((info) => info.id === updatingMsgId) || msg;
|
|
197
|
+
return msg;
|
|
198
|
+
};
|
|
199
|
+
provider.injectRequest({
|
|
200
|
+
onUpdate: (chunk, headers) => {
|
|
201
|
+
return updateMessage("updating", chunk, [], headers);
|
|
202
|
+
},
|
|
203
|
+
onSuccess: (chunks, headers) => {
|
|
204
|
+
if (conversationKey.value) IsRequestingMap.delete(conversationKey.value);
|
|
205
|
+
return updateMessage("success", void 0, chunks, headers);
|
|
206
|
+
},
|
|
207
|
+
onError: async (error, errorInfo) => {
|
|
208
|
+
if (conversationKey.value) IsRequestingMap.delete(conversationKey.value);
|
|
209
|
+
let fallbackMsg;
|
|
210
|
+
if (requestFallback) {
|
|
211
|
+
if (typeof requestFallback === "function") {
|
|
212
|
+
const currentMessages = getRequestMessages();
|
|
213
|
+
fallbackMsg = await requestFallback(requestParams, {
|
|
214
|
+
error,
|
|
215
|
+
errorInfo,
|
|
216
|
+
messageInfo: getMessages().find((info) => info.id === loadingMsgId || info.id === updatingMsgId),
|
|
217
|
+
messages: currentMessages
|
|
218
|
+
});
|
|
219
|
+
} else fallbackMsg = requestFallback;
|
|
220
|
+
setMessages((ori) => [...ori.filter((info) => info.id !== loadingMsgId && info.id !== updatingMsgId), createMessage(fallbackMsg, error.name === "AbortError" ? "abort" : "error")]);
|
|
221
|
+
} else {
|
|
222
|
+
fallbackMsg = getMessages().find((info) => info.id !== loadingMsgId && info.id !== updatingMsgId);
|
|
223
|
+
setMessages((ori) => {
|
|
224
|
+
return ori.map((info) => {
|
|
225
|
+
if (info.id === loadingMsgId || info.id === updatingMsgId) return {
|
|
226
|
+
...info,
|
|
227
|
+
status: error.name === "AbortError" ? "abort" : "error"
|
|
228
|
+
};
|
|
229
|
+
return info;
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
return fallbackMsg;
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
if (conversationKey.value) IsRequestingMap.set(conversationKey.value, true);
|
|
237
|
+
provider.request.run(provider.transformParams(requestParams, provider.request.options));
|
|
238
|
+
};
|
|
239
|
+
const onRequest = (requestParams, opts) => {
|
|
240
|
+
if (!provider) throw new Error("provider is required");
|
|
241
|
+
innerOnRequest(requestParams, opts);
|
|
242
|
+
};
|
|
243
|
+
const onReload = (id, requestParams, opts) => {
|
|
244
|
+
if (!provider) throw new Error("provider is required");
|
|
245
|
+
if (!id || !getMessages().find((info) => info.id === id)) throw new Error(`message [${id}] is not found`);
|
|
246
|
+
innerOnRequest(requestParams, {
|
|
247
|
+
updatingId: id,
|
|
248
|
+
reload: true,
|
|
249
|
+
extraInfo: opts?.extraInfo
|
|
250
|
+
});
|
|
251
|
+
};
|
|
252
|
+
const processMessageQueue = () => {
|
|
253
|
+
const requestParamsList = messageQueueMap.get(conversationKey.value);
|
|
254
|
+
if (requestParamsList && requestParamsList.length > 0) {
|
|
255
|
+
const timer = setTimeout(() => {
|
|
256
|
+
clearTimeout(timer);
|
|
257
|
+
requestParamsList.forEach(({ requestParams, opts }) => {
|
|
258
|
+
onRequest(requestParams, opts);
|
|
259
|
+
});
|
|
260
|
+
messageQueueMap.delete(conversationKey.value);
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
watch(isDefaultMessagesRequesting, (requesting) => {
|
|
265
|
+
if (!requesting) processMessageQueue();
|
|
266
|
+
});
|
|
267
|
+
const queueRequest = (currentConversationKey, requestParams, opts) => {
|
|
268
|
+
if (!messageQueueMap.has(currentConversationKey)) messageQueueMap.set(currentConversationKey, []);
|
|
269
|
+
messageQueueMap.get(currentConversationKey).push({
|
|
270
|
+
requestParams,
|
|
271
|
+
opts
|
|
272
|
+
});
|
|
273
|
+
};
|
|
274
|
+
return {
|
|
275
|
+
onRequest,
|
|
276
|
+
isDefaultMessagesRequesting,
|
|
277
|
+
messages,
|
|
278
|
+
parsedMessages,
|
|
279
|
+
setMessages,
|
|
280
|
+
removeMessage,
|
|
281
|
+
setMessage,
|
|
282
|
+
abort: () => {
|
|
283
|
+
if (!provider) throw new Error("provider is required");
|
|
284
|
+
requestHandlerRef.value?.abort();
|
|
285
|
+
},
|
|
286
|
+
isRequesting: computed(() => conversationKey.value ? IsRequestingMap.get(conversationKey.value) || false : false),
|
|
287
|
+
onReload,
|
|
288
|
+
queueRequest
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
//#endregion
|
|
292
|
+
export { useXChat as default };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export type ConversationKey = string | number | symbol;
|
|
2
|
+
export declare const chatMessagesStoreHelper: {
|
|
3
|
+
_chatMessagesStores: Map<ConversationKey, ChatMessagesStore<any>>;
|
|
4
|
+
get: (conversationKey: ConversationKey) => ChatMessagesStore<any> | undefined;
|
|
5
|
+
set: (key: ConversationKey, store: ChatMessagesStore<any>) => void;
|
|
6
|
+
delete: (key: ConversationKey) => void;
|
|
7
|
+
getMessages: (conversationKey: ConversationKey) => any[] | undefined;
|
|
8
|
+
};
|
|
9
|
+
export interface ChatStoreSnapshot<T> {
|
|
10
|
+
messages: T[];
|
|
11
|
+
isDefaultMessagesRequesting: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare class ChatMessagesStore<T extends {
|
|
14
|
+
id: number | string;
|
|
15
|
+
}> {
|
|
16
|
+
private listeners;
|
|
17
|
+
private conversationKey;
|
|
18
|
+
private snapshotResult;
|
|
19
|
+
private throttleTimer;
|
|
20
|
+
private pendingEmit;
|
|
21
|
+
private readonly throttleInterval;
|
|
22
|
+
private isDestroyed;
|
|
23
|
+
private emitListeners;
|
|
24
|
+
private throttledEmitListeners;
|
|
25
|
+
constructor(defaultMessages: () => Promise<T[]>, conversationKey?: ConversationKey);
|
|
26
|
+
private initializeMessages;
|
|
27
|
+
private setSnapshotResult;
|
|
28
|
+
private setMessagesInternal;
|
|
29
|
+
setMessages: (messages: T[] | ((ori: T[]) => T[])) => boolean;
|
|
30
|
+
getMessages: () => T[];
|
|
31
|
+
getMessage: (id: string | number) => T | undefined;
|
|
32
|
+
addMessage: (message: T) => boolean;
|
|
33
|
+
setMessage: (id: string | number, message: Partial<T> | ((message: T) => Partial<T>)) => boolean;
|
|
34
|
+
removeMessage: (id: string | number) => boolean;
|
|
35
|
+
getSnapshot: () => ChatStoreSnapshot<T>;
|
|
36
|
+
subscribe: (callback: () => void) => () => void;
|
|
37
|
+
destroy: () => void;
|
|
38
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AnyObject } from '../_util/types';
|
|
2
|
+
export interface ConversationData extends AnyObject {
|
|
3
|
+
key: string;
|
|
4
|
+
}
|
|
5
|
+
interface XConversationConfig {
|
|
6
|
+
defaultConversations?: ConversationData[];
|
|
7
|
+
defaultActiveConversationKey?: string;
|
|
8
|
+
}
|
|
9
|
+
export default function useXConversations(config: XConversationConfig): {
|
|
10
|
+
conversations: import('vue').ShallowRef<ConversationData[], ConversationData[]>;
|
|
11
|
+
activeConversationKey: import('vue').Ref<string, string>;
|
|
12
|
+
setActiveConversationKey: (key: string) => boolean;
|
|
13
|
+
addConversation: (conversation: ConversationData, placement?: "prepend" | "append") => boolean;
|
|
14
|
+
removeConversation: (key: ConversationData["key"]) => boolean;
|
|
15
|
+
setConversation: (key: ConversationData["key"], conversation: ConversationData) => boolean;
|
|
16
|
+
getConversation: (key: ConversationData["key"]) => ConversationData | undefined;
|
|
17
|
+
setConversations: (list: ConversationData[]) => boolean;
|
|
18
|
+
getMessages: (key: ConversationData["key"]) => any[] | undefined;
|
|
19
|
+
};
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ConversationData } from '.';
|
|
2
|
+
export declare const conversationStoreHelper: {
|
|
3
|
+
_allConversationStores: Map<string, ConversationStore>;
|
|
4
|
+
set: (key: string, store: ConversationStore) => void;
|
|
5
|
+
delete: (key: string) => void;
|
|
6
|
+
getConversation: (conversationKey: string) => ConversationData | undefined;
|
|
7
|
+
};
|
|
8
|
+
export declare class ConversationStore {
|
|
9
|
+
private conversations;
|
|
10
|
+
private listeners;
|
|
11
|
+
private storeKey;
|
|
12
|
+
private activeConversationKey;
|
|
13
|
+
private emitListeners;
|
|
14
|
+
constructor(defaultConversations: ConversationData[], defaultActiveConversationKey: string);
|
|
15
|
+
setActiveConversationKey: (key: string) => boolean;
|
|
16
|
+
setConversations: (list: ConversationData[]) => boolean;
|
|
17
|
+
getConversation: (key: ConversationData["key"]) => ConversationData | undefined;
|
|
18
|
+
addConversation: (conversation: ConversationData, placement?: "prepend" | "append") => boolean;
|
|
19
|
+
setConversation: (key: ConversationData["key"], conversation: ConversationData) => boolean;
|
|
20
|
+
removeConversation: (key: ConversationData["key"]) => boolean;
|
|
21
|
+
getMessages: (key: ConversationData["key"]) => any[] | undefined;
|
|
22
|
+
getSnapshot: () => ConversationData[];
|
|
23
|
+
getActiveConversationKey: () => string;
|
|
24
|
+
subscribe: (callback: () => void) => () => void;
|
|
25
|
+
destroy: () => void;
|
|
26
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { n as chatMessagesStoreHelper } from "./store-C1diHqNH.js";
|
|
2
|
+
import { onScopeDispose, ref, shallowRef } from "vue";
|
|
3
|
+
//#region src/x-conversations/store.ts
|
|
4
|
+
var conversationStoreHelper = {
|
|
5
|
+
_allConversationStores: /* @__PURE__ */ new Map(),
|
|
6
|
+
set: (key, store) => {
|
|
7
|
+
conversationStoreHelper._allConversationStores.set(key, store);
|
|
8
|
+
},
|
|
9
|
+
delete: (key) => {
|
|
10
|
+
conversationStoreHelper._allConversationStores.delete(key);
|
|
11
|
+
},
|
|
12
|
+
getConversation: (conversationKey) => {
|
|
13
|
+
for (const store of conversationStoreHelper._allConversationStores.values()) if (store) {
|
|
14
|
+
const conversation = store.getConversation(conversationKey);
|
|
15
|
+
if (conversation) return conversation;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
var ConversationStore = class {
|
|
20
|
+
conversations = [];
|
|
21
|
+
listeners = [];
|
|
22
|
+
storeKey;
|
|
23
|
+
activeConversationKey;
|
|
24
|
+
emitListeners() {
|
|
25
|
+
this.listeners.forEach((listener) => {
|
|
26
|
+
listener();
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
constructor(defaultConversations, defaultActiveConversationKey) {
|
|
30
|
+
this.setConversations(defaultConversations);
|
|
31
|
+
this.storeKey = Math.random().toString();
|
|
32
|
+
conversationStoreHelper.set(this.storeKey, this);
|
|
33
|
+
this.activeConversationKey = defaultActiveConversationKey;
|
|
34
|
+
}
|
|
35
|
+
setActiveConversationKey = (key) => {
|
|
36
|
+
if (this.activeConversationKey === key) return true;
|
|
37
|
+
this.activeConversationKey = key;
|
|
38
|
+
this.emitListeners();
|
|
39
|
+
return true;
|
|
40
|
+
};
|
|
41
|
+
setConversations = (list) => {
|
|
42
|
+
this.conversations = [...list];
|
|
43
|
+
this.emitListeners();
|
|
44
|
+
return true;
|
|
45
|
+
};
|
|
46
|
+
getConversation = (key) => {
|
|
47
|
+
return this.conversations.find((item) => item.key === key);
|
|
48
|
+
};
|
|
49
|
+
addConversation = (conversation, placement) => {
|
|
50
|
+
if (!this.getConversation(conversation.key)) {
|
|
51
|
+
this.setConversations(placement === "prepend" ? [conversation, ...this.conversations] : [...this.conversations, conversation]);
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
};
|
|
56
|
+
setConversation = (key, conversation) => {
|
|
57
|
+
const exist = this.getConversation(key);
|
|
58
|
+
if (exist) {
|
|
59
|
+
Object.assign(exist, conversation);
|
|
60
|
+
this.setConversations([...this.conversations]);
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
};
|
|
65
|
+
removeConversation = (key) => {
|
|
66
|
+
const index = this.conversations.findIndex((item) => item.key === key);
|
|
67
|
+
if (index !== -1) {
|
|
68
|
+
this.conversations.splice(index, 1);
|
|
69
|
+
this.setConversations([...this.conversations]);
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
return false;
|
|
73
|
+
};
|
|
74
|
+
getMessages = (key) => {
|
|
75
|
+
return chatMessagesStoreHelper.getMessages(key);
|
|
76
|
+
};
|
|
77
|
+
getSnapshot = () => {
|
|
78
|
+
return this.conversations;
|
|
79
|
+
};
|
|
80
|
+
getActiveConversationKey = () => {
|
|
81
|
+
return this.activeConversationKey;
|
|
82
|
+
};
|
|
83
|
+
subscribe = (callback) => {
|
|
84
|
+
this.listeners.push(callback);
|
|
85
|
+
return () => {
|
|
86
|
+
this.listeners = this.listeners.filter((listener) => listener !== callback);
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
destroy = () => {
|
|
90
|
+
conversationStoreHelper.delete(this.storeKey);
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/x-conversations/index.ts
|
|
95
|
+
function useXConversations(config) {
|
|
96
|
+
const store = new ConversationStore(config?.defaultConversations || [], config?.defaultActiveConversationKey || "");
|
|
97
|
+
const conversations = shallowRef(store.getSnapshot());
|
|
98
|
+
const activeConversationKey = ref(store.getActiveConversationKey());
|
|
99
|
+
const syncStore = () => {
|
|
100
|
+
conversations.value = store.getSnapshot();
|
|
101
|
+
activeConversationKey.value = store.getActiveConversationKey();
|
|
102
|
+
};
|
|
103
|
+
const unsubscribe = store.subscribe(syncStore);
|
|
104
|
+
syncStore();
|
|
105
|
+
onScopeDispose(() => {
|
|
106
|
+
unsubscribe();
|
|
107
|
+
store.destroy();
|
|
108
|
+
});
|
|
109
|
+
return {
|
|
110
|
+
conversations,
|
|
111
|
+
activeConversationKey,
|
|
112
|
+
setActiveConversationKey: store.setActiveConversationKey,
|
|
113
|
+
addConversation: store.addConversation,
|
|
114
|
+
removeConversation: store.removeConversation,
|
|
115
|
+
setConversation: store.setConversation,
|
|
116
|
+
getConversation: store.getConversation,
|
|
117
|
+
setConversations: store.setConversations,
|
|
118
|
+
getMessages: store.getMessages
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
export { useXConversations as t };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { AnyObject } from '../_util/types';
|
|
2
|
+
import { MessageInfo, SimpleType } from '../x-chat';
|
|
3
|
+
import { SSEOutput, XStreamOptions } from '../x-stream';
|
|
4
|
+
import { XFetchMiddlewares } from './x-fetch';
|
|
5
|
+
export interface XRequestCallbacks<Output, ChatMessage extends SimpleType = any> {
|
|
6
|
+
onSuccess: (chunks: Output[], responseHeaders: Headers, chatMessage?: MessageInfo<ChatMessage>) => void;
|
|
7
|
+
onError: (error: Error, errorInfo?: any, responseHeaders?: Headers, fallbackMsg?: MessageInfo<ChatMessage>) => void;
|
|
8
|
+
onUpdate?: (chunk: Output, responseHeaders: Headers, chatMessage?: MessageInfo<ChatMessage>) => void;
|
|
9
|
+
}
|
|
10
|
+
export interface XRequestOptions<Input = AnyObject, Output = SSEOutput, ChatMessage extends SimpleType = any> extends RequestInit {
|
|
11
|
+
callbacks?: XRequestCallbacks<Output, ChatMessage>;
|
|
12
|
+
params?: Partial<Input>;
|
|
13
|
+
headers?: Record<string, string>;
|
|
14
|
+
timeout?: number;
|
|
15
|
+
streamTimeout?: number;
|
|
16
|
+
fetch?: (baseURL: Parameters<typeof fetch>[0], options: XRequestOptions<Input, Output>) => Promise<Response>;
|
|
17
|
+
middlewares?: XFetchMiddlewares<Input, Output>;
|
|
18
|
+
transformStream?: XStreamOptions<Output>["transformStream"] | ((baseURL: string, responseHeaders: Headers) => XStreamOptions<Output>["transformStream"]);
|
|
19
|
+
streamSeparator?: string;
|
|
20
|
+
partSeparator?: string;
|
|
21
|
+
kvSeparator?: string;
|
|
22
|
+
manual?: boolean;
|
|
23
|
+
retryInterval?: number;
|
|
24
|
+
retryTimes?: number;
|
|
25
|
+
}
|
|
26
|
+
export type XRequestGlobalOptions<Input, Output> = Pick<XRequestOptions<Input, Output>, "headers" | "timeout" | "streamTimeout" | "middlewares" | "fetch" | "transformStream" | "manual">;
|
|
27
|
+
export type XRequestFunction<Input = AnyObject, Output = SSEOutput> = (baseURL: string, options?: XRequestOptions<Input, Output>) => XRequestClass<Input, Output>;
|
|
28
|
+
export declare function setXRequestGlobalOptions<Input, Output>(options: XRequestGlobalOptions<Input, Output>): void;
|
|
29
|
+
export declare abstract class AbstractXRequestClass<Input, Output, ChatMessage extends SimpleType = any> {
|
|
30
|
+
baseURL: string;
|
|
31
|
+
options: XRequestOptions<Input, Output, ChatMessage>;
|
|
32
|
+
constructor(baseURL: string, options?: XRequestOptions<Input, Output, ChatMessage>);
|
|
33
|
+
abstract get asyncHandler(): Promise<any>;
|
|
34
|
+
abstract get isTimeout(): boolean;
|
|
35
|
+
abstract get isStreamTimeout(): boolean;
|
|
36
|
+
abstract get isRequesting(): boolean;
|
|
37
|
+
abstract get manual(): boolean;
|
|
38
|
+
abstract run(params?: Input): void;
|
|
39
|
+
abstract abort(): void;
|
|
40
|
+
}
|
|
41
|
+
export declare class XRequestClass<Input = AnyObject, Output = SSEOutput, ChatMessage extends SimpleType = any> extends AbstractXRequestClass<Input, Output, ChatMessage> {
|
|
42
|
+
private _asyncHandler;
|
|
43
|
+
private timeoutHandler;
|
|
44
|
+
private _isTimeout;
|
|
45
|
+
private streamTimeoutHandler;
|
|
46
|
+
private _isStreamTimeout;
|
|
47
|
+
private abortController;
|
|
48
|
+
private _isRequesting;
|
|
49
|
+
private _manual;
|
|
50
|
+
private lastManualParams?;
|
|
51
|
+
private retryTimes;
|
|
52
|
+
private retryTimer;
|
|
53
|
+
private lastEventId;
|
|
54
|
+
get asyncHandler(): Promise<any>;
|
|
55
|
+
get isTimeout(): boolean;
|
|
56
|
+
private set isTimeout(value);
|
|
57
|
+
get isStreamTimeout(): boolean;
|
|
58
|
+
private set isStreamTimeout(value);
|
|
59
|
+
get isRequesting(): boolean;
|
|
60
|
+
get manual(): boolean;
|
|
61
|
+
constructor(baseURL: string, options?: XRequestOptions<Input, Output, ChatMessage>);
|
|
62
|
+
run(params?: Input): boolean;
|
|
63
|
+
abort(): void;
|
|
64
|
+
private init;
|
|
65
|
+
private startRequest;
|
|
66
|
+
private finishRequest;
|
|
67
|
+
private customResponseHandler;
|
|
68
|
+
private sseResponseHandler;
|
|
69
|
+
private processStream;
|
|
70
|
+
private jsonResponseHandler;
|
|
71
|
+
private resetRetry;
|
|
72
|
+
}
|
|
73
|
+
declare function XRequest<Input = AnyObject, Output = SSEOutput, ChatMessage extends SimpleType = any>(baseURL: string, options?: XRequestOptions<Input, Output, ChatMessage>): AbstractXRequestClass<Input, Output, ChatMessage>;
|
|
74
|
+
export default XRequest;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { XRequestOptions } from '.';
|
|
2
|
+
export interface XFetchMiddlewares<Input, Output> {
|
|
3
|
+
onRequest?: (baseURL: Parameters<typeof fetch>[0], options: XRequestOptions<Input, Output>) => Promise<[Parameters<typeof fetch>[0], XRequestOptions<Input, Output>]>;
|
|
4
|
+
onResponse?: (response: Response) => Promise<Response>;
|
|
5
|
+
}
|
|
6
|
+
export type XFetchType<Input, Output> = (baseURL: Parameters<typeof fetch>[0], options?: XRequestOptions<Input, Output>) => Promise<Response>;
|
|
7
|
+
declare const XFetch: <Input, Output>(baseURL: Parameters<typeof fetch>[0], options: XRequestOptions<Input, Output>) => Promise<Response>;
|
|
8
|
+
export default XFetch;
|