@ai-sdk/vue 4.0.0-beta.15 → 4.0.0-beta.177

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
@@ -1,6 +1,6 @@
1
- import { CompletionRequestOptions, UseCompletionOptions, UIMessage, AbstractChat, ChatInit, FlexibleSchema, DeepPartial, InferSchema } from 'ai';
1
+ import { CompletionRequestOptions, UseCompletionOptions, UIMessage, AbstractChat, ChatInit, ChatStatus, FlexibleSchema, DeepPartial, InferSchema } from 'ai';
2
2
  export { UseCompletionOptions } from 'ai';
3
- import { Ref } from 'vue';
3
+ import { Ref, ComputedRef, ShallowRef, MaybeRefOrGetter } from 'vue';
4
4
  import { FetchFunction } from '@ai-sdk/provider-utils';
5
5
 
6
6
  type UseCompletionHelpers = {
@@ -39,10 +39,54 @@ type UseCompletionHelpers = {
39
39
  };
40
40
  declare function useCompletion({ api, id, initialCompletion, initialInput, credentials, headers, body, streamProtocol, onFinish, onError, fetch, }?: UseCompletionOptions): UseCompletionHelpers;
41
41
 
42
+ /**
43
+ * @deprecated Use the {@link useChat} composable instead. It exposes reactive
44
+ * refs and automatically recreates the chat when its init object changes.
45
+ */
42
46
  declare class Chat<UI_MESSAGE extends UIMessage> extends AbstractChat<UI_MESSAGE> {
43
47
  constructor({ messages, ...init }: ChatInit<UI_MESSAGE>);
44
48
  }
45
49
 
50
+ /**
51
+ * Return type of the {@link useChat} composable, which includes the chat
52
+ * instance methods and reactive properties for messages, status, and error.
53
+ */
54
+ interface UseChatHelpers<UI_MESSAGE extends UIMessage> extends Pick<AbstractChat<UI_MESSAGE>, 'sendMessage' | 'regenerate' | 'stop' | 'resumeStream' | 'addToolOutput' | 'addToolApprovalResponse' | 'clearError'> {
55
+ /**
56
+ * The id of the chat.
57
+ */
58
+ id: ComputedRef<string>;
59
+ /**
60
+ * The current error state of the chat, if any.
61
+ */
62
+ error: ShallowRef<Error | undefined>;
63
+ /**
64
+ * The current status of the chat, which can be 'ready', 'generating', 'streaming', or 'error'.
65
+ */
66
+ status: ShallowRef<ChatStatus>;
67
+ /**
68
+ * The list of messages in the chat, which can be updated by the chat instance methods or directly by setting this property.
69
+ */
70
+ messages: ShallowRef<UI_MESSAGE[]>;
71
+ }
72
+ /**
73
+ * Composable to access messages, status, and other chat properties and
74
+ * methods. Accepts an optional reactive initial configuration object
75
+ *
76
+ * @example
77
+ *
78
+ * ```ts
79
+ * // passing a getter if any reactive properties are used within
80
+ * // the init object
81
+ * const { messages, sendMessage } = useChat(() => ({
82
+ * // ...
83
+ * })
84
+ * ```
85
+ *
86
+ * @see BaseChatInit
87
+ */
88
+ declare function useChat<UI_MESSAGE extends UIMessage = UIMessage>(init?: MaybeRefOrGetter<ChatInit<UI_MESSAGE>>): UseChatHelpers<UI_MESSAGE>;
89
+
46
90
  type Experimental_UseObjectOptions<SCHEMA extends FlexibleSchema, RESULT> = {
47
91
  /** API endpoint that streams JSON chunks matching the schema */
48
92
  api: string;
@@ -82,4 +126,4 @@ type Experimental_UseObjectHelpers<RESULT, INPUT> = {
82
126
  };
83
127
  declare const experimental_useObject: <SCHEMA extends FlexibleSchema, RESULT = InferSchema<SCHEMA>, INPUT = any>({ api, id, schema, initialValue, fetch, onError, onFinish, headers, credentials, }: Experimental_UseObjectOptions<SCHEMA, RESULT>) => Experimental_UseObjectHelpers<RESULT, INPUT>;
84
128
 
85
- export { Chat, Experimental_UseObjectHelpers, Experimental_UseObjectOptions, UseCompletionHelpers, experimental_useObject, useCompletion };
129
+ export { Chat, Experimental_UseObjectHelpers, Experimental_UseObjectOptions, UseChatHelpers, UseCompletionHelpers, experimental_useObject, useChat, useCompletion };
package/dist/index.js CHANGED
@@ -1,47 +1,11 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/index.ts
31
- var src_exports = {};
32
- __export(src_exports, {
33
- Chat: () => Chat,
34
- experimental_useObject: () => experimental_useObject,
35
- useCompletion: () => useCompletion
36
- });
37
- module.exports = __toCommonJS(src_exports);
38
-
39
1
  // src/use-completion.ts
40
- var import_ai = require("ai");
41
- var import_swrv = __toESM(require("swrv"));
42
- var import_vue = require("vue");
2
+ import {
3
+ callCompletionApi
4
+ } from "ai";
5
+ import swrv from "swrv";
6
+ import { ref, unref } from "vue";
43
7
  var uniqueId = 0;
44
- var useSWRV = import_swrv.default.default || import_swrv.default;
8
+ var useSWRV = swrv.default || swrv;
45
9
  var store = {};
46
10
  function useCompletion({
47
11
  api = "/api/completion",
@@ -74,10 +38,10 @@ function useCompletion({
74
38
  return originalMutate();
75
39
  };
76
40
  const completion = data;
77
- const error = (0, import_vue.ref)(void 0);
41
+ const error = ref(void 0);
78
42
  let abortController = null;
79
43
  async function triggerRequest(prompt, options) {
80
- return (0, import_ai.callCompletionApi)({
44
+ return callCompletionApi({
81
45
  api,
82
46
  prompt,
83
47
  credentials,
@@ -86,7 +50,7 @@ function useCompletion({
86
50
  ...options == null ? void 0 : options.headers
87
51
  },
88
52
  body: {
89
- ...(0, import_vue.unref)(body),
53
+ ...unref(body),
90
54
  ...options == null ? void 0 : options.body
91
55
  },
92
56
  streamProtocol,
@@ -115,7 +79,7 @@ function useCompletion({
115
79
  const setCompletion = (completion2) => {
116
80
  mutate(completion2);
117
81
  };
118
- const input = (0, import_vue.ref)(initialInput);
82
+ const input = ref(initialInput);
119
83
  const handleSubmit = (event) => {
120
84
  var _a2;
121
85
  (_a2 = event == null ? void 0 : event.preventDefault) == null ? void 0 : _a2.call(event);
@@ -135,12 +99,14 @@ function useCompletion({
135
99
  }
136
100
 
137
101
  // src/chat.vue.ts
138
- var import_ai2 = require("ai");
139
- var import_vue2 = require("vue");
102
+ import {
103
+ AbstractChat
104
+ } from "ai";
105
+ import { ref as ref2 } from "vue";
140
106
  var VueChatState = class {
141
107
  constructor(messages) {
142
- this.statusRef = (0, import_vue2.ref)("ready");
143
- this.errorRef = (0, import_vue2.ref)(void 0);
108
+ this.statusRef = ref2("ready");
109
+ this.errorRef = ref2(void 0);
144
110
  this.pushMessage = (message) => {
145
111
  this.messagesRef.value = [...this.messagesRef.value, message];
146
112
  };
@@ -151,7 +117,7 @@ var VueChatState = class {
151
117
  this.messagesRef.value[index] = { ...message };
152
118
  };
153
119
  this.snapshot = (value) => value;
154
- this.messagesRef = (0, import_vue2.ref)(messages != null ? messages : []);
120
+ this.messagesRef = ref2(messages != null ? messages : []);
155
121
  }
156
122
  get messages() {
157
123
  return this.messagesRef.value;
@@ -172,7 +138,7 @@ var VueChatState = class {
172
138
  this.errorRef.value = error;
173
139
  }
174
140
  };
175
- var Chat = class extends import_ai2.AbstractChat {
141
+ var Chat = class extends AbstractChat {
176
142
  constructor({ messages, ...init }) {
177
143
  super({
178
144
  ...init,
@@ -181,14 +147,110 @@ var Chat = class extends import_ai2.AbstractChat {
181
147
  }
182
148
  };
183
149
 
150
+ // src/use-chat.ts
151
+ import {
152
+ AbstractChat as AbstractChat2
153
+ } from "ai";
154
+ import {
155
+ computed,
156
+ shallowRef,
157
+ toValue,
158
+ triggerRef,
159
+ watch
160
+ } from "vue";
161
+ var VueChat = class extends AbstractChat2 {
162
+ constructor({
163
+ state,
164
+ ...init
165
+ }) {
166
+ super({
167
+ ...init,
168
+ state
169
+ });
170
+ }
171
+ };
172
+ function useChat(init) {
173
+ const messages = shallowRef([]);
174
+ const status = shallowRef("ready");
175
+ const error = shallowRef();
176
+ const chatStateWrapper = {
177
+ get messages() {
178
+ return messages.value;
179
+ },
180
+ set messages(messageList) {
181
+ messages.value = messageList;
182
+ },
183
+ get status() {
184
+ return status.value;
185
+ },
186
+ set status(statusValue) {
187
+ status.value = statusValue;
188
+ },
189
+ get error() {
190
+ return error.value;
191
+ },
192
+ set error(errorValue) {
193
+ error.value = errorValue;
194
+ },
195
+ pushMessage(message) {
196
+ messages.value.push(message);
197
+ triggerRef(messages);
198
+ },
199
+ popMessage() {
200
+ messages.value.pop();
201
+ triggerRef(messages);
202
+ },
203
+ replaceMessage(index, message) {
204
+ messages.value[index] = { ...message };
205
+ triggerRef(messages);
206
+ },
207
+ snapshot: (value) => value
208
+ };
209
+ const chatInstance = shallowRef();
210
+ watch(
211
+ () => toValue(init),
212
+ (opts) => {
213
+ var _a;
214
+ messages.value = (_a = opts == null ? void 0 : opts.messages) != null ? _a : [];
215
+ status.value = "ready";
216
+ error.value = void 0;
217
+ chatInstance.value = new VueChat({
218
+ ...opts,
219
+ state: chatStateWrapper
220
+ });
221
+ },
222
+ { immediate: true }
223
+ );
224
+ return {
225
+ id: computed(() => chatInstance.value.id),
226
+ status,
227
+ messages,
228
+ error,
229
+ addToolApprovalResponse: (opts) => chatInstance.value.addToolApprovalResponse(opts),
230
+ addToolOutput: (opts) => chatInstance.value.addToolOutput(opts),
231
+ clearError: () => chatInstance.value.clearError(),
232
+ regenerate: (opts) => chatInstance.value.regenerate(opts),
233
+ sendMessage: (...args) => chatInstance.value.sendMessage(...args),
234
+ stop: () => chatInstance.value.stop(),
235
+ resumeStream: (opts) => chatInstance.value.resumeStream(opts)
236
+ };
237
+ }
238
+
184
239
  // src/use-object.ts
185
- var import_provider_utils = require("@ai-sdk/provider-utils");
186
- var import_ai3 = require("ai");
187
- var import_swrv2 = __toESM(require("swrv"));
188
- var import_vue3 = require("vue");
240
+ import {
241
+ isAbortError,
242
+ safeValidateTypes
243
+ } from "@ai-sdk/provider-utils";
244
+ import {
245
+ asSchema,
246
+ isDeepEqualData,
247
+ parsePartialJson
248
+ } from "ai";
249
+ import swrv2 from "swrv";
250
+ import { ref as ref3 } from "vue";
189
251
  var getOriginalFetch = () => fetch;
190
252
  var uniqueId2 = 0;
191
- var useSWRV2 = import_swrv2.default.default || import_swrv2.default;
253
+ var useSWRV2 = swrv2.default || swrv2;
192
254
  var store2 = {};
193
255
  var experimental_useObject = function useObject({
194
256
  api,
@@ -215,7 +277,7 @@ var experimental_useObject = function useObject({
215
277
  store2[key] = value;
216
278
  return originalMutate();
217
279
  };
218
- const error = (0, import_vue3.ref)(void 0);
280
+ const error = ref3(void 0);
219
281
  let abortController = null;
220
282
  const stop = async () => {
221
283
  if (abortController) {
@@ -268,9 +330,9 @@ var experimental_useObject = function useObject({
268
330
  new WritableStream({
269
331
  async write(chunk) {
270
332
  accumulatedText += chunk;
271
- const { value } = await (0, import_ai3.parsePartialJson)(accumulatedText);
333
+ const { value } = await parsePartialJson(accumulatedText);
272
334
  const currentObject = value;
273
- if (!(0, import_ai3.isDeepEqualData)(latestObject, currentObject)) {
335
+ if (!isDeepEqualData(latestObject, currentObject)) {
274
336
  latestObject = currentObject;
275
337
  await mutateObject(currentObject);
276
338
  }
@@ -279,9 +341,9 @@ var experimental_useObject = function useObject({
279
341
  await mutateLoading(() => false);
280
342
  abortController = null;
281
343
  if (onFinish) {
282
- const validationResult = await (0, import_provider_utils.safeValidateTypes)({
344
+ const validationResult = await safeValidateTypes({
283
345
  value: latestObject,
284
- schema: (0, import_ai3.asSchema)(schema)
346
+ schema: asSchema(schema)
285
347
  });
286
348
  onFinish(
287
349
  validationResult.success ? {
@@ -294,7 +356,7 @@ var experimental_useObject = function useObject({
294
356
  })
295
357
  );
296
358
  } catch (err) {
297
- if ((0, import_provider_utils.isAbortError)(err))
359
+ if (isAbortError(err))
298
360
  return;
299
361
  if (onError && err instanceof Error)
300
362
  onError(err);
@@ -311,10 +373,10 @@ var experimental_useObject = function useObject({
311
373
  clear
312
374
  };
313
375
  };
314
- // Annotate the CommonJS export names for ESM import in node:
315
- 0 && (module.exports = {
376
+ export {
316
377
  Chat,
317
378
  experimental_useObject,
379
+ useChat,
318
380
  useCompletion
319
- });
381
+ };
320
382
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/use-completion.ts","../src/chat.vue.ts","../src/use-object.ts"],"sourcesContent":["export * from './use-completion';\nexport { Chat } from './chat.vue';\nexport * from './use-object';\n","import type { CompletionRequestOptions, UseCompletionOptions } from 'ai';\nimport { callCompletionApi } from 'ai';\nimport swrv from 'swrv';\nimport type { Ref } from 'vue';\nimport { ref, unref } from 'vue';\n\nexport type { UseCompletionOptions };\n\nexport type UseCompletionHelpers = {\n /** The current completion result */\n completion: Ref<string>;\n /** The error object of the API request */\n error: Ref<undefined | Error>;\n /**\n * Send a new prompt to the API endpoint and update the completion state.\n */\n complete: (\n prompt: string,\n options?: CompletionRequestOptions,\n ) => Promise<string | null | undefined>;\n /**\n * Abort the current API request but keep the generated tokens.\n */\n stop: () => void;\n /**\n * Update the `completion` state locally.\n */\n setCompletion: (completion: string) => void;\n /** The current value of the input */\n input: Ref<string>;\n /**\n * Form submission handler to automatically reset input and append a user message\n * @example\n * ```jsx\n * <form @submit=\"handleSubmit\">\n * <input @change=\"handleInputChange\" v-model=\"input\" />\n * </form>\n * ```\n */\n handleSubmit: (event?: { preventDefault?: () => void }) => void;\n /** Whether the API request is in progress */\n isLoading: Ref<boolean | undefined>;\n};\n\nlet uniqueId = 0;\n\n// @ts-expect-error - some issues with the default export of useSWRV\nconst useSWRV = (swrv.default as (typeof import('swrv'))['default']) || swrv;\nconst store: Record<string, any> = {};\n\nexport function useCompletion({\n api = '/api/completion',\n id,\n initialCompletion = '',\n initialInput = '',\n credentials,\n headers,\n body,\n streamProtocol,\n onFinish,\n onError,\n fetch,\n}: UseCompletionOptions = {}): UseCompletionHelpers {\n // Generate an unique id for the completion if not provided.\n const completionId = id || `completion-${uniqueId++}`;\n\n const key = `${api}|${completionId}`;\n const { data, mutate: originalMutate } = useSWRV<string>(\n key,\n () => store[key] || initialCompletion,\n );\n\n const { data: isLoading, mutate: mutateLoading } = useSWRV<boolean>(\n `${completionId}-loading`,\n null,\n );\n\n isLoading.value ??= false;\n\n // Force the `data` to be `initialCompletion` if it's `undefined`.\n data.value ||= initialCompletion;\n\n const mutate = (data: string) => {\n store[key] = data;\n return originalMutate();\n };\n\n // Because of the `initialData` option, the `data` will never be `undefined`.\n const completion = data as Ref<string>;\n\n const error = ref<undefined | Error>(undefined);\n\n let abortController: AbortController | null = null;\n\n async function triggerRequest(\n prompt: string,\n options?: CompletionRequestOptions,\n ) {\n return callCompletionApi({\n api,\n prompt,\n credentials,\n headers: {\n ...headers,\n ...options?.headers,\n },\n body: {\n ...unref(body),\n ...options?.body,\n },\n streamProtocol,\n setCompletion: mutate,\n setLoading: loading => mutateLoading(() => loading),\n setError: err => {\n error.value = err;\n },\n setAbortController: controller => {\n abortController = controller;\n },\n onFinish,\n onError,\n fetch,\n });\n }\n\n const complete: UseCompletionHelpers['complete'] = async (\n prompt,\n options,\n ) => {\n return triggerRequest(prompt, options);\n };\n\n const stop = () => {\n if (abortController) {\n abortController.abort();\n abortController = null;\n }\n };\n\n const setCompletion = (completion: string) => {\n mutate(completion);\n };\n\n const input = ref(initialInput);\n\n const handleSubmit = (event?: { preventDefault?: () => void }) => {\n event?.preventDefault?.();\n const inputValue = input.value;\n return inputValue ? complete(inputValue) : undefined;\n };\n\n return {\n completion,\n complete,\n error,\n stop,\n setCompletion,\n input,\n handleSubmit,\n isLoading,\n };\n}\n","import {\n AbstractChat,\n ChatInit as BaseChatInit,\n ChatState,\n ChatStatus,\n UIMessage,\n} from 'ai';\nimport { Ref, ref } from 'vue';\n\nclass VueChatState<UI_MESSAGE extends UIMessage>\n implements ChatState<UI_MESSAGE>\n{\n private messagesRef: Ref<UI_MESSAGE[]>;\n private statusRef = ref<ChatStatus>('ready');\n private errorRef = ref<Error | undefined>(undefined);\n\n constructor(messages?: UI_MESSAGE[]) {\n this.messagesRef = ref(messages ?? []) as Ref<UI_MESSAGE[]>;\n }\n\n get messages(): UI_MESSAGE[] {\n return this.messagesRef.value;\n }\n\n set messages(messages: UI_MESSAGE[]) {\n this.messagesRef.value = messages;\n }\n\n get status(): ChatStatus {\n return this.statusRef.value;\n }\n\n set status(status: ChatStatus) {\n this.statusRef.value = status;\n }\n\n get error(): Error | undefined {\n return this.errorRef.value;\n }\n\n set error(error: Error | undefined) {\n this.errorRef.value = error;\n }\n\n pushMessage = (message: UI_MESSAGE) => {\n this.messagesRef.value = [...this.messagesRef.value, message];\n };\n\n popMessage = () => {\n this.messagesRef.value = this.messagesRef.value.slice(0, -1);\n };\n\n replaceMessage = (index: number, message: UI_MESSAGE) => {\n // message is cloned here because vue's deep reactivity shows unexpected behavior, particularly when updating tool invocation parts\n this.messagesRef.value[index] = { ...message };\n };\n\n snapshot = <T>(value: T): T => value;\n}\n\nexport class Chat<\n UI_MESSAGE extends UIMessage,\n> extends AbstractChat<UI_MESSAGE> {\n constructor({ messages, ...init }: BaseChatInit<UI_MESSAGE>) {\n super({\n ...init,\n state: new VueChatState(messages),\n });\n }\n}\n","import {\n isAbortError,\n safeValidateTypes,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport {\n asSchema,\n isDeepEqualData,\n parsePartialJson,\n type DeepPartial,\n type FlexibleSchema,\n type InferSchema,\n} from 'ai';\nimport swrv from 'swrv';\nimport { ref, type Ref } from 'vue';\n\n// use function to allow for mocking in tests\nconst getOriginalFetch = () => fetch;\n\nexport type Experimental_UseObjectOptions<\n SCHEMA extends FlexibleSchema,\n RESULT,\n> = {\n /** API endpoint that streams JSON chunks matching the schema */\n api: string;\n\n /** Schema that defines the final object shape */\n schema: SCHEMA;\n\n /** Shared state key. If omitted a random one is generated */\n id?: string;\n\n /** Initial partial value */\n initialValue?: DeepPartial<RESULT>;\n\n /** Optional custom fetch implementation */\n fetch?: FetchFunction;\n\n /** Called when stream ends */\n onFinish?: (event: {\n object: RESULT | undefined;\n error: Error | undefined;\n }) => Promise<void> | void;\n\n /** Called on error */\n onError?: (error: Error) => void;\n\n /** Extra request headers */\n headers?: Record<string, string> | Headers;\n\n /** Request credentials mode. Defaults to 'same-origin' if omitted */\n credentials?: RequestCredentials;\n};\n\nexport type Experimental_UseObjectHelpers<RESULT, INPUT> = {\n /** POST the input and start streaming */\n submit: (input: INPUT) => void;\n\n /** Current partial object, updated as chunks arrive */\n object: Ref<DeepPartial<RESULT> | undefined>;\n\n /** Latest error if any */\n error: Ref<Error | undefined>;\n\n /** Loading flag for the in-flight request */\n isLoading: Ref<boolean | undefined>;\n\n /** Abort the current request. Keeps current partial object. */\n stop: () => void;\n\n /** Abort and clear all state */\n clear: () => void;\n};\n\nlet uniqueId = 0;\n\n// @ts-expect-error - some issues with the default export of useSWRV\nconst useSWRV = (swrv.default as (typeof import('swrv'))['default']) || swrv;\nconst store: Record<string, any> = {};\n\nexport const experimental_useObject = function useObject<\n SCHEMA extends FlexibleSchema,\n RESULT = InferSchema<SCHEMA>,\n INPUT = any,\n>({\n api,\n id,\n schema,\n initialValue,\n fetch,\n onError,\n onFinish,\n headers,\n credentials,\n}: Experimental_UseObjectOptions<\n SCHEMA,\n RESULT\n>): Experimental_UseObjectHelpers<RESULT, INPUT> {\n // Generate an unique id for the object if not provided.\n const completionId = id || `completion-${uniqueId++}`;\n\n const key = `${api}|${completionId}`;\n const { data, mutate: originalMutate } = useSWRV<\n DeepPartial<RESULT> | undefined\n >(key, () => (key in store ? store[key] : initialValue));\n\n const { data: isLoading, mutate: mutateLoading } = useSWRV<boolean>(\n `${completionId}-loading`,\n null,\n );\n\n isLoading.value ??= false;\n data.value ||= initialValue as DeepPartial<RESULT> | undefined;\n\n const mutateObject = (value: DeepPartial<RESULT> | undefined) => {\n store[key] = value;\n return originalMutate();\n };\n\n const error = ref<Error | undefined>(undefined);\n let abortController: AbortController | null = null;\n\n const stop = async () => {\n if (abortController) {\n try {\n abortController.abort();\n } catch {\n // ignore\n } finally {\n abortController = null;\n }\n }\n await mutateLoading(() => false);\n };\n\n const clearObject = async () => {\n error.value = undefined;\n await mutateLoading(() => false);\n await mutateObject(undefined);\n // Need to explicitly set the value to undefined to trigger a re-render\n data.value = undefined;\n };\n\n const clear = async () => {\n await stop();\n await clearObject();\n };\n\n const submit = async (input: INPUT) => {\n try {\n await clearObject();\n await mutateLoading(() => true);\n\n abortController = new AbortController();\n\n const actualFetch = fetch ?? getOriginalFetch();\n const response = await actualFetch(api, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(headers as any),\n },\n credentials: credentials ?? 'same-origin',\n signal: abortController.signal,\n body: JSON.stringify(input),\n });\n\n if (!response.ok) {\n throw new Error(\n (await response.text()) || 'Failed to fetch the response.',\n );\n }\n\n if (!response.body) {\n throw new Error('The response body is empty.');\n }\n\n let accumulatedText = '';\n let latestObject: DeepPartial<RESULT> | undefined = undefined;\n\n await response.body.pipeThrough(new TextDecoderStream()).pipeTo(\n new WritableStream<string>({\n async write(chunk) {\n accumulatedText += chunk;\n const { value } = await parsePartialJson(accumulatedText);\n const currentObject = value as DeepPartial<RESULT>;\n if (!isDeepEqualData(latestObject, currentObject)) {\n latestObject = currentObject;\n await mutateObject(currentObject);\n }\n },\n async close() {\n await mutateLoading(() => false);\n abortController = null;\n\n if (onFinish) {\n const validationResult = await safeValidateTypes({\n value: latestObject,\n schema: asSchema(schema),\n });\n\n onFinish(\n validationResult.success\n ? {\n object: validationResult.value as RESULT,\n error: undefined,\n }\n : { object: undefined, error: validationResult.error },\n );\n }\n },\n }),\n );\n } catch (err: unknown) {\n if (isAbortError(err)) return;\n\n if (onError && err instanceof Error) onError(err);\n\n await mutateLoading(() => false);\n error.value = err instanceof Error ? err : new Error(String(err));\n }\n };\n\n return {\n submit,\n object: data,\n error,\n isLoading,\n stop,\n clear,\n };\n};\n"],"mappings":"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","names":["swrv","fetch","data","completion","_a","import_ai","import_vue","import_ai","import_swrv","import_vue","uniqueId","useSWRV","swrv","store","fetch"]}
1
+ {"version":3,"sources":["../src/use-completion.ts","../src/chat.vue.ts","../src/use-chat.ts","../src/use-object.ts"],"sourcesContent":["import {\n callCompletionApi,\n type CompletionRequestOptions,\n type UseCompletionOptions,\n} from 'ai';\nimport type * as SwrvModule from 'swrv';\nimport swrv from 'swrv';\nimport { ref, unref, type Ref } from 'vue';\nexport type { UseCompletionOptions };\n\nexport type UseCompletionHelpers = {\n /** The current completion result */\n completion: Ref<string>;\n /** The error object of the API request */\n error: Ref<undefined | Error>;\n /**\n * Send a new prompt to the API endpoint and update the completion state.\n */\n complete: (\n prompt: string,\n options?: CompletionRequestOptions,\n ) => Promise<string | null | undefined>;\n /**\n * Abort the current API request but keep the generated tokens.\n */\n stop: () => void;\n /**\n * Update the `completion` state locally.\n */\n setCompletion: (completion: string) => void;\n /** The current value of the input */\n input: Ref<string>;\n /**\n * Form submission handler to automatically reset input and append a user message\n * @example\n * ```jsx\n * <form @submit=\"handleSubmit\">\n * <input @change=\"handleInputChange\" v-model=\"input\" />\n * </form>\n * ```\n */\n handleSubmit: (event?: { preventDefault?: () => void }) => void;\n /** Whether the API request is in progress */\n isLoading: Ref<boolean | undefined>;\n};\n\nlet uniqueId = 0;\n\n// @ts-expect-error - some issues with the default export of useSWRV\nconst useSWRV = (swrv.default as (typeof SwrvModule)['default']) || swrv;\nconst store: Record<string, any> = {};\n\nexport function useCompletion({\n api = '/api/completion',\n id,\n initialCompletion = '',\n initialInput = '',\n credentials,\n headers,\n body,\n streamProtocol,\n onFinish,\n onError,\n fetch,\n}: UseCompletionOptions = {}): UseCompletionHelpers {\n // Generate an unique id for the completion if not provided.\n const completionId = id || `completion-${uniqueId++}`;\n\n const key = `${api}|${completionId}`;\n const { data, mutate: originalMutate } = useSWRV<string>(\n key,\n () => store[key] || initialCompletion,\n );\n\n const { data: isLoading, mutate: mutateLoading } = useSWRV<boolean>(\n `${completionId}-loading`,\n null,\n );\n\n isLoading.value ??= false;\n\n // Force the `data` to be `initialCompletion` if it's `undefined`.\n data.value ||= initialCompletion;\n\n const mutate = (data: string) => {\n store[key] = data;\n return originalMutate();\n };\n\n // Because of the `initialData` option, the `data` will never be `undefined`.\n const completion = data as Ref<string>;\n\n const error = ref<undefined | Error>(undefined);\n\n let abortController: AbortController | null = null;\n\n async function triggerRequest(\n prompt: string,\n options?: CompletionRequestOptions,\n ) {\n return callCompletionApi({\n api,\n prompt,\n credentials,\n headers: {\n ...headers,\n ...options?.headers,\n },\n body: {\n ...unref(body),\n ...options?.body,\n },\n streamProtocol,\n setCompletion: mutate,\n setLoading: loading => mutateLoading(() => loading),\n setError: err => {\n error.value = err;\n },\n setAbortController: controller => {\n abortController = controller;\n },\n onFinish,\n onError,\n fetch,\n });\n }\n\n const complete: UseCompletionHelpers['complete'] = async (\n prompt,\n options,\n ) => {\n return triggerRequest(prompt, options);\n };\n\n const stop = () => {\n if (abortController) {\n abortController.abort();\n abortController = null;\n }\n };\n\n const setCompletion = (completion: string) => {\n mutate(completion);\n };\n\n const input = ref(initialInput);\n\n const handleSubmit = (event?: { preventDefault?: () => void }) => {\n event?.preventDefault?.();\n const inputValue = input.value;\n return inputValue ? complete(inputValue) : undefined;\n };\n\n return {\n completion,\n complete,\n error,\n stop,\n setCompletion,\n input,\n handleSubmit,\n isLoading,\n };\n}\n","import {\n AbstractChat,\n type ChatInit,\n type ChatState,\n type ChatStatus,\n type UIMessage,\n} from 'ai';\nimport { ref, type Ref } from 'vue';\nclass VueChatState<\n UI_MESSAGE extends UIMessage,\n> implements ChatState<UI_MESSAGE> {\n private messagesRef: Ref<UI_MESSAGE[]>;\n private statusRef = ref<ChatStatus>('ready');\n private errorRef = ref<Error | undefined>(undefined);\n\n constructor(messages?: UI_MESSAGE[]) {\n this.messagesRef = ref(messages ?? []) as Ref<UI_MESSAGE[]>;\n }\n\n get messages(): UI_MESSAGE[] {\n return this.messagesRef.value;\n }\n\n set messages(messages: UI_MESSAGE[]) {\n this.messagesRef.value = messages;\n }\n\n get status(): ChatStatus {\n return this.statusRef.value;\n }\n\n set status(status: ChatStatus) {\n this.statusRef.value = status;\n }\n\n get error(): Error | undefined {\n return this.errorRef.value;\n }\n\n set error(error: Error | undefined) {\n this.errorRef.value = error;\n }\n\n pushMessage = (message: UI_MESSAGE) => {\n this.messagesRef.value = [...this.messagesRef.value, message];\n };\n\n popMessage = () => {\n this.messagesRef.value = this.messagesRef.value.slice(0, -1);\n };\n\n replaceMessage = (index: number, message: UI_MESSAGE) => {\n // message is cloned here because vue's deep reactivity shows unexpected behavior, particularly when updating tool invocation parts\n this.messagesRef.value[index] = { ...message };\n };\n\n snapshot = <T>(value: T): T => value;\n}\n\n/**\n * @deprecated Use the {@link useChat} composable instead. It exposes reactive\n * refs and automatically recreates the chat when its init object changes.\n */\nexport class Chat<\n UI_MESSAGE extends UIMessage,\n> extends AbstractChat<UI_MESSAGE> {\n constructor({ messages, ...init }: ChatInit<UI_MESSAGE>) {\n super({\n ...init,\n state: new VueChatState(messages),\n });\n }\n}\n","import {\n AbstractChat,\n type ChatInit as BaseChatInit,\n type ChatInit,\n type ChatState,\n type ChatStatus,\n type UIMessage,\n} from 'ai';\nimport {\n computed,\n shallowRef,\n toValue,\n triggerRef,\n watch,\n type ComputedRef,\n type MaybeRefOrGetter,\n type ShallowRef,\n} from 'vue';\n\n/**\n * @internal\n */\nexport class VueChat<\n UI_MESSAGE extends UIMessage,\n> extends AbstractChat<UI_MESSAGE> {\n constructor({\n state,\n ...init\n }: Omit<ChatInit<UI_MESSAGE>, 'messages'> & {\n state: ChatState<UI_MESSAGE>;\n }) {\n super({\n ...init,\n state,\n });\n }\n}\n\n/**\n * Return type of the {@link useChat} composable, which includes the chat\n * instance methods and reactive properties for messages, status, and error.\n */\nexport interface UseChatHelpers<UI_MESSAGE extends UIMessage> extends Pick<\n AbstractChat<UI_MESSAGE>,\n | 'sendMessage'\n | 'regenerate'\n | 'stop'\n | 'resumeStream'\n | 'addToolOutput'\n | 'addToolApprovalResponse'\n | 'clearError'\n> {\n /**\n * The id of the chat.\n */\n id: ComputedRef<string>;\n\n /**\n * The current error state of the chat, if any.\n */\n error: ShallowRef<Error | undefined>;\n\n /**\n * The current status of the chat, which can be 'ready', 'generating', 'streaming', or 'error'.\n */\n status: ShallowRef<ChatStatus>;\n\n /**\n * The list of messages in the chat, which can be updated by the chat instance methods or directly by setting this property.\n */\n messages: ShallowRef<UI_MESSAGE[]>;\n}\n\n/**\n * Composable to access messages, status, and other chat properties and\n * methods. Accepts an optional reactive initial configuration object\n *\n * @example\n *\n * ```ts\n * // passing a getter if any reactive properties are used within\n * // the init object\n * const { messages, sendMessage } = useChat(() => ({\n * // ...\n * })\n * ```\n *\n * @see BaseChatInit\n */\nexport function useChat<UI_MESSAGE extends UIMessage = UIMessage>(\n init?: MaybeRefOrGetter<BaseChatInit<UI_MESSAGE>>,\n): UseChatHelpers<UI_MESSAGE> {\n const messages = shallowRef<UI_MESSAGE[]>([]);\n const status = shallowRef<ChatStatus>('ready');\n const error = shallowRef<Error | undefined>();\n\n // this wrapper doesn't need to be reactive and can be reused across chat\n // instance changes, because the inner refs are reactive and the wrapper\n // methods trigger updates when needed\n const chatStateWrapper = {\n get messages(): UI_MESSAGE[] {\n return messages.value;\n },\n\n set messages(messageList: UI_MESSAGE[]) {\n messages.value = messageList;\n },\n\n get status(): ChatStatus {\n return status.value;\n },\n\n set status(statusValue: ChatStatus) {\n status.value = statusValue;\n },\n\n get error(): Error | undefined {\n return error.value;\n },\n\n set error(errorValue: Error | undefined) {\n error.value = errorValue;\n },\n\n pushMessage(message: UI_MESSAGE) {\n messages.value.push(message);\n // needed because messagesRef is a shallowRef\n triggerRef(messages);\n },\n\n popMessage() {\n messages.value.pop();\n triggerRef(messages);\n },\n\n replaceMessage(index: number, message: UI_MESSAGE) {\n // message is cloned here because vue's deep reactivity shows unexpected behavior, particularly when updating tool invocation parts\n messages.value[index] = { ...message };\n triggerRef(messages);\n },\n\n snapshot: <T>(value: T): T => value,\n } satisfies ChatState<UI_MESSAGE>;\n\n // the instance is created right away thanks to immediate: true. We do it this\n // way instead of a computed to ensure all changes to reactive state happen\n // in the same tick\n const chatInstance = shallowRef<VueChat<UI_MESSAGE>>() as ShallowRef<\n VueChat<UI_MESSAGE>\n >;\n\n watch(\n () => toValue(init),\n opts => {\n // reset the initial state\n messages.value = opts?.messages ?? [];\n status.value = 'ready';\n error.value = undefined;\n\n chatInstance.value = new VueChat<UI_MESSAGE>({\n ...opts,\n state: chatStateWrapper,\n });\n },\n { immediate: true },\n );\n\n return {\n id: computed(() => chatInstance.value.id),\n status,\n messages,\n error,\n addToolApprovalResponse: opts =>\n chatInstance.value.addToolApprovalResponse(opts),\n addToolOutput: opts => chatInstance.value.addToolOutput(opts),\n clearError: () => chatInstance.value.clearError(),\n regenerate: opts => chatInstance.value.regenerate(opts),\n sendMessage: (...args) => chatInstance.value.sendMessage(...args),\n stop: () => chatInstance.value.stop(),\n resumeStream: opts => chatInstance.value.resumeStream(opts),\n };\n}\n","import {\n isAbortError,\n safeValidateTypes,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport {\n asSchema,\n isDeepEqualData,\n parsePartialJson,\n type DeepPartial,\n type FlexibleSchema,\n type InferSchema,\n} from 'ai';\nimport type * as SwrvModule from 'swrv';\nimport swrv from 'swrv';\nimport { ref, type Ref } from 'vue';\n// use function to allow for mocking in tests\nconst getOriginalFetch = () => fetch;\n\nexport type Experimental_UseObjectOptions<\n SCHEMA extends FlexibleSchema,\n RESULT,\n> = {\n /** API endpoint that streams JSON chunks matching the schema */\n api: string;\n\n /** Schema that defines the final object shape */\n schema: SCHEMA;\n\n /** Shared state key. If omitted a random one is generated */\n id?: string;\n\n /** Initial partial value */\n initialValue?: DeepPartial<RESULT>;\n\n /** Optional custom fetch implementation */\n fetch?: FetchFunction;\n\n /** Called when stream ends */\n onFinish?: (event: {\n object: RESULT | undefined;\n error: Error | undefined;\n }) => Promise<void> | void;\n\n /** Called on error */\n onError?: (error: Error) => void;\n\n /** Extra request headers */\n headers?: Record<string, string> | Headers;\n\n /** Request credentials mode. Defaults to 'same-origin' if omitted */\n credentials?: RequestCredentials;\n};\n\nexport type Experimental_UseObjectHelpers<RESULT, INPUT> = {\n /** POST the input and start streaming */\n submit: (input: INPUT) => void;\n\n /** Current partial object, updated as chunks arrive */\n object: Ref<DeepPartial<RESULT> | undefined>;\n\n /** Latest error if any */\n error: Ref<Error | undefined>;\n\n /** Loading flag for the in-flight request */\n isLoading: Ref<boolean | undefined>;\n\n /** Abort the current request. Keeps current partial object. */\n stop: () => void;\n\n /** Abort and clear all state */\n clear: () => void;\n};\n\nlet uniqueId = 0;\n\n// @ts-expect-error - some issues with the default export of useSWRV\nconst useSWRV = (swrv.default as (typeof SwrvModule)['default']) || swrv;\nconst store: Record<string, any> = {};\n\nexport const experimental_useObject = function useObject<\n SCHEMA extends FlexibleSchema,\n RESULT = InferSchema<SCHEMA>,\n INPUT = any,\n>({\n api,\n id,\n schema,\n initialValue,\n fetch,\n onError,\n onFinish,\n headers,\n credentials,\n}: Experimental_UseObjectOptions<\n SCHEMA,\n RESULT\n>): Experimental_UseObjectHelpers<RESULT, INPUT> {\n // Generate an unique id for the object if not provided.\n const completionId = id || `completion-${uniqueId++}`;\n\n const key = `${api}|${completionId}`;\n const { data, mutate: originalMutate } = useSWRV<\n DeepPartial<RESULT> | undefined\n >(key, () => (key in store ? store[key] : initialValue));\n\n const { data: isLoading, mutate: mutateLoading } = useSWRV<boolean>(\n `${completionId}-loading`,\n null,\n );\n\n isLoading.value ??= false;\n data.value ||= initialValue as DeepPartial<RESULT> | undefined;\n\n const mutateObject = (value: DeepPartial<RESULT> | undefined) => {\n store[key] = value;\n return originalMutate();\n };\n\n const error = ref<Error | undefined>(undefined);\n let abortController: AbortController | null = null;\n\n const stop = async () => {\n if (abortController) {\n try {\n abortController.abort();\n } catch {\n // ignore\n } finally {\n abortController = null;\n }\n }\n await mutateLoading(() => false);\n };\n\n const clearObject = async () => {\n error.value = undefined;\n await mutateLoading(() => false);\n await mutateObject(undefined);\n // Need to explicitly set the value to undefined to trigger a re-render\n data.value = undefined;\n };\n\n const clear = async () => {\n await stop();\n await clearObject();\n };\n\n const submit = async (input: INPUT) => {\n try {\n await clearObject();\n await mutateLoading(() => true);\n\n abortController = new AbortController();\n\n const actualFetch = fetch ?? getOriginalFetch();\n const response = await actualFetch(api, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(headers as any),\n },\n credentials: credentials ?? 'same-origin',\n signal: abortController.signal,\n body: JSON.stringify(input),\n });\n\n if (!response.ok) {\n throw new Error(\n (await response.text()) || 'Failed to fetch the response.',\n );\n }\n\n if (!response.body) {\n throw new Error('The response body is empty.');\n }\n\n let accumulatedText = '';\n let latestObject: DeepPartial<RESULT> | undefined = undefined;\n\n await response.body.pipeThrough(new TextDecoderStream()).pipeTo(\n new WritableStream<string>({\n async write(chunk) {\n accumulatedText += chunk;\n const { value } = await parsePartialJson(accumulatedText);\n const currentObject = value as DeepPartial<RESULT>;\n if (!isDeepEqualData(latestObject, currentObject)) {\n latestObject = currentObject;\n await mutateObject(currentObject);\n }\n },\n async close() {\n await mutateLoading(() => false);\n abortController = null;\n\n if (onFinish) {\n const validationResult = await safeValidateTypes({\n value: latestObject,\n schema: asSchema(schema),\n });\n\n onFinish(\n validationResult.success\n ? {\n object: validationResult.value as RESULT,\n error: undefined,\n }\n : { object: undefined, error: validationResult.error },\n );\n }\n },\n }),\n );\n } catch (err: unknown) {\n if (isAbortError(err)) return;\n\n if (onError && err instanceof Error) onError(err);\n\n await mutateLoading(() => false);\n error.value = err instanceof Error ? err : new Error(String(err));\n }\n };\n\n return {\n submit,\n object: data,\n error,\n isLoading,\n stop,\n clear,\n };\n};\n"],"mappings":"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","names":["fetch","data","completion","_a","ref","AbstractChat","swrv","ref","uniqueId","useSWRV","store","fetch"]}
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@ai-sdk/vue",
3
- "version": "4.0.0-beta.15",
3
+ "version": "4.0.0-beta.177",
4
+ "type": "module",
4
5
  "license": "Apache-2.0",
5
6
  "sideEffects": false,
6
7
  "main": "./dist/index.js",
7
- "module": "./dist/index.mjs",
8
8
  "types": "./dist/index.d.ts",
9
9
  "exports": {
10
10
  "./package.json": "./package.json",
11
11
  ".": {
12
12
  "types": "./dist/index.d.ts",
13
- "import": "./dist/index.mjs",
14
- "require": "./dist/index.js"
13
+ "import": "./dist/index.js",
14
+ "default": "./dist/index.js"
15
15
  }
16
16
  },
17
17
  "files": [
@@ -26,40 +26,40 @@
26
26
  "README.md"
27
27
  ],
28
28
  "dependencies": {
29
- "swrv": "^1.0.4",
30
- "@ai-sdk/provider-utils": "5.0.0-beta.1",
31
- "ai": "7.0.0-beta.15"
29
+ "swrv": "^1.2.0",
30
+ "@ai-sdk/provider-utils": "5.0.0-beta.49",
31
+ "ai": "7.0.0-beta.177"
32
32
  },
33
33
  "devDependencies": {
34
- "@testing-library/jest-dom": "^6.6.3",
35
- "@testing-library/user-event": "^14.5.2",
34
+ "@testing-library/jest-dom": "^6.9.1",
35
+ "@testing-library/user-event": "^14.6.1",
36
36
  "@testing-library/vue": "^8.1.0",
37
- "@types/node": "20.17.24",
37
+ "@types/node": "22.19.19",
38
38
  "@vitejs/plugin-vue": "5.2.0",
39
- "eslint": "8.57.1",
40
- "jsdom": "^24.0.0",
39
+ "jsdom": "^24.1.3",
41
40
  "msw": "2.6.4",
42
41
  "tsup": "^7.2.0",
43
42
  "typescript": "5.8.3",
44
- "vitest": "2.1.4",
43
+ "vitest": "4.1.5",
45
44
  "zod": "3.25.76",
46
- "@ai-sdk/test-server": "2.0.0-beta.0",
47
- "@vercel/ai-tsconfig": "0.0.0",
48
- "eslint-config-vercel-ai": "0.0.0"
45
+ "@ai-sdk/test-server": "2.0.0-beta.7",
46
+ "@vercel/ai-tsconfig": "0.0.0"
49
47
  },
50
48
  "peerDependencies": {
51
49
  "vue": "^3.3.4"
52
50
  },
53
51
  "engines": {
54
- "node": ">=18"
52
+ "node": ">=22"
55
53
  },
56
54
  "publishConfig": {
57
- "access": "public"
55
+ "access": "public",
56
+ "provenance": true
58
57
  },
59
58
  "homepage": "https://ai-sdk.dev/docs",
60
59
  "repository": {
61
60
  "type": "git",
62
- "url": "git+https://github.com/vercel/ai.git"
61
+ "url": "https://github.com/vercel/ai",
62
+ "directory": "packages/vue"
63
63
  },
64
64
  "bugs": {
65
65
  "url": "https://github.com/vercel/ai/issues"
@@ -72,9 +72,7 @@
72
72
  "build": "pnpm clean && tsup --tsconfig tsconfig.build.json",
73
73
  "build:watch": "pnpm clean && tsup --watch",
74
74
  "clean": "del-cli dist *.tsbuildinfo",
75
- "lint": "eslint \"./**/*.ts*\"",
76
75
  "type-check": "tsc --build",
77
- "prettier-check": "prettier --check \"./**/*.ts*\"",
78
76
  "test": "vitest --config vitest.config.js --run",
79
77
  "test:update": "vitest --config vitest.config.js --run -u",
80
78
  "test:watch": "vitest --config vitest.config.js"
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { UIMessage } from 'ai';
2
+ import type { UIMessage } from 'ai';
3
3
  import { reactive } from 'vue';
4
4
  import { Chat } from './chat.vue';
5
5
 
@@ -1,11 +1,19 @@
1
1
  <script setup lang="ts">
2
- import { UIMessage } from 'ai';
2
+ import type { UIMessage } from 'ai';
3
3
  import { Chat } from './chat.vue';
4
4
  import { ref } from 'vue';
5
5
 
6
6
  const messages = ref<UIMessage[]>([
7
- { id: 'message-0', role: 'user', parts: [{ type: 'text', text: 'Greetings.' }] },
8
- { id: 'message-1', role: 'assistant', parts: [{ type: 'text', text: 'Hello.' }] },
7
+ {
8
+ id: 'message-0',
9
+ role: 'user',
10
+ parts: [{ type: 'text', text: 'Greetings.' }],
11
+ },
12
+ {
13
+ id: 'message-1',
14
+ role: 'assistant',
15
+ parts: [{ type: 'text', text: 'Hello.' }],
16
+ },
9
17
  ]);
10
18
 
11
19
  const chat = new Chat({
@@ -28,6 +36,9 @@ const chat = new Chat({
28
36
  }}
29
37
  </div>
30
38
 
31
- <button data-testid="do-append" @click="chat.sendMessage({ text: 'Hi.' })" />
39
+ <button
40
+ data-testid="do-append"
41
+ @click="chat.sendMessage({ text: 'Hi.' })"
42
+ />
32
43
  </div>
33
44
  </template>
@@ -1,8 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { reactive } from 'vue';
3
- import { TextStreamChatTransport } from 'ai';
3
+ import { TextStreamChatTransport, type UIMessage } from 'ai';
4
4
  import { Chat } from './chat.vue';
5
- import { UIMessage } from 'ai';
6
5
 
7
6
  const onFinishCalls: Array<{ message: UIMessage }> = reactive([]);
8
7
 
package/src/chat.vue.ts CHANGED
@@ -1,15 +1,14 @@
1
1
  import {
2
2
  AbstractChat,
3
- ChatInit as BaseChatInit,
4
- ChatState,
5
- ChatStatus,
6
- UIMessage,
3
+ type ChatInit,
4
+ type ChatState,
5
+ type ChatStatus,
6
+ type UIMessage,
7
7
  } from 'ai';
8
- import { Ref, ref } from 'vue';
9
-
10
- class VueChatState<UI_MESSAGE extends UIMessage>
11
- implements ChatState<UI_MESSAGE>
12
- {
8
+ import { ref, type Ref } from 'vue';
9
+ class VueChatState<
10
+ UI_MESSAGE extends UIMessage,
11
+ > implements ChatState<UI_MESSAGE> {
13
12
  private messagesRef: Ref<UI_MESSAGE[]>;
14
13
  private statusRef = ref<ChatStatus>('ready');
15
14
  private errorRef = ref<Error | undefined>(undefined);
@@ -58,10 +57,14 @@ class VueChatState<UI_MESSAGE extends UIMessage>
58
57
  snapshot = <T>(value: T): T => value;
59
58
  }
60
59
 
60
+ /**
61
+ * @deprecated Use the {@link useChat} composable instead. It exposes reactive
62
+ * refs and automatically recreates the chat when its init object changes.
63
+ */
61
64
  export class Chat<
62
65
  UI_MESSAGE extends UIMessage,
63
66
  > extends AbstractChat<UI_MESSAGE> {
64
- constructor({ messages, ...init }: BaseChatInit<UI_MESSAGE>) {
67
+ constructor({ messages, ...init }: ChatInit<UI_MESSAGE>) {
65
68
  super({
66
69
  ...init,
67
70
  state: new VueChatState(messages),
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './use-completion';
2
2
  export { Chat } from './chat.vue';
3
+ export { useChat, type UseChatHelpers } from './use-chat';
3
4
  export * from './use-object';