ai 2.2.22 → 2.2.24
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 +59 -25
- package/dist/index.js +318 -39
- package/dist/index.mjs +317 -36
- package/package.json +10 -6
- package/react/dist/index.d.ts +40 -2
- package/react/dist/index.js +445 -195
- package/react/dist/index.mjs +444 -195
- package/solid/dist/index.d.ts +7 -1
- package/solid/dist/index.js +426 -107
- package/solid/dist/index.mjs +426 -107
- package/svelte/dist/index.d.ts +2 -0
- package/svelte/dist/index.js +124 -25
- package/svelte/dist/index.mjs +124 -25
- package/vue/dist/index.d.ts +1 -0
- package/vue/dist/index.js +124 -25
- package/vue/dist/index.mjs +124 -25
package/react/dist/index.mjs
CHANGED
@@ -6,6 +6,129 @@ import useSWR from "swr";
|
|
6
6
|
|
7
7
|
// shared/utils.ts
|
8
8
|
import { customAlphabet } from "nanoid/non-secure";
|
9
|
+
|
10
|
+
// shared/stream-parts.ts
|
11
|
+
var textStreamPart = {
|
12
|
+
code: "0",
|
13
|
+
name: "text",
|
14
|
+
parse: (value) => {
|
15
|
+
if (typeof value !== "string") {
|
16
|
+
throw new Error('"text" parts expect a string value.');
|
17
|
+
}
|
18
|
+
return { type: "text", value };
|
19
|
+
}
|
20
|
+
};
|
21
|
+
var functionCallStreamPart = {
|
22
|
+
code: "1",
|
23
|
+
name: "function_call",
|
24
|
+
parse: (value) => {
|
25
|
+
if (value == null || typeof value !== "object" || !("function_call" in value) || typeof value.function_call !== "object" || value.function_call == null || !("name" in value.function_call) || !("arguments" in value.function_call) || typeof value.function_call.name !== "string" || typeof value.function_call.arguments !== "string") {
|
26
|
+
throw new Error(
|
27
|
+
'"function_call" parts expect an object with a "function_call" property.'
|
28
|
+
);
|
29
|
+
}
|
30
|
+
return {
|
31
|
+
type: "function_call",
|
32
|
+
value
|
33
|
+
};
|
34
|
+
}
|
35
|
+
};
|
36
|
+
var dataStreamPart = {
|
37
|
+
code: "2",
|
38
|
+
name: "data",
|
39
|
+
parse: (value) => {
|
40
|
+
if (!Array.isArray(value)) {
|
41
|
+
throw new Error('"data" parts expect an array value.');
|
42
|
+
}
|
43
|
+
return { type: "data", value };
|
44
|
+
}
|
45
|
+
};
|
46
|
+
var errorStreamPart = {
|
47
|
+
code: "3",
|
48
|
+
name: "error",
|
49
|
+
parse: (value) => {
|
50
|
+
if (typeof value !== "string") {
|
51
|
+
throw new Error('"error" parts expect a string value.');
|
52
|
+
}
|
53
|
+
return { type: "error", value };
|
54
|
+
}
|
55
|
+
};
|
56
|
+
var assistantMessage = {
|
57
|
+
code: "4",
|
58
|
+
name: "assistant_message",
|
59
|
+
parse: (value) => {
|
60
|
+
if (value == null || typeof value !== "object" || !("id" in value) || !("role" in value) || !("content" in value) || typeof value.id !== "string" || typeof value.role !== "string" || value.role !== "assistant" || !Array.isArray(value.content) || !value.content.every(
|
61
|
+
(item) => item != null && typeof item === "object" && "type" in item && item.type === "text" && "text" in item && item.text != null && typeof item.text === "object" && "value" in item.text && typeof item.text.value === "string"
|
62
|
+
)) {
|
63
|
+
throw new Error(
|
64
|
+
'"assistant_message" parts expect an object with an "id", "role", and "content" property.'
|
65
|
+
);
|
66
|
+
}
|
67
|
+
return {
|
68
|
+
type: "assistant_message",
|
69
|
+
value
|
70
|
+
};
|
71
|
+
}
|
72
|
+
};
|
73
|
+
var assistantControlData = {
|
74
|
+
code: "5",
|
75
|
+
name: "assistant_control_data",
|
76
|
+
parse: (value) => {
|
77
|
+
if (value == null || typeof value !== "object" || !("threadId" in value) || !("messageId" in value) || typeof value.threadId !== "string" || typeof value.messageId !== "string") {
|
78
|
+
throw new Error(
|
79
|
+
'"assistant_control_data" parts expect an object with a "threadId" and "messageId" property.'
|
80
|
+
);
|
81
|
+
}
|
82
|
+
return {
|
83
|
+
type: "assistant_control_data",
|
84
|
+
value: {
|
85
|
+
threadId: value.threadId,
|
86
|
+
messageId: value.messageId
|
87
|
+
}
|
88
|
+
};
|
89
|
+
}
|
90
|
+
};
|
91
|
+
var streamParts = [
|
92
|
+
textStreamPart,
|
93
|
+
functionCallStreamPart,
|
94
|
+
dataStreamPart,
|
95
|
+
errorStreamPart,
|
96
|
+
assistantMessage,
|
97
|
+
assistantControlData
|
98
|
+
];
|
99
|
+
var streamPartsByCode = {
|
100
|
+
[textStreamPart.code]: textStreamPart,
|
101
|
+
[functionCallStreamPart.code]: functionCallStreamPart,
|
102
|
+
[dataStreamPart.code]: dataStreamPart,
|
103
|
+
[errorStreamPart.code]: errorStreamPart,
|
104
|
+
[assistantMessage.code]: assistantMessage,
|
105
|
+
[assistantControlData.code]: assistantControlData
|
106
|
+
};
|
107
|
+
var StreamStringPrefixes = {
|
108
|
+
[textStreamPart.name]: textStreamPart.code,
|
109
|
+
[functionCallStreamPart.name]: functionCallStreamPart.code,
|
110
|
+
[dataStreamPart.name]: dataStreamPart.code,
|
111
|
+
[errorStreamPart.name]: errorStreamPart.code,
|
112
|
+
[assistantMessage.name]: assistantMessage.code,
|
113
|
+
[assistantControlData.name]: assistantControlData.code
|
114
|
+
};
|
115
|
+
var validCodes = streamParts.map((part) => part.code);
|
116
|
+
var parseStreamPart = (line) => {
|
117
|
+
const firstSeparatorIndex = line.indexOf(":");
|
118
|
+
if (firstSeparatorIndex === -1) {
|
119
|
+
throw new Error("Failed to parse stream string. No separator found.");
|
120
|
+
}
|
121
|
+
const prefix = line.slice(0, firstSeparatorIndex);
|
122
|
+
if (!validCodes.includes(prefix)) {
|
123
|
+
throw new Error(`Failed to parse stream string. Invalid code ${prefix}.`);
|
124
|
+
}
|
125
|
+
const code = prefix;
|
126
|
+
const textValue = line.slice(firstSeparatorIndex + 1);
|
127
|
+
const jsonValue = JSON.parse(textValue);
|
128
|
+
return streamPartsByCode[code].parse(jsonValue);
|
129
|
+
};
|
130
|
+
|
131
|
+
// shared/utils.ts
|
9
132
|
var nanoid = customAlphabet(
|
10
133
|
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
11
134
|
7
|
@@ -21,46 +144,30 @@ function createChunkDecoder(complex) {
|
|
21
144
|
}
|
22
145
|
return function(chunk) {
|
23
146
|
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
24
|
-
return decoded.map(
|
147
|
+
return decoded.map(parseStreamPart).filter(Boolean);
|
25
148
|
};
|
26
149
|
}
|
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
150
|
var COMPLEX_HEADER = "X-Experimental-Stream-Data";
|
52
151
|
|
53
|
-
//
|
152
|
+
// shared/call-api.ts
|
153
|
+
import { nanoid as nanoid2 } from "nanoid";
|
154
|
+
|
155
|
+
// shared/parse-complex-response.ts
|
54
156
|
async function parseComplexResponse({
|
55
157
|
reader,
|
56
158
|
abortControllerRef,
|
57
|
-
update
|
159
|
+
update,
|
160
|
+
onFinish,
|
161
|
+
generateId = nanoid,
|
162
|
+
getCurrentDate = () => /* @__PURE__ */ new Date()
|
58
163
|
}) {
|
164
|
+
const createdAt = getCurrentDate();
|
59
165
|
const decode = createChunkDecoder(true);
|
60
|
-
const
|
61
|
-
|
166
|
+
const prefixMap = {
|
167
|
+
data: []
|
168
|
+
};
|
62
169
|
const NEWLINE = "\n".charCodeAt(0);
|
63
|
-
|
170
|
+
const chunks = [];
|
64
171
|
let totalLength = 0;
|
65
172
|
while (true) {
|
66
173
|
const { value } = await reader.read();
|
@@ -97,7 +204,7 @@ async function parseComplexResponse({
|
|
97
204
|
};
|
98
205
|
} else {
|
99
206
|
prefixMap["text"] = {
|
100
|
-
id:
|
207
|
+
id: generateId(),
|
101
208
|
role: "assistant",
|
102
209
|
content: value2,
|
103
210
|
createdAt
|
@@ -106,44 +213,182 @@ async function parseComplexResponse({
|
|
106
213
|
}
|
107
214
|
let functionCallMessage = null;
|
108
215
|
if (type === "function_call") {
|
109
|
-
prefixMap["function_call"] =
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
content: "",
|
119
|
-
function_call: parsedFunctionCall,
|
120
|
-
name: parsedFunctionCall.name,
|
121
|
-
createdAt
|
122
|
-
};
|
123
|
-
prefixMap["function_call"] = functionCallMessage;
|
124
|
-
}
|
216
|
+
prefixMap["function_call"] = {
|
217
|
+
id: generateId(),
|
218
|
+
role: "assistant",
|
219
|
+
content: "",
|
220
|
+
function_call: value2.function_call,
|
221
|
+
name: value2.function_call.name,
|
222
|
+
createdAt
|
223
|
+
};
|
224
|
+
functionCallMessage = prefixMap["function_call"];
|
125
225
|
}
|
126
226
|
if (type === "data") {
|
127
|
-
|
128
|
-
if (prefixMap["data"]) {
|
129
|
-
prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
|
130
|
-
} else {
|
131
|
-
prefixMap["data"] = parsedValue;
|
132
|
-
}
|
227
|
+
prefixMap["data"].push(...value2);
|
133
228
|
}
|
134
|
-
const data = prefixMap["data"];
|
135
229
|
const responseMessage = prefixMap["text"];
|
136
230
|
const merged = [functionCallMessage, responseMessage].filter(
|
137
231
|
Boolean
|
138
232
|
);
|
139
|
-
update(merged, data);
|
140
|
-
if (abortControllerRef.current === null) {
|
233
|
+
update(merged, [...prefixMap["data"]]);
|
234
|
+
if ((abortControllerRef == null ? void 0 : abortControllerRef.current) === null) {
|
235
|
+
reader.cancel();
|
236
|
+
break;
|
237
|
+
}
|
238
|
+
}
|
239
|
+
}
|
240
|
+
onFinish == null ? void 0 : onFinish(prefixMap);
|
241
|
+
return {
|
242
|
+
messages: [prefixMap.text, prefixMap.function_call].filter(
|
243
|
+
Boolean
|
244
|
+
),
|
245
|
+
data: prefixMap.data
|
246
|
+
};
|
247
|
+
}
|
248
|
+
|
249
|
+
// shared/call-api.ts
|
250
|
+
async function callApi({
|
251
|
+
api,
|
252
|
+
messages,
|
253
|
+
body,
|
254
|
+
credentials,
|
255
|
+
headers,
|
256
|
+
abortController,
|
257
|
+
appendMessage,
|
258
|
+
restoreMessagesOnFailure,
|
259
|
+
onResponse,
|
260
|
+
onUpdate,
|
261
|
+
onFinish
|
262
|
+
}) {
|
263
|
+
var _a;
|
264
|
+
const response = await fetch(api, {
|
265
|
+
method: "POST",
|
266
|
+
body: JSON.stringify({
|
267
|
+
messages,
|
268
|
+
...body
|
269
|
+
}),
|
270
|
+
headers,
|
271
|
+
signal: (_a = abortController == null ? void 0 : abortController()) == null ? void 0 : _a.signal,
|
272
|
+
credentials
|
273
|
+
}).catch((err) => {
|
274
|
+
restoreMessagesOnFailure();
|
275
|
+
throw err;
|
276
|
+
});
|
277
|
+
if (onResponse) {
|
278
|
+
try {
|
279
|
+
await onResponse(response);
|
280
|
+
} catch (err) {
|
281
|
+
throw err;
|
282
|
+
}
|
283
|
+
}
|
284
|
+
if (!response.ok) {
|
285
|
+
restoreMessagesOnFailure();
|
286
|
+
throw new Error(
|
287
|
+
await response.text() || "Failed to fetch the chat response."
|
288
|
+
);
|
289
|
+
}
|
290
|
+
if (!response.body) {
|
291
|
+
throw new Error("The response body is empty.");
|
292
|
+
}
|
293
|
+
const reader = response.body.getReader();
|
294
|
+
const isComplexMode = response.headers.get(COMPLEX_HEADER) === "true";
|
295
|
+
if (isComplexMode) {
|
296
|
+
return await parseComplexResponse({
|
297
|
+
reader,
|
298
|
+
abortControllerRef: abortController != null ? { current: abortController() } : void 0,
|
299
|
+
update: onUpdate,
|
300
|
+
onFinish(prefixMap) {
|
301
|
+
if (onFinish && prefixMap.text != null) {
|
302
|
+
onFinish(prefixMap.text);
|
303
|
+
}
|
304
|
+
}
|
305
|
+
});
|
306
|
+
} else {
|
307
|
+
const createdAt = /* @__PURE__ */ new Date();
|
308
|
+
const decode = createChunkDecoder(false);
|
309
|
+
let streamedResponse = "";
|
310
|
+
const replyId = nanoid2();
|
311
|
+
let responseMessage = {
|
312
|
+
id: replyId,
|
313
|
+
createdAt,
|
314
|
+
content: "",
|
315
|
+
role: "assistant"
|
316
|
+
};
|
317
|
+
while (true) {
|
318
|
+
const { done, value } = await reader.read();
|
319
|
+
if (done) {
|
320
|
+
break;
|
321
|
+
}
|
322
|
+
streamedResponse += decode(value);
|
323
|
+
if (streamedResponse.startsWith('{"function_call":')) {
|
324
|
+
responseMessage["function_call"] = streamedResponse;
|
325
|
+
} else {
|
326
|
+
responseMessage["content"] = streamedResponse;
|
327
|
+
}
|
328
|
+
appendMessage({ ...responseMessage });
|
329
|
+
if ((abortController == null ? void 0 : abortController()) === null) {
|
141
330
|
reader.cancel();
|
142
331
|
break;
|
143
332
|
}
|
144
333
|
}
|
334
|
+
if (streamedResponse.startsWith('{"function_call":')) {
|
335
|
+
const parsedFunctionCall = JSON.parse(streamedResponse).function_call;
|
336
|
+
responseMessage["function_call"] = parsedFunctionCall;
|
337
|
+
appendMessage({ ...responseMessage });
|
338
|
+
}
|
339
|
+
if (onFinish) {
|
340
|
+
onFinish(responseMessage);
|
341
|
+
}
|
342
|
+
return responseMessage;
|
343
|
+
}
|
344
|
+
}
|
345
|
+
|
346
|
+
// shared/process-chat-stream.ts
|
347
|
+
async function processChatStream({
|
348
|
+
getStreamedResponse: getStreamedResponse2,
|
349
|
+
experimental_onFunctionCall,
|
350
|
+
updateChatRequest,
|
351
|
+
getCurrentMessages
|
352
|
+
}) {
|
353
|
+
while (true) {
|
354
|
+
const messagesAndDataOrJustMessage = await getStreamedResponse2();
|
355
|
+
if ("messages" in messagesAndDataOrJustMessage) {
|
356
|
+
let hasFollowingResponse = false;
|
357
|
+
for (const message of messagesAndDataOrJustMessage.messages) {
|
358
|
+
if (message.function_call === void 0 || typeof message.function_call === "string") {
|
359
|
+
continue;
|
360
|
+
}
|
361
|
+
hasFollowingResponse = true;
|
362
|
+
if (experimental_onFunctionCall) {
|
363
|
+
const functionCall = message.function_call;
|
364
|
+
const functionCallResponse = await experimental_onFunctionCall(
|
365
|
+
getCurrentMessages(),
|
366
|
+
functionCall
|
367
|
+
);
|
368
|
+
if (functionCallResponse === void 0) {
|
369
|
+
hasFollowingResponse = false;
|
370
|
+
break;
|
371
|
+
}
|
372
|
+
updateChatRequest(functionCallResponse);
|
373
|
+
}
|
374
|
+
}
|
375
|
+
if (!hasFollowingResponse) {
|
376
|
+
break;
|
377
|
+
}
|
378
|
+
} else {
|
379
|
+
const streamedResponseMessage = messagesAndDataOrJustMessage;
|
380
|
+
if (streamedResponseMessage.function_call === void 0 || typeof streamedResponseMessage.function_call === "string") {
|
381
|
+
break;
|
382
|
+
}
|
383
|
+
if (experimental_onFunctionCall) {
|
384
|
+
const functionCall = streamedResponseMessage.function_call;
|
385
|
+
const functionCallResponse = await experimental_onFunctionCall(getCurrentMessages(), functionCall);
|
386
|
+
if (functionCallResponse === void 0)
|
387
|
+
break;
|
388
|
+
updateChatRequest(functionCallResponse);
|
389
|
+
}
|
390
|
+
}
|
145
391
|
}
|
146
|
-
return prefixMap;
|
147
392
|
}
|
148
393
|
|
149
394
|
// react/use-chat.ts
|
@@ -179,7 +424,8 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
179
424
|
}
|
180
425
|
try {
|
181
426
|
const promise = api({
|
182
|
-
messages: constructedMessagesPayload
|
427
|
+
messages: constructedMessagesPayload,
|
428
|
+
data: chatRequest.data
|
183
429
|
});
|
184
430
|
await readRow(promise);
|
185
431
|
} catch (e) {
|
@@ -191,10 +437,11 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
191
437
|
}
|
192
438
|
return responseMessage;
|
193
439
|
}
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
440
|
+
return await callApi({
|
441
|
+
api,
|
442
|
+
messages: constructedMessagesPayload,
|
443
|
+
body: {
|
444
|
+
data: chatRequest.data,
|
198
445
|
...extraMetadataRef.current.body,
|
199
446
|
...(_a = chatRequest.options) == null ? void 0 : _a.body,
|
200
447
|
...chatRequest.functions !== void 0 && {
|
@@ -203,95 +450,26 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
203
450
|
...chatRequest.function_call !== void 0 && {
|
204
451
|
function_call: chatRequest.function_call
|
205
452
|
}
|
206
|
-
}
|
453
|
+
},
|
207
454
|
credentials: extraMetadataRef.current.credentials,
|
208
455
|
headers: {
|
209
456
|
...extraMetadataRef.current.headers,
|
210
457
|
...(_b = chatRequest.options) == null ? void 0 : _b.headers
|
211
458
|
},
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
459
|
+
abortController: () => abortControllerRef.current,
|
460
|
+
appendMessage(message) {
|
461
|
+
mutate([...chatRequest.messages, message], false);
|
462
|
+
},
|
463
|
+
restoreMessagesOnFailure() {
|
464
|
+
mutate(previousMessages, false);
|
465
|
+
},
|
466
|
+
onResponse,
|
467
|
+
onUpdate(merged, data) {
|
468
|
+
mutate([...chatRequest.messages, ...merged], false);
|
469
|
+
mutateStreamData([...existingData || [], ...data || []], false);
|
470
|
+
},
|
471
|
+
onFinish
|
218
472
|
});
|
219
|
-
if (onResponse) {
|
220
|
-
try {
|
221
|
-
await onResponse(res);
|
222
|
-
} catch (err) {
|
223
|
-
throw err;
|
224
|
-
}
|
225
|
-
}
|
226
|
-
if (!res.ok) {
|
227
|
-
mutate(previousMessages, false);
|
228
|
-
throw new Error(await res.text() || "Failed to fetch the chat response.");
|
229
|
-
}
|
230
|
-
if (!res.body) {
|
231
|
-
throw new Error("The response body is empty.");
|
232
|
-
}
|
233
|
-
const isComplexMode = res.headers.get(COMPLEX_HEADER) === "true";
|
234
|
-
let responseMessages = [];
|
235
|
-
const reader = res.body.getReader();
|
236
|
-
let responseData = [];
|
237
|
-
if (isComplexMode) {
|
238
|
-
const prefixMap = await parseComplexResponse({
|
239
|
-
reader,
|
240
|
-
abortControllerRef,
|
241
|
-
update(merged, data) {
|
242
|
-
mutate([...chatRequest.messages, ...merged], false);
|
243
|
-
mutateStreamData([...existingData || [], ...data || []], false);
|
244
|
-
}
|
245
|
-
});
|
246
|
-
for (const [type, item] of Object.entries(prefixMap)) {
|
247
|
-
if (onFinish && type === "text") {
|
248
|
-
onFinish(item);
|
249
|
-
}
|
250
|
-
if (type === "data") {
|
251
|
-
responseData.push(item);
|
252
|
-
} else {
|
253
|
-
responseMessages.push(item);
|
254
|
-
}
|
255
|
-
}
|
256
|
-
return { messages: responseMessages, data: responseData };
|
257
|
-
} else {
|
258
|
-
const createdAt = /* @__PURE__ */ new Date();
|
259
|
-
const decode = createChunkDecoder(false);
|
260
|
-
let streamedResponse = "";
|
261
|
-
const replyId = nanoid();
|
262
|
-
let responseMessage = {
|
263
|
-
id: replyId,
|
264
|
-
createdAt,
|
265
|
-
content: "",
|
266
|
-
role: "assistant"
|
267
|
-
};
|
268
|
-
while (true) {
|
269
|
-
const { done, value } = await reader.read();
|
270
|
-
if (done) {
|
271
|
-
break;
|
272
|
-
}
|
273
|
-
streamedResponse += decode(value);
|
274
|
-
if (streamedResponse.startsWith('{"function_call":')) {
|
275
|
-
responseMessage["function_call"] = streamedResponse;
|
276
|
-
} else {
|
277
|
-
responseMessage["content"] = streamedResponse;
|
278
|
-
}
|
279
|
-
mutate([...chatRequest.messages, { ...responseMessage }], false);
|
280
|
-
if (abortControllerRef.current === null) {
|
281
|
-
reader.cancel();
|
282
|
-
break;
|
283
|
-
}
|
284
|
-
}
|
285
|
-
if (streamedResponse.startsWith('{"function_call":')) {
|
286
|
-
const parsedFunctionCall = JSON.parse(streamedResponse).function_call;
|
287
|
-
responseMessage["function_call"] = parsedFunctionCall;
|
288
|
-
mutate([...chatRequest.messages, { ...responseMessage }]);
|
289
|
-
}
|
290
|
-
if (onFinish) {
|
291
|
-
onFinish(responseMessage);
|
292
|
-
}
|
293
|
-
return responseMessage;
|
294
|
-
}
|
295
473
|
};
|
296
474
|
function useChat({
|
297
475
|
api = "/api/chat",
|
@@ -317,10 +495,7 @@ function useChat({
|
|
317
495
|
[chatId, "loading"],
|
318
496
|
null
|
319
497
|
);
|
320
|
-
const { data: streamData, mutate: mutateStreamData } = useSWR(
|
321
|
-
[chatId, "streamData"],
|
322
|
-
null
|
323
|
-
);
|
498
|
+
const { data: streamData, mutate: mutateStreamData } = useSWR([chatId, "streamData"], null);
|
324
499
|
const messagesRef = useRef(messages || []);
|
325
500
|
useEffect(() => {
|
326
501
|
messagesRef.current = messages || [];
|
@@ -346,8 +521,8 @@ function useChat({
|
|
346
521
|
setError(void 0);
|
347
522
|
const abortController = new AbortController();
|
348
523
|
abortControllerRef.current = abortController;
|
349
|
-
|
350
|
-
|
524
|
+
await processChatStream({
|
525
|
+
getStreamedResponse: () => getStreamedResponse(
|
351
526
|
api,
|
352
527
|
chatRequest,
|
353
528
|
mutate,
|
@@ -359,47 +534,13 @@ function useChat({
|
|
359
534
|
onFinish,
|
360
535
|
onResponse,
|
361
536
|
sendExtraMessageFields
|
362
|
-
)
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
hasFollowingResponse = true;
|
370
|
-
if (experimental_onFunctionCall) {
|
371
|
-
const functionCall = message.function_call;
|
372
|
-
const functionCallResponse = await experimental_onFunctionCall(
|
373
|
-
messagesRef.current,
|
374
|
-
functionCall
|
375
|
-
);
|
376
|
-
if (functionCallResponse === void 0) {
|
377
|
-
hasFollowingResponse = false;
|
378
|
-
break;
|
379
|
-
}
|
380
|
-
chatRequest = functionCallResponse;
|
381
|
-
}
|
382
|
-
}
|
383
|
-
if (!hasFollowingResponse) {
|
384
|
-
break;
|
385
|
-
}
|
386
|
-
} else {
|
387
|
-
const streamedResponseMessage = messagesAndDataOrJustMessage;
|
388
|
-
if (streamedResponseMessage.function_call === void 0 || typeof streamedResponseMessage.function_call === "string") {
|
389
|
-
break;
|
390
|
-
}
|
391
|
-
if (experimental_onFunctionCall) {
|
392
|
-
const functionCall = streamedResponseMessage.function_call;
|
393
|
-
const functionCallResponse = await experimental_onFunctionCall(
|
394
|
-
messagesRef.current,
|
395
|
-
functionCall
|
396
|
-
);
|
397
|
-
if (functionCallResponse === void 0)
|
398
|
-
break;
|
399
|
-
chatRequest = functionCallResponse;
|
400
|
-
}
|
401
|
-
}
|
402
|
-
}
|
537
|
+
),
|
538
|
+
experimental_onFunctionCall,
|
539
|
+
updateChatRequest: (chatRequestParam) => {
|
540
|
+
chatRequest = chatRequestParam;
|
541
|
+
},
|
542
|
+
getCurrentMessages: () => messagesRef.current
|
543
|
+
});
|
403
544
|
abortControllerRef.current = null;
|
404
545
|
} catch (err) {
|
405
546
|
if (err.name === "AbortError") {
|
@@ -432,13 +573,14 @@ function useChat({
|
|
432
573
|
]
|
433
574
|
);
|
434
575
|
const append = useCallback(
|
435
|
-
async (message, { options, functions, function_call } = {}) => {
|
576
|
+
async (message, { options, functions, function_call, data } = {}) => {
|
436
577
|
if (!message.id) {
|
437
578
|
message.id = nanoid();
|
438
579
|
}
|
439
580
|
const chatRequest = {
|
440
581
|
messages: messagesRef.current.concat(message),
|
441
582
|
options,
|
583
|
+
data,
|
442
584
|
...functions !== void 0 && { functions },
|
443
585
|
...function_call !== void 0 && { function_call }
|
444
586
|
};
|
@@ -485,7 +627,7 @@ function useChat({
|
|
485
627
|
);
|
486
628
|
const [input, setInput] = useState(initialInput);
|
487
629
|
const handleSubmit = useCallback(
|
488
|
-
(e,
|
630
|
+
(e, options = {}, metadata) => {
|
489
631
|
if (metadata) {
|
490
632
|
extraMetadataRef.current = {
|
491
633
|
...extraMetadataRef.current,
|
@@ -501,7 +643,7 @@ function useChat({
|
|
501
643
|
role: "user",
|
502
644
|
createdAt: /* @__PURE__ */ new Date()
|
503
645
|
},
|
504
|
-
|
646
|
+
options
|
505
647
|
);
|
506
648
|
setInput("");
|
507
649
|
},
|
@@ -695,7 +837,114 @@ function useCompletion({
|
|
695
837
|
isLoading
|
696
838
|
};
|
697
839
|
}
|
840
|
+
|
841
|
+
// react/use-assistant.ts
|
842
|
+
import { useState as useState3 } from "react";
|
843
|
+
|
844
|
+
// shared/process-message-stream.ts
|
845
|
+
async function processMessageStream(reader, processMessage) {
|
846
|
+
const decoder = new TextDecoder();
|
847
|
+
let buffer = "";
|
848
|
+
while (true) {
|
849
|
+
const { done, value } = await reader.read();
|
850
|
+
if (done) {
|
851
|
+
if (buffer.length > 0) {
|
852
|
+
processMessage(buffer);
|
853
|
+
}
|
854
|
+
break;
|
855
|
+
}
|
856
|
+
buffer += decoder.decode(value, { stream: true });
|
857
|
+
let endIndex;
|
858
|
+
while ((endIndex = buffer.indexOf("\n")) !== -1) {
|
859
|
+
processMessage(buffer.substring(0, endIndex).trim());
|
860
|
+
buffer = buffer.substring(endIndex + 1);
|
861
|
+
}
|
862
|
+
}
|
863
|
+
}
|
864
|
+
|
865
|
+
// react/use-assistant.ts
|
866
|
+
function experimental_useAssistant({
|
867
|
+
api,
|
868
|
+
threadId: threadIdParam
|
869
|
+
}) {
|
870
|
+
const [messages, setMessages] = useState3([]);
|
871
|
+
const [input, setInput] = useState3("");
|
872
|
+
const [threadId, setThreadId] = useState3(void 0);
|
873
|
+
const [status, setStatus] = useState3("awaiting_message");
|
874
|
+
const [error, setError] = useState3(void 0);
|
875
|
+
const handleInputChange = (e) => {
|
876
|
+
setInput(e.target.value);
|
877
|
+
};
|
878
|
+
const submitMessage = async (e) => {
|
879
|
+
var _a;
|
880
|
+
e.preventDefault();
|
881
|
+
if (input === "") {
|
882
|
+
return;
|
883
|
+
}
|
884
|
+
setStatus("in_progress");
|
885
|
+
setMessages((messages2) => [
|
886
|
+
...messages2,
|
887
|
+
{ id: "", role: "user", content: input }
|
888
|
+
]);
|
889
|
+
setInput("");
|
890
|
+
const result = await fetch(api, {
|
891
|
+
method: "POST",
|
892
|
+
headers: { "Content-Type": "application/json" },
|
893
|
+
body: JSON.stringify({
|
894
|
+
// always use user-provided threadId when available:
|
895
|
+
threadId: (_a = threadIdParam != null ? threadIdParam : threadId) != null ? _a : null,
|
896
|
+
message: input
|
897
|
+
})
|
898
|
+
});
|
899
|
+
if (result.body == null) {
|
900
|
+
throw new Error("The response body is empty.");
|
901
|
+
}
|
902
|
+
await processMessageStream(result.body.getReader(), (message) => {
|
903
|
+
try {
|
904
|
+
const { type, value } = parseStreamPart(message);
|
905
|
+
switch (type) {
|
906
|
+
case "assistant_message": {
|
907
|
+
setMessages((messages2) => [
|
908
|
+
...messages2,
|
909
|
+
{
|
910
|
+
id: value.id,
|
911
|
+
role: value.role,
|
912
|
+
content: value.content[0].text.value
|
913
|
+
}
|
914
|
+
]);
|
915
|
+
break;
|
916
|
+
}
|
917
|
+
case "assistant_control_data": {
|
918
|
+
setThreadId(value.threadId);
|
919
|
+
setMessages((messages2) => {
|
920
|
+
const lastMessage = messages2[messages2.length - 1];
|
921
|
+
lastMessage.id = value.messageId;
|
922
|
+
return [...messages2.slice(0, messages2.length - 1), lastMessage];
|
923
|
+
});
|
924
|
+
break;
|
925
|
+
}
|
926
|
+
case "error": {
|
927
|
+
setError(value);
|
928
|
+
break;
|
929
|
+
}
|
930
|
+
}
|
931
|
+
} catch (error2) {
|
932
|
+
setError(error2);
|
933
|
+
}
|
934
|
+
});
|
935
|
+
setStatus("awaiting_message");
|
936
|
+
};
|
937
|
+
return {
|
938
|
+
messages,
|
939
|
+
input,
|
940
|
+
handleInputChange,
|
941
|
+
submitMessage,
|
942
|
+
status,
|
943
|
+
error
|
944
|
+
};
|
945
|
+
}
|
698
946
|
export {
|
947
|
+
experimental_useAssistant,
|
699
948
|
useChat,
|
700
949
|
useCompletion
|
701
950
|
};
|