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.
package/vue/dist/index.js CHANGED
@@ -182,6 +182,251 @@ function createChunkDecoder(complex) {
182
182
  return decoded.map(parseStreamPart).filter(Boolean);
183
183
  };
184
184
  }
185
+ var COMPLEX_HEADER = "X-Experimental-Stream-Data";
186
+
187
+ // shared/parse-complex-response.ts
188
+ async function parseComplexResponse({
189
+ reader,
190
+ abortControllerRef,
191
+ update,
192
+ onFinish,
193
+ generateId = nanoid,
194
+ getCurrentDate = () => /* @__PURE__ */ new Date()
195
+ }) {
196
+ const createdAt = getCurrentDate();
197
+ const decode = createChunkDecoder(true);
198
+ const prefixMap = {
199
+ data: []
200
+ };
201
+ const NEWLINE = "\n".charCodeAt(0);
202
+ const chunks = [];
203
+ let totalLength = 0;
204
+ while (true) {
205
+ const { value } = await reader.read();
206
+ if (value) {
207
+ chunks.push(value);
208
+ totalLength += value.length;
209
+ if (value[value.length - 1] !== NEWLINE) {
210
+ continue;
211
+ }
212
+ }
213
+ if (chunks.length === 0) {
214
+ break;
215
+ }
216
+ let concatenatedChunks = new Uint8Array(totalLength);
217
+ let offset = 0;
218
+ for (const chunk of chunks) {
219
+ concatenatedChunks.set(chunk, offset);
220
+ offset += chunk.length;
221
+ }
222
+ chunks.length = 0;
223
+ totalLength = 0;
224
+ const lines = decode(concatenatedChunks);
225
+ if (typeof lines === "string") {
226
+ throw new Error(
227
+ "Invalid response format. Complex mode was set but the response is a string. This should never happen."
228
+ );
229
+ }
230
+ for (const { type, value: value2 } of lines) {
231
+ if (type === "text") {
232
+ if (prefixMap["text"]) {
233
+ prefixMap["text"] = {
234
+ ...prefixMap["text"],
235
+ content: (prefixMap["text"].content || "") + value2
236
+ };
237
+ } else {
238
+ prefixMap["text"] = {
239
+ id: generateId(),
240
+ role: "assistant",
241
+ content: value2,
242
+ createdAt
243
+ };
244
+ }
245
+ }
246
+ let functionCallMessage = null;
247
+ if (type === "function_call") {
248
+ prefixMap["function_call"] = {
249
+ id: generateId(),
250
+ role: "assistant",
251
+ content: "",
252
+ function_call: value2.function_call,
253
+ name: value2.function_call.name,
254
+ createdAt
255
+ };
256
+ functionCallMessage = prefixMap["function_call"];
257
+ }
258
+ if (type === "data") {
259
+ prefixMap["data"].push(...value2);
260
+ }
261
+ const responseMessage = prefixMap["text"];
262
+ const merged = [functionCallMessage, responseMessage].filter(
263
+ Boolean
264
+ );
265
+ update(merged, [...prefixMap["data"]]);
266
+ if ((abortControllerRef == null ? void 0 : abortControllerRef.current) === null) {
267
+ reader.cancel();
268
+ break;
269
+ }
270
+ }
271
+ }
272
+ onFinish == null ? void 0 : onFinish(prefixMap);
273
+ return {
274
+ messages: [prefixMap.text, prefixMap.function_call].filter(
275
+ Boolean
276
+ ),
277
+ data: prefixMap.data
278
+ };
279
+ }
280
+
281
+ // shared/call-api.ts
282
+ async function callApi({
283
+ api,
284
+ messages,
285
+ body,
286
+ credentials,
287
+ headers,
288
+ abortController,
289
+ appendMessage,
290
+ restoreMessagesOnFailure,
291
+ onResponse,
292
+ onUpdate,
293
+ onFinish,
294
+ generateId
295
+ }) {
296
+ var _a;
297
+ const response = await fetch(api, {
298
+ method: "POST",
299
+ body: JSON.stringify({
300
+ messages,
301
+ ...body
302
+ }),
303
+ headers: {
304
+ "Content-Type": "application/json",
305
+ ...headers
306
+ },
307
+ signal: (_a = abortController == null ? void 0 : abortController()) == null ? void 0 : _a.signal,
308
+ credentials
309
+ }).catch((err) => {
310
+ restoreMessagesOnFailure();
311
+ throw err;
312
+ });
313
+ if (onResponse) {
314
+ try {
315
+ await onResponse(response);
316
+ } catch (err) {
317
+ throw err;
318
+ }
319
+ }
320
+ if (!response.ok) {
321
+ restoreMessagesOnFailure();
322
+ throw new Error(
323
+ await response.text() || "Failed to fetch the chat response."
324
+ );
325
+ }
326
+ if (!response.body) {
327
+ throw new Error("The response body is empty.");
328
+ }
329
+ const reader = response.body.getReader();
330
+ const isComplexMode = response.headers.get(COMPLEX_HEADER) === "true";
331
+ if (isComplexMode) {
332
+ return await parseComplexResponse({
333
+ reader,
334
+ abortControllerRef: abortController != null ? { current: abortController() } : void 0,
335
+ update: onUpdate,
336
+ onFinish(prefixMap) {
337
+ if (onFinish && prefixMap.text != null) {
338
+ onFinish(prefixMap.text);
339
+ }
340
+ },
341
+ generateId
342
+ });
343
+ } else {
344
+ const createdAt = /* @__PURE__ */ new Date();
345
+ const decode = createChunkDecoder(false);
346
+ let streamedResponse = "";
347
+ const replyId = generateId();
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,
386
+ experimental_onFunctionCall,
387
+ updateChatRequest,
388
+ getCurrentMessages
389
+ }) {
390
+ while (true) {
391
+ const messagesAndDataOrJustMessage = await getStreamedResponse();
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
+ }
429
+ }
185
430
 
186
431
  // vue/use-chat.ts
187
432
  var uniqueId = 0;
@@ -193,17 +438,19 @@ function useChat({
193
438
  initialMessages = [],
194
439
  initialInput = "",
195
440
  sendExtraMessageFields,
441
+ experimental_onFunctionCall,
196
442
  onResponse,
197
443
  onFinish,
198
444
  onError,
199
445
  credentials,
200
446
  headers,
201
- body
447
+ body,
448
+ generateId = nanoid
202
449
  } = {}) {
203
- var _a;
450
+ var _a, _b;
204
451
  const chatId = id || `chat-${uniqueId++}`;
205
452
  const key = `${api}|${chatId}`;
206
- const { data, mutate: originalMutate } = useSWRV(
453
+ const { data: messagesData, mutate: originalMutate } = useSWRV(
207
454
  key,
208
455
  () => store[key] || initialMessages
209
456
  );
@@ -212,99 +459,78 @@ function useChat({
212
459
  null
213
460
  );
214
461
  (_a = isLoading.value) != null ? _a : isLoading.value = false;
215
- data.value || (data.value = initialMessages);
216
- const mutate = (data2) => {
217
- store[key] = data2;
462
+ (_b = messagesData.value) != null ? _b : messagesData.value = initialMessages;
463
+ const mutate = (data) => {
464
+ store[key] = data;
218
465
  return originalMutate();
219
466
  };
220
- const messages = data;
467
+ const messages = messagesData;
221
468
  const error = (0, import_vue.ref)(void 0);
469
+ const streamData = (0, import_vue.ref)(void 0);
222
470
  let abortController = null;
223
471
  async function triggerRequest(messagesSnapshot, options) {
224
472
  try {
225
473
  error.value = void 0;
226
474
  mutateLoading(() => true);
227
475
  abortController = new AbortController();
228
- const previousMessages = messages.value;
476
+ const previousMessages = messagesData.value;
229
477
  mutate(messagesSnapshot);
230
- const res = await fetch(api, {
231
- method: "POST",
232
- body: JSON.stringify({
233
- messages: sendExtraMessageFields ? messagesSnapshot : messagesSnapshot.map(
234
- ({ role, content, name, function_call }) => ({
235
- role,
236
- content,
237
- ...name !== void 0 && { name },
238
- ...function_call !== void 0 && {
239
- function_call
240
- }
241
- })
242
- ),
243
- ...(0, import_vue.unref)(body),
244
- // Use unref to unwrap the ref value
245
- ...options == null ? void 0 : options.body
246
- }),
247
- headers: {
248
- ...headers,
249
- ...options == null ? void 0 : options.headers
478
+ let chatRequest = {
479
+ messages: messagesSnapshot,
480
+ options
481
+ };
482
+ await processChatStream({
483
+ getStreamedResponse: async () => {
484
+ var _a2;
485
+ const existingData = (_a2 = streamData.value) != null ? _a2 : [];
486
+ return await callApi({
487
+ api,
488
+ messages: sendExtraMessageFields ? chatRequest.messages : chatRequest.messages.map(
489
+ ({ role, content, name, function_call }) => ({
490
+ role,
491
+ content,
492
+ ...name !== void 0 && { name },
493
+ ...function_call !== void 0 && {
494
+ function_call
495
+ }
496
+ })
497
+ ),
498
+ body: {
499
+ ...(0, import_vue.unref)(body),
500
+ // Use unref to unwrap the ref value
501
+ ...options == null ? void 0 : options.body
502
+ },
503
+ headers: {
504
+ ...headers,
505
+ ...options == null ? void 0 : options.headers
506
+ },
507
+ abortController: () => abortController,
508
+ credentials,
509
+ onResponse,
510
+ onUpdate(merged, data) {
511
+ mutate([...chatRequest.messages, ...merged]);
512
+ streamData.value = [...existingData, ...data != null ? data : []];
513
+ },
514
+ onFinish(message) {
515
+ mutate([...chatRequest.messages, message]);
516
+ onFinish == null ? void 0 : onFinish(message);
517
+ },
518
+ appendMessage(message) {
519
+ mutate([...chatRequest.messages, message]);
520
+ },
521
+ restoreMessagesOnFailure() {
522
+ mutate(previousMessages);
523
+ },
524
+ generateId
525
+ });
250
526
  },
251
- signal: abortController.signal,
252
- credentials
253
- }).catch((err) => {
254
- mutate(previousMessages);
255
- throw err;
527
+ experimental_onFunctionCall,
528
+ updateChatRequest(newChatRequest) {
529
+ chatRequest = newChatRequest;
530
+ },
531
+ getCurrentMessages: () => messages.value
256
532
  });
257
- if (onResponse) {
258
- try {
259
- await onResponse(res);
260
- } catch (err) {
261
- throw err;
262
- }
263
- }
264
- if (!res.ok) {
265
- mutate(previousMessages);
266
- throw new Error(
267
- await res.text() || "Failed to fetch the chat response."
268
- );
269
- }
270
- if (!res.body) {
271
- throw new Error("The response body is empty.");
272
- }
273
- let result = "";
274
- const createdAt = /* @__PURE__ */ new Date();
275
- const replyId = nanoid();
276
- const reader = res.body.getReader();
277
- const decoder = createChunkDecoder();
278
- while (true) {
279
- const { done, value } = await reader.read();
280
- if (done) {
281
- break;
282
- }
283
- result += decoder(value);
284
- mutate([
285
- ...messagesSnapshot,
286
- {
287
- id: replyId,
288
- createdAt,
289
- content: result,
290
- role: "assistant"
291
- }
292
- ]);
293
- if (abortController === null) {
294
- reader.cancel();
295
- break;
296
- }
297
- }
298
- if (onFinish) {
299
- onFinish({
300
- id: replyId,
301
- createdAt,
302
- content: result,
303
- role: "assistant"
304
- });
305
- }
306
533
  abortController = null;
307
- return result;
308
534
  } catch (err) {
309
535
  if (err.name === "AbortError") {
310
536
  abortController = null;
@@ -320,7 +546,7 @@ function useChat({
320
546
  }
321
547
  const append = async (message, options) => {
322
548
  if (!message.id) {
323
- message.id = nanoid();
549
+ message.id = generateId();
324
550
  }
325
551
  return triggerRequest(messages.value.concat(message), options);
326
552
  };
@@ -364,7 +590,8 @@ function useChat({
364
590
  setMessages,
365
591
  input,
366
592
  handleSubmit,
367
- isLoading
593
+ isLoading,
594
+ data: streamData
368
595
  };
369
596
  }
370
597