ai 2.2.25 → 2.2.27

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
@@ -39,9 +39,6 @@ module.exports = __toCommonJS(vue_exports);
39
39
  var import_swrv = __toESM(require("swrv"));
40
40
  var import_vue = require("vue");
41
41
 
42
- // shared/utils.ts
43
- var import_non_secure = require("nanoid/non-secure");
44
-
45
42
  // shared/stream-parts.ts
46
43
  var textStreamPart = {
47
44
  code: "0",
@@ -163,7 +160,51 @@ var parseStreamPart = (line) => {
163
160
  return streamPartsByCode[code].parse(jsonValue);
164
161
  };
165
162
 
163
+ // shared/read-data-stream.ts
164
+ var NEWLINE = "\n".charCodeAt(0);
165
+ function concatChunks(chunks, totalLength) {
166
+ const concatenatedChunks = new Uint8Array(totalLength);
167
+ let offset = 0;
168
+ for (const chunk of chunks) {
169
+ concatenatedChunks.set(chunk, offset);
170
+ offset += chunk.length;
171
+ }
172
+ chunks.length = 0;
173
+ return concatenatedChunks;
174
+ }
175
+ async function* readDataStream(reader, {
176
+ isAborted
177
+ } = {}) {
178
+ const decoder = new TextDecoder();
179
+ const chunks = [];
180
+ let totalLength = 0;
181
+ while (true) {
182
+ const { value } = await reader.read();
183
+ if (value) {
184
+ chunks.push(value);
185
+ totalLength += value.length;
186
+ if (value[value.length - 1] !== NEWLINE) {
187
+ continue;
188
+ }
189
+ }
190
+ if (chunks.length === 0) {
191
+ break;
192
+ }
193
+ const concatenatedChunks = concatChunks(chunks, totalLength);
194
+ totalLength = 0;
195
+ const streamParts2 = decoder.decode(concatenatedChunks, { stream: true }).split("\n").filter((line) => line !== "").map(parseStreamPart);
196
+ for (const streamPart of streamParts2) {
197
+ yield streamPart;
198
+ }
199
+ if (isAborted == null ? void 0 : isAborted()) {
200
+ reader.cancel();
201
+ break;
202
+ }
203
+ }
204
+ }
205
+
166
206
  // shared/utils.ts
207
+ var import_non_secure = require("nanoid/non-secure");
167
208
  var nanoid = (0, import_non_secure.customAlphabet)(
168
209
  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
169
210
  7
@@ -182,6 +223,218 @@ function createChunkDecoder(complex) {
182
223
  return decoded.map(parseStreamPart).filter(Boolean);
183
224
  };
184
225
  }
226
+ var COMPLEX_HEADER = "X-Experimental-Stream-Data";
227
+
228
+ // shared/parse-complex-response.ts
229
+ async function parseComplexResponse({
230
+ reader,
231
+ abortControllerRef,
232
+ update,
233
+ onFinish,
234
+ generateId = nanoid,
235
+ getCurrentDate = () => /* @__PURE__ */ new Date()
236
+ }) {
237
+ const createdAt = getCurrentDate();
238
+ const prefixMap = {
239
+ data: []
240
+ };
241
+ for await (const { type, value } of readDataStream(reader, {
242
+ isAborted: () => (abortControllerRef == null ? void 0 : abortControllerRef.current) === null
243
+ })) {
244
+ if (type === "text") {
245
+ if (prefixMap["text"]) {
246
+ prefixMap["text"] = {
247
+ ...prefixMap["text"],
248
+ content: (prefixMap["text"].content || "") + value
249
+ };
250
+ } else {
251
+ prefixMap["text"] = {
252
+ id: generateId(),
253
+ role: "assistant",
254
+ content: value,
255
+ createdAt
256
+ };
257
+ }
258
+ }
259
+ let functionCallMessage = null;
260
+ if (type === "function_call") {
261
+ prefixMap["function_call"] = {
262
+ id: generateId(),
263
+ role: "assistant",
264
+ content: "",
265
+ function_call: value.function_call,
266
+ name: value.function_call.name,
267
+ createdAt
268
+ };
269
+ functionCallMessage = prefixMap["function_call"];
270
+ }
271
+ if (type === "data") {
272
+ prefixMap["data"].push(...value);
273
+ }
274
+ const responseMessage = prefixMap["text"];
275
+ const merged = [functionCallMessage, responseMessage].filter(
276
+ Boolean
277
+ );
278
+ update(merged, [...prefixMap["data"]]);
279
+ }
280
+ onFinish == null ? void 0 : onFinish(prefixMap);
281
+ return {
282
+ messages: [prefixMap.text, prefixMap.function_call].filter(
283
+ Boolean
284
+ ),
285
+ data: prefixMap.data
286
+ };
287
+ }
288
+
289
+ // shared/call-api.ts
290
+ async function callApi({
291
+ api,
292
+ messages,
293
+ body,
294
+ credentials,
295
+ headers,
296
+ abortController,
297
+ appendMessage,
298
+ restoreMessagesOnFailure,
299
+ onResponse,
300
+ onUpdate,
301
+ onFinish,
302
+ generateId
303
+ }) {
304
+ var _a;
305
+ const response = await fetch(api, {
306
+ method: "POST",
307
+ body: JSON.stringify({
308
+ messages,
309
+ ...body
310
+ }),
311
+ headers: {
312
+ "Content-Type": "application/json",
313
+ ...headers
314
+ },
315
+ signal: (_a = abortController == null ? void 0 : abortController()) == null ? void 0 : _a.signal,
316
+ credentials
317
+ }).catch((err) => {
318
+ restoreMessagesOnFailure();
319
+ throw err;
320
+ });
321
+ if (onResponse) {
322
+ try {
323
+ await onResponse(response);
324
+ } catch (err) {
325
+ throw err;
326
+ }
327
+ }
328
+ if (!response.ok) {
329
+ restoreMessagesOnFailure();
330
+ throw new Error(
331
+ await response.text() || "Failed to fetch the chat response."
332
+ );
333
+ }
334
+ if (!response.body) {
335
+ throw new Error("The response body is empty.");
336
+ }
337
+ const reader = response.body.getReader();
338
+ const isComplexMode = response.headers.get(COMPLEX_HEADER) === "true";
339
+ if (isComplexMode) {
340
+ return await parseComplexResponse({
341
+ reader,
342
+ abortControllerRef: abortController != null ? { current: abortController() } : void 0,
343
+ update: onUpdate,
344
+ onFinish(prefixMap) {
345
+ if (onFinish && prefixMap.text != null) {
346
+ onFinish(prefixMap.text);
347
+ }
348
+ },
349
+ generateId
350
+ });
351
+ } else {
352
+ const createdAt = /* @__PURE__ */ new Date();
353
+ const decode = createChunkDecoder(false);
354
+ let streamedResponse = "";
355
+ const replyId = generateId();
356
+ let responseMessage = {
357
+ id: replyId,
358
+ createdAt,
359
+ content: "",
360
+ role: "assistant"
361
+ };
362
+ while (true) {
363
+ const { done, value } = await reader.read();
364
+ if (done) {
365
+ break;
366
+ }
367
+ streamedResponse += decode(value);
368
+ if (streamedResponse.startsWith('{"function_call":')) {
369
+ responseMessage["function_call"] = streamedResponse;
370
+ } else {
371
+ responseMessage["content"] = streamedResponse;
372
+ }
373
+ appendMessage({ ...responseMessage });
374
+ if ((abortController == null ? void 0 : abortController()) === null) {
375
+ reader.cancel();
376
+ break;
377
+ }
378
+ }
379
+ if (streamedResponse.startsWith('{"function_call":')) {
380
+ const parsedFunctionCall = JSON.parse(streamedResponse).function_call;
381
+ responseMessage["function_call"] = parsedFunctionCall;
382
+ appendMessage({ ...responseMessage });
383
+ }
384
+ if (onFinish) {
385
+ onFinish(responseMessage);
386
+ }
387
+ return responseMessage;
388
+ }
389
+ }
390
+
391
+ // shared/process-chat-stream.ts
392
+ async function processChatStream({
393
+ getStreamedResponse,
394
+ experimental_onFunctionCall,
395
+ updateChatRequest,
396
+ getCurrentMessages
397
+ }) {
398
+ while (true) {
399
+ const messagesAndDataOrJustMessage = await getStreamedResponse();
400
+ if ("messages" in messagesAndDataOrJustMessage) {
401
+ let hasFollowingResponse = false;
402
+ for (const message of messagesAndDataOrJustMessage.messages) {
403
+ if (message.function_call === void 0 || typeof message.function_call === "string") {
404
+ continue;
405
+ }
406
+ hasFollowingResponse = true;
407
+ if (experimental_onFunctionCall) {
408
+ const functionCall = message.function_call;
409
+ const functionCallResponse = await experimental_onFunctionCall(
410
+ getCurrentMessages(),
411
+ functionCall
412
+ );
413
+ if (functionCallResponse === void 0) {
414
+ hasFollowingResponse = false;
415
+ break;
416
+ }
417
+ updateChatRequest(functionCallResponse);
418
+ }
419
+ }
420
+ if (!hasFollowingResponse) {
421
+ break;
422
+ }
423
+ } else {
424
+ const streamedResponseMessage = messagesAndDataOrJustMessage;
425
+ if (streamedResponseMessage.function_call === void 0 || typeof streamedResponseMessage.function_call === "string") {
426
+ break;
427
+ }
428
+ if (experimental_onFunctionCall) {
429
+ const functionCall = streamedResponseMessage.function_call;
430
+ const functionCallResponse = await experimental_onFunctionCall(getCurrentMessages(), functionCall);
431
+ if (functionCallResponse === void 0)
432
+ break;
433
+ updateChatRequest(functionCallResponse);
434
+ }
435
+ }
436
+ }
437
+ }
185
438
 
186
439
  // vue/use-chat.ts
187
440
  var uniqueId = 0;
@@ -193,17 +446,19 @@ function useChat({
193
446
  initialMessages = [],
194
447
  initialInput = "",
195
448
  sendExtraMessageFields,
449
+ experimental_onFunctionCall,
196
450
  onResponse,
197
451
  onFinish,
198
452
  onError,
199
453
  credentials,
200
454
  headers,
201
- body
455
+ body,
456
+ generateId = nanoid
202
457
  } = {}) {
203
- var _a;
458
+ var _a, _b;
204
459
  const chatId = id || `chat-${uniqueId++}`;
205
460
  const key = `${api}|${chatId}`;
206
- const { data, mutate: originalMutate } = useSWRV(
461
+ const { data: messagesData, mutate: originalMutate } = useSWRV(
207
462
  key,
208
463
  () => store[key] || initialMessages
209
464
  );
@@ -212,99 +467,78 @@ function useChat({
212
467
  null
213
468
  );
214
469
  (_a = isLoading.value) != null ? _a : isLoading.value = false;
215
- data.value || (data.value = initialMessages);
216
- const mutate = (data2) => {
217
- store[key] = data2;
470
+ (_b = messagesData.value) != null ? _b : messagesData.value = initialMessages;
471
+ const mutate = (data) => {
472
+ store[key] = data;
218
473
  return originalMutate();
219
474
  };
220
- const messages = data;
475
+ const messages = messagesData;
221
476
  const error = (0, import_vue.ref)(void 0);
477
+ const streamData = (0, import_vue.ref)(void 0);
222
478
  let abortController = null;
223
479
  async function triggerRequest(messagesSnapshot, options) {
224
480
  try {
225
481
  error.value = void 0;
226
482
  mutateLoading(() => true);
227
483
  abortController = new AbortController();
228
- const previousMessages = messages.value;
484
+ const previousMessages = messagesData.value;
229
485
  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
486
+ let chatRequest = {
487
+ messages: messagesSnapshot,
488
+ options
489
+ };
490
+ await processChatStream({
491
+ getStreamedResponse: async () => {
492
+ var _a2;
493
+ const existingData = (_a2 = streamData.value) != null ? _a2 : [];
494
+ return await callApi({
495
+ api,
496
+ messages: sendExtraMessageFields ? chatRequest.messages : chatRequest.messages.map(
497
+ ({ role, content, name, function_call }) => ({
498
+ role,
499
+ content,
500
+ ...name !== void 0 && { name },
501
+ ...function_call !== void 0 && {
502
+ function_call
503
+ }
504
+ })
505
+ ),
506
+ body: {
507
+ ...(0, import_vue.unref)(body),
508
+ // Use unref to unwrap the ref value
509
+ ...options == null ? void 0 : options.body
510
+ },
511
+ headers: {
512
+ ...headers,
513
+ ...options == null ? void 0 : options.headers
514
+ },
515
+ abortController: () => abortController,
516
+ credentials,
517
+ onResponse,
518
+ onUpdate(merged, data) {
519
+ mutate([...chatRequest.messages, ...merged]);
520
+ streamData.value = [...existingData, ...data != null ? data : []];
521
+ },
522
+ onFinish(message) {
523
+ mutate([...chatRequest.messages, message]);
524
+ onFinish == null ? void 0 : onFinish(message);
525
+ },
526
+ appendMessage(message) {
527
+ mutate([...chatRequest.messages, message]);
528
+ },
529
+ restoreMessagesOnFailure() {
530
+ mutate(previousMessages);
531
+ },
532
+ generateId
533
+ });
250
534
  },
251
- signal: abortController.signal,
252
- credentials
253
- }).catch((err) => {
254
- mutate(previousMessages);
255
- throw err;
535
+ experimental_onFunctionCall,
536
+ updateChatRequest(newChatRequest) {
537
+ chatRequest = newChatRequest;
538
+ },
539
+ getCurrentMessages: () => messages.value
256
540
  });
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
541
  abortController = null;
307
- return result;
308
542
  } catch (err) {
309
543
  if (err.name === "AbortError") {
310
544
  abortController = null;
@@ -320,7 +554,7 @@ function useChat({
320
554
  }
321
555
  const append = async (message, options) => {
322
556
  if (!message.id) {
323
- message.id = nanoid();
557
+ message.id = generateId();
324
558
  }
325
559
  return triggerRequest(messages.value.concat(message), options);
326
560
  };
@@ -364,7 +598,8 @@ function useChat({
364
598
  setMessages,
365
599
  input,
366
600
  handleSubmit,
367
- isLoading
601
+ isLoading,
602
+ data: streamData
368
603
  };
369
604
  }
370
605
 
@@ -398,6 +633,7 @@ function useCompletion({
398
633
  null
399
634
  );
400
635
  (_a = isLoading.value) != null ? _a : isLoading.value = false;
636
+ const { data: streamData, mutate: mutateStreamData } = useSWRV2(`${completionId}-data`, null);
401
637
  data.value || (data.value = initialCompletion);
402
638
  const mutate = (data2) => {
403
639
  store2[key] = data2;
@@ -407,6 +643,7 @@ function useCompletion({
407
643
  const error = (0, import_vue2.ref)(void 0);
408
644
  let abortController = null;
409
645
  async function triggerRequest(prompt, options) {
646
+ var _a2;
410
647
  try {
411
648
  error.value = void 0;
412
649
  mutateLoading(() => true);
@@ -420,6 +657,7 @@ function useCompletion({
420
657
  ...options == null ? void 0 : options.body
421
658
  }),
422
659
  headers: {
660
+ "Content-Type": "application/json",
423
661
  ...headers,
424
662
  ...options == null ? void 0 : options.headers
425
663
  },
@@ -445,17 +683,37 @@ function useCompletion({
445
683
  }
446
684
  let result = "";
447
685
  const reader = res.body.getReader();
448
- const decoder = createChunkDecoder();
449
- while (true) {
450
- const { done, value } = await reader.read();
451
- if (done) {
452
- break;
686
+ const existingData = (_a2 = streamData.value) != null ? _a2 : [];
687
+ const isComplexMode = res.headers.get(COMPLEX_HEADER) === "true";
688
+ if (isComplexMode) {
689
+ for await (const { type, value } of readDataStream(reader, {
690
+ isAborted: () => abortController === null
691
+ })) {
692
+ switch (type) {
693
+ case "text": {
694
+ result += value;
695
+ mutate(result);
696
+ break;
697
+ }
698
+ case "data": {
699
+ streamData.value = [...existingData, ...value != null ? value : []];
700
+ break;
701
+ }
702
+ }
453
703
  }
454
- result += decoder(value);
455
- mutate(result);
456
- if (abortController === null) {
457
- reader.cancel();
458
- break;
704
+ } else {
705
+ const decoder = createChunkDecoder();
706
+ while (true) {
707
+ const { done, value } = await reader.read();
708
+ if (done) {
709
+ break;
710
+ }
711
+ result += decoder(value);
712
+ mutate(result);
713
+ if (abortController === null) {
714
+ reader.cancel();
715
+ break;
716
+ }
459
717
  }
460
718
  }
461
719
  if (onFinish) {
@@ -504,7 +762,8 @@ function useCompletion({
504
762
  setCompletion,
505
763
  input,
506
764
  handleSubmit,
507
- isLoading
765
+ isLoading,
766
+ data: streamData
508
767
  };
509
768
  }
510
769
  // Annotate the CommonJS export names for ESM import in node: