@antdv-next/x-sdk 0.0.1 → 0.0.2

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.
Files changed (54) hide show
  1. package/dist/_util/resolveMaybeRef.d.ts +2 -0
  2. package/dist/_util/resolveMaybeRef.js +7 -0
  3. package/dist/_util/types.js +0 -0
  4. package/dist/chat-providers/AbstractChatProvider.d.ts +2 -2
  5. package/dist/chat-providers/AbstractChatProvider.js +42 -0
  6. package/dist/chat-providers/DeepSeekChatProvider.d.ts +2 -2
  7. package/dist/chat-providers/DeepSeekChatProvider.js +59 -0
  8. package/dist/chat-providers/DefaultChatProvider.d.ts +2 -2
  9. package/dist/chat-providers/DefaultChatProvider.js +26 -0
  10. package/dist/chat-providers/OpenAIChatProvider.d.ts +2 -2
  11. package/dist/chat-providers/OpenAIChatProvider.js +49 -0
  12. package/dist/chat-providers/index.js +4 -1
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.js +7 -3
  15. package/dist/node_modules/vitest/dist/@vitest/expect/index.js +1456 -0
  16. package/dist/node_modules/vitest/dist/@vitest/pretty-format/index.js +884 -0
  17. package/dist/node_modules/vitest/dist/@vitest/runner/chunk-artifact.js +1543 -0
  18. package/dist/node_modules/vitest/dist/@vitest/snapshot/index.js +660 -0
  19. package/dist/node_modules/vitest/dist/@vitest/spy/index.js +384 -0
  20. package/dist/node_modules/vitest/dist/@vitest/utils/chunk-pathe.M-eThtNZ.js +80 -0
  21. package/dist/node_modules/vitest/dist/@vitest/utils/diff.js +1304 -0
  22. package/dist/node_modules/vitest/dist/@vitest/utils/display.js +556 -0
  23. package/dist/node_modules/vitest/dist/@vitest/utils/error.js +27 -0
  24. package/dist/node_modules/vitest/dist/@vitest/utils/helpers.js +179 -0
  25. package/dist/node_modules/vitest/dist/@vitest/utils/offset.js +25 -0
  26. package/dist/node_modules/vitest/dist/@vitest/utils/serialize.js +75 -0
  27. package/dist/node_modules/vitest/dist/@vitest/utils/source-map.js +371 -0
  28. package/dist/node_modules/vitest/dist/@vitest/utils/timers.js +35 -0
  29. package/dist/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js +4 -0
  30. package/dist/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js +50 -0
  31. package/dist/node_modules/vitest/dist/chunks/test.CBQUpOM3.js +2640 -0
  32. package/dist/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js +42 -0
  33. package/dist/node_modules/vitest/dist/vendor/chai.js +2872 -0
  34. package/dist/node_modules/vitest/dist/vendor/magic-string.js +1009 -0
  35. package/dist/node_modules/vitest/dist/vendor/tinyrainbow.js +84 -0
  36. package/dist/x-chat/__tests__/index.test.d.ts +1 -0
  37. package/dist/x-chat/__tests__/index.test.js +257 -0
  38. package/dist/x-chat/index.d.ts +14 -23
  39. package/dist/x-chat/index.js +83 -66
  40. package/dist/x-chat/store.d.ts +2 -0
  41. package/dist/{store-C1diHqNH.js → x-chat/store.js} +15 -9
  42. package/dist/x-conversations/__tests__/index.test.d.ts +1 -0
  43. package/dist/x-conversations/__tests__/index.test.js +36 -0
  44. package/dist/x-conversations/index.d.ts +4 -4
  45. package/dist/x-conversations/index.js +37 -1
  46. package/dist/{x-conversations-BrKWhj5r.js → x-conversations/store.js} +2 -31
  47. package/dist/x-request/__tests__/index.test.d.ts +1 -0
  48. package/dist/x-request/__tests__/index.test.js +90 -0
  49. package/dist/x-request/index.d.ts +36 -11
  50. package/dist/x-request/index.js +246 -1
  51. package/dist/x-request/x-fetch.js +18 -0
  52. package/package.json +1 -1
  53. package/dist/chat-providers-5x9Va7p5.js +0 -167
  54. package/dist/x-request-BSFGaKND.js +0 -234
@@ -0,0 +1,84 @@
1
+ //#region ../../node_modules/vitest/dist/vendor/tinyrainbow.mjs
2
+ var d = {
3
+ reset: [0, 0],
4
+ bold: [
5
+ 1,
6
+ 22,
7
+ "\x1B[22m\x1B[1m"
8
+ ],
9
+ dim: [
10
+ 2,
11
+ 22,
12
+ "\x1B[22m\x1B[2m"
13
+ ],
14
+ italic: [3, 23],
15
+ underline: [4, 24],
16
+ inverse: [7, 27],
17
+ hidden: [8, 28],
18
+ strikethrough: [9, 29],
19
+ black: [30, 39],
20
+ red: [31, 39],
21
+ green: [32, 39],
22
+ yellow: [33, 39],
23
+ blue: [34, 39],
24
+ magenta: [35, 39],
25
+ cyan: [36, 39],
26
+ white: [37, 39],
27
+ gray: [90, 39],
28
+ bgBlack: [40, 49],
29
+ bgRed: [41, 49],
30
+ bgGreen: [42, 49],
31
+ bgYellow: [43, 49],
32
+ bgBlue: [44, 49],
33
+ bgMagenta: [45, 49],
34
+ bgCyan: [46, 49],
35
+ bgWhite: [47, 49],
36
+ blackBright: [90, 39],
37
+ redBright: [91, 39],
38
+ greenBright: [92, 39],
39
+ yellowBright: [93, 39],
40
+ blueBright: [94, 39],
41
+ magentaBright: [95, 39],
42
+ cyanBright: [96, 39],
43
+ whiteBright: [97, 39],
44
+ bgBlackBright: [100, 49],
45
+ bgRedBright: [101, 49],
46
+ bgGreenBright: [102, 49],
47
+ bgYellowBright: [103, 49],
48
+ bgBlueBright: [104, 49],
49
+ bgMagentaBright: [105, 49],
50
+ bgCyanBright: [106, 49],
51
+ bgWhiteBright: [107, 49]
52
+ };
53
+ function g(e) {
54
+ return String(e);
55
+ }
56
+ g.open = "";
57
+ g.close = "";
58
+ function h() {
59
+ let e = typeof process != "undefined" ? process : void 0, n = (e == null ? void 0 : e.env) || {}, a = n.FORCE_TTY !== "false", i = (e == null ? void 0 : e.argv) || [];
60
+ return !("NO_COLOR" in n || i.includes("--no-color")) && ("FORCE_COLOR" in n || i.includes("--color") || (e == null ? void 0 : e.platform) === "win32" || a && n.TERM !== "dumb" || "CI" in n) || typeof window != "undefined" && !!window.chrome;
61
+ }
62
+ function f() {
63
+ let e = h(), n = (r, t, u, o) => {
64
+ let l = "", s = 0;
65
+ do
66
+ l += r.substring(s, o) + u, s = o + t.length, o = r.indexOf(t, s);
67
+ while (~o);
68
+ return l + r.substring(s);
69
+ }, a = (r, t, u = r) => {
70
+ let o = (l) => {
71
+ let s = String(l), b = s.indexOf(t, r.length);
72
+ return ~b ? r + n(s, t, u, b) + t : r + s + t;
73
+ };
74
+ return o.open = r, o.close = t, o;
75
+ }, i = { isColorSupported: e }, c = (r) => `\x1B[${r}m`;
76
+ for (let r in d) {
77
+ let t = d[r];
78
+ i[r] = e ? a(c(t[0]), c(t[1]), t[2]) : g;
79
+ }
80
+ return i;
81
+ }
82
+ var C = f();
83
+ //#endregion
84
+ export { C };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,257 @@
1
+ import AbstractChatProvider from "../../chat-providers/AbstractChatProvider.js";
2
+ import { AbstractXRequestClass } from "../../x-request/index.js";
3
+ import { chatMessagesStoreHelper } from "../store.js";
4
+ import useXChat from "../index.js";
5
+ import { describe, it } from "../../node_modules/vitest/dist/@vitest/runner/chunk-artifact.js";
6
+ import { globalExpect, vi } from "../../node_modules/vitest/dist/chunks/test.CBQUpOM3.js";
7
+ import { computed, effectScope, nextTick, reactive, readonly, ref } from "vue";
8
+ //#region src/x-chat/__tests__/index.test.ts
9
+ var MockManualRequest = class extends AbstractXRequestClass {
10
+ _asyncHandler = Promise.resolve();
11
+ _state = reactive({
12
+ isTimeout: false,
13
+ isStreamTimeout: false,
14
+ isRequesting: false
15
+ });
16
+ constructor(shouldFail) {
17
+ super("https://mock.request", { manual: true });
18
+ this.shouldFail = shouldFail;
19
+ }
20
+ get asyncHandler() {
21
+ return this._asyncHandler;
22
+ }
23
+ get isTimeout() {
24
+ return this._state.isTimeout;
25
+ }
26
+ get isStreamTimeout() {
27
+ return this._state.isStreamTimeout;
28
+ }
29
+ get isRequesting() {
30
+ return this._state.isRequesting;
31
+ }
32
+ get manual() {
33
+ return true;
34
+ }
35
+ get state() {
36
+ return readonly(this._state);
37
+ }
38
+ run(params) {
39
+ const callbacks = this.options.callbacks;
40
+ this._state.isRequesting = true;
41
+ this._asyncHandler = new Promise((resolve) => {
42
+ setTimeout(() => {
43
+ const headers = new Headers({ "content-type": "application/json" });
44
+ if (this.shouldFail.value) callbacks?.onError?.(/* @__PURE__ */ new Error("MockError"), { error: { message: "mock failed" } }, headers);
45
+ else {
46
+ const chunk = `echo:${params?.input || ""}`;
47
+ callbacks?.onUpdate?.(chunk, headers);
48
+ callbacks?.onSuccess?.([chunk], headers);
49
+ }
50
+ this._state.isRequesting = false;
51
+ resolve();
52
+ }, 0);
53
+ });
54
+ }
55
+ abort() {
56
+ this._state.isRequesting = false;
57
+ }
58
+ };
59
+ var MockProvider = class extends AbstractChatProvider {
60
+ transformParams(requestParams) {
61
+ return { input: requestParams.input || "" };
62
+ }
63
+ transformLocalMessage(requestParams) {
64
+ return requestParams.input || "";
65
+ }
66
+ transformMessage(info) {
67
+ if (info.chunk) return info.chunk;
68
+ if (Array.isArray(info.chunks) && info.chunks.length > 0) return info.chunks[info.chunks.length - 1];
69
+ return info.originMessage || "";
70
+ }
71
+ };
72
+ var DeferredManualRequest = class extends AbstractXRequestClass {
73
+ _state = reactive({
74
+ isTimeout: false,
75
+ isStreamTimeout: false,
76
+ isRequesting: false
77
+ });
78
+ callbacks;
79
+ params;
80
+ constructor() {
81
+ super("https://mock.request", { manual: true });
82
+ }
83
+ get asyncHandler() {
84
+ return Promise.resolve();
85
+ }
86
+ get isTimeout() {
87
+ return this._state.isTimeout;
88
+ }
89
+ get isStreamTimeout() {
90
+ return this._state.isStreamTimeout;
91
+ }
92
+ get isRequesting() {
93
+ return this._state.isRequesting;
94
+ }
95
+ get manual() {
96
+ return true;
97
+ }
98
+ get state() {
99
+ return readonly(this._state);
100
+ }
101
+ run(params) {
102
+ this.params = params;
103
+ this.callbacks = this.options.callbacks;
104
+ this._state.isRequesting = true;
105
+ }
106
+ resolve() {
107
+ const headers = new Headers({ "content-type": "application/json" });
108
+ const chunk = `echo:${this.params?.input || ""}`;
109
+ this.callbacks?.onUpdate?.(chunk, headers);
110
+ this.callbacks?.onSuccess?.([chunk], headers);
111
+ this._state.isRequesting = false;
112
+ }
113
+ abort() {
114
+ this._state.isRequesting = false;
115
+ }
116
+ };
117
+ describe("useXChat", () => {
118
+ it("uses reactive requestPlaceholder and requestFallback refs", async () => {
119
+ vi.useFakeTimers();
120
+ const shouldFail = ref(false);
121
+ const request = new MockManualRequest(shouldFail);
122
+ const provider = new MockProvider({ request });
123
+ const requestPlaceholder = ref("Thinking #1");
124
+ const requestFallback = ref("Fallback #1");
125
+ const scope = effectScope();
126
+ const chat = scope.run(() => useXChat({
127
+ provider,
128
+ requestPlaceholder,
129
+ requestFallback
130
+ }));
131
+ globalExpect(chat).toBeTruthy();
132
+ if (!chat) return;
133
+ chat.onRequest({ input: "hello" });
134
+ globalExpect(chat.messages.value.at(-1)?.status).toBe("loading");
135
+ globalExpect(chat.messages.value.at(-1)?.message).toBe("Thinking #1");
136
+ await vi.runAllTimersAsync();
137
+ await request.asyncHandler;
138
+ requestPlaceholder.value = "Thinking #2";
139
+ chat.onRequest({ input: "again" });
140
+ globalExpect(chat.messages.value.at(-1)?.status).toBe("loading");
141
+ globalExpect(chat.messages.value.at(-1)?.message).toBe("Thinking #2");
142
+ await vi.runAllTimersAsync();
143
+ await request.asyncHandler;
144
+ shouldFail.value = true;
145
+ chat.onRequest({ input: "error" });
146
+ await vi.runAllTimersAsync();
147
+ await request.asyncHandler;
148
+ globalExpect(chat.messages.value.at(-1)?.status).toBe("error");
149
+ globalExpect(chat.messages.value.at(-1)?.message).toBe("Fallback #1");
150
+ requestFallback.value = "Fallback #2";
151
+ chat.onRequest({ input: "error-again" });
152
+ await vi.runAllTimersAsync();
153
+ await request.asyncHandler;
154
+ globalExpect(chat.messages.value.at(-1)?.status).toBe("error");
155
+ globalExpect(chat.messages.value.at(-1)?.message).toBe("Fallback #2");
156
+ scope.stop();
157
+ vi.useRealTimers();
158
+ });
159
+ it("refreshes default messages when defaultMessages ref changes", async () => {
160
+ const defaultMessages = ref([{ message: "history-1" }]);
161
+ const scope = effectScope();
162
+ const chat = scope.run(() => useXChat({ defaultMessages }));
163
+ globalExpect(chat).toBeTruthy();
164
+ if (!chat) return;
165
+ await Promise.resolve();
166
+ await nextTick();
167
+ globalExpect(chat.messages.value.map((item) => item.message)).toEqual(["history-1"]);
168
+ defaultMessages.value = [{ message: "history-2" }];
169
+ await nextTick();
170
+ await Promise.resolve();
171
+ globalExpect(chat.messages.value.map((item) => item.message)).toEqual(["history-2"]);
172
+ scope.stop();
173
+ });
174
+ it("accepts computed provider refs", async () => {
175
+ vi.useFakeTimers();
176
+ const shouldFail = ref(false);
177
+ const provider = computed(() => new MockProvider({ request: new MockManualRequest(shouldFail) }));
178
+ const scope = effectScope();
179
+ const chat = scope.run(() => useXChat({ provider }));
180
+ globalExpect(chat).toBeTruthy();
181
+ if (!chat) return;
182
+ chat.onRequest({ input: "provider" });
183
+ await vi.runAllTimersAsync();
184
+ globalExpect(chat.messages.value.at(-1)?.status).toBe("success");
185
+ scope.stop();
186
+ vi.useRealTimers();
187
+ });
188
+ it("derives parsedMessages from parser output", async () => {
189
+ vi.useFakeTimers();
190
+ const scope = effectScope();
191
+ const chat = scope.run(() => useXChat({ parser: (message) => [message.toUpperCase(), `${message}!`] }));
192
+ globalExpect(chat).toBeTruthy();
193
+ if (!chat) return;
194
+ await Promise.resolve();
195
+ await nextTick();
196
+ chat.setMessages([{
197
+ id: "msg_1",
198
+ message: "hello",
199
+ status: "success"
200
+ }]);
201
+ await vi.advanceTimersByTimeAsync(60);
202
+ await nextTick();
203
+ globalExpect(chat.parsedMessages.value).toEqual([{
204
+ id: "msg_1_0",
205
+ message: "HELLO",
206
+ status: "success"
207
+ }, {
208
+ id: "msg_1_1",
209
+ message: "hello!",
210
+ status: "success"
211
+ }]);
212
+ scope.stop();
213
+ vi.useRealTimers();
214
+ });
215
+ it("keeps streaming updates isolated to the request conversation after switching", async () => {
216
+ const activeConversationKey = ref("a");
217
+ const requestA = new DeferredManualRequest();
218
+ const requestB = new DeferredManualRequest();
219
+ const providers = {
220
+ a: new MockProvider({ request: requestA }),
221
+ b: new MockProvider({ request: requestB })
222
+ };
223
+ const scope = effectScope();
224
+ const chat = scope.run(() => useXChat({
225
+ provider: computed(() => providers[activeConversationKey.value]),
226
+ conversationKey: activeConversationKey
227
+ }));
228
+ globalExpect(chat).toBeTruthy();
229
+ if (!chat) return;
230
+ await Promise.resolve();
231
+ await nextTick();
232
+ chat.onRequest({ input: "from-a" });
233
+ globalExpect(chat.messages.value.map((item) => item.message)).toEqual(["from-a"]);
234
+ activeConversationKey.value = "b";
235
+ await nextTick();
236
+ globalExpect(chat.messages.value).toEqual([]);
237
+ requestA.resolve();
238
+ await nextTick();
239
+ globalExpect(chat.messages.value).toEqual([]);
240
+ globalExpect(chatMessagesStoreHelper.getMessages("a")?.map((item) => ({
241
+ message: item.message,
242
+ status: item.status
243
+ }))).toEqual([{
244
+ message: "from-a",
245
+ status: "local"
246
+ }, {
247
+ message: "echo:from-a",
248
+ status: "success"
249
+ }]);
250
+ globalExpect(chatMessagesStoreHelper.getMessages("b")).toEqual([]);
251
+ activeConversationKey.value = "a";
252
+ await nextTick();
253
+ globalExpect(chat.messages.value.map((item) => item.message)).toEqual(["from-a", "echo:from-a"]);
254
+ scope.stop();
255
+ });
256
+ });
257
+ //#endregion
@@ -1,4 +1,4 @@
1
- import { Ref } from 'vue';
1
+ import { MaybeRef } from 'vue';
2
2
  import { AnyObject } from '../_util/types';
3
3
  import { ConversationData } from '../x-conversations';
4
4
  import { SSEOutput } from '../x-stream';
@@ -26,18 +26,19 @@ type RequestFallbackFn<Input, MessageInfoType, Message> = (requestParams: Partia
26
26
  export type RequestParams<Message> = {
27
27
  [Key: PropertyKey]: Message;
28
28
  } & AnyObject;
29
- type MaybeRef<T> = T | Ref<T>;
29
+ type ParserFn<ChatMessage, BubbleMessage> = (message: ChatMessage) => BubbleMessage | BubbleMessage[];
30
+ type DefaultMessagesFn<ChatMessage extends SimpleType> = ((info: {
31
+ conversationKey?: ConversationData["key"];
32
+ }) => Promise<DefaultMessageInfo<ChatMessage>[]>) | ((info?: {
33
+ conversationKey?: ConversationData["key"];
34
+ }) => DefaultMessageInfo<ChatMessage>[]);
30
35
  export interface XChatConfig<ChatMessage extends SimpleType = string, BubbleMessage extends SimpleType = ChatMessage, Input = ChatMessage, Output = ChatMessage> {
31
- provider?: AbstractChatProvider<ChatMessage, Input, Output>;
36
+ provider?: MaybeRef<AbstractChatProvider<ChatMessage, Input, Output>>;
32
37
  conversationKey?: MaybeRef<ConversationData["key"] | undefined>;
33
- defaultMessages?: DefaultMessageInfo<ChatMessage>[] | ((info: {
34
- conversationKey?: ConversationData["key"];
35
- }) => Promise<DefaultMessageInfo<ChatMessage>[]>) | ((info?: {
36
- conversationKey?: ConversationData["key"];
37
- }) => DefaultMessageInfo<ChatMessage>[]);
38
- parser?: (message: ChatMessage) => BubbleMessage | BubbleMessage[];
39
- requestPlaceholder?: ChatMessage | RequestPlaceholderFn<Input, ChatMessage>;
40
- requestFallback?: ChatMessage | RequestFallbackFn<Input, MessageInfo<ChatMessage>, ChatMessage>;
38
+ defaultMessages?: MaybeRef<DefaultMessageInfo<ChatMessage>[]> | DefaultMessagesFn<ChatMessage>;
39
+ parser?: ParserFn<ChatMessage, BubbleMessage> | undefined;
40
+ requestPlaceholder?: MaybeRef<ChatMessage> | RequestPlaceholderFn<Input, ChatMessage>;
41
+ requestFallback?: MaybeRef<ChatMessage> | RequestFallbackFn<Input, MessageInfo<ChatMessage>, ChatMessage>;
41
42
  }
42
43
  export interface MessageInfo<Message extends SimpleType> {
43
44
  id: number | string;
@@ -58,18 +59,8 @@ export default function useXChat<ChatMessage extends SimpleType = string, Parsed
58
59
  readonly onRequest: (requestParams: Partial<Input>, opts?: {
59
60
  extraInfo: AnyObject;
60
61
  }) => void;
61
- readonly isDefaultMessagesRequesting: Ref<boolean, boolean>;
62
- readonly messages: Ref<{
63
- id: number | string;
64
- message: import('vue').UnwrapRef<ChatMessage>;
65
- status: MessageStatus;
66
- extraInfo?: AnyObject | undefined;
67
- }[], MessageInfo<ChatMessage>[] | {
68
- id: number | string;
69
- message: import('vue').UnwrapRef<ChatMessage>;
70
- status: MessageStatus;
71
- extraInfo?: AnyObject | undefined;
72
- }[]>;
62
+ readonly isDefaultMessagesRequesting: Readonly<import('vue').Ref<boolean, boolean>>;
63
+ readonly messages: import('vue').ShallowRef<MessageInfo<ChatMessage>[], MessageInfo<ChatMessage>[]>;
73
64
  readonly parsedMessages: import('vue').ComputedRef<MessageInfo<ParsedMessage>[]>;
74
65
  readonly setMessages: (updater: MessageInfo<ChatMessage>[] | ((ori: MessageInfo<ChatMessage>[]) => MessageInfo<ChatMessage>[])) => boolean;
75
66
  readonly removeMessage: (id: string | number) => boolean;
@@ -1,28 +1,49 @@
1
- import { n as chatMessagesStoreHelper, t as ChatMessagesStore } from "../store-C1diHqNH.js";
2
- import { computed, isRef, onScopeDispose, reactive, ref, shallowRef, watch } from "vue";
1
+ import resolveMaybeRef from "../_util/resolveMaybeRef.js";
2
+ import "../chat-providers/index.js";
3
+ import "../x-request/index.js";
4
+ import { ChatMessagesStore, chatMessagesStoreHelper } from "./store.js";
5
+ import { computed, isRef, onScopeDispose, reactive, readonly, ref, shallowRef, watch } from "vue";
3
6
  //#region src/x-chat/index.ts
4
7
  function toArray(item) {
5
8
  return Array.isArray(item) ? item : [item];
6
9
  }
7
- function resolveMaybeRef(value) {
8
- return isRef(value) ? value.value : value;
9
- }
10
10
  var IsRequestingMap = reactive(/* @__PURE__ */ new Map());
11
11
  var generateConversationKey = () => Symbol("ConversationKey");
12
12
  function useXChat(config) {
13
- const { defaultMessages, requestFallback, requestPlaceholder, parser, provider } = config;
14
13
  const idRef = ref(0);
15
14
  const requestHandlerRef = shallowRef();
15
+ const providerRef = isRef(config.provider) ? config.provider : shallowRef(config.provider);
16
+ let provider = providerRef.value;
16
17
  const conversationKey = ref((config.conversationKey ? resolveMaybeRef(config.conversationKey) : void 0) ?? generateConversationKey());
17
18
  if (config.conversationKey && isRef(config.conversationKey)) watch(config.conversationKey, (value) => {
18
19
  if (value !== void 0 && value !== null) conversationKey.value = value;
19
20
  });
20
21
  const messageQueueMap = /* @__PURE__ */ new Map();
21
22
  const activeStore = shallowRef();
22
- const messages = ref([]);
23
- const isDefaultMessagesRequesting = ref(false);
23
+ const messages = shallowRef([]);
24
+ const isDefaultMessagesRequestingRef = shallowRef(false);
25
+ const parsedMessages = computed(() => {
26
+ const parser = config.parser;
27
+ const list = [];
28
+ messages.value.forEach((agentMsg) => {
29
+ const sourceMessage = agentMsg.message;
30
+ const bubbleMsgs = toArray(parser ? parser(sourceMessage) : sourceMessage);
31
+ bubbleMsgs.forEach((bubbleMsg, bubbleMsgIndex) => {
32
+ let key = agentMsg.id;
33
+ if (bubbleMsgs.length > 1) key = `${key}_${bubbleMsgIndex}`;
34
+ list.push({
35
+ id: key,
36
+ message: bubbleMsg,
37
+ status: agentMsg.status
38
+ });
39
+ });
40
+ });
41
+ return list;
42
+ });
24
43
  let unsubscribeStore = null;
25
44
  const resolveDefaultMessages = async (currentConversationKey) => {
45
+ const sourceDefaultMessages = config.defaultMessages;
46
+ const defaultMessages = typeof sourceDefaultMessages === "function" ? sourceDefaultMessages : resolveMaybeRef(sourceDefaultMessages);
26
47
  return ((typeof defaultMessages === "function" ? await defaultMessages({ conversationKey: currentConversationKey }) : defaultMessages) || []).map((info, index) => ({
27
48
  id: `default_${index}`,
28
49
  status: "local",
@@ -37,12 +58,12 @@ function useXChat(config) {
37
58
  const syncStoreSnapshot = () => {
38
59
  if (!activeStore.value) {
39
60
  messages.value = [];
40
- isDefaultMessagesRequesting.value = false;
61
+ isDefaultMessagesRequestingRef.value = false;
41
62
  return;
42
63
  }
43
64
  const snapshot = activeStore.value.getSnapshot();
44
65
  messages.value = snapshot.messages;
45
- isDefaultMessagesRequesting.value = snapshot.isDefaultMessagesRequesting;
66
+ isDefaultMessagesRequestingRef.value = snapshot.isDefaultMessagesRequesting;
46
67
  };
47
68
  const bindStore = (currentConversationKey) => {
48
69
  if (unsubscribeStore) {
@@ -85,38 +106,32 @@ function useXChat(config) {
85
106
  idRef.value += 1;
86
107
  return msg;
87
108
  };
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
109
  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());
110
+ const setupProvider = (nextProvider) => {
111
+ provider = nextProvider;
112
+ if (nextProvider) {
113
+ nextProvider.injectGetMessages(() => {
114
+ return getFilteredMessages(getMessages());
115
+ });
116
+ requestHandlerRef.value = nextProvider.request;
117
+ } else requestHandlerRef.value = void 0;
118
+ };
119
+ setupProvider(provider);
120
+ watch(providerRef, setupProvider);
111
121
  const innerOnRequest = (requestParams, opts) => {
112
122
  if (!provider) return;
123
+ const activeProvider = provider;
124
+ const requestKey = conversationKey.value;
125
+ const requestStore = createStore(requestKey);
113
126
  const { updatingId, reload } = opts || {};
114
127
  let loadingMsgId = null;
115
- const localMessage = provider.transformLocalMessage(requestParams);
128
+ const sourceRequestPlaceholder = config.requestPlaceholder;
129
+ const requestPlaceholder = typeof sourceRequestPlaceholder === "function" ? sourceRequestPlaceholder : resolveMaybeRef(sourceRequestPlaceholder);
130
+ const localMessage = activeProvider.transformLocalMessage(requestParams);
116
131
  const localMessages = (Array.isArray(localMessage) ? localMessage : [localMessage]).map((message) => createMessage(message, "local", opts?.extraInfo));
117
132
  if (reload) {
118
133
  loadingMsgId = updatingId;
119
- setMessages((ori) => {
134
+ requestStore.setMessages((ori) => {
120
135
  const nextMessages = [...ori];
121
136
  if (requestPlaceholder) {
122
137
  let placeholderMsg;
@@ -132,7 +147,7 @@ function useXChat(config) {
132
147
  }
133
148
  return nextMessages;
134
149
  });
135
- } else setMessages((ori) => {
150
+ } else requestStore.setMessages((ori) => {
136
151
  let nextMessages = [...ori, ...localMessages];
137
152
  if (requestPlaceholder) {
138
153
  let placeholderMsg;
@@ -146,38 +161,38 @@ function useXChat(config) {
146
161
  });
147
162
  let updatingMsgId = null;
148
163
  const updateMessage = (status, chunk, chunks, responseHeaders) => {
149
- let msg = getMessages().find((info) => info.id === updatingMsgId);
164
+ let msg = requestStore.getMessages().find((info) => info.id === updatingMsgId);
150
165
  if (!msg) if (reload && updatingId) {
151
- msg = getMessages().find((info) => info.id === updatingId);
166
+ msg = requestStore.getMessages().find((info) => info.id === updatingId);
152
167
  if (msg) {
153
168
  msg.status = status;
154
- msg.message = provider.transformMessage({
169
+ msg.message = activeProvider.transformMessage({
155
170
  chunk,
156
171
  status,
157
172
  chunks,
158
173
  responseHeaders
159
174
  });
160
- setMessages((ori) => {
175
+ requestStore.setMessages((ori) => {
161
176
  return [...ori];
162
177
  });
163
178
  updatingMsgId = msg.id;
164
179
  }
165
180
  } else {
166
- msg = createMessage(provider.transformMessage({
181
+ msg = createMessage(activeProvider.transformMessage({
167
182
  chunk,
168
183
  status,
169
184
  chunks,
170
185
  responseHeaders
171
186
  }), status);
172
- setMessages((ori) => {
187
+ requestStore.setMessages((ori) => {
173
188
  return [...ori.filter((info) => info.id !== loadingMsgId), msg];
174
189
  });
175
190
  updatingMsgId = msg.id;
176
191
  }
177
- else setMessages((ori) => {
192
+ else requestStore.setMessages((ori) => {
178
193
  return ori.map((info) => {
179
194
  if (info.id === updatingMsgId) {
180
- const transformData = provider.transformMessage({
195
+ const transformData = activeProvider.transformMessage({
181
196
  originMessage: info.message,
182
197
  chunk,
183
198
  chunks,
@@ -193,34 +208,36 @@ function useXChat(config) {
193
208
  return info;
194
209
  });
195
210
  });
196
- msg = getMessages().find((info) => info.id === updatingMsgId) || msg;
211
+ msg = requestStore.getMessages().find((info) => info.id === updatingMsgId) || msg;
197
212
  return msg;
198
213
  };
199
- provider.injectRequest({
214
+ activeProvider.injectRequest({
200
215
  onUpdate: (chunk, headers) => {
201
216
  return updateMessage("updating", chunk, [], headers);
202
217
  },
203
218
  onSuccess: (chunks, headers) => {
204
- if (conversationKey.value) IsRequestingMap.delete(conversationKey.value);
219
+ if (requestKey) IsRequestingMap.delete(requestKey);
205
220
  return updateMessage("success", void 0, chunks, headers);
206
221
  },
207
222
  onError: async (error, errorInfo) => {
208
- if (conversationKey.value) IsRequestingMap.delete(conversationKey.value);
223
+ if (requestKey) IsRequestingMap.delete(requestKey);
209
224
  let fallbackMsg;
225
+ const sourceRequestFallback = config.requestFallback;
226
+ const requestFallback = typeof sourceRequestFallback === "function" ? sourceRequestFallback : resolveMaybeRef(sourceRequestFallback);
210
227
  if (requestFallback) {
211
228
  if (typeof requestFallback === "function") {
212
- const currentMessages = getRequestMessages();
229
+ const currentMessages = getFilteredMessages(requestStore.getMessages());
213
230
  fallbackMsg = await requestFallback(requestParams, {
214
231
  error,
215
232
  errorInfo,
216
- messageInfo: getMessages().find((info) => info.id === loadingMsgId || info.id === updatingMsgId),
233
+ messageInfo: requestStore.getMessages().find((info) => info.id === loadingMsgId || info.id === updatingMsgId),
217
234
  messages: currentMessages
218
235
  });
219
236
  } else fallbackMsg = requestFallback;
220
- setMessages((ori) => [...ori.filter((info) => info.id !== loadingMsgId && info.id !== updatingMsgId), createMessage(fallbackMsg, error.name === "AbortError" ? "abort" : "error")]);
237
+ requestStore.setMessages((ori) => [...ori.filter((info) => info.id !== loadingMsgId && info.id !== updatingMsgId), createMessage(fallbackMsg, error.name === "AbortError" ? "abort" : "error")]);
221
238
  } else {
222
- fallbackMsg = getMessages().find((info) => info.id !== loadingMsgId && info.id !== updatingMsgId);
223
- setMessages((ori) => {
239
+ fallbackMsg = requestStore.getMessages().find((info) => info.id !== loadingMsgId && info.id !== updatingMsgId)?.message;
240
+ requestStore.setMessages((ori) => {
224
241
  return ori.map((info) => {
225
242
  if (info.id === loadingMsgId || info.id === updatingMsgId) return {
226
243
  ...info,
@@ -233,15 +250,15 @@ function useXChat(config) {
233
250
  return fallbackMsg;
234
251
  }
235
252
  });
236
- if (conversationKey.value) IsRequestingMap.set(conversationKey.value, true);
237
- provider.request.run(provider.transformParams(requestParams, provider.request.options));
253
+ if (requestKey) IsRequestingMap.set(requestKey, true);
254
+ activeProvider.request.run(activeProvider.transformParams(requestParams, activeProvider.request.options));
238
255
  };
239
256
  const onRequest = (requestParams, opts) => {
240
- if (!provider) throw new Error("provider is required");
257
+ if (!providerRef.value) throw new Error("provider is required");
241
258
  innerOnRequest(requestParams, opts);
242
259
  };
243
260
  const onReload = (id, requestParams, opts) => {
244
- if (!provider) throw new Error("provider is required");
261
+ if (!providerRef.value) throw new Error("provider is required");
245
262
  if (!id || !getMessages().find((info) => info.id === id)) throw new Error(`message [${id}] is not found`);
246
263
  innerOnRequest(requestParams, {
247
264
  updatingId: id,
@@ -251,19 +268,19 @@ function useXChat(config) {
251
268
  };
252
269
  const processMessageQueue = () => {
253
270
  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);
271
+ if (requestParamsList && requestParamsList.length > 0) setTimeout(() => {
272
+ requestParamsList.forEach(({ requestParams, opts }) => {
273
+ onRequest(requestParams, opts);
261
274
  });
262
- }
275
+ messageQueueMap.delete(conversationKey.value);
276
+ });
263
277
  };
264
- watch(isDefaultMessagesRequesting, (requesting) => {
278
+ watch(isDefaultMessagesRequestingRef, (requesting) => {
265
279
  if (!requesting) processMessageQueue();
266
280
  });
281
+ if (config.defaultMessages && isRef(config.defaultMessages)) watch(config.defaultMessages, () => {
282
+ activeStore.value?.refreshDefaultMessages();
283
+ }, { deep: true });
267
284
  const queueRequest = (currentConversationKey, requestParams, opts) => {
268
285
  if (!messageQueueMap.has(currentConversationKey)) messageQueueMap.set(currentConversationKey, []);
269
286
  messageQueueMap.get(currentConversationKey).push({
@@ -273,7 +290,7 @@ function useXChat(config) {
273
290
  };
274
291
  return {
275
292
  onRequest,
276
- isDefaultMessagesRequesting,
293
+ isDefaultMessagesRequesting: readonly(isDefaultMessagesRequestingRef),
277
294
  messages,
278
295
  parsedMessages,
279
296
  setMessages,