ai 2.2.1 → 2.2.3
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 +214 -101
- package/dist/index.js +290 -92
- package/dist/index.mjs +283 -92
- package/package.json +1 -1
- package/react/dist/index.d.ts +2 -0
- package/react/dist/index.js +194 -52
- package/react/dist/index.mjs +194 -52
- 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,126 @@ 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();
|
116
|
-
let
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
145
|
+
const decode = createChunkDecoder(isComplexMode);
|
146
|
+
let responseMessages = [];
|
147
|
+
let responseData = [];
|
148
|
+
const prefixMap = {};
|
149
|
+
if (isComplexMode) {
|
150
|
+
while (true) {
|
151
|
+
const { done, value } = await reader.read();
|
152
|
+
if (done) {
|
153
|
+
break;
|
154
|
+
}
|
155
|
+
const lines = decode(value);
|
156
|
+
if (typeof lines === "string") {
|
157
|
+
throw new Error(
|
158
|
+
"Invalid response format. Complex mode was set but the response is a string. This should never happen."
|
159
|
+
);
|
160
|
+
}
|
161
|
+
for (const { type, value: value2 } of lines) {
|
162
|
+
if (type === "text") {
|
163
|
+
if (prefixMap["text"]) {
|
164
|
+
prefixMap["text"] = {
|
165
|
+
...prefixMap["text"],
|
166
|
+
content: (prefixMap["text"].content || "") + value2
|
167
|
+
};
|
168
|
+
} else {
|
169
|
+
prefixMap["text"] = {
|
170
|
+
id: nanoid(),
|
171
|
+
role: "assistant",
|
172
|
+
content: value2,
|
173
|
+
createdAt
|
174
|
+
};
|
175
|
+
}
|
176
|
+
}
|
177
|
+
let functionCallMessage = null;
|
178
|
+
if (type === "function_call") {
|
179
|
+
prefixMap["function_call"] = value2;
|
180
|
+
let functionCall = prefixMap["function_call"];
|
181
|
+
if (functionCall && typeof functionCall === "string") {
|
182
|
+
const parsedFunctionCall = JSON.parse(functionCall).function_call;
|
183
|
+
functionCallMessage = {
|
184
|
+
id: nanoid(),
|
185
|
+
role: "assistant",
|
186
|
+
content: "",
|
187
|
+
function_call: parsedFunctionCall,
|
188
|
+
name: parsedFunctionCall.name,
|
189
|
+
createdAt
|
190
|
+
};
|
191
|
+
prefixMap["function_call"] = functionCallMessage;
|
192
|
+
}
|
193
|
+
}
|
194
|
+
if (type === "data") {
|
195
|
+
const parsedValue = JSON.parse(value2);
|
196
|
+
if (prefixMap["data"]) {
|
197
|
+
prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
|
198
|
+
} else {
|
199
|
+
prefixMap["data"] = parsedValue;
|
200
|
+
}
|
201
|
+
}
|
202
|
+
const data = prefixMap["data"];
|
203
|
+
const responseMessage = prefixMap["text"];
|
204
|
+
const merged = [functionCallMessage, responseMessage].filter(
|
205
|
+
Boolean
|
206
|
+
);
|
207
|
+
mutate([...chatRequest.messages, ...merged], false);
|
208
|
+
mutateStreamData([...existingData || [], ...data || []], false);
|
209
|
+
if (abortControllerRef.current === null) {
|
210
|
+
reader.cancel();
|
211
|
+
break;
|
212
|
+
}
|
213
|
+
}
|
214
|
+
}
|
215
|
+
for (const [type, item] of Object.entries(prefixMap)) {
|
216
|
+
if (onFinish && type === "text") {
|
217
|
+
onFinish(item);
|
218
|
+
}
|
219
|
+
if (type === "data") {
|
220
|
+
responseData.push(item);
|
221
|
+
} else {
|
222
|
+
responseMessages.push(item);
|
223
|
+
}
|
224
|
+
}
|
225
|
+
return { messages: responseMessages, data: responseData };
|
226
|
+
} else {
|
227
|
+
let streamedResponse = "";
|
228
|
+
const replyId = nanoid();
|
229
|
+
let responseMessage = {
|
230
|
+
id: replyId,
|
231
|
+
createdAt,
|
232
|
+
content: "",
|
233
|
+
role: "assistant"
|
234
|
+
};
|
235
|
+
while (true) {
|
236
|
+
const { done, value } = await reader.read();
|
237
|
+
if (done) {
|
238
|
+
break;
|
239
|
+
}
|
240
|
+
streamedResponse += decode(value);
|
241
|
+
if (streamedResponse.startsWith('{"function_call":')) {
|
242
|
+
responseMessage["function_call"] = streamedResponse;
|
243
|
+
} else {
|
244
|
+
responseMessage["content"] = streamedResponse;
|
245
|
+
}
|
246
|
+
mutate([...chatRequest.messages, { ...responseMessage }], false);
|
247
|
+
if (abortControllerRef.current === null) {
|
248
|
+
reader.cancel();
|
249
|
+
break;
|
250
|
+
}
|
126
251
|
}
|
127
|
-
streamedResponse += decode(value);
|
128
252
|
if (streamedResponse.startsWith('{"function_call":')) {
|
129
|
-
|
130
|
-
|
131
|
-
|
253
|
+
const parsedFunctionCall = JSON.parse(streamedResponse).function_call;
|
254
|
+
responseMessage["function_call"] = parsedFunctionCall;
|
255
|
+
mutate([...chatRequest.messages, { ...responseMessage }]);
|
132
256
|
}
|
133
|
-
|
134
|
-
|
135
|
-
reader.cancel();
|
136
|
-
break;
|
257
|
+
if (onFinish) {
|
258
|
+
onFinish(responseMessage);
|
137
259
|
}
|
260
|
+
return responseMessage;
|
138
261
|
}
|
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
262
|
};
|
149
263
|
function useChat({
|
150
264
|
api = "/api/chat",
|
@@ -162,17 +276,20 @@ function useChat({
|
|
162
276
|
} = {}) {
|
163
277
|
const hookId = (0, import_react.useId)();
|
164
278
|
const chatId = id || hookId;
|
165
|
-
const { data, mutate } = (0, import_swr.default)([api, chatId], null, {
|
279
|
+
const { data: messages, mutate } = (0, import_swr.default)([api, chatId], null, {
|
166
280
|
fallbackData: initialMessages
|
167
281
|
});
|
168
282
|
const { data: isLoading = false, mutate: mutateLoading } = (0, import_swr.default)(
|
169
283
|
[chatId, "loading"],
|
170
284
|
null
|
171
285
|
);
|
172
|
-
const
|
173
|
-
|
286
|
+
const { data: streamData, mutate: mutateStreamData } = (0, import_swr.default)(
|
287
|
+
[chatId, "streamData"],
|
288
|
+
null
|
289
|
+
);
|
290
|
+
const messagesRef = (0, import_react.useRef)(messages || []);
|
174
291
|
(0, import_react.useEffect)(() => {
|
175
|
-
messagesRef.current = messages;
|
292
|
+
messagesRef.current = messages || [];
|
176
293
|
}, [messages]);
|
177
294
|
const abortControllerRef = (0, import_react.useRef)(null);
|
178
295
|
const extraMetadataRef = (0, import_react.useRef)({
|
@@ -194,10 +311,12 @@ function useChat({
|
|
194
311
|
const abortController = new AbortController();
|
195
312
|
abortControllerRef.current = abortController;
|
196
313
|
while (true) {
|
197
|
-
const
|
314
|
+
const messagesAndDataOrJustMessage = await getStreamedResponse(
|
198
315
|
api,
|
199
316
|
chatRequest,
|
200
317
|
mutate,
|
318
|
+
mutateStreamData,
|
319
|
+
streamData,
|
201
320
|
extraMetadataRef,
|
202
321
|
messagesRef,
|
203
322
|
abortControllerRef,
|
@@ -205,19 +324,41 @@ function useChat({
|
|
205
324
|
onResponse,
|
206
325
|
sendExtraMessageFields
|
207
326
|
);
|
208
|
-
if (
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
327
|
+
if ("messages" in messagesAndDataOrJustMessage) {
|
328
|
+
for (const message of messagesAndDataOrJustMessage.messages) {
|
329
|
+
if (message.function_call === void 0 || typeof message.function_call === "string") {
|
330
|
+
break;
|
331
|
+
}
|
332
|
+
if (experimental_onFunctionCall) {
|
333
|
+
const functionCall = message.function_call;
|
334
|
+
const functionCallResponse = await experimental_onFunctionCall(
|
335
|
+
messagesRef.current,
|
336
|
+
functionCall
|
337
|
+
);
|
338
|
+
if (functionCallResponse === void 0)
|
339
|
+
break;
|
340
|
+
chatRequest = functionCallResponse;
|
341
|
+
}
|
342
|
+
}
|
343
|
+
} else {
|
344
|
+
const streamedResponseMessage = messagesAndDataOrJustMessage;
|
345
|
+
if (streamedResponseMessage.function_call === void 0 || typeof streamedResponseMessage.function_call === "string") {
|
215
346
|
break;
|
216
|
-
|
347
|
+
}
|
348
|
+
if (experimental_onFunctionCall) {
|
349
|
+
const functionCall = streamedResponseMessage.function_call;
|
350
|
+
const functionCallResponse = await experimental_onFunctionCall(
|
351
|
+
messagesRef.current,
|
352
|
+
functionCall
|
353
|
+
);
|
354
|
+
if (functionCallResponse === void 0)
|
355
|
+
break;
|
356
|
+
chatRequest = functionCallResponse;
|
357
|
+
}
|
217
358
|
}
|
359
|
+
abortControllerRef.current = null;
|
360
|
+
return null;
|
218
361
|
}
|
219
|
-
abortControllerRef.current = null;
|
220
|
-
return null;
|
221
362
|
} catch (err) {
|
222
363
|
if (err.name === "AbortError") {
|
223
364
|
abortControllerRef.current = null;
|
@@ -311,7 +452,7 @@ function useChat({
|
|
311
452
|
setInput(e.target.value);
|
312
453
|
};
|
313
454
|
return {
|
314
|
-
messages,
|
455
|
+
messages: messages || [],
|
315
456
|
error,
|
316
457
|
append,
|
317
458
|
reload,
|
@@ -321,7 +462,8 @@ function useChat({
|
|
321
462
|
setInput,
|
322
463
|
handleInputChange,
|
323
464
|
handleSubmit,
|
324
|
-
isLoading
|
465
|
+
isLoading,
|
466
|
+
data: streamData
|
325
467
|
};
|
326
468
|
}
|
327
469
|
|
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,126 @@ 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();
|
80
|
-
let
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
109
|
+
const decode = createChunkDecoder(isComplexMode);
|
110
|
+
let responseMessages = [];
|
111
|
+
let responseData = [];
|
112
|
+
const prefixMap = {};
|
113
|
+
if (isComplexMode) {
|
114
|
+
while (true) {
|
115
|
+
const { done, value } = await reader.read();
|
116
|
+
if (done) {
|
117
|
+
break;
|
118
|
+
}
|
119
|
+
const lines = decode(value);
|
120
|
+
if (typeof lines === "string") {
|
121
|
+
throw new Error(
|
122
|
+
"Invalid response format. Complex mode was set but the response is a string. This should never happen."
|
123
|
+
);
|
124
|
+
}
|
125
|
+
for (const { type, value: value2 } of lines) {
|
126
|
+
if (type === "text") {
|
127
|
+
if (prefixMap["text"]) {
|
128
|
+
prefixMap["text"] = {
|
129
|
+
...prefixMap["text"],
|
130
|
+
content: (prefixMap["text"].content || "") + value2
|
131
|
+
};
|
132
|
+
} else {
|
133
|
+
prefixMap["text"] = {
|
134
|
+
id: nanoid(),
|
135
|
+
role: "assistant",
|
136
|
+
content: value2,
|
137
|
+
createdAt
|
138
|
+
};
|
139
|
+
}
|
140
|
+
}
|
141
|
+
let functionCallMessage = null;
|
142
|
+
if (type === "function_call") {
|
143
|
+
prefixMap["function_call"] = value2;
|
144
|
+
let functionCall = prefixMap["function_call"];
|
145
|
+
if (functionCall && typeof functionCall === "string") {
|
146
|
+
const parsedFunctionCall = JSON.parse(functionCall).function_call;
|
147
|
+
functionCallMessage = {
|
148
|
+
id: nanoid(),
|
149
|
+
role: "assistant",
|
150
|
+
content: "",
|
151
|
+
function_call: parsedFunctionCall,
|
152
|
+
name: parsedFunctionCall.name,
|
153
|
+
createdAt
|
154
|
+
};
|
155
|
+
prefixMap["function_call"] = functionCallMessage;
|
156
|
+
}
|
157
|
+
}
|
158
|
+
if (type === "data") {
|
159
|
+
const parsedValue = JSON.parse(value2);
|
160
|
+
if (prefixMap["data"]) {
|
161
|
+
prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
|
162
|
+
} else {
|
163
|
+
prefixMap["data"] = parsedValue;
|
164
|
+
}
|
165
|
+
}
|
166
|
+
const data = prefixMap["data"];
|
167
|
+
const responseMessage = prefixMap["text"];
|
168
|
+
const merged = [functionCallMessage, responseMessage].filter(
|
169
|
+
Boolean
|
170
|
+
);
|
171
|
+
mutate([...chatRequest.messages, ...merged], false);
|
172
|
+
mutateStreamData([...existingData || [], ...data || []], false);
|
173
|
+
if (abortControllerRef.current === null) {
|
174
|
+
reader.cancel();
|
175
|
+
break;
|
176
|
+
}
|
177
|
+
}
|
178
|
+
}
|
179
|
+
for (const [type, item] of Object.entries(prefixMap)) {
|
180
|
+
if (onFinish && type === "text") {
|
181
|
+
onFinish(item);
|
182
|
+
}
|
183
|
+
if (type === "data") {
|
184
|
+
responseData.push(item);
|
185
|
+
} else {
|
186
|
+
responseMessages.push(item);
|
187
|
+
}
|
188
|
+
}
|
189
|
+
return { messages: responseMessages, data: responseData };
|
190
|
+
} else {
|
191
|
+
let streamedResponse = "";
|
192
|
+
const replyId = nanoid();
|
193
|
+
let responseMessage = {
|
194
|
+
id: replyId,
|
195
|
+
createdAt,
|
196
|
+
content: "",
|
197
|
+
role: "assistant"
|
198
|
+
};
|
199
|
+
while (true) {
|
200
|
+
const { done, value } = await reader.read();
|
201
|
+
if (done) {
|
202
|
+
break;
|
203
|
+
}
|
204
|
+
streamedResponse += decode(value);
|
205
|
+
if (streamedResponse.startsWith('{"function_call":')) {
|
206
|
+
responseMessage["function_call"] = streamedResponse;
|
207
|
+
} else {
|
208
|
+
responseMessage["content"] = streamedResponse;
|
209
|
+
}
|
210
|
+
mutate([...chatRequest.messages, { ...responseMessage }], false);
|
211
|
+
if (abortControllerRef.current === null) {
|
212
|
+
reader.cancel();
|
213
|
+
break;
|
214
|
+
}
|
90
215
|
}
|
91
|
-
streamedResponse += decode(value);
|
92
216
|
if (streamedResponse.startsWith('{"function_call":')) {
|
93
|
-
|
94
|
-
|
95
|
-
|
217
|
+
const parsedFunctionCall = JSON.parse(streamedResponse).function_call;
|
218
|
+
responseMessage["function_call"] = parsedFunctionCall;
|
219
|
+
mutate([...chatRequest.messages, { ...responseMessage }]);
|
96
220
|
}
|
97
|
-
|
98
|
-
|
99
|
-
reader.cancel();
|
100
|
-
break;
|
221
|
+
if (onFinish) {
|
222
|
+
onFinish(responseMessage);
|
101
223
|
}
|
224
|
+
return responseMessage;
|
102
225
|
}
|
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
226
|
};
|
113
227
|
function useChat({
|
114
228
|
api = "/api/chat",
|
@@ -126,17 +240,20 @@ function useChat({
|
|
126
240
|
} = {}) {
|
127
241
|
const hookId = useId();
|
128
242
|
const chatId = id || hookId;
|
129
|
-
const { data, mutate } = useSWR([api, chatId], null, {
|
243
|
+
const { data: messages, mutate } = useSWR([api, chatId], null, {
|
130
244
|
fallbackData: initialMessages
|
131
245
|
});
|
132
246
|
const { data: isLoading = false, mutate: mutateLoading } = useSWR(
|
133
247
|
[chatId, "loading"],
|
134
248
|
null
|
135
249
|
);
|
136
|
-
const
|
137
|
-
|
250
|
+
const { data: streamData, mutate: mutateStreamData } = useSWR(
|
251
|
+
[chatId, "streamData"],
|
252
|
+
null
|
253
|
+
);
|
254
|
+
const messagesRef = useRef(messages || []);
|
138
255
|
useEffect(() => {
|
139
|
-
messagesRef.current = messages;
|
256
|
+
messagesRef.current = messages || [];
|
140
257
|
}, [messages]);
|
141
258
|
const abortControllerRef = useRef(null);
|
142
259
|
const extraMetadataRef = useRef({
|
@@ -158,10 +275,12 @@ function useChat({
|
|
158
275
|
const abortController = new AbortController();
|
159
276
|
abortControllerRef.current = abortController;
|
160
277
|
while (true) {
|
161
|
-
const
|
278
|
+
const messagesAndDataOrJustMessage = await getStreamedResponse(
|
162
279
|
api,
|
163
280
|
chatRequest,
|
164
281
|
mutate,
|
282
|
+
mutateStreamData,
|
283
|
+
streamData,
|
165
284
|
extraMetadataRef,
|
166
285
|
messagesRef,
|
167
286
|
abortControllerRef,
|
@@ -169,19 +288,41 @@ function useChat({
|
|
169
288
|
onResponse,
|
170
289
|
sendExtraMessageFields
|
171
290
|
);
|
172
|
-
if (
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
291
|
+
if ("messages" in messagesAndDataOrJustMessage) {
|
292
|
+
for (const message of messagesAndDataOrJustMessage.messages) {
|
293
|
+
if (message.function_call === void 0 || typeof message.function_call === "string") {
|
294
|
+
break;
|
295
|
+
}
|
296
|
+
if (experimental_onFunctionCall) {
|
297
|
+
const functionCall = message.function_call;
|
298
|
+
const functionCallResponse = await experimental_onFunctionCall(
|
299
|
+
messagesRef.current,
|
300
|
+
functionCall
|
301
|
+
);
|
302
|
+
if (functionCallResponse === void 0)
|
303
|
+
break;
|
304
|
+
chatRequest = functionCallResponse;
|
305
|
+
}
|
306
|
+
}
|
307
|
+
} else {
|
308
|
+
const streamedResponseMessage = messagesAndDataOrJustMessage;
|
309
|
+
if (streamedResponseMessage.function_call === void 0 || typeof streamedResponseMessage.function_call === "string") {
|
179
310
|
break;
|
180
|
-
|
311
|
+
}
|
312
|
+
if (experimental_onFunctionCall) {
|
313
|
+
const functionCall = streamedResponseMessage.function_call;
|
314
|
+
const functionCallResponse = await experimental_onFunctionCall(
|
315
|
+
messagesRef.current,
|
316
|
+
functionCall
|
317
|
+
);
|
318
|
+
if (functionCallResponse === void 0)
|
319
|
+
break;
|
320
|
+
chatRequest = functionCallResponse;
|
321
|
+
}
|
181
322
|
}
|
323
|
+
abortControllerRef.current = null;
|
324
|
+
return null;
|
182
325
|
}
|
183
|
-
abortControllerRef.current = null;
|
184
|
-
return null;
|
185
326
|
} catch (err) {
|
186
327
|
if (err.name === "AbortError") {
|
187
328
|
abortControllerRef.current = null;
|
@@ -275,7 +416,7 @@ function useChat({
|
|
275
416
|
setInput(e.target.value);
|
276
417
|
};
|
277
418
|
return {
|
278
|
-
messages,
|
419
|
+
messages: messages || [],
|
279
420
|
error,
|
280
421
|
append,
|
281
422
|
reload,
|
@@ -285,7 +426,8 @@ function useChat({
|
|
285
426
|
setInput,
|
286
427
|
handleInputChange,
|
287
428
|
handleSubmit,
|
288
|
-
isLoading
|
429
|
+
isLoading,
|
430
|
+
data: streamData
|
289
431
|
};
|
290
432
|
}
|
291
433
|
|
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;
|