ai 2.1.16 → 2.1.18

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 CHANGED
@@ -65,6 +65,14 @@ declare function trimStartOfStreamHelper(): (text: string) => string;
65
65
  * Returns a ReadableStream created from the response, parsed and handled with custom logic.
66
66
  * The stream goes through two transformation stages, first parsing the events and then
67
67
  * invoking the provided callbacks.
68
+ *
69
+ * For 2xx HTTP responses:
70
+ * - The function continues with standard stream processing.
71
+ *
72
+ * For non-2xx HTTP responses:
73
+ * - If the response body is defined, it asynchronously extracts and decodes the response body.
74
+ * - It then creates a custom ReadableStream to propagate a detailed error message.
75
+ *
68
76
  * @param {Response} response - The response.
69
77
  * @param {AIStreamParser} customParser - The custom parser function.
70
78
  * @param {AIStreamCallbacks} callbacks - The callbacks.
package/dist/index.js CHANGED
@@ -142,9 +142,27 @@ function trimStartOfStreamHelper() {
142
142
  }
143
143
  function AIStream(response, customParser, callbacks) {
144
144
  if (!response.ok) {
145
- throw new Error(
146
- `Failed to convert the response to stream. Received status code: ${response.status}.`
147
- );
145
+ if (response.body) {
146
+ let _a;
147
+ const reader = response.body.getReader();
148
+ return new ReadableStream({
149
+ start(controller) {
150
+ return __async(this, null, function* () {
151
+ const { done, value } = yield reader.read();
152
+ if (!done) {
153
+ const errorText = new TextDecoder().decode(value);
154
+ controller.error(new Error(`Response error: ${errorText}`));
155
+ }
156
+ });
157
+ }
158
+ });
159
+ } else {
160
+ return new ReadableStream({
161
+ start(controller) {
162
+ controller.error(new Error("Response error: No response body"));
163
+ }
164
+ });
165
+ }
148
166
  }
149
167
  const responseBodyStream = response.body || createEmptyReadableStream();
150
168
  return responseBodyStream.pipeThrough(createEventStreamTransformer(customParser)).pipeThrough(createCallbacksTransformer(callbacks));
@@ -370,8 +388,8 @@ function LangChainStream(callbacks) {
370
388
  }
371
389
 
372
390
  // shared/utils.ts
373
- var import_nanoid = require("nanoid");
374
- var nanoid = (0, import_nanoid.customAlphabet)(
391
+ var import_non_secure = require("nanoid/non-secure");
392
+ var nanoid = (0, import_non_secure.customAlphabet)(
375
393
  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
376
394
  7
377
395
  );
package/dist/index.mjs CHANGED
@@ -109,9 +109,27 @@ function trimStartOfStreamHelper() {
109
109
  }
110
110
  function AIStream(response, customParser, callbacks) {
111
111
  if (!response.ok) {
112
- throw new Error(
113
- `Failed to convert the response to stream. Received status code: ${response.status}.`
114
- );
112
+ if (response.body) {
113
+ let _a;
114
+ const reader = response.body.getReader();
115
+ return new ReadableStream({
116
+ start(controller) {
117
+ return __async(this, null, function* () {
118
+ const { done, value } = yield reader.read();
119
+ if (!done) {
120
+ const errorText = new TextDecoder().decode(value);
121
+ controller.error(new Error(`Response error: ${errorText}`));
122
+ }
123
+ });
124
+ }
125
+ });
126
+ } else {
127
+ return new ReadableStream({
128
+ start(controller) {
129
+ controller.error(new Error("Response error: No response body"));
130
+ }
131
+ });
132
+ }
115
133
  }
116
134
  const responseBodyStream = response.body || createEmptyReadableStream();
117
135
  return responseBodyStream.pipeThrough(createEventStreamTransformer(customParser)).pipeThrough(createCallbacksTransformer(callbacks));
@@ -337,7 +355,7 @@ function LangChainStream(callbacks) {
337
355
  }
338
356
 
339
357
  // shared/utils.ts
340
- import { customAlphabet } from "nanoid";
358
+ import { customAlphabet } from "nanoid/non-secure";
341
359
  var nanoid = customAlphabet(
342
360
  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
343
361
  7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai",
3
- "version": "2.1.16",
3
+ "version": "2.1.18",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -76,8 +76,8 @@ var import_mutation = __toESM(require("swr/mutation"));
76
76
  var import_swr = __toESM(require("swr"));
77
77
 
78
78
  // shared/utils.ts
79
- var import_nanoid = require("nanoid");
80
- var nanoid = (0, import_nanoid.customAlphabet)(
79
+ var import_non_secure = require("nanoid/non-secure");
80
+ var nanoid = (0, import_non_secure.customAlphabet)(
81
81
  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
82
82
  7
83
83
  );
@@ -42,7 +42,7 @@ import useSWRMutation from "swr/mutation";
42
42
  import useSWR from "swr";
43
43
 
44
44
  // shared/utils.ts
45
- import { customAlphabet } from "nanoid";
45
+ import { customAlphabet } from "nanoid/non-secure";
46
46
  var nanoid = customAlphabet(
47
47
  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
48
48
  7
@@ -36,6 +36,11 @@ type RequestOptions = {
36
36
  headers?: Record<string, string> | Headers;
37
37
  body?: object;
38
38
  };
39
+ type ChatRequestOptions = {
40
+ options?: RequestOptions;
41
+ functions?: Array<ChatCompletionFunctions>;
42
+ function_call?: CreateChatCompletionRequestFunctionCall;
43
+ };
39
44
  type UseChatOptions = {
40
45
  /**
41
46
  * The API endpoint that accepts a `{ messages: Message[] }` object and returns
@@ -169,14 +174,16 @@ type UseChatHelpers = {
169
174
  /**
170
175
  * Append a user message to the chat list. This triggers the API call to fetch
171
176
  * the assistant's response.
177
+ * @param message The message to append
178
+ * @param chatRequestOptions Additional options to pass to the API call
172
179
  */
173
- append: (message: Message | CreateMessage, options?: RequestOptions) => Promise<string | null | undefined>;
180
+ append: (message: Message | CreateMessage, chatRequestOptions?: ChatRequestOptions) => Promise<string | null | undefined>;
174
181
  /**
175
182
  * Reload the last AI chat response for the given chat history. If the last
176
183
  * message isn't from the assistant, it will request the API to generate a
177
184
  * new response.
178
185
  */
179
- reload: (options?: RequestOptions) => Promise<string | null | undefined>;
186
+ reload: (chatRequestOptions?: ChatRequestOptions) => Promise<string | null | undefined>;
180
187
  /**
181
188
  * Abort the current request immediately, keep the generated tokens if any.
182
189
  */
@@ -190,11 +197,12 @@ type UseChatHelpers = {
190
197
  /** The current value of the input */
191
198
  input: Writable<string>;
192
199
  /** Form submission handler to automattically reset input and append a user message */
193
- handleSubmit: (e: any) => void;
200
+ handleSubmit: (e: any, chatRequestOptions?: ChatRequestOptions) => void;
201
+ metadata?: Object;
194
202
  /** Whether the API request is in progress */
195
203
  isLoading: Writable<boolean>;
196
204
  };
197
- declare function useChat({ api, id, initialMessages, initialInput, sendExtraMessageFields, onResponse, onFinish, onError, credentials, headers, body }?: UseChatOptions): UseChatHelpers;
205
+ declare function useChat({ api, id, initialMessages, initialInput, sendExtraMessageFields, experimental_onFunctionCall, onResponse, onFinish, onError, credentials, headers, body }?: UseChatOptions): UseChatHelpers;
198
206
 
199
207
  type UseCompletionHelpers = {
200
208
  /** The current completion result */
@@ -59,6 +59,9 @@ __export(svelte_exports, {
59
59
  });
60
60
  module.exports = __toCommonJS(svelte_exports);
61
61
 
62
+ // svelte/use-chat.ts
63
+ var import_store = require("svelte/store");
64
+
62
65
  // ../../node_modules/.pnpm/swrev@3.0.0/node_modules/swrev/dist/swrev.es.js
63
66
  var __defProp2 = Object.defineProperty;
64
67
  var __defProps = Object.defineProperties;
@@ -497,12 +500,9 @@ var W = (t) => new A(t);
497
500
  var u = W();
498
501
  var $ = (t, e) => u.useSWR(t, e);
499
502
 
500
- // svelte/use-chat.ts
501
- var import_store = require("svelte/store");
502
-
503
503
  // shared/utils.ts
504
- var import_nanoid = require("nanoid");
505
- var nanoid = (0, import_nanoid.customAlphabet)(
504
+ var import_non_secure = require("nanoid/non-secure");
505
+ var nanoid = (0, import_non_secure.customAlphabet)(
506
506
  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
507
507
  7
508
508
  );
@@ -516,6 +516,90 @@ function createChunkDecoder() {
516
516
  }
517
517
 
518
518
  // svelte/use-chat.ts
519
+ var getStreamedResponse = (api, chatRequest, mutate, extraMetadata, previousMessages, abortControllerRef, onFinish, onResponse, sendExtraMessageFields) => __async(void 0, null, function* () {
520
+ var _a, _b, _c, _d;
521
+ mutate(chatRequest.messages);
522
+ const res = yield fetch(api, __spreadValues({
523
+ method: "POST",
524
+ body: JSON.stringify(__spreadValues(__spreadValues(__spreadValues(__spreadValues({
525
+ messages: sendExtraMessageFields ? chatRequest.messages : chatRequest.messages.map(
526
+ ({ role, content, name, function_call }) => __spreadValues(__spreadValues({
527
+ role,
528
+ content
529
+ }, name !== void 0 && { name }), function_call !== void 0 && {
530
+ function_call
531
+ })
532
+ )
533
+ }, extraMetadata.body), (_a = chatRequest.options) == null ? void 0 : _a.body), chatRequest.functions !== void 0 && {
534
+ functions: chatRequest.functions
535
+ }), chatRequest.function_call !== void 0 && {
536
+ function_call: chatRequest.function_call
537
+ })),
538
+ credentials: extraMetadata.credentials,
539
+ headers: __spreadValues(__spreadValues({}, extraMetadata.headers), (_b = chatRequest.options) == null ? void 0 : _b.headers)
540
+ }, abortControllerRef !== null && {
541
+ signal: abortControllerRef.signal
542
+ })).catch((err) => {
543
+ mutate(previousMessages);
544
+ throw err;
545
+ });
546
+ if (onResponse) {
547
+ try {
548
+ yield onResponse(res);
549
+ } catch (err) {
550
+ throw err;
551
+ }
552
+ }
553
+ if (!res.ok) {
554
+ mutate(previousMessages);
555
+ throw new Error((yield res.text()) || "Failed to fetch the chat response.");
556
+ }
557
+ if (!res.body) {
558
+ throw new Error("The response body is empty.");
559
+ }
560
+ let streamedResponse = "";
561
+ const createdAt = /* @__PURE__ */ new Date();
562
+ const replyId = nanoid();
563
+ const reader = res.body.getReader();
564
+ const decode = createChunkDecoder();
565
+ let responseMessage = {
566
+ id: replyId,
567
+ createdAt,
568
+ content: "",
569
+ role: "assistant"
570
+ };
571
+ while (true) {
572
+ const { done, value } = yield reader.read();
573
+ if (done) {
574
+ break;
575
+ }
576
+ streamedResponse += decode(value);
577
+ const functionStart = streamedResponse.indexOf("{");
578
+ if (functionStart !== -1) {
579
+ const matches = new RegExp('(.*?)(?:({"function_call".*?}})(.*))?$', "gs").exec(
580
+ streamedResponse
581
+ );
582
+ responseMessage.content = `${(_c = matches == null ? void 0 : matches[1]) != null ? _c : ""}${(_d = matches == null ? void 0 : matches[3]) != null ? _d : ""}`;
583
+ responseMessage.function_call = matches == null ? void 0 : matches[2];
584
+ } else {
585
+ responseMessage.content = streamedResponse;
586
+ }
587
+ mutate([...chatRequest.messages, __spreadValues({}, responseMessage)]);
588
+ if (abortControllerRef === null) {
589
+ reader.cancel();
590
+ break;
591
+ }
592
+ }
593
+ if (typeof responseMessage.function_call === "string") {
594
+ const parsedFunctionCall = JSON.parse(responseMessage.function_call).function_call;
595
+ responseMessage.function_call = parsedFunctionCall;
596
+ mutate([...chatRequest.messages, __spreadValues({}, responseMessage)]);
597
+ }
598
+ if (onFinish) {
599
+ onFinish(responseMessage);
600
+ }
601
+ return responseMessage;
602
+ });
519
603
  var uniqueId = 0;
520
604
  var store = {};
521
605
  function useChat({
@@ -524,6 +608,7 @@ function useChat({
524
608
  initialMessages = [],
525
609
  initialInput = "",
526
610
  sendExtraMessageFields,
611
+ experimental_onFunctionCall,
527
612
  onResponse,
528
613
  onFinish,
529
614
  onError,
@@ -543,82 +628,44 @@ function useChat({
543
628
  return originalMutate(data2);
544
629
  };
545
630
  const messages = data;
631
+ let abortController = null;
632
+ const extraMetadata = {
633
+ credentials,
634
+ headers,
635
+ body
636
+ };
546
637
  const error = (0, import_store.writable)(void 0);
547
638
  const isLoading = (0, import_store.writable)(false);
548
- let abortController = null;
549
- function triggerRequest(messagesSnapshot, options) {
639
+ function triggerRequest(chatRequest) {
550
640
  return __async(this, null, function* () {
551
641
  try {
552
642
  isLoading.set(true);
553
643
  abortController = new AbortController();
554
- const previousMessages = (0, import_store.get)(messages);
555
- mutate(messagesSnapshot);
556
- const res = yield fetch(api, {
557
- method: "POST",
558
- body: JSON.stringify(__spreadValues(__spreadValues({
559
- messages: sendExtraMessageFields ? messagesSnapshot : messagesSnapshot.map(({ role, content }) => ({
560
- role,
561
- content
562
- }))
563
- }, body), options == null ? void 0 : options.body)),
564
- headers: __spreadValues(__spreadValues({}, headers), options == null ? void 0 : options.headers),
565
- signal: abortController.signal,
566
- credentials
567
- }).catch((err) => {
568
- mutate(previousMessages);
569
- throw err;
570
- });
571
- if (onResponse) {
572
- try {
573
- yield onResponse(res);
574
- } catch (err) {
575
- throw err;
576
- }
577
- }
578
- if (!res.ok) {
579
- mutate(previousMessages);
580
- throw new Error(
581
- (yield res.text()) || "Failed to fetch the chat response."
582
- );
583
- }
584
- if (!res.body) {
585
- throw new Error("The response body is empty.");
586
- }
587
- let result = "";
588
- const createdAt = /* @__PURE__ */ new Date();
589
- const replyId = nanoid();
590
- const reader = res.body.getReader();
591
- const decoder = createChunkDecoder();
592
644
  while (true) {
593
- const { done, value } = yield reader.read();
594
- if (done) {
645
+ const streamedResponseMessage = yield getStreamedResponse(
646
+ api,
647
+ chatRequest,
648
+ mutate,
649
+ extraMetadata,
650
+ (0, import_store.get)(messages),
651
+ abortController,
652
+ onFinish,
653
+ onResponse,
654
+ sendExtraMessageFields
655
+ );
656
+ if (streamedResponseMessage.function_call === void 0 || typeof streamedResponseMessage.function_call === "string") {
595
657
  break;
596
658
  }
597
- result += decoder(value);
598
- mutate([
599
- ...messagesSnapshot,
600
- {
601
- id: replyId,
602
- createdAt,
603
- content: result,
604
- role: "assistant"
605
- }
606
- ]);
607
- if (abortController === null) {
608
- reader.cancel();
609
- break;
659
+ if (experimental_onFunctionCall) {
660
+ const functionCall = streamedResponseMessage.function_call;
661
+ const functionCallResponse = yield experimental_onFunctionCall((0, import_store.get)(messages), functionCall);
662
+ if (functionCallResponse === void 0)
663
+ break;
664
+ chatRequest = functionCallResponse;
610
665
  }
611
666
  }
612
- if (onFinish) {
613
- onFinish({
614
- id: replyId,
615
- createdAt,
616
- content: result,
617
- role: "assistant"
618
- });
619
- }
620
667
  abortController = null;
621
- return result;
668
+ return null;
622
669
  } catch (err) {
623
670
  if (err.name === "AbortError") {
624
671
  abortController = null;
@@ -633,21 +680,37 @@ function useChat({
633
680
  }
634
681
  });
635
682
  }
636
- const append = (message, options) => __async(this, null, function* () {
683
+ const append = (_0, ..._1) => __async(this, [_0, ..._1], function* (message, { options, functions, function_call } = {}) {
637
684
  if (!message.id) {
638
685
  message.id = nanoid();
639
686
  }
640
- return triggerRequest((0, import_store.get)(messages).concat(message), options);
687
+ const chatRequest = __spreadValues(__spreadValues({
688
+ messages: (0, import_store.get)(messages).concat(message),
689
+ options
690
+ }, functions !== void 0 && { functions }), function_call !== void 0 && { function_call });
691
+ return triggerRequest(chatRequest);
641
692
  });
642
- const reload = (options) => __async(this, null, function* () {
693
+ const reload = (..._0) => __async(this, [..._0], function* ({
694
+ options,
695
+ functions,
696
+ function_call
697
+ } = {}) {
643
698
  const messagesSnapshot = (0, import_store.get)(messages);
644
699
  if (messagesSnapshot.length === 0)
645
700
  return null;
646
- const lastMessage = messagesSnapshot[messagesSnapshot.length - 1];
647
- if (lastMessage.role === "assistant") {
648
- return triggerRequest(messagesSnapshot.slice(0, -1), options);
701
+ const lastMessage = messagesSnapshot.at(-1);
702
+ if ((lastMessage == null ? void 0 : lastMessage.role) === "assistant") {
703
+ const chatRequest2 = __spreadValues(__spreadValues({
704
+ messages: messagesSnapshot.slice(0, -1),
705
+ options
706
+ }, functions !== void 0 && { functions }), function_call !== void 0 && { function_call });
707
+ return triggerRequest(chatRequest2);
649
708
  }
650
- return triggerRequest(messagesSnapshot, options);
709
+ const chatRequest = __spreadValues(__spreadValues({
710
+ messages: messagesSnapshot,
711
+ options
712
+ }, functions !== void 0 && { functions }), function_call !== void 0 && { function_call });
713
+ return triggerRequest(chatRequest);
651
714
  });
652
715
  const stop = () => {
653
716
  if (abortController) {
@@ -659,22 +722,25 @@ function useChat({
659
722
  mutate(messages2);
660
723
  };
661
724
  const input = (0, import_store.writable)(initialInput);
662
- const handleSubmit = (e) => {
725
+ const handleSubmit = (e, options = {}) => {
663
726
  e.preventDefault();
664
727
  const inputValue = (0, import_store.get)(input);
665
728
  if (!inputValue)
666
729
  return;
667
- append({
668
- content: inputValue,
669
- role: "user",
670
- createdAt: /* @__PURE__ */ new Date()
671
- });
730
+ append(
731
+ {
732
+ content: inputValue,
733
+ role: "user",
734
+ createdAt: /* @__PURE__ */ new Date()
735
+ },
736
+ options
737
+ );
672
738
  input.set("");
673
739
  };
674
740
  return {
675
741
  messages,
676
- append,
677
742
  error,
743
+ append,
678
744
  reload,
679
745
  stop,
680
746
  setMessages,
@@ -35,6 +35,9 @@ var __async = (__this, __arguments, generator) => {
35
35
  });
36
36
  };
37
37
 
38
+ // svelte/use-chat.ts
39
+ import { get, writable } from "svelte/store";
40
+
38
41
  // ../../node_modules/.pnpm/swrev@3.0.0/node_modules/swrev/dist/swrev.es.js
39
42
  var __defProp2 = Object.defineProperty;
40
43
  var __defProps = Object.defineProperties;
@@ -473,11 +476,8 @@ var W = (t) => new A(t);
473
476
  var u = W();
474
477
  var $ = (t, e) => u.useSWR(t, e);
475
478
 
476
- // svelte/use-chat.ts
477
- import { get, writable } from "svelte/store";
478
-
479
479
  // shared/utils.ts
480
- import { customAlphabet } from "nanoid";
480
+ import { customAlphabet } from "nanoid/non-secure";
481
481
  var nanoid = customAlphabet(
482
482
  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
483
483
  7
@@ -492,6 +492,90 @@ function createChunkDecoder() {
492
492
  }
493
493
 
494
494
  // svelte/use-chat.ts
495
+ var getStreamedResponse = (api, chatRequest, mutate, extraMetadata, previousMessages, abortControllerRef, onFinish, onResponse, sendExtraMessageFields) => __async(void 0, null, function* () {
496
+ var _a, _b, _c, _d;
497
+ mutate(chatRequest.messages);
498
+ const res = yield fetch(api, __spreadValues({
499
+ method: "POST",
500
+ body: JSON.stringify(__spreadValues(__spreadValues(__spreadValues(__spreadValues({
501
+ messages: sendExtraMessageFields ? chatRequest.messages : chatRequest.messages.map(
502
+ ({ role, content, name, function_call }) => __spreadValues(__spreadValues({
503
+ role,
504
+ content
505
+ }, name !== void 0 && { name }), function_call !== void 0 && {
506
+ function_call
507
+ })
508
+ )
509
+ }, extraMetadata.body), (_a = chatRequest.options) == null ? void 0 : _a.body), chatRequest.functions !== void 0 && {
510
+ functions: chatRequest.functions
511
+ }), chatRequest.function_call !== void 0 && {
512
+ function_call: chatRequest.function_call
513
+ })),
514
+ credentials: extraMetadata.credentials,
515
+ headers: __spreadValues(__spreadValues({}, extraMetadata.headers), (_b = chatRequest.options) == null ? void 0 : _b.headers)
516
+ }, abortControllerRef !== null && {
517
+ signal: abortControllerRef.signal
518
+ })).catch((err) => {
519
+ mutate(previousMessages);
520
+ throw err;
521
+ });
522
+ if (onResponse) {
523
+ try {
524
+ yield onResponse(res);
525
+ } catch (err) {
526
+ throw err;
527
+ }
528
+ }
529
+ if (!res.ok) {
530
+ mutate(previousMessages);
531
+ throw new Error((yield res.text()) || "Failed to fetch the chat response.");
532
+ }
533
+ if (!res.body) {
534
+ throw new Error("The response body is empty.");
535
+ }
536
+ let streamedResponse = "";
537
+ const createdAt = /* @__PURE__ */ new Date();
538
+ const replyId = nanoid();
539
+ const reader = res.body.getReader();
540
+ const decode = createChunkDecoder();
541
+ let responseMessage = {
542
+ id: replyId,
543
+ createdAt,
544
+ content: "",
545
+ role: "assistant"
546
+ };
547
+ while (true) {
548
+ const { done, value } = yield reader.read();
549
+ if (done) {
550
+ break;
551
+ }
552
+ streamedResponse += decode(value);
553
+ const functionStart = streamedResponse.indexOf("{");
554
+ if (functionStart !== -1) {
555
+ const matches = new RegExp('(.*?)(?:({"function_call".*?}})(.*))?$', "gs").exec(
556
+ streamedResponse
557
+ );
558
+ responseMessage.content = `${(_c = matches == null ? void 0 : matches[1]) != null ? _c : ""}${(_d = matches == null ? void 0 : matches[3]) != null ? _d : ""}`;
559
+ responseMessage.function_call = matches == null ? void 0 : matches[2];
560
+ } else {
561
+ responseMessage.content = streamedResponse;
562
+ }
563
+ mutate([...chatRequest.messages, __spreadValues({}, responseMessage)]);
564
+ if (abortControllerRef === null) {
565
+ reader.cancel();
566
+ break;
567
+ }
568
+ }
569
+ if (typeof responseMessage.function_call === "string") {
570
+ const parsedFunctionCall = JSON.parse(responseMessage.function_call).function_call;
571
+ responseMessage.function_call = parsedFunctionCall;
572
+ mutate([...chatRequest.messages, __spreadValues({}, responseMessage)]);
573
+ }
574
+ if (onFinish) {
575
+ onFinish(responseMessage);
576
+ }
577
+ return responseMessage;
578
+ });
495
579
  var uniqueId = 0;
496
580
  var store = {};
497
581
  function useChat({
@@ -500,6 +584,7 @@ function useChat({
500
584
  initialMessages = [],
501
585
  initialInput = "",
502
586
  sendExtraMessageFields,
587
+ experimental_onFunctionCall,
503
588
  onResponse,
504
589
  onFinish,
505
590
  onError,
@@ -519,82 +604,44 @@ function useChat({
519
604
  return originalMutate(data2);
520
605
  };
521
606
  const messages = data;
607
+ let abortController = null;
608
+ const extraMetadata = {
609
+ credentials,
610
+ headers,
611
+ body
612
+ };
522
613
  const error = writable(void 0);
523
614
  const isLoading = writable(false);
524
- let abortController = null;
525
- function triggerRequest(messagesSnapshot, options) {
615
+ function triggerRequest(chatRequest) {
526
616
  return __async(this, null, function* () {
527
617
  try {
528
618
  isLoading.set(true);
529
619
  abortController = new AbortController();
530
- const previousMessages = get(messages);
531
- mutate(messagesSnapshot);
532
- const res = yield fetch(api, {
533
- method: "POST",
534
- body: JSON.stringify(__spreadValues(__spreadValues({
535
- messages: sendExtraMessageFields ? messagesSnapshot : messagesSnapshot.map(({ role, content }) => ({
536
- role,
537
- content
538
- }))
539
- }, body), options == null ? void 0 : options.body)),
540
- headers: __spreadValues(__spreadValues({}, headers), options == null ? void 0 : options.headers),
541
- signal: abortController.signal,
542
- credentials
543
- }).catch((err) => {
544
- mutate(previousMessages);
545
- throw err;
546
- });
547
- if (onResponse) {
548
- try {
549
- yield onResponse(res);
550
- } catch (err) {
551
- throw err;
552
- }
553
- }
554
- if (!res.ok) {
555
- mutate(previousMessages);
556
- throw new Error(
557
- (yield res.text()) || "Failed to fetch the chat response."
558
- );
559
- }
560
- if (!res.body) {
561
- throw new Error("The response body is empty.");
562
- }
563
- let result = "";
564
- const createdAt = /* @__PURE__ */ new Date();
565
- const replyId = nanoid();
566
- const reader = res.body.getReader();
567
- const decoder = createChunkDecoder();
568
620
  while (true) {
569
- const { done, value } = yield reader.read();
570
- if (done) {
621
+ const streamedResponseMessage = yield getStreamedResponse(
622
+ api,
623
+ chatRequest,
624
+ mutate,
625
+ extraMetadata,
626
+ get(messages),
627
+ abortController,
628
+ onFinish,
629
+ onResponse,
630
+ sendExtraMessageFields
631
+ );
632
+ if (streamedResponseMessage.function_call === void 0 || typeof streamedResponseMessage.function_call === "string") {
571
633
  break;
572
634
  }
573
- result += decoder(value);
574
- mutate([
575
- ...messagesSnapshot,
576
- {
577
- id: replyId,
578
- createdAt,
579
- content: result,
580
- role: "assistant"
581
- }
582
- ]);
583
- if (abortController === null) {
584
- reader.cancel();
585
- break;
635
+ if (experimental_onFunctionCall) {
636
+ const functionCall = streamedResponseMessage.function_call;
637
+ const functionCallResponse = yield experimental_onFunctionCall(get(messages), functionCall);
638
+ if (functionCallResponse === void 0)
639
+ break;
640
+ chatRequest = functionCallResponse;
586
641
  }
587
642
  }
588
- if (onFinish) {
589
- onFinish({
590
- id: replyId,
591
- createdAt,
592
- content: result,
593
- role: "assistant"
594
- });
595
- }
596
643
  abortController = null;
597
- return result;
644
+ return null;
598
645
  } catch (err) {
599
646
  if (err.name === "AbortError") {
600
647
  abortController = null;
@@ -609,21 +656,37 @@ function useChat({
609
656
  }
610
657
  });
611
658
  }
612
- const append = (message, options) => __async(this, null, function* () {
659
+ const append = (_0, ..._1) => __async(this, [_0, ..._1], function* (message, { options, functions, function_call } = {}) {
613
660
  if (!message.id) {
614
661
  message.id = nanoid();
615
662
  }
616
- return triggerRequest(get(messages).concat(message), options);
663
+ const chatRequest = __spreadValues(__spreadValues({
664
+ messages: get(messages).concat(message),
665
+ options
666
+ }, functions !== void 0 && { functions }), function_call !== void 0 && { function_call });
667
+ return triggerRequest(chatRequest);
617
668
  });
618
- const reload = (options) => __async(this, null, function* () {
669
+ const reload = (..._0) => __async(this, [..._0], function* ({
670
+ options,
671
+ functions,
672
+ function_call
673
+ } = {}) {
619
674
  const messagesSnapshot = get(messages);
620
675
  if (messagesSnapshot.length === 0)
621
676
  return null;
622
- const lastMessage = messagesSnapshot[messagesSnapshot.length - 1];
623
- if (lastMessage.role === "assistant") {
624
- return triggerRequest(messagesSnapshot.slice(0, -1), options);
677
+ const lastMessage = messagesSnapshot.at(-1);
678
+ if ((lastMessage == null ? void 0 : lastMessage.role) === "assistant") {
679
+ const chatRequest2 = __spreadValues(__spreadValues({
680
+ messages: messagesSnapshot.slice(0, -1),
681
+ options
682
+ }, functions !== void 0 && { functions }), function_call !== void 0 && { function_call });
683
+ return triggerRequest(chatRequest2);
625
684
  }
626
- return triggerRequest(messagesSnapshot, options);
685
+ const chatRequest = __spreadValues(__spreadValues({
686
+ messages: messagesSnapshot,
687
+ options
688
+ }, functions !== void 0 && { functions }), function_call !== void 0 && { function_call });
689
+ return triggerRequest(chatRequest);
627
690
  });
628
691
  const stop = () => {
629
692
  if (abortController) {
@@ -635,22 +698,25 @@ function useChat({
635
698
  mutate(messages2);
636
699
  };
637
700
  const input = writable(initialInput);
638
- const handleSubmit = (e) => {
701
+ const handleSubmit = (e, options = {}) => {
639
702
  e.preventDefault();
640
703
  const inputValue = get(input);
641
704
  if (!inputValue)
642
705
  return;
643
- append({
644
- content: inputValue,
645
- role: "user",
646
- createdAt: /* @__PURE__ */ new Date()
647
- });
706
+ append(
707
+ {
708
+ content: inputValue,
709
+ role: "user",
710
+ createdAt: /* @__PURE__ */ new Date()
711
+ },
712
+ options
713
+ );
648
714
  input.set("");
649
715
  };
650
716
  return {
651
717
  messages,
652
- append,
653
718
  error,
719
+ append,
654
720
  reload,
655
721
  stop,
656
722
  setMessages,
package/vue/dist/index.js CHANGED
@@ -74,8 +74,8 @@ var import_swrv = __toESM(require("swrv"));
74
74
  var import_vue = require("vue");
75
75
 
76
76
  // shared/utils.ts
77
- var import_nanoid = require("nanoid");
78
- var nanoid = (0, import_nanoid.customAlphabet)(
77
+ var import_non_secure = require("nanoid/non-secure");
78
+ var nanoid = (0, import_non_secure.customAlphabet)(
79
79
  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
80
80
  7
81
81
  );
@@ -40,7 +40,7 @@ import swrv from "swrv";
40
40
  import { ref } from "vue";
41
41
 
42
42
  // shared/utils.ts
43
- import { customAlphabet } from "nanoid";
43
+ import { customAlphabet } from "nanoid/non-secure";
44
44
  var nanoid = customAlphabet(
45
45
  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
46
46
  7