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.js
CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
31
31
|
// react/index.ts
|
32
32
|
var react_exports = {};
|
33
33
|
__export(react_exports, {
|
34
|
+
experimental_useAssistant: () => experimental_useAssistant,
|
34
35
|
useChat: () => useChat,
|
35
36
|
useCompletion: () => useCompletion
|
36
37
|
});
|
@@ -42,6 +43,129 @@ var import_swr = __toESM(require("swr"));
|
|
42
43
|
|
43
44
|
// shared/utils.ts
|
44
45
|
var import_non_secure = require("nanoid/non-secure");
|
46
|
+
|
47
|
+
// shared/stream-parts.ts
|
48
|
+
var textStreamPart = {
|
49
|
+
code: "0",
|
50
|
+
name: "text",
|
51
|
+
parse: (value) => {
|
52
|
+
if (typeof value !== "string") {
|
53
|
+
throw new Error('"text" parts expect a string value.');
|
54
|
+
}
|
55
|
+
return { type: "text", value };
|
56
|
+
}
|
57
|
+
};
|
58
|
+
var functionCallStreamPart = {
|
59
|
+
code: "1",
|
60
|
+
name: "function_call",
|
61
|
+
parse: (value) => {
|
62
|
+
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") {
|
63
|
+
throw new Error(
|
64
|
+
'"function_call" parts expect an object with a "function_call" property.'
|
65
|
+
);
|
66
|
+
}
|
67
|
+
return {
|
68
|
+
type: "function_call",
|
69
|
+
value
|
70
|
+
};
|
71
|
+
}
|
72
|
+
};
|
73
|
+
var dataStreamPart = {
|
74
|
+
code: "2",
|
75
|
+
name: "data",
|
76
|
+
parse: (value) => {
|
77
|
+
if (!Array.isArray(value)) {
|
78
|
+
throw new Error('"data" parts expect an array value.');
|
79
|
+
}
|
80
|
+
return { type: "data", value };
|
81
|
+
}
|
82
|
+
};
|
83
|
+
var errorStreamPart = {
|
84
|
+
code: "3",
|
85
|
+
name: "error",
|
86
|
+
parse: (value) => {
|
87
|
+
if (typeof value !== "string") {
|
88
|
+
throw new Error('"error" parts expect a string value.');
|
89
|
+
}
|
90
|
+
return { type: "error", value };
|
91
|
+
}
|
92
|
+
};
|
93
|
+
var assistantMessage = {
|
94
|
+
code: "4",
|
95
|
+
name: "assistant_message",
|
96
|
+
parse: (value) => {
|
97
|
+
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(
|
98
|
+
(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"
|
99
|
+
)) {
|
100
|
+
throw new Error(
|
101
|
+
'"assistant_message" parts expect an object with an "id", "role", and "content" property.'
|
102
|
+
);
|
103
|
+
}
|
104
|
+
return {
|
105
|
+
type: "assistant_message",
|
106
|
+
value
|
107
|
+
};
|
108
|
+
}
|
109
|
+
};
|
110
|
+
var assistantControlData = {
|
111
|
+
code: "5",
|
112
|
+
name: "assistant_control_data",
|
113
|
+
parse: (value) => {
|
114
|
+
if (value == null || typeof value !== "object" || !("threadId" in value) || !("messageId" in value) || typeof value.threadId !== "string" || typeof value.messageId !== "string") {
|
115
|
+
throw new Error(
|
116
|
+
'"assistant_control_data" parts expect an object with a "threadId" and "messageId" property.'
|
117
|
+
);
|
118
|
+
}
|
119
|
+
return {
|
120
|
+
type: "assistant_control_data",
|
121
|
+
value: {
|
122
|
+
threadId: value.threadId,
|
123
|
+
messageId: value.messageId
|
124
|
+
}
|
125
|
+
};
|
126
|
+
}
|
127
|
+
};
|
128
|
+
var streamParts = [
|
129
|
+
textStreamPart,
|
130
|
+
functionCallStreamPart,
|
131
|
+
dataStreamPart,
|
132
|
+
errorStreamPart,
|
133
|
+
assistantMessage,
|
134
|
+
assistantControlData
|
135
|
+
];
|
136
|
+
var streamPartsByCode = {
|
137
|
+
[textStreamPart.code]: textStreamPart,
|
138
|
+
[functionCallStreamPart.code]: functionCallStreamPart,
|
139
|
+
[dataStreamPart.code]: dataStreamPart,
|
140
|
+
[errorStreamPart.code]: errorStreamPart,
|
141
|
+
[assistantMessage.code]: assistantMessage,
|
142
|
+
[assistantControlData.code]: assistantControlData
|
143
|
+
};
|
144
|
+
var StreamStringPrefixes = {
|
145
|
+
[textStreamPart.name]: textStreamPart.code,
|
146
|
+
[functionCallStreamPart.name]: functionCallStreamPart.code,
|
147
|
+
[dataStreamPart.name]: dataStreamPart.code,
|
148
|
+
[errorStreamPart.name]: errorStreamPart.code,
|
149
|
+
[assistantMessage.name]: assistantMessage.code,
|
150
|
+
[assistantControlData.name]: assistantControlData.code
|
151
|
+
};
|
152
|
+
var validCodes = streamParts.map((part) => part.code);
|
153
|
+
var parseStreamPart = (line) => {
|
154
|
+
const firstSeparatorIndex = line.indexOf(":");
|
155
|
+
if (firstSeparatorIndex === -1) {
|
156
|
+
throw new Error("Failed to parse stream string. No separator found.");
|
157
|
+
}
|
158
|
+
const prefix = line.slice(0, firstSeparatorIndex);
|
159
|
+
if (!validCodes.includes(prefix)) {
|
160
|
+
throw new Error(`Failed to parse stream string. Invalid code ${prefix}.`);
|
161
|
+
}
|
162
|
+
const code = prefix;
|
163
|
+
const textValue = line.slice(firstSeparatorIndex + 1);
|
164
|
+
const jsonValue = JSON.parse(textValue);
|
165
|
+
return streamPartsByCode[code].parse(jsonValue);
|
166
|
+
};
|
167
|
+
|
168
|
+
// shared/utils.ts
|
45
169
|
var nanoid = (0, import_non_secure.customAlphabet)(
|
46
170
|
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
47
171
|
7
|
@@ -57,46 +181,30 @@ function createChunkDecoder(complex) {
|
|
57
181
|
}
|
58
182
|
return function(chunk) {
|
59
183
|
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
60
|
-
return decoded.map(
|
184
|
+
return decoded.map(parseStreamPart).filter(Boolean);
|
61
185
|
};
|
62
186
|
}
|
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
187
|
var COMPLEX_HEADER = "X-Experimental-Stream-Data";
|
88
188
|
|
89
|
-
//
|
189
|
+
// shared/call-api.ts
|
190
|
+
var import_nanoid = require("nanoid");
|
191
|
+
|
192
|
+
// shared/parse-complex-response.ts
|
90
193
|
async function parseComplexResponse({
|
91
194
|
reader,
|
92
195
|
abortControllerRef,
|
93
|
-
update
|
196
|
+
update,
|
197
|
+
onFinish,
|
198
|
+
generateId = nanoid,
|
199
|
+
getCurrentDate = () => /* @__PURE__ */ new Date()
|
94
200
|
}) {
|
201
|
+
const createdAt = getCurrentDate();
|
95
202
|
const decode = createChunkDecoder(true);
|
96
|
-
const
|
97
|
-
|
203
|
+
const prefixMap = {
|
204
|
+
data: []
|
205
|
+
};
|
98
206
|
const NEWLINE = "\n".charCodeAt(0);
|
99
|
-
|
207
|
+
const chunks = [];
|
100
208
|
let totalLength = 0;
|
101
209
|
while (true) {
|
102
210
|
const { value } = await reader.read();
|
@@ -133,7 +241,7 @@ async function parseComplexResponse({
|
|
133
241
|
};
|
134
242
|
} else {
|
135
243
|
prefixMap["text"] = {
|
136
|
-
id:
|
244
|
+
id: generateId(),
|
137
245
|
role: "assistant",
|
138
246
|
content: value2,
|
139
247
|
createdAt
|
@@ -142,44 +250,182 @@ async function parseComplexResponse({
|
|
142
250
|
}
|
143
251
|
let functionCallMessage = null;
|
144
252
|
if (type === "function_call") {
|
145
|
-
prefixMap["function_call"] =
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
content: "",
|
155
|
-
function_call: parsedFunctionCall,
|
156
|
-
name: parsedFunctionCall.name,
|
157
|
-
createdAt
|
158
|
-
};
|
159
|
-
prefixMap["function_call"] = functionCallMessage;
|
160
|
-
}
|
253
|
+
prefixMap["function_call"] = {
|
254
|
+
id: generateId(),
|
255
|
+
role: "assistant",
|
256
|
+
content: "",
|
257
|
+
function_call: value2.function_call,
|
258
|
+
name: value2.function_call.name,
|
259
|
+
createdAt
|
260
|
+
};
|
261
|
+
functionCallMessage = prefixMap["function_call"];
|
161
262
|
}
|
162
263
|
if (type === "data") {
|
163
|
-
|
164
|
-
if (prefixMap["data"]) {
|
165
|
-
prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
|
166
|
-
} else {
|
167
|
-
prefixMap["data"] = parsedValue;
|
168
|
-
}
|
264
|
+
prefixMap["data"].push(...value2);
|
169
265
|
}
|
170
|
-
const data = prefixMap["data"];
|
171
266
|
const responseMessage = prefixMap["text"];
|
172
267
|
const merged = [functionCallMessage, responseMessage].filter(
|
173
268
|
Boolean
|
174
269
|
);
|
175
|
-
update(merged, data);
|
176
|
-
if (abortControllerRef.current === null) {
|
270
|
+
update(merged, [...prefixMap["data"]]);
|
271
|
+
if ((abortControllerRef == null ? void 0 : abortControllerRef.current) === null) {
|
272
|
+
reader.cancel();
|
273
|
+
break;
|
274
|
+
}
|
275
|
+
}
|
276
|
+
}
|
277
|
+
onFinish == null ? void 0 : onFinish(prefixMap);
|
278
|
+
return {
|
279
|
+
messages: [prefixMap.text, prefixMap.function_call].filter(
|
280
|
+
Boolean
|
281
|
+
),
|
282
|
+
data: prefixMap.data
|
283
|
+
};
|
284
|
+
}
|
285
|
+
|
286
|
+
// shared/call-api.ts
|
287
|
+
async function callApi({
|
288
|
+
api,
|
289
|
+
messages,
|
290
|
+
body,
|
291
|
+
credentials,
|
292
|
+
headers,
|
293
|
+
abortController,
|
294
|
+
appendMessage,
|
295
|
+
restoreMessagesOnFailure,
|
296
|
+
onResponse,
|
297
|
+
onUpdate,
|
298
|
+
onFinish
|
299
|
+
}) {
|
300
|
+
var _a;
|
301
|
+
const response = await fetch(api, {
|
302
|
+
method: "POST",
|
303
|
+
body: JSON.stringify({
|
304
|
+
messages,
|
305
|
+
...body
|
306
|
+
}),
|
307
|
+
headers,
|
308
|
+
signal: (_a = abortController == null ? void 0 : abortController()) == null ? void 0 : _a.signal,
|
309
|
+
credentials
|
310
|
+
}).catch((err) => {
|
311
|
+
restoreMessagesOnFailure();
|
312
|
+
throw err;
|
313
|
+
});
|
314
|
+
if (onResponse) {
|
315
|
+
try {
|
316
|
+
await onResponse(response);
|
317
|
+
} catch (err) {
|
318
|
+
throw err;
|
319
|
+
}
|
320
|
+
}
|
321
|
+
if (!response.ok) {
|
322
|
+
restoreMessagesOnFailure();
|
323
|
+
throw new Error(
|
324
|
+
await response.text() || "Failed to fetch the chat response."
|
325
|
+
);
|
326
|
+
}
|
327
|
+
if (!response.body) {
|
328
|
+
throw new Error("The response body is empty.");
|
329
|
+
}
|
330
|
+
const reader = response.body.getReader();
|
331
|
+
const isComplexMode = response.headers.get(COMPLEX_HEADER) === "true";
|
332
|
+
if (isComplexMode) {
|
333
|
+
return await parseComplexResponse({
|
334
|
+
reader,
|
335
|
+
abortControllerRef: abortController != null ? { current: abortController() } : void 0,
|
336
|
+
update: onUpdate,
|
337
|
+
onFinish(prefixMap) {
|
338
|
+
if (onFinish && prefixMap.text != null) {
|
339
|
+
onFinish(prefixMap.text);
|
340
|
+
}
|
341
|
+
}
|
342
|
+
});
|
343
|
+
} else {
|
344
|
+
const createdAt = /* @__PURE__ */ new Date();
|
345
|
+
const decode = createChunkDecoder(false);
|
346
|
+
let streamedResponse = "";
|
347
|
+
const replyId = (0, import_nanoid.nanoid)();
|
348
|
+
let responseMessage = {
|
349
|
+
id: replyId,
|
350
|
+
createdAt,
|
351
|
+
content: "",
|
352
|
+
role: "assistant"
|
353
|
+
};
|
354
|
+
while (true) {
|
355
|
+
const { done, value } = await reader.read();
|
356
|
+
if (done) {
|
357
|
+
break;
|
358
|
+
}
|
359
|
+
streamedResponse += decode(value);
|
360
|
+
if (streamedResponse.startsWith('{"function_call":')) {
|
361
|
+
responseMessage["function_call"] = streamedResponse;
|
362
|
+
} else {
|
363
|
+
responseMessage["content"] = streamedResponse;
|
364
|
+
}
|
365
|
+
appendMessage({ ...responseMessage });
|
366
|
+
if ((abortController == null ? void 0 : abortController()) === null) {
|
177
367
|
reader.cancel();
|
178
368
|
break;
|
179
369
|
}
|
180
370
|
}
|
371
|
+
if (streamedResponse.startsWith('{"function_call":')) {
|
372
|
+
const parsedFunctionCall = JSON.parse(streamedResponse).function_call;
|
373
|
+
responseMessage["function_call"] = parsedFunctionCall;
|
374
|
+
appendMessage({ ...responseMessage });
|
375
|
+
}
|
376
|
+
if (onFinish) {
|
377
|
+
onFinish(responseMessage);
|
378
|
+
}
|
379
|
+
return responseMessage;
|
380
|
+
}
|
381
|
+
}
|
382
|
+
|
383
|
+
// shared/process-chat-stream.ts
|
384
|
+
async function processChatStream({
|
385
|
+
getStreamedResponse: getStreamedResponse2,
|
386
|
+
experimental_onFunctionCall,
|
387
|
+
updateChatRequest,
|
388
|
+
getCurrentMessages
|
389
|
+
}) {
|
390
|
+
while (true) {
|
391
|
+
const messagesAndDataOrJustMessage = await getStreamedResponse2();
|
392
|
+
if ("messages" in messagesAndDataOrJustMessage) {
|
393
|
+
let hasFollowingResponse = false;
|
394
|
+
for (const message of messagesAndDataOrJustMessage.messages) {
|
395
|
+
if (message.function_call === void 0 || typeof message.function_call === "string") {
|
396
|
+
continue;
|
397
|
+
}
|
398
|
+
hasFollowingResponse = true;
|
399
|
+
if (experimental_onFunctionCall) {
|
400
|
+
const functionCall = message.function_call;
|
401
|
+
const functionCallResponse = await experimental_onFunctionCall(
|
402
|
+
getCurrentMessages(),
|
403
|
+
functionCall
|
404
|
+
);
|
405
|
+
if (functionCallResponse === void 0) {
|
406
|
+
hasFollowingResponse = false;
|
407
|
+
break;
|
408
|
+
}
|
409
|
+
updateChatRequest(functionCallResponse);
|
410
|
+
}
|
411
|
+
}
|
412
|
+
if (!hasFollowingResponse) {
|
413
|
+
break;
|
414
|
+
}
|
415
|
+
} else {
|
416
|
+
const streamedResponseMessage = messagesAndDataOrJustMessage;
|
417
|
+
if (streamedResponseMessage.function_call === void 0 || typeof streamedResponseMessage.function_call === "string") {
|
418
|
+
break;
|
419
|
+
}
|
420
|
+
if (experimental_onFunctionCall) {
|
421
|
+
const functionCall = streamedResponseMessage.function_call;
|
422
|
+
const functionCallResponse = await experimental_onFunctionCall(getCurrentMessages(), functionCall);
|
423
|
+
if (functionCallResponse === void 0)
|
424
|
+
break;
|
425
|
+
updateChatRequest(functionCallResponse);
|
426
|
+
}
|
427
|
+
}
|
181
428
|
}
|
182
|
-
return prefixMap;
|
183
429
|
}
|
184
430
|
|
185
431
|
// react/use-chat.ts
|
@@ -215,7 +461,8 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
215
461
|
}
|
216
462
|
try {
|
217
463
|
const promise = api({
|
218
|
-
messages: constructedMessagesPayload
|
464
|
+
messages: constructedMessagesPayload,
|
465
|
+
data: chatRequest.data
|
219
466
|
});
|
220
467
|
await readRow(promise);
|
221
468
|
} catch (e) {
|
@@ -227,10 +474,11 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
227
474
|
}
|
228
475
|
return responseMessage;
|
229
476
|
}
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
477
|
+
return await callApi({
|
478
|
+
api,
|
479
|
+
messages: constructedMessagesPayload,
|
480
|
+
body: {
|
481
|
+
data: chatRequest.data,
|
234
482
|
...extraMetadataRef.current.body,
|
235
483
|
...(_a = chatRequest.options) == null ? void 0 : _a.body,
|
236
484
|
...chatRequest.functions !== void 0 && {
|
@@ -239,95 +487,26 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
239
487
|
...chatRequest.function_call !== void 0 && {
|
240
488
|
function_call: chatRequest.function_call
|
241
489
|
}
|
242
|
-
}
|
490
|
+
},
|
243
491
|
credentials: extraMetadataRef.current.credentials,
|
244
492
|
headers: {
|
245
493
|
...extraMetadataRef.current.headers,
|
246
494
|
...(_b = chatRequest.options) == null ? void 0 : _b.headers
|
247
495
|
},
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
496
|
+
abortController: () => abortControllerRef.current,
|
497
|
+
appendMessage(message) {
|
498
|
+
mutate([...chatRequest.messages, message], false);
|
499
|
+
},
|
500
|
+
restoreMessagesOnFailure() {
|
501
|
+
mutate(previousMessages, false);
|
502
|
+
},
|
503
|
+
onResponse,
|
504
|
+
onUpdate(merged, data) {
|
505
|
+
mutate([...chatRequest.messages, ...merged], false);
|
506
|
+
mutateStreamData([...existingData || [], ...data || []], false);
|
507
|
+
},
|
508
|
+
onFinish
|
254
509
|
});
|
255
|
-
if (onResponse) {
|
256
|
-
try {
|
257
|
-
await onResponse(res);
|
258
|
-
} catch (err) {
|
259
|
-
throw err;
|
260
|
-
}
|
261
|
-
}
|
262
|
-
if (!res.ok) {
|
263
|
-
mutate(previousMessages, false);
|
264
|
-
throw new Error(await res.text() || "Failed to fetch the chat response.");
|
265
|
-
}
|
266
|
-
if (!res.body) {
|
267
|
-
throw new Error("The response body is empty.");
|
268
|
-
}
|
269
|
-
const isComplexMode = res.headers.get(COMPLEX_HEADER) === "true";
|
270
|
-
let responseMessages = [];
|
271
|
-
const reader = res.body.getReader();
|
272
|
-
let responseData = [];
|
273
|
-
if (isComplexMode) {
|
274
|
-
const prefixMap = await parseComplexResponse({
|
275
|
-
reader,
|
276
|
-
abortControllerRef,
|
277
|
-
update(merged, data) {
|
278
|
-
mutate([...chatRequest.messages, ...merged], false);
|
279
|
-
mutateStreamData([...existingData || [], ...data || []], false);
|
280
|
-
}
|
281
|
-
});
|
282
|
-
for (const [type, item] of Object.entries(prefixMap)) {
|
283
|
-
if (onFinish && type === "text") {
|
284
|
-
onFinish(item);
|
285
|
-
}
|
286
|
-
if (type === "data") {
|
287
|
-
responseData.push(item);
|
288
|
-
} else {
|
289
|
-
responseMessages.push(item);
|
290
|
-
}
|
291
|
-
}
|
292
|
-
return { messages: responseMessages, data: responseData };
|
293
|
-
} else {
|
294
|
-
const createdAt = /* @__PURE__ */ new Date();
|
295
|
-
const decode = createChunkDecoder(false);
|
296
|
-
let streamedResponse = "";
|
297
|
-
const replyId = nanoid();
|
298
|
-
let responseMessage = {
|
299
|
-
id: replyId,
|
300
|
-
createdAt,
|
301
|
-
content: "",
|
302
|
-
role: "assistant"
|
303
|
-
};
|
304
|
-
while (true) {
|
305
|
-
const { done, value } = await reader.read();
|
306
|
-
if (done) {
|
307
|
-
break;
|
308
|
-
}
|
309
|
-
streamedResponse += decode(value);
|
310
|
-
if (streamedResponse.startsWith('{"function_call":')) {
|
311
|
-
responseMessage["function_call"] = streamedResponse;
|
312
|
-
} else {
|
313
|
-
responseMessage["content"] = streamedResponse;
|
314
|
-
}
|
315
|
-
mutate([...chatRequest.messages, { ...responseMessage }], false);
|
316
|
-
if (abortControllerRef.current === null) {
|
317
|
-
reader.cancel();
|
318
|
-
break;
|
319
|
-
}
|
320
|
-
}
|
321
|
-
if (streamedResponse.startsWith('{"function_call":')) {
|
322
|
-
const parsedFunctionCall = JSON.parse(streamedResponse).function_call;
|
323
|
-
responseMessage["function_call"] = parsedFunctionCall;
|
324
|
-
mutate([...chatRequest.messages, { ...responseMessage }]);
|
325
|
-
}
|
326
|
-
if (onFinish) {
|
327
|
-
onFinish(responseMessage);
|
328
|
-
}
|
329
|
-
return responseMessage;
|
330
|
-
}
|
331
510
|
};
|
332
511
|
function useChat({
|
333
512
|
api = "/api/chat",
|
@@ -353,10 +532,7 @@ function useChat({
|
|
353
532
|
[chatId, "loading"],
|
354
533
|
null
|
355
534
|
);
|
356
|
-
const { data: streamData, mutate: mutateStreamData } = (0, import_swr.default)(
|
357
|
-
[chatId, "streamData"],
|
358
|
-
null
|
359
|
-
);
|
535
|
+
const { data: streamData, mutate: mutateStreamData } = (0, import_swr.default)([chatId, "streamData"], null);
|
360
536
|
const messagesRef = (0, import_react.useRef)(messages || []);
|
361
537
|
(0, import_react.useEffect)(() => {
|
362
538
|
messagesRef.current = messages || [];
|
@@ -382,8 +558,8 @@ function useChat({
|
|
382
558
|
setError(void 0);
|
383
559
|
const abortController = new AbortController();
|
384
560
|
abortControllerRef.current = abortController;
|
385
|
-
|
386
|
-
|
561
|
+
await processChatStream({
|
562
|
+
getStreamedResponse: () => getStreamedResponse(
|
387
563
|
api,
|
388
564
|
chatRequest,
|
389
565
|
mutate,
|
@@ -395,47 +571,13 @@ function useChat({
|
|
395
571
|
onFinish,
|
396
572
|
onResponse,
|
397
573
|
sendExtraMessageFields
|
398
|
-
)
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
hasFollowingResponse = true;
|
406
|
-
if (experimental_onFunctionCall) {
|
407
|
-
const functionCall = message.function_call;
|
408
|
-
const functionCallResponse = await experimental_onFunctionCall(
|
409
|
-
messagesRef.current,
|
410
|
-
functionCall
|
411
|
-
);
|
412
|
-
if (functionCallResponse === void 0) {
|
413
|
-
hasFollowingResponse = false;
|
414
|
-
break;
|
415
|
-
}
|
416
|
-
chatRequest = functionCallResponse;
|
417
|
-
}
|
418
|
-
}
|
419
|
-
if (!hasFollowingResponse) {
|
420
|
-
break;
|
421
|
-
}
|
422
|
-
} else {
|
423
|
-
const streamedResponseMessage = messagesAndDataOrJustMessage;
|
424
|
-
if (streamedResponseMessage.function_call === void 0 || typeof streamedResponseMessage.function_call === "string") {
|
425
|
-
break;
|
426
|
-
}
|
427
|
-
if (experimental_onFunctionCall) {
|
428
|
-
const functionCall = streamedResponseMessage.function_call;
|
429
|
-
const functionCallResponse = await experimental_onFunctionCall(
|
430
|
-
messagesRef.current,
|
431
|
-
functionCall
|
432
|
-
);
|
433
|
-
if (functionCallResponse === void 0)
|
434
|
-
break;
|
435
|
-
chatRequest = functionCallResponse;
|
436
|
-
}
|
437
|
-
}
|
438
|
-
}
|
574
|
+
),
|
575
|
+
experimental_onFunctionCall,
|
576
|
+
updateChatRequest: (chatRequestParam) => {
|
577
|
+
chatRequest = chatRequestParam;
|
578
|
+
},
|
579
|
+
getCurrentMessages: () => messagesRef.current
|
580
|
+
});
|
439
581
|
abortControllerRef.current = null;
|
440
582
|
} catch (err) {
|
441
583
|
if (err.name === "AbortError") {
|
@@ -468,13 +610,14 @@ function useChat({
|
|
468
610
|
]
|
469
611
|
);
|
470
612
|
const append = (0, import_react.useCallback)(
|
471
|
-
async (message, { options, functions, function_call } = {}) => {
|
613
|
+
async (message, { options, functions, function_call, data } = {}) => {
|
472
614
|
if (!message.id) {
|
473
615
|
message.id = nanoid();
|
474
616
|
}
|
475
617
|
const chatRequest = {
|
476
618
|
messages: messagesRef.current.concat(message),
|
477
619
|
options,
|
620
|
+
data,
|
478
621
|
...functions !== void 0 && { functions },
|
479
622
|
...function_call !== void 0 && { function_call }
|
480
623
|
};
|
@@ -521,7 +664,7 @@ function useChat({
|
|
521
664
|
);
|
522
665
|
const [input, setInput] = (0, import_react.useState)(initialInput);
|
523
666
|
const handleSubmit = (0, import_react.useCallback)(
|
524
|
-
(e,
|
667
|
+
(e, options = {}, metadata) => {
|
525
668
|
if (metadata) {
|
526
669
|
extraMetadataRef.current = {
|
527
670
|
...extraMetadataRef.current,
|
@@ -537,7 +680,7 @@ function useChat({
|
|
537
680
|
role: "user",
|
538
681
|
createdAt: /* @__PURE__ */ new Date()
|
539
682
|
},
|
540
|
-
|
683
|
+
options
|
541
684
|
);
|
542
685
|
setInput("");
|
543
686
|
},
|
@@ -731,8 +874,115 @@ function useCompletion({
|
|
731
874
|
isLoading
|
732
875
|
};
|
733
876
|
}
|
877
|
+
|
878
|
+
// react/use-assistant.ts
|
879
|
+
var import_react3 = require("react");
|
880
|
+
|
881
|
+
// shared/process-message-stream.ts
|
882
|
+
async function processMessageStream(reader, processMessage) {
|
883
|
+
const decoder = new TextDecoder();
|
884
|
+
let buffer = "";
|
885
|
+
while (true) {
|
886
|
+
const { done, value } = await reader.read();
|
887
|
+
if (done) {
|
888
|
+
if (buffer.length > 0) {
|
889
|
+
processMessage(buffer);
|
890
|
+
}
|
891
|
+
break;
|
892
|
+
}
|
893
|
+
buffer += decoder.decode(value, { stream: true });
|
894
|
+
let endIndex;
|
895
|
+
while ((endIndex = buffer.indexOf("\n")) !== -1) {
|
896
|
+
processMessage(buffer.substring(0, endIndex).trim());
|
897
|
+
buffer = buffer.substring(endIndex + 1);
|
898
|
+
}
|
899
|
+
}
|
900
|
+
}
|
901
|
+
|
902
|
+
// react/use-assistant.ts
|
903
|
+
function experimental_useAssistant({
|
904
|
+
api,
|
905
|
+
threadId: threadIdParam
|
906
|
+
}) {
|
907
|
+
const [messages, setMessages] = (0, import_react3.useState)([]);
|
908
|
+
const [input, setInput] = (0, import_react3.useState)("");
|
909
|
+
const [threadId, setThreadId] = (0, import_react3.useState)(void 0);
|
910
|
+
const [status, setStatus] = (0, import_react3.useState)("awaiting_message");
|
911
|
+
const [error, setError] = (0, import_react3.useState)(void 0);
|
912
|
+
const handleInputChange = (e) => {
|
913
|
+
setInput(e.target.value);
|
914
|
+
};
|
915
|
+
const submitMessage = async (e) => {
|
916
|
+
var _a;
|
917
|
+
e.preventDefault();
|
918
|
+
if (input === "") {
|
919
|
+
return;
|
920
|
+
}
|
921
|
+
setStatus("in_progress");
|
922
|
+
setMessages((messages2) => [
|
923
|
+
...messages2,
|
924
|
+
{ id: "", role: "user", content: input }
|
925
|
+
]);
|
926
|
+
setInput("");
|
927
|
+
const result = await fetch(api, {
|
928
|
+
method: "POST",
|
929
|
+
headers: { "Content-Type": "application/json" },
|
930
|
+
body: JSON.stringify({
|
931
|
+
// always use user-provided threadId when available:
|
932
|
+
threadId: (_a = threadIdParam != null ? threadIdParam : threadId) != null ? _a : null,
|
933
|
+
message: input
|
934
|
+
})
|
935
|
+
});
|
936
|
+
if (result.body == null) {
|
937
|
+
throw new Error("The response body is empty.");
|
938
|
+
}
|
939
|
+
await processMessageStream(result.body.getReader(), (message) => {
|
940
|
+
try {
|
941
|
+
const { type, value } = parseStreamPart(message);
|
942
|
+
switch (type) {
|
943
|
+
case "assistant_message": {
|
944
|
+
setMessages((messages2) => [
|
945
|
+
...messages2,
|
946
|
+
{
|
947
|
+
id: value.id,
|
948
|
+
role: value.role,
|
949
|
+
content: value.content[0].text.value
|
950
|
+
}
|
951
|
+
]);
|
952
|
+
break;
|
953
|
+
}
|
954
|
+
case "assistant_control_data": {
|
955
|
+
setThreadId(value.threadId);
|
956
|
+
setMessages((messages2) => {
|
957
|
+
const lastMessage = messages2[messages2.length - 1];
|
958
|
+
lastMessage.id = value.messageId;
|
959
|
+
return [...messages2.slice(0, messages2.length - 1), lastMessage];
|
960
|
+
});
|
961
|
+
break;
|
962
|
+
}
|
963
|
+
case "error": {
|
964
|
+
setError(value);
|
965
|
+
break;
|
966
|
+
}
|
967
|
+
}
|
968
|
+
} catch (error2) {
|
969
|
+
setError(error2);
|
970
|
+
}
|
971
|
+
});
|
972
|
+
setStatus("awaiting_message");
|
973
|
+
};
|
974
|
+
return {
|
975
|
+
messages,
|
976
|
+
input,
|
977
|
+
handleInputChange,
|
978
|
+
submitMessage,
|
979
|
+
status,
|
980
|
+
error
|
981
|
+
};
|
982
|
+
}
|
734
983
|
// Annotate the CommonJS export names for ESM import in node:
|
735
984
|
0 && (module.exports = {
|
985
|
+
experimental_useAssistant,
|
736
986
|
useChat,
|
737
987
|
useCompletion
|
738
988
|
});
|