ai 2.2.24 → 2.2.26

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.
@@ -145,6 +145,251 @@ function createChunkDecoder(complex) {
145
145
  return decoded.map(parseStreamPart).filter(Boolean);
146
146
  };
147
147
  }
148
+ var COMPLEX_HEADER = "X-Experimental-Stream-Data";
149
+
150
+ // shared/parse-complex-response.ts
151
+ async function parseComplexResponse({
152
+ reader,
153
+ abortControllerRef,
154
+ update,
155
+ onFinish,
156
+ generateId = nanoid,
157
+ getCurrentDate = () => /* @__PURE__ */ new Date()
158
+ }) {
159
+ const createdAt = getCurrentDate();
160
+ const decode = createChunkDecoder(true);
161
+ const prefixMap = {
162
+ data: []
163
+ };
164
+ const NEWLINE = "\n".charCodeAt(0);
165
+ const chunks = [];
166
+ let totalLength = 0;
167
+ while (true) {
168
+ const { value } = await reader.read();
169
+ if (value) {
170
+ chunks.push(value);
171
+ totalLength += value.length;
172
+ if (value[value.length - 1] !== NEWLINE) {
173
+ continue;
174
+ }
175
+ }
176
+ if (chunks.length === 0) {
177
+ break;
178
+ }
179
+ let concatenatedChunks = new Uint8Array(totalLength);
180
+ let offset = 0;
181
+ for (const chunk of chunks) {
182
+ concatenatedChunks.set(chunk, offset);
183
+ offset += chunk.length;
184
+ }
185
+ chunks.length = 0;
186
+ totalLength = 0;
187
+ const lines = decode(concatenatedChunks);
188
+ if (typeof lines === "string") {
189
+ throw new Error(
190
+ "Invalid response format. Complex mode was set but the response is a string. This should never happen."
191
+ );
192
+ }
193
+ for (const { type, value: value2 } of lines) {
194
+ if (type === "text") {
195
+ if (prefixMap["text"]) {
196
+ prefixMap["text"] = {
197
+ ...prefixMap["text"],
198
+ content: (prefixMap["text"].content || "") + value2
199
+ };
200
+ } else {
201
+ prefixMap["text"] = {
202
+ id: generateId(),
203
+ role: "assistant",
204
+ content: value2,
205
+ createdAt
206
+ };
207
+ }
208
+ }
209
+ let functionCallMessage = null;
210
+ if (type === "function_call") {
211
+ prefixMap["function_call"] = {
212
+ id: generateId(),
213
+ role: "assistant",
214
+ content: "",
215
+ function_call: value2.function_call,
216
+ name: value2.function_call.name,
217
+ createdAt
218
+ };
219
+ functionCallMessage = prefixMap["function_call"];
220
+ }
221
+ if (type === "data") {
222
+ prefixMap["data"].push(...value2);
223
+ }
224
+ const responseMessage = prefixMap["text"];
225
+ const merged = [functionCallMessage, responseMessage].filter(
226
+ Boolean
227
+ );
228
+ update(merged, [...prefixMap["data"]]);
229
+ if ((abortControllerRef == null ? void 0 : abortControllerRef.current) === null) {
230
+ reader.cancel();
231
+ break;
232
+ }
233
+ }
234
+ }
235
+ onFinish == null ? void 0 : onFinish(prefixMap);
236
+ return {
237
+ messages: [prefixMap.text, prefixMap.function_call].filter(
238
+ Boolean
239
+ ),
240
+ data: prefixMap.data
241
+ };
242
+ }
243
+
244
+ // shared/call-api.ts
245
+ async function callApi({
246
+ api,
247
+ messages,
248
+ body,
249
+ credentials,
250
+ headers,
251
+ abortController,
252
+ appendMessage,
253
+ restoreMessagesOnFailure,
254
+ onResponse,
255
+ onUpdate,
256
+ onFinish,
257
+ generateId
258
+ }) {
259
+ var _a;
260
+ const response = await fetch(api, {
261
+ method: "POST",
262
+ body: JSON.stringify({
263
+ messages,
264
+ ...body
265
+ }),
266
+ headers: {
267
+ "Content-Type": "application/json",
268
+ ...headers
269
+ },
270
+ signal: (_a = abortController == null ? void 0 : abortController()) == null ? void 0 : _a.signal,
271
+ credentials
272
+ }).catch((err) => {
273
+ restoreMessagesOnFailure();
274
+ throw err;
275
+ });
276
+ if (onResponse) {
277
+ try {
278
+ await onResponse(response);
279
+ } catch (err) {
280
+ throw err;
281
+ }
282
+ }
283
+ if (!response.ok) {
284
+ restoreMessagesOnFailure();
285
+ throw new Error(
286
+ await response.text() || "Failed to fetch the chat response."
287
+ );
288
+ }
289
+ if (!response.body) {
290
+ throw new Error("The response body is empty.");
291
+ }
292
+ const reader = response.body.getReader();
293
+ const isComplexMode = response.headers.get(COMPLEX_HEADER) === "true";
294
+ if (isComplexMode) {
295
+ return await parseComplexResponse({
296
+ reader,
297
+ abortControllerRef: abortController != null ? { current: abortController() } : void 0,
298
+ update: onUpdate,
299
+ onFinish(prefixMap) {
300
+ if (onFinish && prefixMap.text != null) {
301
+ onFinish(prefixMap.text);
302
+ }
303
+ },
304
+ generateId
305
+ });
306
+ } else {
307
+ const createdAt = /* @__PURE__ */ new Date();
308
+ const decode = createChunkDecoder(false);
309
+ let streamedResponse = "";
310
+ const replyId = generateId();
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) {
330
+ reader.cancel();
331
+ break;
332
+ }
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,
349
+ experimental_onFunctionCall,
350
+ updateChatRequest,
351
+ getCurrentMessages
352
+ }) {
353
+ while (true) {
354
+ const messagesAndDataOrJustMessage = await getStreamedResponse();
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
+ }
391
+ }
392
+ }
148
393
 
149
394
  // vue/use-chat.ts
150
395
  var uniqueId = 0;
@@ -156,17 +401,19 @@ function useChat({
156
401
  initialMessages = [],
157
402
  initialInput = "",
158
403
  sendExtraMessageFields,
404
+ experimental_onFunctionCall,
159
405
  onResponse,
160
406
  onFinish,
161
407
  onError,
162
408
  credentials,
163
409
  headers,
164
- body
410
+ body,
411
+ generateId = nanoid
165
412
  } = {}) {
166
- var _a;
413
+ var _a, _b;
167
414
  const chatId = id || `chat-${uniqueId++}`;
168
415
  const key = `${api}|${chatId}`;
169
- const { data, mutate: originalMutate } = useSWRV(
416
+ const { data: messagesData, mutate: originalMutate } = useSWRV(
170
417
  key,
171
418
  () => store[key] || initialMessages
172
419
  );
@@ -175,99 +422,78 @@ function useChat({
175
422
  null
176
423
  );
177
424
  (_a = isLoading.value) != null ? _a : isLoading.value = false;
178
- data.value || (data.value = initialMessages);
179
- const mutate = (data2) => {
180
- store[key] = data2;
425
+ (_b = messagesData.value) != null ? _b : messagesData.value = initialMessages;
426
+ const mutate = (data) => {
427
+ store[key] = data;
181
428
  return originalMutate();
182
429
  };
183
- const messages = data;
430
+ const messages = messagesData;
184
431
  const error = ref(void 0);
432
+ const streamData = ref(void 0);
185
433
  let abortController = null;
186
434
  async function triggerRequest(messagesSnapshot, options) {
187
435
  try {
188
436
  error.value = void 0;
189
437
  mutateLoading(() => true);
190
438
  abortController = new AbortController();
191
- const previousMessages = messages.value;
439
+ const previousMessages = messagesData.value;
192
440
  mutate(messagesSnapshot);
193
- const res = await fetch(api, {
194
- method: "POST",
195
- body: JSON.stringify({
196
- messages: sendExtraMessageFields ? messagesSnapshot : messagesSnapshot.map(
197
- ({ role, content, name, function_call }) => ({
198
- role,
199
- content,
200
- ...name !== void 0 && { name },
201
- ...function_call !== void 0 && {
202
- function_call
203
- }
204
- })
205
- ),
206
- ...unref(body),
207
- // Use unref to unwrap the ref value
208
- ...options == null ? void 0 : options.body
209
- }),
210
- headers: {
211
- ...headers,
212
- ...options == null ? void 0 : options.headers
441
+ let chatRequest = {
442
+ messages: messagesSnapshot,
443
+ options
444
+ };
445
+ await processChatStream({
446
+ getStreamedResponse: async () => {
447
+ var _a2;
448
+ const existingData = (_a2 = streamData.value) != null ? _a2 : [];
449
+ return await callApi({
450
+ api,
451
+ messages: sendExtraMessageFields ? chatRequest.messages : chatRequest.messages.map(
452
+ ({ role, content, name, function_call }) => ({
453
+ role,
454
+ content,
455
+ ...name !== void 0 && { name },
456
+ ...function_call !== void 0 && {
457
+ function_call
458
+ }
459
+ })
460
+ ),
461
+ body: {
462
+ ...unref(body),
463
+ // Use unref to unwrap the ref value
464
+ ...options == null ? void 0 : options.body
465
+ },
466
+ headers: {
467
+ ...headers,
468
+ ...options == null ? void 0 : options.headers
469
+ },
470
+ abortController: () => abortController,
471
+ credentials,
472
+ onResponse,
473
+ onUpdate(merged, data) {
474
+ mutate([...chatRequest.messages, ...merged]);
475
+ streamData.value = [...existingData, ...data != null ? data : []];
476
+ },
477
+ onFinish(message) {
478
+ mutate([...chatRequest.messages, message]);
479
+ onFinish == null ? void 0 : onFinish(message);
480
+ },
481
+ appendMessage(message) {
482
+ mutate([...chatRequest.messages, message]);
483
+ },
484
+ restoreMessagesOnFailure() {
485
+ mutate(previousMessages);
486
+ },
487
+ generateId
488
+ });
213
489
  },
214
- signal: abortController.signal,
215
- credentials
216
- }).catch((err) => {
217
- mutate(previousMessages);
218
- throw err;
490
+ experimental_onFunctionCall,
491
+ updateChatRequest(newChatRequest) {
492
+ chatRequest = newChatRequest;
493
+ },
494
+ getCurrentMessages: () => messages.value
219
495
  });
220
- if (onResponse) {
221
- try {
222
- await onResponse(res);
223
- } catch (err) {
224
- throw err;
225
- }
226
- }
227
- if (!res.ok) {
228
- mutate(previousMessages);
229
- throw new Error(
230
- await res.text() || "Failed to fetch the chat response."
231
- );
232
- }
233
- if (!res.body) {
234
- throw new Error("The response body is empty.");
235
- }
236
- let result = "";
237
- const createdAt = /* @__PURE__ */ new Date();
238
- const replyId = nanoid();
239
- const reader = res.body.getReader();
240
- const decoder = createChunkDecoder();
241
- while (true) {
242
- const { done, value } = await reader.read();
243
- if (done) {
244
- break;
245
- }
246
- result += decoder(value);
247
- mutate([
248
- ...messagesSnapshot,
249
- {
250
- id: replyId,
251
- createdAt,
252
- content: result,
253
- role: "assistant"
254
- }
255
- ]);
256
- if (abortController === null) {
257
- reader.cancel();
258
- break;
259
- }
260
- }
261
- if (onFinish) {
262
- onFinish({
263
- id: replyId,
264
- createdAt,
265
- content: result,
266
- role: "assistant"
267
- });
268
- }
269
496
  abortController = null;
270
- return result;
271
497
  } catch (err) {
272
498
  if (err.name === "AbortError") {
273
499
  abortController = null;
@@ -283,7 +509,7 @@ function useChat({
283
509
  }
284
510
  const append = async (message, options) => {
285
511
  if (!message.id) {
286
- message.id = nanoid();
512
+ message.id = generateId();
287
513
  }
288
514
  return triggerRequest(messages.value.concat(message), options);
289
515
  };
@@ -327,7 +553,8 @@ function useChat({
327
553
  setMessages,
328
554
  input,
329
555
  handleSubmit,
330
- isLoading
556
+ isLoading,
557
+ data: streamData
331
558
  };
332
559
  }
333
560