ai 2.2.23 → 2.2.25
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 +66 -25
- package/dist/index.js +282 -87
- package/dist/index.mjs +277 -84
- package/package.json +4 -3
- package/prompts/dist/index.d.ts +8 -1
- package/prompts/dist/index.js +17 -0
- package/prompts/dist/index.mjs +16 -0
- package/react/dist/index.d.ts +16 -2
- package/react/dist/index.js +436 -193
- package/react/dist/index.mjs +435 -193
- package/solid/dist/index.d.ts +6 -1
- package/solid/dist/index.js +425 -109
- package/solid/dist/index.mjs +425 -109
- package/svelte/dist/index.d.ts +5 -0
- package/svelte/dist/index.js +409 -121
- package/svelte/dist/index.mjs +409 -121
- package/vue/dist/index.js +124 -28
- package/vue/dist/index.mjs +124 -28
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,50 +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
|
-
if (firstSeperatorIndex === -1) {
|
72
|
-
throw new Error("Failed to parse stream string");
|
73
|
-
}
|
74
|
-
const prefix = line.slice(0, firstSeperatorIndex);
|
75
|
-
const type = Object.keys(StreamStringPrefixes).find(
|
76
|
-
(key) => StreamStringPrefixes[key] === Number(prefix)
|
77
|
-
);
|
78
|
-
const val = line.slice(firstSeperatorIndex + 1);
|
79
|
-
let parsedVal = val;
|
80
|
-
if (!val) {
|
81
|
-
return { type, value: "" };
|
82
|
-
}
|
83
|
-
try {
|
84
|
-
parsedVal = JSON.parse(val);
|
85
|
-
} catch (e) {
|
86
|
-
console.error("Failed to parse JSON value:", val);
|
87
|
-
}
|
88
|
-
return { type, value: parsedVal };
|
89
|
-
};
|
90
187
|
var COMPLEX_HEADER = "X-Experimental-Stream-Data";
|
91
188
|
|
92
|
-
//
|
189
|
+
// shared/call-api.ts
|
190
|
+
var import_nanoid = require("nanoid");
|
191
|
+
|
192
|
+
// shared/parse-complex-response.ts
|
93
193
|
async function parseComplexResponse({
|
94
194
|
reader,
|
95
195
|
abortControllerRef,
|
96
196
|
update,
|
97
|
-
onFinish
|
197
|
+
onFinish,
|
198
|
+
generateId = nanoid,
|
199
|
+
getCurrentDate = () => /* @__PURE__ */ new Date()
|
98
200
|
}) {
|
201
|
+
const createdAt = getCurrentDate();
|
99
202
|
const decode = createChunkDecoder(true);
|
100
|
-
const
|
101
|
-
|
203
|
+
const prefixMap = {
|
204
|
+
data: []
|
205
|
+
};
|
102
206
|
const NEWLINE = "\n".charCodeAt(0);
|
103
|
-
|
207
|
+
const chunks = [];
|
104
208
|
let totalLength = 0;
|
105
209
|
while (true) {
|
106
210
|
const { value } = await reader.read();
|
@@ -137,7 +241,7 @@ async function parseComplexResponse({
|
|
137
241
|
};
|
138
242
|
} else {
|
139
243
|
prefixMap["text"] = {
|
140
|
-
id:
|
244
|
+
id: generateId(),
|
141
245
|
role: "assistant",
|
142
246
|
content: value2,
|
143
247
|
createdAt
|
@@ -146,37 +250,24 @@ async function parseComplexResponse({
|
|
146
250
|
}
|
147
251
|
let functionCallMessage = null;
|
148
252
|
if (type === "function_call") {
|
149
|
-
prefixMap["function_call"] =
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
content: "",
|
159
|
-
function_call: parsedFunctionCall,
|
160
|
-
name: parsedFunctionCall.name,
|
161
|
-
createdAt
|
162
|
-
};
|
163
|
-
prefixMap["function_call"] = functionCallMessage;
|
164
|
-
}
|
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"];
|
165
262
|
}
|
166
263
|
if (type === "data") {
|
167
|
-
|
168
|
-
if (prefixMap["data"]) {
|
169
|
-
prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
|
170
|
-
} else {
|
171
|
-
prefixMap["data"] = parsedValue;
|
172
|
-
}
|
264
|
+
prefixMap["data"].push(...value2);
|
173
265
|
}
|
174
|
-
const data = prefixMap["data"];
|
175
266
|
const responseMessage = prefixMap["text"];
|
176
267
|
const merged = [functionCallMessage, responseMessage].filter(
|
177
268
|
Boolean
|
178
269
|
);
|
179
|
-
update(merged, data);
|
270
|
+
update(merged, [...prefixMap["data"]]);
|
180
271
|
if ((abortControllerRef == null ? void 0 : abortControllerRef.current) === null) {
|
181
272
|
reader.cancel();
|
182
273
|
break;
|
@@ -184,7 +275,157 @@ async function parseComplexResponse({
|
|
184
275
|
}
|
185
276
|
}
|
186
277
|
onFinish == null ? void 0 : onFinish(prefixMap);
|
187
|
-
return
|
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) {
|
367
|
+
reader.cancel();
|
368
|
+
break;
|
369
|
+
}
|
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
|
+
}
|
428
|
+
}
|
188
429
|
}
|
189
430
|
|
190
431
|
// react/use-chat.ts
|
@@ -233,10 +474,10 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
233
474
|
}
|
234
475
|
return responseMessage;
|
235
476
|
}
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
477
|
+
return await callApi({
|
478
|
+
api,
|
479
|
+
messages: constructedMessagesPayload,
|
480
|
+
body: {
|
240
481
|
data: chatRequest.data,
|
241
482
|
...extraMetadataRef.current.body,
|
242
483
|
...(_a = chatRequest.options) == null ? void 0 : _a.body,
|
@@ -246,95 +487,26 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
246
487
|
...chatRequest.function_call !== void 0 && {
|
247
488
|
function_call: chatRequest.function_call
|
248
489
|
}
|
249
|
-
}
|
490
|
+
},
|
250
491
|
credentials: extraMetadataRef.current.credentials,
|
251
492
|
headers: {
|
252
493
|
...extraMetadataRef.current.headers,
|
253
494
|
...(_b = chatRequest.options) == null ? void 0 : _b.headers
|
254
495
|
},
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
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
|
261
509
|
});
|
262
|
-
if (onResponse) {
|
263
|
-
try {
|
264
|
-
await onResponse(res);
|
265
|
-
} catch (err) {
|
266
|
-
throw err;
|
267
|
-
}
|
268
|
-
}
|
269
|
-
if (!res.ok) {
|
270
|
-
mutate(previousMessages, false);
|
271
|
-
throw new Error(await res.text() || "Failed to fetch the chat response.");
|
272
|
-
}
|
273
|
-
if (!res.body) {
|
274
|
-
throw new Error("The response body is empty.");
|
275
|
-
}
|
276
|
-
const isComplexMode = res.headers.get(COMPLEX_HEADER) === "true";
|
277
|
-
let responseMessages = [];
|
278
|
-
const reader = res.body.getReader();
|
279
|
-
let responseData = [];
|
280
|
-
if (isComplexMode) {
|
281
|
-
const prefixMap = await parseComplexResponse({
|
282
|
-
reader,
|
283
|
-
abortControllerRef,
|
284
|
-
update(merged, data) {
|
285
|
-
mutate([...chatRequest.messages, ...merged], false);
|
286
|
-
mutateStreamData([...existingData || [], ...data || []], false);
|
287
|
-
}
|
288
|
-
});
|
289
|
-
for (const [type, item] of Object.entries(prefixMap)) {
|
290
|
-
if (onFinish && type === "text") {
|
291
|
-
onFinish(item);
|
292
|
-
}
|
293
|
-
if (type === "data") {
|
294
|
-
responseData.push(item);
|
295
|
-
} else {
|
296
|
-
responseMessages.push(item);
|
297
|
-
}
|
298
|
-
}
|
299
|
-
return { messages: responseMessages, data: responseData };
|
300
|
-
} else {
|
301
|
-
const createdAt = /* @__PURE__ */ new Date();
|
302
|
-
const decode = createChunkDecoder(false);
|
303
|
-
let streamedResponse = "";
|
304
|
-
const replyId = nanoid();
|
305
|
-
let responseMessage = {
|
306
|
-
id: replyId,
|
307
|
-
createdAt,
|
308
|
-
content: "",
|
309
|
-
role: "assistant"
|
310
|
-
};
|
311
|
-
while (true) {
|
312
|
-
const { done, value } = await reader.read();
|
313
|
-
if (done) {
|
314
|
-
break;
|
315
|
-
}
|
316
|
-
streamedResponse += decode(value);
|
317
|
-
if (streamedResponse.startsWith('{"function_call":')) {
|
318
|
-
responseMessage["function_call"] = streamedResponse;
|
319
|
-
} else {
|
320
|
-
responseMessage["content"] = streamedResponse;
|
321
|
-
}
|
322
|
-
mutate([...chatRequest.messages, { ...responseMessage }], false);
|
323
|
-
if (abortControllerRef.current === null) {
|
324
|
-
reader.cancel();
|
325
|
-
break;
|
326
|
-
}
|
327
|
-
}
|
328
|
-
if (streamedResponse.startsWith('{"function_call":')) {
|
329
|
-
const parsedFunctionCall = JSON.parse(streamedResponse).function_call;
|
330
|
-
responseMessage["function_call"] = parsedFunctionCall;
|
331
|
-
mutate([...chatRequest.messages, { ...responseMessage }]);
|
332
|
-
}
|
333
|
-
if (onFinish) {
|
334
|
-
onFinish(responseMessage);
|
335
|
-
}
|
336
|
-
return responseMessage;
|
337
|
-
}
|
338
510
|
};
|
339
511
|
function useChat({
|
340
512
|
api = "/api/chat",
|
@@ -360,10 +532,7 @@ function useChat({
|
|
360
532
|
[chatId, "loading"],
|
361
533
|
null
|
362
534
|
);
|
363
|
-
const { data: streamData, mutate: mutateStreamData } = (0, import_swr.default)(
|
364
|
-
[chatId, "streamData"],
|
365
|
-
null
|
366
|
-
);
|
535
|
+
const { data: streamData, mutate: mutateStreamData } = (0, import_swr.default)([chatId, "streamData"], null);
|
367
536
|
const messagesRef = (0, import_react.useRef)(messages || []);
|
368
537
|
(0, import_react.useEffect)(() => {
|
369
538
|
messagesRef.current = messages || [];
|
@@ -389,8 +558,8 @@ function useChat({
|
|
389
558
|
setError(void 0);
|
390
559
|
const abortController = new AbortController();
|
391
560
|
abortControllerRef.current = abortController;
|
392
|
-
|
393
|
-
|
561
|
+
await processChatStream({
|
562
|
+
getStreamedResponse: () => getStreamedResponse(
|
394
563
|
api,
|
395
564
|
chatRequest,
|
396
565
|
mutate,
|
@@ -402,47 +571,13 @@ function useChat({
|
|
402
571
|
onFinish,
|
403
572
|
onResponse,
|
404
573
|
sendExtraMessageFields
|
405
|
-
)
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
hasFollowingResponse = true;
|
413
|
-
if (experimental_onFunctionCall) {
|
414
|
-
const functionCall = message.function_call;
|
415
|
-
const functionCallResponse = await experimental_onFunctionCall(
|
416
|
-
messagesRef.current,
|
417
|
-
functionCall
|
418
|
-
);
|
419
|
-
if (functionCallResponse === void 0) {
|
420
|
-
hasFollowingResponse = false;
|
421
|
-
break;
|
422
|
-
}
|
423
|
-
chatRequest = functionCallResponse;
|
424
|
-
}
|
425
|
-
}
|
426
|
-
if (!hasFollowingResponse) {
|
427
|
-
break;
|
428
|
-
}
|
429
|
-
} else {
|
430
|
-
const streamedResponseMessage = messagesAndDataOrJustMessage;
|
431
|
-
if (streamedResponseMessage.function_call === void 0 || typeof streamedResponseMessage.function_call === "string") {
|
432
|
-
break;
|
433
|
-
}
|
434
|
-
if (experimental_onFunctionCall) {
|
435
|
-
const functionCall = streamedResponseMessage.function_call;
|
436
|
-
const functionCallResponse = await experimental_onFunctionCall(
|
437
|
-
messagesRef.current,
|
438
|
-
functionCall
|
439
|
-
);
|
440
|
-
if (functionCallResponse === void 0)
|
441
|
-
break;
|
442
|
-
chatRequest = functionCallResponse;
|
443
|
-
}
|
444
|
-
}
|
445
|
-
}
|
574
|
+
),
|
575
|
+
experimental_onFunctionCall,
|
576
|
+
updateChatRequest: (chatRequestParam) => {
|
577
|
+
chatRequest = chatRequestParam;
|
578
|
+
},
|
579
|
+
getCurrentMessages: () => messagesRef.current
|
580
|
+
});
|
446
581
|
abortControllerRef.current = null;
|
447
582
|
} catch (err) {
|
448
583
|
if (err.name === "AbortError") {
|
@@ -739,8 +874,116 @@ function useCompletion({
|
|
739
874
|
isLoading
|
740
875
|
};
|
741
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
|
+
threadId,
|
977
|
+
input,
|
978
|
+
handleInputChange,
|
979
|
+
submitMessage,
|
980
|
+
status,
|
981
|
+
error
|
982
|
+
};
|
983
|
+
}
|
742
984
|
// Annotate the CommonJS export names for ESM import in node:
|
743
985
|
0 && (module.exports = {
|
986
|
+
experimental_useAssistant,
|
744
987
|
useChat,
|
745
988
|
useCompletion
|
746
989
|
});
|