ai 2.2.1 → 2.2.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.
- package/dist/index.d.ts +174 -99
- package/dist/index.js +280 -88
- package/dist/index.mjs +273 -88
- package/package.json +1 -1
- package/react/dist/index.d.ts +2 -0
- package/react/dist/index.js +186 -46
- package/react/dist/index.mjs +186 -46
- package/solid/dist/index.js +34 -4
- package/solid/dist/index.mjs +34 -4
- package/svelte/dist/index.js +34 -4
- package/svelte/dist/index.mjs +34 -4
- package/vue/dist/index.js +34 -4
- package/vue/dist/index.mjs +34 -4
package/react/dist/index.js
CHANGED
@@ -46,17 +46,48 @@ var nanoid = (0, import_non_secure.customAlphabet)(
|
|
46
46
|
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
47
47
|
7
|
48
48
|
);
|
49
|
-
function createChunkDecoder() {
|
49
|
+
function createChunkDecoder(complex) {
|
50
50
|
const decoder = new TextDecoder();
|
51
|
+
if (!complex) {
|
52
|
+
return function(chunk) {
|
53
|
+
if (!chunk)
|
54
|
+
return "";
|
55
|
+
return decoder.decode(chunk, { stream: true });
|
56
|
+
};
|
57
|
+
}
|
51
58
|
return function(chunk) {
|
52
|
-
|
53
|
-
|
54
|
-
return decoder.decode(chunk, { stream: true });
|
59
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
60
|
+
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
55
61
|
};
|
56
62
|
}
|
63
|
+
var StreamStringPrefixes = {
|
64
|
+
text: 0,
|
65
|
+
function_call: 1,
|
66
|
+
data: 2
|
67
|
+
// user_err: 3?
|
68
|
+
};
|
69
|
+
var getStreamStringTypeAndValue = (line) => {
|
70
|
+
const firstSeperatorIndex = line.indexOf(":");
|
71
|
+
const prefix = line.slice(0, firstSeperatorIndex);
|
72
|
+
const type = Object.keys(StreamStringPrefixes).find(
|
73
|
+
(key) => StreamStringPrefixes[key] === Number(prefix)
|
74
|
+
);
|
75
|
+
const val = line.slice(firstSeperatorIndex + 1);
|
76
|
+
let parsedVal = val;
|
77
|
+
if (!val) {
|
78
|
+
return { type, value: "" };
|
79
|
+
}
|
80
|
+
try {
|
81
|
+
parsedVal = JSON.parse(val);
|
82
|
+
} catch (e) {
|
83
|
+
console.error("Failed to parse JSON value:", val);
|
84
|
+
}
|
85
|
+
return { type, value: parsedVal };
|
86
|
+
};
|
87
|
+
var COMPLEX_HEADER = "X-Experimental-Stream-Data";
|
57
88
|
|
58
89
|
// react/use-chat.ts
|
59
|
-
var getStreamedResponse = async (api, chatRequest, mutate, extraMetadataRef, messagesRef, abortControllerRef, onFinish, onResponse, sendExtraMessageFields) => {
|
90
|
+
var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, existingData, extraMetadataRef, messagesRef, abortControllerRef, onFinish, onResponse, sendExtraMessageFields) => {
|
60
91
|
var _a, _b;
|
61
92
|
const previousMessages = messagesRef.current;
|
62
93
|
mutate(chatRequest.messages, false);
|
@@ -108,43 +139,124 @@ var getStreamedResponse = async (api, chatRequest, mutate, extraMetadataRef, mes
|
|
108
139
|
if (!res.body) {
|
109
140
|
throw new Error("The response body is empty.");
|
110
141
|
}
|
111
|
-
|
142
|
+
const isComplexMode = res.headers.get(COMPLEX_HEADER) === "true";
|
112
143
|
const createdAt = /* @__PURE__ */ new Date();
|
113
|
-
const replyId = nanoid();
|
114
144
|
const reader = res.body.getReader();
|
115
|
-
const decode = createChunkDecoder();
|
145
|
+
const decode = createChunkDecoder(isComplexMode);
|
146
|
+
let responseMessages = [];
|
147
|
+
let streamedResponse = "";
|
148
|
+
const replyId = nanoid();
|
116
149
|
let responseMessage = {
|
117
150
|
id: replyId,
|
118
151
|
createdAt,
|
119
152
|
content: "",
|
120
153
|
role: "assistant"
|
121
154
|
};
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
155
|
+
let responseData = [];
|
156
|
+
const prefixMap = {};
|
157
|
+
if (isComplexMode) {
|
158
|
+
while (true) {
|
159
|
+
const { done, value } = await reader.read();
|
160
|
+
if (done) {
|
161
|
+
break;
|
162
|
+
}
|
163
|
+
const lines = decode(value);
|
164
|
+
if (typeof lines === "string") {
|
165
|
+
throw new Error(
|
166
|
+
"Invalid response format. Complex mode was set but the response is a string. This should never happen."
|
167
|
+
);
|
168
|
+
}
|
169
|
+
for (const { type, value: value2 } of lines) {
|
170
|
+
if (type === "text") {
|
171
|
+
if (prefixMap["text"]) {
|
172
|
+
prefixMap["text"] = {
|
173
|
+
...prefixMap["text"],
|
174
|
+
content: (prefixMap["text"].content || "") + value2
|
175
|
+
};
|
176
|
+
} else {
|
177
|
+
prefixMap["text"] = {
|
178
|
+
id: nanoid(),
|
179
|
+
role: "assistant",
|
180
|
+
content: value2,
|
181
|
+
createdAt
|
182
|
+
};
|
183
|
+
}
|
184
|
+
}
|
185
|
+
if (type === "function_call") {
|
186
|
+
prefixMap["function_call"] = value2;
|
187
|
+
}
|
188
|
+
if (type === "data") {
|
189
|
+
const parsedValue = JSON.parse(value2);
|
190
|
+
if (prefixMap["data"]) {
|
191
|
+
prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
|
192
|
+
} else {
|
193
|
+
prefixMap["data"] = parsedValue;
|
194
|
+
}
|
195
|
+
}
|
196
|
+
const data = prefixMap["data"];
|
197
|
+
const responseMessage2 = prefixMap["text"];
|
198
|
+
let functionCall = prefixMap["function_call"];
|
199
|
+
let functionCallMessage = null;
|
200
|
+
if (functionCall) {
|
201
|
+
const parsedFunctionCall = JSON.parse(functionCall).function_call;
|
202
|
+
functionCallMessage = {
|
203
|
+
id: nanoid(),
|
204
|
+
role: "function",
|
205
|
+
content: "",
|
206
|
+
name: parsedFunctionCall.name,
|
207
|
+
createdAt
|
208
|
+
};
|
209
|
+
}
|
210
|
+
const merged = [functionCallMessage, responseMessage2].filter(
|
211
|
+
Boolean
|
212
|
+
);
|
213
|
+
mutate([...chatRequest.messages, ...merged], false);
|
214
|
+
mutateStreamData([...existingData || [], ...data || []]);
|
215
|
+
if (abortControllerRef.current === null) {
|
216
|
+
reader.cancel();
|
217
|
+
break;
|
218
|
+
}
|
219
|
+
}
|
220
|
+
}
|
221
|
+
for (const [type, item] of Object.entries(prefixMap)) {
|
222
|
+
if (onFinish && type === "text") {
|
223
|
+
onFinish(item);
|
224
|
+
}
|
225
|
+
if (type === "data") {
|
226
|
+
responseData.push(item);
|
227
|
+
} else {
|
228
|
+
responseMessages.push(item);
|
229
|
+
}
|
230
|
+
}
|
231
|
+
return { messages: responseMessages, data: responseData };
|
232
|
+
} else {
|
233
|
+
while (true) {
|
234
|
+
const { done, value } = await reader.read();
|
235
|
+
if (done) {
|
236
|
+
break;
|
237
|
+
}
|
238
|
+
streamedResponse += decode(value);
|
239
|
+
if (streamedResponse.startsWith('{"function_call":')) {
|
240
|
+
responseMessage["function_call"] = streamedResponse;
|
241
|
+
} else {
|
242
|
+
responseMessage["content"] = streamedResponse;
|
243
|
+
}
|
244
|
+
mutate([...chatRequest.messages, { ...responseMessage }], false);
|
245
|
+
if (abortControllerRef.current === null) {
|
246
|
+
reader.cancel();
|
247
|
+
break;
|
248
|
+
}
|
126
249
|
}
|
127
|
-
streamedResponse += decode(value);
|
128
250
|
if (streamedResponse.startsWith('{"function_call":')) {
|
129
|
-
|
130
|
-
|
131
|
-
|
251
|
+
const parsedFunctionCall = JSON.parse(streamedResponse).function_call;
|
252
|
+
responseMessage["function_call"] = parsedFunctionCall;
|
253
|
+
mutate([...chatRequest.messages, { ...responseMessage }]);
|
132
254
|
}
|
133
|
-
|
134
|
-
|
135
|
-
reader.cancel();
|
136
|
-
break;
|
255
|
+
if (onFinish) {
|
256
|
+
onFinish(responseMessage);
|
137
257
|
}
|
258
|
+
return responseMessage;
|
138
259
|
}
|
139
|
-
if (streamedResponse.startsWith('{"function_call":')) {
|
140
|
-
const parsedFunctionCall = JSON.parse(streamedResponse).function_call;
|
141
|
-
responseMessage["function_call"] = parsedFunctionCall;
|
142
|
-
mutate([...chatRequest.messages, { ...responseMessage }]);
|
143
|
-
}
|
144
|
-
if (onFinish) {
|
145
|
-
onFinish(responseMessage);
|
146
|
-
}
|
147
|
-
return responseMessage;
|
148
260
|
};
|
149
261
|
function useChat({
|
150
262
|
api = "/api/chat",
|
@@ -162,17 +274,20 @@ function useChat({
|
|
162
274
|
} = {}) {
|
163
275
|
const hookId = (0, import_react.useId)();
|
164
276
|
const chatId = id || hookId;
|
165
|
-
const { data, mutate } = (0, import_swr.default)([api, chatId], null, {
|
277
|
+
const { data: messages, mutate } = (0, import_swr.default)([api, chatId], null, {
|
166
278
|
fallbackData: initialMessages
|
167
279
|
});
|
168
280
|
const { data: isLoading = false, mutate: mutateLoading } = (0, import_swr.default)(
|
169
281
|
[chatId, "loading"],
|
170
282
|
null
|
171
283
|
);
|
172
|
-
const
|
173
|
-
|
284
|
+
const { data: streamData, mutate: mutateStreamData } = (0, import_swr.default)(
|
285
|
+
[chatId, "streamData"],
|
286
|
+
null
|
287
|
+
);
|
288
|
+
const messagesRef = (0, import_react.useRef)(messages || []);
|
174
289
|
(0, import_react.useEffect)(() => {
|
175
|
-
messagesRef.current = messages;
|
290
|
+
messagesRef.current = messages || [];
|
176
291
|
}, [messages]);
|
177
292
|
const abortControllerRef = (0, import_react.useRef)(null);
|
178
293
|
const extraMetadataRef = (0, import_react.useRef)({
|
@@ -194,10 +309,12 @@ function useChat({
|
|
194
309
|
const abortController = new AbortController();
|
195
310
|
abortControllerRef.current = abortController;
|
196
311
|
while (true) {
|
197
|
-
const
|
312
|
+
const messagesAndDataOrJustMessage = await getStreamedResponse(
|
198
313
|
api,
|
199
314
|
chatRequest,
|
200
315
|
mutate,
|
316
|
+
mutateStreamData,
|
317
|
+
streamData,
|
201
318
|
extraMetadataRef,
|
202
319
|
messagesRef,
|
203
320
|
abortControllerRef,
|
@@ -205,19 +322,41 @@ function useChat({
|
|
205
322
|
onResponse,
|
206
323
|
sendExtraMessageFields
|
207
324
|
);
|
208
|
-
if (
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
325
|
+
if ("messages" in messagesAndDataOrJustMessage) {
|
326
|
+
for (const message of messagesAndDataOrJustMessage.messages) {
|
327
|
+
if (message.function_call === void 0 || typeof message.function_call === "string") {
|
328
|
+
break;
|
329
|
+
}
|
330
|
+
if (experimental_onFunctionCall) {
|
331
|
+
const functionCall = message.function_call;
|
332
|
+
const functionCallResponse = await experimental_onFunctionCall(
|
333
|
+
messagesRef.current,
|
334
|
+
functionCall
|
335
|
+
);
|
336
|
+
if (functionCallResponse === void 0)
|
337
|
+
break;
|
338
|
+
chatRequest = functionCallResponse;
|
339
|
+
}
|
340
|
+
}
|
341
|
+
} else {
|
342
|
+
const streamedResponseMessage = messagesAndDataOrJustMessage;
|
343
|
+
if (streamedResponseMessage.function_call === void 0 || typeof streamedResponseMessage.function_call === "string") {
|
215
344
|
break;
|
216
|
-
|
345
|
+
}
|
346
|
+
if (experimental_onFunctionCall) {
|
347
|
+
const functionCall = streamedResponseMessage.function_call;
|
348
|
+
const functionCallResponse = await experimental_onFunctionCall(
|
349
|
+
messagesRef.current,
|
350
|
+
functionCall
|
351
|
+
);
|
352
|
+
if (functionCallResponse === void 0)
|
353
|
+
break;
|
354
|
+
chatRequest = functionCallResponse;
|
355
|
+
}
|
217
356
|
}
|
357
|
+
abortControllerRef.current = null;
|
358
|
+
return null;
|
218
359
|
}
|
219
|
-
abortControllerRef.current = null;
|
220
|
-
return null;
|
221
360
|
} catch (err) {
|
222
361
|
if (err.name === "AbortError") {
|
223
362
|
abortControllerRef.current = null;
|
@@ -311,7 +450,7 @@ function useChat({
|
|
311
450
|
setInput(e.target.value);
|
312
451
|
};
|
313
452
|
return {
|
314
|
-
messages,
|
453
|
+
messages: messages || [],
|
315
454
|
error,
|
316
455
|
append,
|
317
456
|
reload,
|
@@ -321,7 +460,8 @@ function useChat({
|
|
321
460
|
setInput,
|
322
461
|
handleInputChange,
|
323
462
|
handleSubmit,
|
324
|
-
isLoading
|
463
|
+
isLoading,
|
464
|
+
data: streamData
|
325
465
|
};
|
326
466
|
}
|
327
467
|
|
package/react/dist/index.mjs
CHANGED
@@ -10,17 +10,48 @@ var nanoid = customAlphabet(
|
|
10
10
|
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
11
11
|
7
|
12
12
|
);
|
13
|
-
function createChunkDecoder() {
|
13
|
+
function createChunkDecoder(complex) {
|
14
14
|
const decoder = new TextDecoder();
|
15
|
+
if (!complex) {
|
16
|
+
return function(chunk) {
|
17
|
+
if (!chunk)
|
18
|
+
return "";
|
19
|
+
return decoder.decode(chunk, { stream: true });
|
20
|
+
};
|
21
|
+
}
|
15
22
|
return function(chunk) {
|
16
|
-
|
17
|
-
|
18
|
-
return decoder.decode(chunk, { stream: true });
|
23
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
24
|
+
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
19
25
|
};
|
20
26
|
}
|
27
|
+
var StreamStringPrefixes = {
|
28
|
+
text: 0,
|
29
|
+
function_call: 1,
|
30
|
+
data: 2
|
31
|
+
// user_err: 3?
|
32
|
+
};
|
33
|
+
var getStreamStringTypeAndValue = (line) => {
|
34
|
+
const firstSeperatorIndex = line.indexOf(":");
|
35
|
+
const prefix = line.slice(0, firstSeperatorIndex);
|
36
|
+
const type = Object.keys(StreamStringPrefixes).find(
|
37
|
+
(key) => StreamStringPrefixes[key] === Number(prefix)
|
38
|
+
);
|
39
|
+
const val = line.slice(firstSeperatorIndex + 1);
|
40
|
+
let parsedVal = val;
|
41
|
+
if (!val) {
|
42
|
+
return { type, value: "" };
|
43
|
+
}
|
44
|
+
try {
|
45
|
+
parsedVal = JSON.parse(val);
|
46
|
+
} catch (e) {
|
47
|
+
console.error("Failed to parse JSON value:", val);
|
48
|
+
}
|
49
|
+
return { type, value: parsedVal };
|
50
|
+
};
|
51
|
+
var COMPLEX_HEADER = "X-Experimental-Stream-Data";
|
21
52
|
|
22
53
|
// react/use-chat.ts
|
23
|
-
var getStreamedResponse = async (api, chatRequest, mutate, extraMetadataRef, messagesRef, abortControllerRef, onFinish, onResponse, sendExtraMessageFields) => {
|
54
|
+
var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, existingData, extraMetadataRef, messagesRef, abortControllerRef, onFinish, onResponse, sendExtraMessageFields) => {
|
24
55
|
var _a, _b;
|
25
56
|
const previousMessages = messagesRef.current;
|
26
57
|
mutate(chatRequest.messages, false);
|
@@ -72,43 +103,124 @@ var getStreamedResponse = async (api, chatRequest, mutate, extraMetadataRef, mes
|
|
72
103
|
if (!res.body) {
|
73
104
|
throw new Error("The response body is empty.");
|
74
105
|
}
|
75
|
-
|
106
|
+
const isComplexMode = res.headers.get(COMPLEX_HEADER) === "true";
|
76
107
|
const createdAt = /* @__PURE__ */ new Date();
|
77
|
-
const replyId = nanoid();
|
78
108
|
const reader = res.body.getReader();
|
79
|
-
const decode = createChunkDecoder();
|
109
|
+
const decode = createChunkDecoder(isComplexMode);
|
110
|
+
let responseMessages = [];
|
111
|
+
let streamedResponse = "";
|
112
|
+
const replyId = nanoid();
|
80
113
|
let responseMessage = {
|
81
114
|
id: replyId,
|
82
115
|
createdAt,
|
83
116
|
content: "",
|
84
117
|
role: "assistant"
|
85
118
|
};
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
119
|
+
let responseData = [];
|
120
|
+
const prefixMap = {};
|
121
|
+
if (isComplexMode) {
|
122
|
+
while (true) {
|
123
|
+
const { done, value } = await reader.read();
|
124
|
+
if (done) {
|
125
|
+
break;
|
126
|
+
}
|
127
|
+
const lines = decode(value);
|
128
|
+
if (typeof lines === "string") {
|
129
|
+
throw new Error(
|
130
|
+
"Invalid response format. Complex mode was set but the response is a string. This should never happen."
|
131
|
+
);
|
132
|
+
}
|
133
|
+
for (const { type, value: value2 } of lines) {
|
134
|
+
if (type === "text") {
|
135
|
+
if (prefixMap["text"]) {
|
136
|
+
prefixMap["text"] = {
|
137
|
+
...prefixMap["text"],
|
138
|
+
content: (prefixMap["text"].content || "") + value2
|
139
|
+
};
|
140
|
+
} else {
|
141
|
+
prefixMap["text"] = {
|
142
|
+
id: nanoid(),
|
143
|
+
role: "assistant",
|
144
|
+
content: value2,
|
145
|
+
createdAt
|
146
|
+
};
|
147
|
+
}
|
148
|
+
}
|
149
|
+
if (type === "function_call") {
|
150
|
+
prefixMap["function_call"] = value2;
|
151
|
+
}
|
152
|
+
if (type === "data") {
|
153
|
+
const parsedValue = JSON.parse(value2);
|
154
|
+
if (prefixMap["data"]) {
|
155
|
+
prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
|
156
|
+
} else {
|
157
|
+
prefixMap["data"] = parsedValue;
|
158
|
+
}
|
159
|
+
}
|
160
|
+
const data = prefixMap["data"];
|
161
|
+
const responseMessage2 = prefixMap["text"];
|
162
|
+
let functionCall = prefixMap["function_call"];
|
163
|
+
let functionCallMessage = null;
|
164
|
+
if (functionCall) {
|
165
|
+
const parsedFunctionCall = JSON.parse(functionCall).function_call;
|
166
|
+
functionCallMessage = {
|
167
|
+
id: nanoid(),
|
168
|
+
role: "function",
|
169
|
+
content: "",
|
170
|
+
name: parsedFunctionCall.name,
|
171
|
+
createdAt
|
172
|
+
};
|
173
|
+
}
|
174
|
+
const merged = [functionCallMessage, responseMessage2].filter(
|
175
|
+
Boolean
|
176
|
+
);
|
177
|
+
mutate([...chatRequest.messages, ...merged], false);
|
178
|
+
mutateStreamData([...existingData || [], ...data || []]);
|
179
|
+
if (abortControllerRef.current === null) {
|
180
|
+
reader.cancel();
|
181
|
+
break;
|
182
|
+
}
|
183
|
+
}
|
184
|
+
}
|
185
|
+
for (const [type, item] of Object.entries(prefixMap)) {
|
186
|
+
if (onFinish && type === "text") {
|
187
|
+
onFinish(item);
|
188
|
+
}
|
189
|
+
if (type === "data") {
|
190
|
+
responseData.push(item);
|
191
|
+
} else {
|
192
|
+
responseMessages.push(item);
|
193
|
+
}
|
194
|
+
}
|
195
|
+
return { messages: responseMessages, data: responseData };
|
196
|
+
} else {
|
197
|
+
while (true) {
|
198
|
+
const { done, value } = await reader.read();
|
199
|
+
if (done) {
|
200
|
+
break;
|
201
|
+
}
|
202
|
+
streamedResponse += decode(value);
|
203
|
+
if (streamedResponse.startsWith('{"function_call":')) {
|
204
|
+
responseMessage["function_call"] = streamedResponse;
|
205
|
+
} else {
|
206
|
+
responseMessage["content"] = streamedResponse;
|
207
|
+
}
|
208
|
+
mutate([...chatRequest.messages, { ...responseMessage }], false);
|
209
|
+
if (abortControllerRef.current === null) {
|
210
|
+
reader.cancel();
|
211
|
+
break;
|
212
|
+
}
|
90
213
|
}
|
91
|
-
streamedResponse += decode(value);
|
92
214
|
if (streamedResponse.startsWith('{"function_call":')) {
|
93
|
-
|
94
|
-
|
95
|
-
|
215
|
+
const parsedFunctionCall = JSON.parse(streamedResponse).function_call;
|
216
|
+
responseMessage["function_call"] = parsedFunctionCall;
|
217
|
+
mutate([...chatRequest.messages, { ...responseMessage }]);
|
96
218
|
}
|
97
|
-
|
98
|
-
|
99
|
-
reader.cancel();
|
100
|
-
break;
|
219
|
+
if (onFinish) {
|
220
|
+
onFinish(responseMessage);
|
101
221
|
}
|
222
|
+
return responseMessage;
|
102
223
|
}
|
103
|
-
if (streamedResponse.startsWith('{"function_call":')) {
|
104
|
-
const parsedFunctionCall = JSON.parse(streamedResponse).function_call;
|
105
|
-
responseMessage["function_call"] = parsedFunctionCall;
|
106
|
-
mutate([...chatRequest.messages, { ...responseMessage }]);
|
107
|
-
}
|
108
|
-
if (onFinish) {
|
109
|
-
onFinish(responseMessage);
|
110
|
-
}
|
111
|
-
return responseMessage;
|
112
224
|
};
|
113
225
|
function useChat({
|
114
226
|
api = "/api/chat",
|
@@ -126,17 +238,20 @@ function useChat({
|
|
126
238
|
} = {}) {
|
127
239
|
const hookId = useId();
|
128
240
|
const chatId = id || hookId;
|
129
|
-
const { data, mutate } = useSWR([api, chatId], null, {
|
241
|
+
const { data: messages, mutate } = useSWR([api, chatId], null, {
|
130
242
|
fallbackData: initialMessages
|
131
243
|
});
|
132
244
|
const { data: isLoading = false, mutate: mutateLoading } = useSWR(
|
133
245
|
[chatId, "loading"],
|
134
246
|
null
|
135
247
|
);
|
136
|
-
const
|
137
|
-
|
248
|
+
const { data: streamData, mutate: mutateStreamData } = useSWR(
|
249
|
+
[chatId, "streamData"],
|
250
|
+
null
|
251
|
+
);
|
252
|
+
const messagesRef = useRef(messages || []);
|
138
253
|
useEffect(() => {
|
139
|
-
messagesRef.current = messages;
|
254
|
+
messagesRef.current = messages || [];
|
140
255
|
}, [messages]);
|
141
256
|
const abortControllerRef = useRef(null);
|
142
257
|
const extraMetadataRef = useRef({
|
@@ -158,10 +273,12 @@ function useChat({
|
|
158
273
|
const abortController = new AbortController();
|
159
274
|
abortControllerRef.current = abortController;
|
160
275
|
while (true) {
|
161
|
-
const
|
276
|
+
const messagesAndDataOrJustMessage = await getStreamedResponse(
|
162
277
|
api,
|
163
278
|
chatRequest,
|
164
279
|
mutate,
|
280
|
+
mutateStreamData,
|
281
|
+
streamData,
|
165
282
|
extraMetadataRef,
|
166
283
|
messagesRef,
|
167
284
|
abortControllerRef,
|
@@ -169,19 +286,41 @@ function useChat({
|
|
169
286
|
onResponse,
|
170
287
|
sendExtraMessageFields
|
171
288
|
);
|
172
|
-
if (
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
289
|
+
if ("messages" in messagesAndDataOrJustMessage) {
|
290
|
+
for (const message of messagesAndDataOrJustMessage.messages) {
|
291
|
+
if (message.function_call === void 0 || typeof message.function_call === "string") {
|
292
|
+
break;
|
293
|
+
}
|
294
|
+
if (experimental_onFunctionCall) {
|
295
|
+
const functionCall = message.function_call;
|
296
|
+
const functionCallResponse = await experimental_onFunctionCall(
|
297
|
+
messagesRef.current,
|
298
|
+
functionCall
|
299
|
+
);
|
300
|
+
if (functionCallResponse === void 0)
|
301
|
+
break;
|
302
|
+
chatRequest = functionCallResponse;
|
303
|
+
}
|
304
|
+
}
|
305
|
+
} else {
|
306
|
+
const streamedResponseMessage = messagesAndDataOrJustMessage;
|
307
|
+
if (streamedResponseMessage.function_call === void 0 || typeof streamedResponseMessage.function_call === "string") {
|
179
308
|
break;
|
180
|
-
|
309
|
+
}
|
310
|
+
if (experimental_onFunctionCall) {
|
311
|
+
const functionCall = streamedResponseMessage.function_call;
|
312
|
+
const functionCallResponse = await experimental_onFunctionCall(
|
313
|
+
messagesRef.current,
|
314
|
+
functionCall
|
315
|
+
);
|
316
|
+
if (functionCallResponse === void 0)
|
317
|
+
break;
|
318
|
+
chatRequest = functionCallResponse;
|
319
|
+
}
|
181
320
|
}
|
321
|
+
abortControllerRef.current = null;
|
322
|
+
return null;
|
182
323
|
}
|
183
|
-
abortControllerRef.current = null;
|
184
|
-
return null;
|
185
324
|
} catch (err) {
|
186
325
|
if (err.name === "AbortError") {
|
187
326
|
abortControllerRef.current = null;
|
@@ -275,7 +414,7 @@ function useChat({
|
|
275
414
|
setInput(e.target.value);
|
276
415
|
};
|
277
416
|
return {
|
278
|
-
messages,
|
417
|
+
messages: messages || [],
|
279
418
|
error,
|
280
419
|
append,
|
281
420
|
reload,
|
@@ -285,7 +424,8 @@ function useChat({
|
|
285
424
|
setInput,
|
286
425
|
handleInputChange,
|
287
426
|
handleSubmit,
|
288
|
-
isLoading
|
427
|
+
isLoading,
|
428
|
+
data: streamData
|
289
429
|
};
|
290
430
|
}
|
291
431
|
|
package/solid/dist/index.js
CHANGED
@@ -36,14 +36,44 @@ var nanoid = (0, import_non_secure.customAlphabet)(
|
|
36
36
|
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
37
37
|
7
|
38
38
|
);
|
39
|
-
function createChunkDecoder() {
|
39
|
+
function createChunkDecoder(complex) {
|
40
40
|
const decoder = new TextDecoder();
|
41
|
+
if (!complex) {
|
42
|
+
return function(chunk) {
|
43
|
+
if (!chunk)
|
44
|
+
return "";
|
45
|
+
return decoder.decode(chunk, { stream: true });
|
46
|
+
};
|
47
|
+
}
|
41
48
|
return function(chunk) {
|
42
|
-
|
43
|
-
|
44
|
-
return decoder.decode(chunk, { stream: true });
|
49
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
50
|
+
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
45
51
|
};
|
46
52
|
}
|
53
|
+
var StreamStringPrefixes = {
|
54
|
+
text: 0,
|
55
|
+
function_call: 1,
|
56
|
+
data: 2
|
57
|
+
// user_err: 3?
|
58
|
+
};
|
59
|
+
var getStreamStringTypeAndValue = (line) => {
|
60
|
+
const firstSeperatorIndex = line.indexOf(":");
|
61
|
+
const prefix = line.slice(0, firstSeperatorIndex);
|
62
|
+
const type = Object.keys(StreamStringPrefixes).find(
|
63
|
+
(key) => StreamStringPrefixes[key] === Number(prefix)
|
64
|
+
);
|
65
|
+
const val = line.slice(firstSeperatorIndex + 1);
|
66
|
+
let parsedVal = val;
|
67
|
+
if (!val) {
|
68
|
+
return { type, value: "" };
|
69
|
+
}
|
70
|
+
try {
|
71
|
+
parsedVal = JSON.parse(val);
|
72
|
+
} catch (e) {
|
73
|
+
console.error("Failed to parse JSON value:", val);
|
74
|
+
}
|
75
|
+
return { type, value: parsedVal };
|
76
|
+
};
|
47
77
|
|
48
78
|
// solid/use-chat.ts
|
49
79
|
var uniqueId = 0;
|