ai 2.2.19 → 2.2.21
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 +28 -2
- package/dist/index.js +4 -8
- package/dist/index.mjs +4 -8
- package/package.json +4 -1
- package/react/dist/index.d.ts +1 -1
- package/react/dist/index.js +109 -90
- package/react/dist/index.mjs +109 -90
- package/solid/dist/index.js +1 -1
- package/solid/dist/index.mjs +1 -1
- package/svelte/dist/index.js +1 -1
- package/svelte/dist/index.mjs +1 -1
- package/vue/dist/index.js +1 -1
- package/vue/dist/index.mjs +1 -1
package/dist/index.d.ts
CHANGED
@@ -242,7 +242,7 @@ interface ChatCompletionChunk {
|
|
242
242
|
}
|
243
243
|
interface ChatCompletionChunkChoice {
|
244
244
|
delta: ChoiceDelta;
|
245
|
-
finish_reason: 'stop' | 'length' | '
|
245
|
+
finish_reason: 'stop' | 'length' | 'tool_calls' | 'content_filter' | 'function_call' | null;
|
246
246
|
index: number;
|
247
247
|
}
|
248
248
|
interface ChoiceDelta {
|
@@ -258,7 +258,33 @@ interface ChoiceDelta {
|
|
258
258
|
/**
|
259
259
|
* The role of the author of this message.
|
260
260
|
*/
|
261
|
-
role?: 'system' | 'user' | 'assistant' | '
|
261
|
+
role?: 'system' | 'user' | 'assistant' | 'tool';
|
262
|
+
tool_calls?: Array<DeltaToolCall>;
|
263
|
+
}
|
264
|
+
interface DeltaToolCall {
|
265
|
+
index: number;
|
266
|
+
/**
|
267
|
+
* The ID of the tool call.
|
268
|
+
*/
|
269
|
+
id?: string;
|
270
|
+
function?: ToolCallFunction;
|
271
|
+
/**
|
272
|
+
* The type of the tool. Currently, only `function` is supported.
|
273
|
+
*/
|
274
|
+
type?: 'function';
|
275
|
+
}
|
276
|
+
interface ToolCallFunction {
|
277
|
+
/**
|
278
|
+
* The arguments to call the function with, as generated by the model in JSON
|
279
|
+
* format. Note that the model does not always generate valid JSON, and may
|
280
|
+
* hallucinate parameters not defined by your function schema. Validate the
|
281
|
+
* arguments in your code before calling your function.
|
282
|
+
*/
|
283
|
+
arguments?: string;
|
284
|
+
/**
|
285
|
+
* The name of the function to call.
|
286
|
+
*/
|
287
|
+
name?: string;
|
262
288
|
}
|
263
289
|
/**
|
264
290
|
* https://github.com/openai/openai-node/blob/3ec43ee790a2eb6a0ccdd5f25faa23251b0f9b8e/src/resources/completions.ts#L28C1-L64C1
|
package/dist/index.js
CHANGED
@@ -178,7 +178,7 @@ function createChunkDecoder(complex) {
|
|
178
178
|
};
|
179
179
|
}
|
180
180
|
return function(chunk) {
|
181
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
181
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
182
182
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
183
183
|
};
|
184
184
|
}
|
@@ -530,14 +530,12 @@ function createParser2(res) {
|
|
530
530
|
if (!text)
|
531
531
|
return;
|
532
532
|
if (value.generated_text != null && value.generated_text.length > 0) {
|
533
|
-
controller.close();
|
534
533
|
return;
|
535
534
|
}
|
536
535
|
if (text === "</s>" || text === "<|endoftext|>" || text === "<|end|>") {
|
537
|
-
|
538
|
-
} else {
|
539
|
-
controller.enqueue(text);
|
536
|
+
return;
|
540
537
|
}
|
538
|
+
controller.enqueue(text);
|
541
539
|
}
|
542
540
|
});
|
543
541
|
}
|
@@ -552,9 +550,7 @@ var utf8Decoder = new TextDecoder("utf-8");
|
|
552
550
|
async function processLines(lines, controller) {
|
553
551
|
for (const line of lines) {
|
554
552
|
const { text, is_finished } = JSON.parse(line);
|
555
|
-
if (is_finished
|
556
|
-
controller.close();
|
557
|
-
} else {
|
553
|
+
if (!is_finished) {
|
558
554
|
controller.enqueue(text);
|
559
555
|
}
|
560
556
|
}
|
package/dist/index.mjs
CHANGED
@@ -132,7 +132,7 @@ function createChunkDecoder(complex) {
|
|
132
132
|
};
|
133
133
|
}
|
134
134
|
return function(chunk) {
|
135
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
135
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
136
136
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
137
137
|
};
|
138
138
|
}
|
@@ -484,14 +484,12 @@ function createParser2(res) {
|
|
484
484
|
if (!text)
|
485
485
|
return;
|
486
486
|
if (value.generated_text != null && value.generated_text.length > 0) {
|
487
|
-
controller.close();
|
488
487
|
return;
|
489
488
|
}
|
490
489
|
if (text === "</s>" || text === "<|endoftext|>" || text === "<|end|>") {
|
491
|
-
|
492
|
-
} else {
|
493
|
-
controller.enqueue(text);
|
490
|
+
return;
|
494
491
|
}
|
492
|
+
controller.enqueue(text);
|
495
493
|
}
|
496
494
|
});
|
497
495
|
}
|
@@ -506,9 +504,7 @@ var utf8Decoder = new TextDecoder("utf-8");
|
|
506
504
|
async function processLines(lines, controller) {
|
507
505
|
for (const line of lines) {
|
508
506
|
const { text, is_finished } = JSON.parse(line);
|
509
|
-
if (is_finished
|
510
|
-
controller.close();
|
511
|
-
} else {
|
507
|
+
if (!is_finished) {
|
512
508
|
controller.enqueue(text);
|
513
509
|
}
|
514
510
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "ai",
|
3
|
-
"version": "2.2.
|
3
|
+
"version": "2.2.21",
|
4
4
|
"license": "Apache-2.0",
|
5
5
|
"sideEffects": false,
|
6
6
|
"main": "./dist/index.js",
|
@@ -69,12 +69,15 @@
|
|
69
69
|
},
|
70
70
|
"devDependencies": {
|
71
71
|
"@edge-runtime/jest-environment": "1.1.0-beta.31",
|
72
|
+
"@huggingface/inference": "2.6.4",
|
72
73
|
"@types/jest": "29.2.0",
|
73
74
|
"@types/node": "^17.0.12",
|
74
75
|
"@types/react": "^18.2.8",
|
75
76
|
"@types/react-dom": "^18.2.0",
|
76
77
|
"eslint": "^7.32.0",
|
77
78
|
"jest": "29.2.1",
|
79
|
+
"langchain": "0.0.172",
|
80
|
+
"openai": "4.16.1",
|
78
81
|
"ts-jest": "29.0.3",
|
79
82
|
"tsup": "^6.7.0",
|
80
83
|
"typescript": "5.1.3",
|
package/react/dist/index.d.ts
CHANGED
@@ -264,7 +264,7 @@ type UseChatHelpers = {
|
|
264
264
|
type StreamingReactResponseAction = (payload: {
|
265
265
|
messages: Message[];
|
266
266
|
}) => Promise<experimental_StreamingReactResponse>;
|
267
|
-
declare function useChat({ api, id, initialMessages, initialInput, sendExtraMessageFields, experimental_onFunctionCall, onResponse, onFinish, onError, credentials, headers, body, }?: Omit<UseChatOptions, 'api'> & {
|
267
|
+
declare function useChat({ api, id, initialMessages: initialMessagesParam, initialInput, sendExtraMessageFields, experimental_onFunctionCall, onResponse, onFinish, onError, credentials, headers, body, }?: Omit<UseChatOptions, 'api'> & {
|
268
268
|
api?: string | StreamingReactResponseAction;
|
269
269
|
}): UseChatHelpers;
|
270
270
|
|
package/react/dist/index.js
CHANGED
@@ -56,7 +56,7 @@ function createChunkDecoder(complex) {
|
|
56
56
|
};
|
57
57
|
}
|
58
58
|
return function(chunk) {
|
59
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
59
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
60
60
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
61
61
|
};
|
62
62
|
}
|
@@ -86,6 +86,102 @@ var getStreamStringTypeAndValue = (line) => {
|
|
86
86
|
};
|
87
87
|
var COMPLEX_HEADER = "X-Experimental-Stream-Data";
|
88
88
|
|
89
|
+
// react/parse-complex-response.ts
|
90
|
+
async function parseComplexResponse({
|
91
|
+
reader,
|
92
|
+
abortControllerRef,
|
93
|
+
update
|
94
|
+
}) {
|
95
|
+
const decode = createChunkDecoder(true);
|
96
|
+
const createdAt = /* @__PURE__ */ new Date();
|
97
|
+
const prefixMap = {};
|
98
|
+
const NEWLINE = "\n".charCodeAt(0);
|
99
|
+
let chunks = [];
|
100
|
+
let totalLength = 0;
|
101
|
+
while (true) {
|
102
|
+
const { value } = await reader.read();
|
103
|
+
if (value) {
|
104
|
+
chunks.push(value);
|
105
|
+
totalLength += value.length;
|
106
|
+
if (value[value.length - 1] !== NEWLINE) {
|
107
|
+
continue;
|
108
|
+
}
|
109
|
+
}
|
110
|
+
if (chunks.length === 0) {
|
111
|
+
break;
|
112
|
+
}
|
113
|
+
let concatenatedChunks = new Uint8Array(totalLength);
|
114
|
+
let offset = 0;
|
115
|
+
for (const chunk of chunks) {
|
116
|
+
concatenatedChunks.set(chunk, offset);
|
117
|
+
offset += chunk.length;
|
118
|
+
}
|
119
|
+
chunks.length = 0;
|
120
|
+
totalLength = 0;
|
121
|
+
const lines = decode(concatenatedChunks);
|
122
|
+
if (typeof lines === "string") {
|
123
|
+
throw new Error(
|
124
|
+
"Invalid response format. Complex mode was set but the response is a string. This should never happen."
|
125
|
+
);
|
126
|
+
}
|
127
|
+
for (const { type, value: value2 } of lines) {
|
128
|
+
if (type === "text") {
|
129
|
+
if (prefixMap["text"]) {
|
130
|
+
prefixMap["text"] = {
|
131
|
+
...prefixMap["text"],
|
132
|
+
content: (prefixMap["text"].content || "") + value2
|
133
|
+
};
|
134
|
+
} else {
|
135
|
+
prefixMap["text"] = {
|
136
|
+
id: nanoid(),
|
137
|
+
role: "assistant",
|
138
|
+
content: value2,
|
139
|
+
createdAt
|
140
|
+
};
|
141
|
+
}
|
142
|
+
}
|
143
|
+
let functionCallMessage = null;
|
144
|
+
if (type === "function_call") {
|
145
|
+
prefixMap["function_call"] = value2;
|
146
|
+
let functionCall = prefixMap["function_call"];
|
147
|
+
if (functionCall && typeof functionCall === "string") {
|
148
|
+
const parsedFunctionCall = JSON.parse(
|
149
|
+
functionCall
|
150
|
+
).function_call;
|
151
|
+
functionCallMessage = {
|
152
|
+
id: nanoid(),
|
153
|
+
role: "assistant",
|
154
|
+
content: "",
|
155
|
+
function_call: parsedFunctionCall,
|
156
|
+
name: parsedFunctionCall.name,
|
157
|
+
createdAt
|
158
|
+
};
|
159
|
+
prefixMap["function_call"] = functionCallMessage;
|
160
|
+
}
|
161
|
+
}
|
162
|
+
if (type === "data") {
|
163
|
+
const parsedValue = JSON.parse(value2);
|
164
|
+
if (prefixMap["data"]) {
|
165
|
+
prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
|
166
|
+
} else {
|
167
|
+
prefixMap["data"] = parsedValue;
|
168
|
+
}
|
169
|
+
}
|
170
|
+
const data = prefixMap["data"];
|
171
|
+
const responseMessage = prefixMap["text"];
|
172
|
+
const merged = [functionCallMessage, responseMessage].filter(
|
173
|
+
Boolean
|
174
|
+
);
|
175
|
+
update(merged, data);
|
176
|
+
if (abortControllerRef.current === null) {
|
177
|
+
reader.cancel();
|
178
|
+
break;
|
179
|
+
}
|
180
|
+
}
|
181
|
+
}
|
182
|
+
return prefixMap;
|
183
|
+
}
|
184
|
+
|
89
185
|
// react/use-chat.ts
|
90
186
|
var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, existingData, extraMetadataRef, messagesRef, abortControllerRef, onFinish, onResponse, sendExtraMessageFields) => {
|
91
187
|
var _a, _b;
|
@@ -101,10 +197,10 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
101
197
|
}));
|
102
198
|
if (typeof api !== "string") {
|
103
199
|
const replyId = nanoid();
|
104
|
-
const
|
200
|
+
const createdAt = /* @__PURE__ */ new Date();
|
105
201
|
let responseMessage = {
|
106
202
|
id: replyId,
|
107
|
-
createdAt
|
203
|
+
createdAt,
|
108
204
|
content: "",
|
109
205
|
role: "assistant"
|
110
206
|
};
|
@@ -171,98 +267,18 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
171
267
|
throw new Error("The response body is empty.");
|
172
268
|
}
|
173
269
|
const isComplexMode = res.headers.get(COMPLEX_HEADER) === "true";
|
174
|
-
const createdAt = /* @__PURE__ */ new Date();
|
175
|
-
const reader = res.body.getReader();
|
176
|
-
const decode = createChunkDecoder(isComplexMode);
|
177
270
|
let responseMessages = [];
|
271
|
+
const reader = res.body.getReader();
|
178
272
|
let responseData = [];
|
179
|
-
const prefixMap = {};
|
180
|
-
const NEWLINE = "\n".charCodeAt(0);
|
181
|
-
let chunks = [];
|
182
|
-
let totalLength = 0;
|
183
273
|
if (isComplexMode) {
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
totalLength += value.length;
|
189
|
-
if (value[value.length - 1] !== NEWLINE) {
|
190
|
-
continue;
|
191
|
-
}
|
192
|
-
}
|
193
|
-
if (chunks.length === 0) {
|
194
|
-
break;
|
195
|
-
}
|
196
|
-
let concatenatedChunks = new Uint8Array(totalLength);
|
197
|
-
let offset = 0;
|
198
|
-
for (const chunk of chunks) {
|
199
|
-
concatenatedChunks.set(chunk, offset);
|
200
|
-
offset += chunk.length;
|
201
|
-
}
|
202
|
-
chunks.length = 0;
|
203
|
-
totalLength = 0;
|
204
|
-
const lines = decode(concatenatedChunks);
|
205
|
-
if (typeof lines === "string") {
|
206
|
-
throw new Error(
|
207
|
-
"Invalid response format. Complex mode was set but the response is a string. This should never happen."
|
208
|
-
);
|
209
|
-
}
|
210
|
-
for (const { type, value: value2 } of lines) {
|
211
|
-
if (type === "text") {
|
212
|
-
if (prefixMap["text"]) {
|
213
|
-
prefixMap["text"] = {
|
214
|
-
...prefixMap["text"],
|
215
|
-
content: (prefixMap["text"].content || "") + value2
|
216
|
-
};
|
217
|
-
} else {
|
218
|
-
prefixMap["text"] = {
|
219
|
-
id: nanoid(),
|
220
|
-
role: "assistant",
|
221
|
-
content: value2,
|
222
|
-
createdAt
|
223
|
-
};
|
224
|
-
}
|
225
|
-
}
|
226
|
-
let functionCallMessage = null;
|
227
|
-
if (type === "function_call") {
|
228
|
-
prefixMap["function_call"] = value2;
|
229
|
-
let functionCall = prefixMap["function_call"];
|
230
|
-
if (functionCall && typeof functionCall === "string") {
|
231
|
-
const parsedFunctionCall = JSON.parse(
|
232
|
-
functionCall
|
233
|
-
).function_call;
|
234
|
-
functionCallMessage = {
|
235
|
-
id: nanoid(),
|
236
|
-
role: "assistant",
|
237
|
-
content: "",
|
238
|
-
function_call: parsedFunctionCall,
|
239
|
-
name: parsedFunctionCall.name,
|
240
|
-
createdAt
|
241
|
-
};
|
242
|
-
prefixMap["function_call"] = functionCallMessage;
|
243
|
-
}
|
244
|
-
}
|
245
|
-
if (type === "data") {
|
246
|
-
const parsedValue = JSON.parse(value2);
|
247
|
-
if (prefixMap["data"]) {
|
248
|
-
prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
|
249
|
-
} else {
|
250
|
-
prefixMap["data"] = parsedValue;
|
251
|
-
}
|
252
|
-
}
|
253
|
-
const data = prefixMap["data"];
|
254
|
-
const responseMessage = prefixMap["text"];
|
255
|
-
const merged = [functionCallMessage, responseMessage].filter(
|
256
|
-
Boolean
|
257
|
-
);
|
274
|
+
const prefixMap = await parseComplexResponse({
|
275
|
+
reader,
|
276
|
+
abortControllerRef,
|
277
|
+
update(merged, data) {
|
258
278
|
mutate([...chatRequest.messages, ...merged], false);
|
259
279
|
mutateStreamData([...existingData || [], ...data || []], false);
|
260
|
-
if (abortControllerRef.current === null) {
|
261
|
-
reader.cancel();
|
262
|
-
break;
|
263
|
-
}
|
264
280
|
}
|
265
|
-
}
|
281
|
+
});
|
266
282
|
for (const [type, item] of Object.entries(prefixMap)) {
|
267
283
|
if (onFinish && type === "text") {
|
268
284
|
onFinish(item);
|
@@ -275,6 +291,8 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
275
291
|
}
|
276
292
|
return { messages: responseMessages, data: responseData };
|
277
293
|
} else {
|
294
|
+
const createdAt = /* @__PURE__ */ new Date();
|
295
|
+
const decode = createChunkDecoder(false);
|
278
296
|
let streamedResponse = "";
|
279
297
|
const replyId = nanoid();
|
280
298
|
let responseMessage = {
|
@@ -314,7 +332,7 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
314
332
|
function useChat({
|
315
333
|
api = "/api/chat",
|
316
334
|
id,
|
317
|
-
initialMessages
|
335
|
+
initialMessages: initialMessagesParam,
|
318
336
|
initialInput = "",
|
319
337
|
sendExtraMessageFields,
|
320
338
|
experimental_onFunctionCall,
|
@@ -327,6 +345,7 @@ function useChat({
|
|
327
345
|
} = {}) {
|
328
346
|
const hookId = (0, import_react.useId)();
|
329
347
|
const chatId = id || hookId;
|
348
|
+
const [initialMessages] = (0, import_react.useState)(initialMessagesParam != null ? initialMessagesParam : []);
|
330
349
|
const { data: messages, mutate } = (0, import_swr.default)([api, chatId], null, {
|
331
350
|
fallbackData: initialMessages
|
332
351
|
});
|
package/react/dist/index.mjs
CHANGED
@@ -20,7 +20,7 @@ function createChunkDecoder(complex) {
|
|
20
20
|
};
|
21
21
|
}
|
22
22
|
return function(chunk) {
|
23
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
23
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
24
24
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
25
25
|
};
|
26
26
|
}
|
@@ -50,6 +50,102 @@ var getStreamStringTypeAndValue = (line) => {
|
|
50
50
|
};
|
51
51
|
var COMPLEX_HEADER = "X-Experimental-Stream-Data";
|
52
52
|
|
53
|
+
// react/parse-complex-response.ts
|
54
|
+
async function parseComplexResponse({
|
55
|
+
reader,
|
56
|
+
abortControllerRef,
|
57
|
+
update
|
58
|
+
}) {
|
59
|
+
const decode = createChunkDecoder(true);
|
60
|
+
const createdAt = /* @__PURE__ */ new Date();
|
61
|
+
const prefixMap = {};
|
62
|
+
const NEWLINE = "\n".charCodeAt(0);
|
63
|
+
let chunks = [];
|
64
|
+
let totalLength = 0;
|
65
|
+
while (true) {
|
66
|
+
const { value } = await reader.read();
|
67
|
+
if (value) {
|
68
|
+
chunks.push(value);
|
69
|
+
totalLength += value.length;
|
70
|
+
if (value[value.length - 1] !== NEWLINE) {
|
71
|
+
continue;
|
72
|
+
}
|
73
|
+
}
|
74
|
+
if (chunks.length === 0) {
|
75
|
+
break;
|
76
|
+
}
|
77
|
+
let concatenatedChunks = new Uint8Array(totalLength);
|
78
|
+
let offset = 0;
|
79
|
+
for (const chunk of chunks) {
|
80
|
+
concatenatedChunks.set(chunk, offset);
|
81
|
+
offset += chunk.length;
|
82
|
+
}
|
83
|
+
chunks.length = 0;
|
84
|
+
totalLength = 0;
|
85
|
+
const lines = decode(concatenatedChunks);
|
86
|
+
if (typeof lines === "string") {
|
87
|
+
throw new Error(
|
88
|
+
"Invalid response format. Complex mode was set but the response is a string. This should never happen."
|
89
|
+
);
|
90
|
+
}
|
91
|
+
for (const { type, value: value2 } of lines) {
|
92
|
+
if (type === "text") {
|
93
|
+
if (prefixMap["text"]) {
|
94
|
+
prefixMap["text"] = {
|
95
|
+
...prefixMap["text"],
|
96
|
+
content: (prefixMap["text"].content || "") + value2
|
97
|
+
};
|
98
|
+
} else {
|
99
|
+
prefixMap["text"] = {
|
100
|
+
id: nanoid(),
|
101
|
+
role: "assistant",
|
102
|
+
content: value2,
|
103
|
+
createdAt
|
104
|
+
};
|
105
|
+
}
|
106
|
+
}
|
107
|
+
let functionCallMessage = null;
|
108
|
+
if (type === "function_call") {
|
109
|
+
prefixMap["function_call"] = value2;
|
110
|
+
let functionCall = prefixMap["function_call"];
|
111
|
+
if (functionCall && typeof functionCall === "string") {
|
112
|
+
const parsedFunctionCall = JSON.parse(
|
113
|
+
functionCall
|
114
|
+
).function_call;
|
115
|
+
functionCallMessage = {
|
116
|
+
id: nanoid(),
|
117
|
+
role: "assistant",
|
118
|
+
content: "",
|
119
|
+
function_call: parsedFunctionCall,
|
120
|
+
name: parsedFunctionCall.name,
|
121
|
+
createdAt
|
122
|
+
};
|
123
|
+
prefixMap["function_call"] = functionCallMessage;
|
124
|
+
}
|
125
|
+
}
|
126
|
+
if (type === "data") {
|
127
|
+
const parsedValue = JSON.parse(value2);
|
128
|
+
if (prefixMap["data"]) {
|
129
|
+
prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
|
130
|
+
} else {
|
131
|
+
prefixMap["data"] = parsedValue;
|
132
|
+
}
|
133
|
+
}
|
134
|
+
const data = prefixMap["data"];
|
135
|
+
const responseMessage = prefixMap["text"];
|
136
|
+
const merged = [functionCallMessage, responseMessage].filter(
|
137
|
+
Boolean
|
138
|
+
);
|
139
|
+
update(merged, data);
|
140
|
+
if (abortControllerRef.current === null) {
|
141
|
+
reader.cancel();
|
142
|
+
break;
|
143
|
+
}
|
144
|
+
}
|
145
|
+
}
|
146
|
+
return prefixMap;
|
147
|
+
}
|
148
|
+
|
53
149
|
// react/use-chat.ts
|
54
150
|
var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, existingData, extraMetadataRef, messagesRef, abortControllerRef, onFinish, onResponse, sendExtraMessageFields) => {
|
55
151
|
var _a, _b;
|
@@ -65,10 +161,10 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
65
161
|
}));
|
66
162
|
if (typeof api !== "string") {
|
67
163
|
const replyId = nanoid();
|
68
|
-
const
|
164
|
+
const createdAt = /* @__PURE__ */ new Date();
|
69
165
|
let responseMessage = {
|
70
166
|
id: replyId,
|
71
|
-
createdAt
|
167
|
+
createdAt,
|
72
168
|
content: "",
|
73
169
|
role: "assistant"
|
74
170
|
};
|
@@ -135,98 +231,18 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
135
231
|
throw new Error("The response body is empty.");
|
136
232
|
}
|
137
233
|
const isComplexMode = res.headers.get(COMPLEX_HEADER) === "true";
|
138
|
-
const createdAt = /* @__PURE__ */ new Date();
|
139
|
-
const reader = res.body.getReader();
|
140
|
-
const decode = createChunkDecoder(isComplexMode);
|
141
234
|
let responseMessages = [];
|
235
|
+
const reader = res.body.getReader();
|
142
236
|
let responseData = [];
|
143
|
-
const prefixMap = {};
|
144
|
-
const NEWLINE = "\n".charCodeAt(0);
|
145
|
-
let chunks = [];
|
146
|
-
let totalLength = 0;
|
147
237
|
if (isComplexMode) {
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
totalLength += value.length;
|
153
|
-
if (value[value.length - 1] !== NEWLINE) {
|
154
|
-
continue;
|
155
|
-
}
|
156
|
-
}
|
157
|
-
if (chunks.length === 0) {
|
158
|
-
break;
|
159
|
-
}
|
160
|
-
let concatenatedChunks = new Uint8Array(totalLength);
|
161
|
-
let offset = 0;
|
162
|
-
for (const chunk of chunks) {
|
163
|
-
concatenatedChunks.set(chunk, offset);
|
164
|
-
offset += chunk.length;
|
165
|
-
}
|
166
|
-
chunks.length = 0;
|
167
|
-
totalLength = 0;
|
168
|
-
const lines = decode(concatenatedChunks);
|
169
|
-
if (typeof lines === "string") {
|
170
|
-
throw new Error(
|
171
|
-
"Invalid response format. Complex mode was set but the response is a string. This should never happen."
|
172
|
-
);
|
173
|
-
}
|
174
|
-
for (const { type, value: value2 } of lines) {
|
175
|
-
if (type === "text") {
|
176
|
-
if (prefixMap["text"]) {
|
177
|
-
prefixMap["text"] = {
|
178
|
-
...prefixMap["text"],
|
179
|
-
content: (prefixMap["text"].content || "") + value2
|
180
|
-
};
|
181
|
-
} else {
|
182
|
-
prefixMap["text"] = {
|
183
|
-
id: nanoid(),
|
184
|
-
role: "assistant",
|
185
|
-
content: value2,
|
186
|
-
createdAt
|
187
|
-
};
|
188
|
-
}
|
189
|
-
}
|
190
|
-
let functionCallMessage = null;
|
191
|
-
if (type === "function_call") {
|
192
|
-
prefixMap["function_call"] = value2;
|
193
|
-
let functionCall = prefixMap["function_call"];
|
194
|
-
if (functionCall && typeof functionCall === "string") {
|
195
|
-
const parsedFunctionCall = JSON.parse(
|
196
|
-
functionCall
|
197
|
-
).function_call;
|
198
|
-
functionCallMessage = {
|
199
|
-
id: nanoid(),
|
200
|
-
role: "assistant",
|
201
|
-
content: "",
|
202
|
-
function_call: parsedFunctionCall,
|
203
|
-
name: parsedFunctionCall.name,
|
204
|
-
createdAt
|
205
|
-
};
|
206
|
-
prefixMap["function_call"] = functionCallMessage;
|
207
|
-
}
|
208
|
-
}
|
209
|
-
if (type === "data") {
|
210
|
-
const parsedValue = JSON.parse(value2);
|
211
|
-
if (prefixMap["data"]) {
|
212
|
-
prefixMap["data"] = [...prefixMap["data"], ...parsedValue];
|
213
|
-
} else {
|
214
|
-
prefixMap["data"] = parsedValue;
|
215
|
-
}
|
216
|
-
}
|
217
|
-
const data = prefixMap["data"];
|
218
|
-
const responseMessage = prefixMap["text"];
|
219
|
-
const merged = [functionCallMessage, responseMessage].filter(
|
220
|
-
Boolean
|
221
|
-
);
|
238
|
+
const prefixMap = await parseComplexResponse({
|
239
|
+
reader,
|
240
|
+
abortControllerRef,
|
241
|
+
update(merged, data) {
|
222
242
|
mutate([...chatRequest.messages, ...merged], false);
|
223
243
|
mutateStreamData([...existingData || [], ...data || []], false);
|
224
|
-
if (abortControllerRef.current === null) {
|
225
|
-
reader.cancel();
|
226
|
-
break;
|
227
|
-
}
|
228
244
|
}
|
229
|
-
}
|
245
|
+
});
|
230
246
|
for (const [type, item] of Object.entries(prefixMap)) {
|
231
247
|
if (onFinish && type === "text") {
|
232
248
|
onFinish(item);
|
@@ -239,6 +255,8 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
239
255
|
}
|
240
256
|
return { messages: responseMessages, data: responseData };
|
241
257
|
} else {
|
258
|
+
const createdAt = /* @__PURE__ */ new Date();
|
259
|
+
const decode = createChunkDecoder(false);
|
242
260
|
let streamedResponse = "";
|
243
261
|
const replyId = nanoid();
|
244
262
|
let responseMessage = {
|
@@ -278,7 +296,7 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, exi
|
|
278
296
|
function useChat({
|
279
297
|
api = "/api/chat",
|
280
298
|
id,
|
281
|
-
initialMessages
|
299
|
+
initialMessages: initialMessagesParam,
|
282
300
|
initialInput = "",
|
283
301
|
sendExtraMessageFields,
|
284
302
|
experimental_onFunctionCall,
|
@@ -291,6 +309,7 @@ function useChat({
|
|
291
309
|
} = {}) {
|
292
310
|
const hookId = useId();
|
293
311
|
const chatId = id || hookId;
|
312
|
+
const [initialMessages] = useState(initialMessagesParam != null ? initialMessagesParam : []);
|
294
313
|
const { data: messages, mutate } = useSWR([api, chatId], null, {
|
295
314
|
fallbackData: initialMessages
|
296
315
|
});
|
package/solid/dist/index.js
CHANGED
@@ -46,7 +46,7 @@ function createChunkDecoder(complex) {
|
|
46
46
|
};
|
47
47
|
}
|
48
48
|
return function(chunk) {
|
49
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
49
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
50
50
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
51
51
|
};
|
52
52
|
}
|
package/solid/dist/index.mjs
CHANGED
@@ -19,7 +19,7 @@ function createChunkDecoder(complex) {
|
|
19
19
|
};
|
20
20
|
}
|
21
21
|
return function(chunk) {
|
22
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
22
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
23
23
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
24
24
|
};
|
25
25
|
}
|
package/svelte/dist/index.js
CHANGED
@@ -541,7 +541,7 @@ function createChunkDecoder(complex) {
|
|
541
541
|
};
|
542
542
|
}
|
543
543
|
return function(chunk) {
|
544
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
544
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
545
545
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
546
546
|
};
|
547
547
|
}
|
package/svelte/dist/index.mjs
CHANGED
@@ -514,7 +514,7 @@ function createChunkDecoder(complex) {
|
|
514
514
|
};
|
515
515
|
}
|
516
516
|
return function(chunk) {
|
517
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
517
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
518
518
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
519
519
|
};
|
520
520
|
}
|
package/vue/dist/index.js
CHANGED
@@ -55,7 +55,7 @@ function createChunkDecoder(complex) {
|
|
55
55
|
};
|
56
56
|
}
|
57
57
|
return function(chunk) {
|
58
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
58
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
59
59
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
60
60
|
};
|
61
61
|
}
|
package/vue/dist/index.mjs
CHANGED
@@ -18,7 +18,7 @@ function createChunkDecoder(complex) {
|
|
18
18
|
};
|
19
19
|
}
|
20
20
|
return function(chunk) {
|
21
|
-
const decoded = decoder.decode(chunk, { stream: true }).split("\n");
|
21
|
+
const decoded = decoder.decode(chunk, { stream: true }).split("\n").filter((line) => line !== "");
|
22
22
|
return decoded.map(getStreamStringTypeAndValue).filter(Boolean);
|
23
23
|
};
|
24
24
|
}
|