@ai-sdk/svelte 3.0.0-canary.19 → 3.0.0-canary.20

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @ai-sdk/svelte
2
2
 
3
+ ## 3.0.0-canary.20
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [d964901]
8
+ - Updated dependencies [0560977]
9
+ - Updated dependencies [66af894]
10
+ - Updated dependencies [516be5b]
11
+ - Updated dependencies [bfbfc4c]
12
+ - Updated dependencies [ea7a7c9]
13
+ - Updated dependencies [1409e13]
14
+ - ai@5.0.0-canary.21
15
+ - @ai-sdk/provider-utils@3.0.0-canary.17
16
+
3
17
  ## 3.0.0-canary.19
4
18
 
5
19
  ### Major Changes
@@ -1,24 +1,13 @@
1
- import { type ChatRequestOptions, type CreateUIMessage, type JSONValue, type UIMessage, type UseChatOptions } from 'ai';
2
- export type ChatOptions = Readonly<UseChatOptions & {
3
- '~internal'?: {
4
- currentDate?: () => Date;
5
- };
6
- }>;
1
+ import { type ChatRequestOptions, type CreateUIMessage, type UIMessage, type UseChatOptions } from 'ai';
2
+ export type ChatOptions<MESSAGE_METADATA = unknown> = Readonly<UseChatOptions<MESSAGE_METADATA>>;
7
3
  export type { CreateUIMessage, UIMessage };
8
- export declare class Chat {
4
+ export declare class Chat<MESSAGE_METADATA = unknown> {
9
5
  #private;
10
6
  /**
11
7
  * The id of the chat. If not provided through the constructor, a random ID will be generated
12
8
  * using the provided `generateId` function, or a built-in function if not provided.
13
9
  */
14
10
  readonly id: string;
15
- /**
16
- * Additional data added on the server via StreamData.
17
- *
18
- * This is writable, so you can use it to transform or clear the chat data.
19
- */
20
- get data(): JSONValue[] | undefined;
21
- set data(value: JSONValue[] | undefined);
22
11
  /**
23
12
  * Hook status:
24
13
  *
@@ -38,17 +27,16 @@ export declare class Chat {
38
27
  * This is writable, which is useful when you want to edit the messages on the client, and then
39
28
  * trigger {@link reload} to regenerate the AI response.
40
29
  */
41
- get messages(): UIMessage[];
42
- set messages(value: UIMessage[]);
43
- private currentDate;
44
- constructor(options?: ChatOptions);
30
+ get messages(): UIMessage<MESSAGE_METADATA>[];
31
+ set messages(value: UIMessage<MESSAGE_METADATA>[]);
32
+ constructor(options?: ChatOptions<MESSAGE_METADATA>);
45
33
  /**
46
34
  * Append a user message to the chat list. This triggers the API call to fetch
47
35
  * the assistant's response.
48
36
  * @param message The message to append
49
37
  * @param options Additional options to pass to the API call
50
38
  */
51
- append: (message: UIMessage | CreateUIMessage, { data, headers, body }?: ChatRequestOptions) => Promise<void>;
39
+ append: (message: UIMessage<MESSAGE_METADATA> | CreateUIMessage<MESSAGE_METADATA>, { data, headers, body }?: ChatRequestOptions) => Promise<void>;
52
40
  /**
53
41
  * Reload the last AI chat response for the given chat history. If the last
54
42
  * message isn't from the assistant, it will request the API to generate a
@@ -1 +1 @@
1
- {"version":3,"file":"chat.svelte.d.ts","sourceRoot":"","sources":["../src/chat.svelte.ts"],"names":[],"mappings":"AACA,OAAO,EASL,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,cAAc,EACpB,MAAM,IAAI,CAAC;AAQZ,MAAM,MAAM,WAAW,GAAG,QAAQ,CAChC,cAAc,GAAG;IACf,WAAW,CAAC,EAAE;QACZ,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;KAC1B,CAAC;CACH,CACF,CAAC;AAEF,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC;AAE3C,qBAAa,IAAI;;IAOf;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAoD;IAI/D;;;;OAIG;IACH,IAAI,IAAI,IAGQ,SAAS,EAAE,GAAG,SAAS,CADtC;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,SAAS,EAEtC;IAED;;;;;;;OAOG;IACH,IAAI,MAAM,kDAET;IAED,0CAA0C;IAC1C,IAAI,KAAK,sBAER;IAED,mFAAmF;IACnF,KAAK,SAAqB;IAE1B;;;;;OAKG;IACH,IAAI,QAAQ,IAAI,SAAS,EAAE,CAE1B;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,EAE9B;IAED,OAAO,CAAC,WAAW,CAEjB;gBAEU,OAAO,GAAE,WAAgB;IAYrC;;;;;OAKG;IACH,MAAM,YACK,SAAS,GAAG,eAAe,4BACX,kBAAkB,mBAU3C;IAEF;;;;OAIG;IACH,MAAM,6BAAmC,kBAAkB,mBAezD;IAEF;;OAEG;IACH,IAAI,aASF;IAEF,qFAAqF;IACrF,YAAY,WACF;QAAE,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,YAC9B,kBAAkB,GAAG;QAAE,KAAK,CAAC,EAAE,QAAQ,CAAA;KAAE,mBA+BlD;IAEF,aAAa,4BAGV;QACD,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,OAAO,CAAC;KACjB,mBAmBC;CAgGH"}
1
+ {"version":3,"file":"chat.svelte.d.ts","sourceRoot":"","sources":["../src/chat.svelte.ts"],"names":[],"mappings":"AACA,OAAO,EASL,KAAK,kBAAkB,EACvB,KAAK,eAAe,EAEpB,KAAK,SAAS,EACd,KAAK,cAAc,EACpB,MAAM,IAAI,CAAC;AAQZ,MAAM,MAAM,WAAW,CAAC,gBAAgB,GAAG,OAAO,IAAI,QAAQ,CAC5D,cAAc,CAAC,gBAAgB,CAAC,CACjC,CAAC;AAEF,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC;AAE3C,qBAAa,IAAI,CAAC,gBAAgB,GAAG,OAAO;;IAO1C;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAoD;IAS/D;;;;;;;OAOG;IACH,IAAI,MAAM,kDAET;IAED,0CAA0C;IAC1C,IAAI,KAAK,sBAER;IAED,mFAAmF;IACnF,KAAK,SAAqB;IAE1B;;;;;OAKG;IACH,IAAI,QAAQ,IAAI,SAAS,CAAC,gBAAgB,CAAC,EAAE,CAE5C;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,gBAAgB,CAAC,EAAE,EAEhD;gBAEW,OAAO,GAAE,WAAW,CAAC,gBAAgB,CAAM;IAYvD;;;;;OAKG;IACH,MAAM,YACK,SAAS,CAAC,gBAAgB,CAAC,GAAG,eAAe,CAAC,gBAAgB,CAAC,4BAC/C,kBAAkB,mBAQ3C;IAEF;;;;OAIG;IACH,MAAM,6BAAmC,kBAAkB,mBAezD;IAEF;;OAEG;IACH,IAAI,aASF;IAEF,qFAAqF;IACrF,YAAY,WACF;QAAE,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,YAC9B,kBAAkB,GAAG;QAAE,KAAK,CAAC,EAAE,QAAQ,CAAA;KAAE,mBA8BlD;IAEF,aAAa,4BAGV;QACD,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,OAAO,CAAC;KACjB,mBAmBC;CA+FH"}
@@ -15,18 +15,8 @@ export class Chat {
15
15
  */
16
16
  id = $derived(this.#options.id ?? this.#generateId());
17
17
  #store = $derived(this.#keyedStore.get(this.id));
18
+ #messageMetadataSchema = $derived(this.#options.messageMetadataSchema);
18
19
  #abortController;
19
- /**
20
- * Additional data added on the server via StreamData.
21
- *
22
- * This is writable, so you can use it to transform or clear the chat data.
23
- */
24
- get data() {
25
- return this.#store.data;
26
- }
27
- set data(value) {
28
- this.#store.data = value;
29
- }
30
20
  /**
31
21
  * Hook status:
32
22
  *
@@ -56,7 +46,6 @@ export class Chat {
56
46
  set messages(value) {
57
47
  untrack(() => (this.#store.messages = value));
58
48
  }
59
- currentDate = $derived(this.#options['~internal']?.currentDate ?? (() => new Date()));
60
49
  constructor(options = {}) {
61
50
  if (hasChatContext()) {
62
51
  this.#keyedStore = getChatContext();
@@ -78,8 +67,6 @@ export class Chat {
78
67
  const messages = this.messages.concat({
79
68
  ...message,
80
69
  id: message.id ?? this.#generateId(),
81
- createdAt: message.createdAt ?? this.currentDate(),
82
- parts: message.parts,
83
70
  });
84
71
  return this.#triggerRequest({ messages, headers, body, data });
85
72
  };
@@ -127,7 +114,6 @@ export class Chat {
127
114
  : await convertFileListToFileUIParts(options?.files);
128
115
  const messages = this.messages.concat({
129
116
  id: this.#generateId(),
130
- createdAt: this.currentDate(),
131
117
  role: 'user',
132
118
  parts: [...fileParts, { type: 'text', text: this.input }],
133
119
  });
@@ -168,7 +154,6 @@ export class Chat {
168
154
  this.#abortController = abortController;
169
155
  // Optimistically update messages
170
156
  this.messages = messages;
171
- const existingData = this.data ?? [];
172
157
  await callChatApi({
173
158
  api: this.#api,
174
159
  body: {
@@ -186,8 +171,9 @@ export class Chat {
186
171
  },
187
172
  abortController: () => abortController,
188
173
  onResponse: this.#options.onResponse,
189
- onUpdate: ({ message, data, replaceLastMessage }) => {
174
+ onUpdate: ({ message }) => {
190
175
  this.#store.status = 'streaming';
176
+ const replaceLastMessage = message.id === messages[messages.length - 1].id;
191
177
  this.messages = messages;
192
178
  if (replaceLastMessage) {
193
179
  this.messages[this.messages.length - 1] = message;
@@ -195,18 +181,14 @@ export class Chat {
195
181
  else {
196
182
  this.messages.push(message);
197
183
  }
198
- if (data?.length) {
199
- this.data = existingData;
200
- this.data.push(...data);
201
- }
202
184
  },
203
185
  onToolCall: this.#options.onToolCall,
204
186
  onFinish: this.#options.onFinish,
205
187
  generateId: this.#generateId,
206
- getCurrentDate: this.currentDate,
207
188
  fetch: this.#options.fetch,
208
189
  // callChatApi calls structuredClone on the message
209
190
  lastMessage: $state.snapshot(this.messages[this.messages.length - 1]),
191
+ messageMetadataSchema: this.#messageMetadataSchema,
210
192
  });
211
193
  this.#abortController = undefined;
212
194
  this.#store.status = 'ready';
@@ -1,17 +1,10 @@
1
- import { type CompletionRequestOptions, type JSONValue, type UseCompletionOptions } from 'ai';
1
+ import { type CompletionRequestOptions, type UseCompletionOptions } from 'ai';
2
2
  export type CompletionOptions = Readonly<UseCompletionOptions>;
3
3
  export declare class Completion {
4
4
  #private;
5
5
  /** The current completion result */
6
6
  get completion(): string;
7
7
  set completion(value: string);
8
- /**
9
- * Additional data added on the server via StreamData.
10
- *
11
- * This is writable, so you can use it to transform or clear the chat data.
12
- */
13
- get data(): JSONValue[];
14
- set data(value: JSONValue[]);
15
8
  /** The error object of the API request */
16
9
  get error(): Error | undefined;
17
10
  /** The current value of the input. Writable, so it can be bound to form inputs. */
@@ -1 +1 @@
1
- {"version":3,"file":"completion.svelte.d.ts","sourceRoot":"","sources":["../src/completion.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,wBAAwB,EAC7B,KAAK,SAAS,EACd,KAAK,oBAAoB,EAC1B,MAAM,IAAI,CAAC;AAOZ,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAAC;AAE/D,qBAAa,UAAU;;IASrB,oCAAoC;IACpC,IAAI,UAAU,IAAI,MAAM,CAEvB;IACD,IAAI,UAAU,CAAC,KAAK,EAAE,MAAM,EAE3B;IAED;;;;OAIG;IACH,IAAI,IAAI,IAGQ,SAAS,EAAE,CAD1B;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,EAE1B;IAED,0CAA0C;IAC1C,IAAI,KAAK,sBAER;IAED,mFAAmF;IACnF,KAAK,SAAqB;IAE1B;;OAEG;IACH,IAAI,OAAO,YAEV;gBAEW,OAAO,GAAE,iBAAsB;IAY3C;;OAEG;IACH,IAAI,aASF;IAEF;;OAEG;IACH,QAAQ,WAAkB,MAAM,YAAY,wBAAwB,wCAC5B;IAExC,uFAAuF;IACvF,YAAY,WAAkB;QAAE,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,mBAK3D;CAsCH"}
1
+ {"version":3,"file":"completion.svelte.d.ts","sourceRoot":"","sources":["../src/completion.svelte.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EAC1B,MAAM,IAAI,CAAC;AAOZ,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAAC;AAE/D,qBAAa,UAAU;;IASrB,oCAAoC;IACpC,IAAI,UAAU,IAAI,MAAM,CAEvB;IACD,IAAI,UAAU,CAAC,KAAK,EAAE,MAAM,EAE3B;IAED,0CAA0C;IAC1C,IAAI,KAAK,sBAER;IAED,mFAAmF;IACnF,KAAK,SAAqB;IAE1B;;OAEG;IACH,IAAI,OAAO,YAEV;gBAEW,OAAO,GAAE,iBAAsB;IAS3C;;OAEG;IACH,IAAI,aASF;IAEF;;OAEG;IACH,QAAQ,WAAkB,MAAM,YAAY,wBAAwB,wCAC5B;IAExC,uFAAuF;IACvF,YAAY,WAAkB;QAAE,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,mBAK3D;CAmCH"}
@@ -15,17 +15,6 @@ export class Completion {
15
15
  set completion(value) {
16
16
  this.#store.completions.set(this.#id, value);
17
17
  }
18
- /**
19
- * Additional data added on the server via StreamData.
20
- *
21
- * This is writable, so you can use it to transform or clear the chat data.
22
- */
23
- get data() {
24
- return this.#store.data;
25
- }
26
- set data(value) {
27
- this.#store.data = value;
28
- }
29
18
  /** The error object of the API request */
30
19
  get error() {
31
20
  return this.#store.error;
@@ -39,12 +28,9 @@ export class Completion {
39
28
  return this.#store.loading;
40
29
  }
41
30
  constructor(options = {}) {
42
- if (hasCompletionContext()) {
43
- this.#keyedStore = getCompletionContext();
44
- }
45
- else {
46
- this.#keyedStore = new KeyedCompletionStore();
47
- }
31
+ this.#keyedStore = hasCompletionContext()
32
+ ? getCompletionContext()
33
+ : new KeyedCompletionStore();
48
34
  this.#options = options;
49
35
  this.completion = options.initialCompletion ?? '';
50
36
  this.input = options.initialInput ?? '';
@@ -91,9 +77,6 @@ export class Completion {
91
77
  setCompletion: completion => {
92
78
  this.completion = completion;
93
79
  },
94
- onData: data => {
95
- this.data.push(...data);
96
- },
97
80
  setLoading: loading => {
98
81
  this.#store.loading = loading;
99
82
  },
@@ -3,8 +3,8 @@ type $$ComponentProps = {
3
3
  id?: string;
4
4
  };
5
5
  declare const ChatSynchronization: import("svelte").Component<$$ComponentProps, {
6
- chat1: Chat;
7
- chat2: Chat;
6
+ chat1: Chat<unknown>;
7
+ chat2: Chat<unknown>;
8
8
  }, "">;
9
9
  type ChatSynchronization = ReturnType<typeof ChatSynchronization>;
10
10
  export default ChatSynchronization;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/svelte",
3
- "version": "3.0.0-canary.19",
3
+ "version": "3.0.0-canary.20",
4
4
  "license": "Apache-2.0",
5
5
  "files": [
6
6
  "dist",
@@ -36,8 +36,8 @@
36
36
  }
37
37
  },
38
38
  "dependencies": {
39
- "ai": "5.0.0-canary.20",
40
- "@ai-sdk/provider-utils": "3.0.0-canary.16"
39
+ "ai": "5.0.0-canary.21",
40
+ "@ai-sdk/provider-utils": "3.0.0-canary.17"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "20.17.24",
@@ -1,16 +1,21 @@
1
1
  import type { JSONValue, UIMessage } from 'ai';
2
2
  import { createContext, KeyedStore } from './utils.svelte.js';
3
3
 
4
- class ChatStore {
5
- messages = $state<UIMessage[]>([]);
4
+ class ChatStore<MESSAGE_METADATA = unknown> {
5
+ messages = $state<UIMessage<MESSAGE_METADATA>[]>([]);
6
6
  data = $state<JSONValue[]>();
7
7
  status = $state<'submitted' | 'streaming' | 'ready' | 'error'>('ready');
8
8
  error = $state<Error>();
9
9
  }
10
10
 
11
- export class KeyedChatStore extends KeyedStore<ChatStore> {
11
+ export class KeyedChatStore<MESSAGE_METADATA = unknown> extends KeyedStore<
12
+ ChatStore<MESSAGE_METADATA>
13
+ > {
12
14
  constructor(
13
- value?: Iterable<readonly [string, ChatStore]> | null | undefined,
15
+ value?:
16
+ | Iterable<readonly [string, ChatStore<MESSAGE_METADATA>]>
17
+ | null
18
+ | undefined,
14
19
  ) {
15
20
  super(ChatStore, value);
16
21
  }
@@ -21,42 +21,31 @@ import {
21
21
  hasChatContext,
22
22
  } from './chat-context.svelte.js';
23
23
 
24
- export type ChatOptions = Readonly<
25
- UseChatOptions & {
26
- '~internal'?: {
27
- currentDate?: () => Date;
28
- };
29
- }
24
+ export type ChatOptions<MESSAGE_METADATA = unknown> = Readonly<
25
+ UseChatOptions<MESSAGE_METADATA>
30
26
  >;
31
27
 
32
28
  export type { CreateUIMessage, UIMessage };
33
29
 
34
- export class Chat {
35
- readonly #options: ChatOptions = {};
30
+ export class Chat<MESSAGE_METADATA = unknown> {
31
+ readonly #options: ChatOptions<MESSAGE_METADATA> = {};
36
32
  readonly #api = $derived(this.#options.api ?? '/api/chat');
37
33
  readonly #generateId = $derived(this.#options.generateId ?? generateId);
38
34
  readonly #maxSteps = $derived(this.#options.maxSteps ?? 1);
39
35
  readonly #streamProtocol = $derived(this.#options.streamProtocol ?? 'data');
40
- readonly #keyedStore = $state<KeyedChatStore>()!;
36
+ readonly #keyedStore = $state<KeyedChatStore<MESSAGE_METADATA>>()!;
41
37
  /**
42
38
  * The id of the chat. If not provided through the constructor, a random ID will be generated
43
39
  * using the provided `generateId` function, or a built-in function if not provided.
44
40
  */
45
41
  readonly id = $derived(this.#options.id ?? this.#generateId());
46
42
  readonly #store = $derived(this.#keyedStore.get(this.id));
47
- #abortController: AbortController | undefined;
48
43
 
49
- /**
50
- * Additional data added on the server via StreamData.
51
- *
52
- * This is writable, so you can use it to transform or clear the chat data.
53
- */
54
- get data() {
55
- return this.#store.data;
56
- }
57
- set data(value: JSONValue[] | undefined) {
58
- this.#store.data = value;
59
- }
44
+ readonly #messageMetadataSchema = $derived(
45
+ this.#options.messageMetadataSchema,
46
+ );
47
+
48
+ #abortController: AbortController | undefined;
60
49
 
61
50
  /**
62
51
  * Hook status:
@@ -84,22 +73,18 @@ export class Chat {
84
73
  * This is writable, which is useful when you want to edit the messages on the client, and then
85
74
  * trigger {@link reload} to regenerate the AI response.
86
75
  */
87
- get messages(): UIMessage[] {
76
+ get messages(): UIMessage<MESSAGE_METADATA>[] {
88
77
  return this.#store.messages;
89
78
  }
90
- set messages(value: UIMessage[]) {
79
+ set messages(value: UIMessage<MESSAGE_METADATA>[]) {
91
80
  untrack(() => (this.#store.messages = value));
92
81
  }
93
82
 
94
- private currentDate = $derived(
95
- this.#options['~internal']?.currentDate ?? (() => new Date()),
96
- );
97
-
98
- constructor(options: ChatOptions = {}) {
83
+ constructor(options: ChatOptions<MESSAGE_METADATA> = {}) {
99
84
  if (hasChatContext()) {
100
- this.#keyedStore = getChatContext();
85
+ this.#keyedStore = getChatContext() as KeyedChatStore<MESSAGE_METADATA>;
101
86
  } else {
102
- this.#keyedStore = new KeyedChatStore();
87
+ this.#keyedStore = new KeyedChatStore<MESSAGE_METADATA>();
103
88
  }
104
89
 
105
90
  this.#options = options;
@@ -114,14 +99,12 @@ export class Chat {
114
99
  * @param options Additional options to pass to the API call
115
100
  */
116
101
  append = async (
117
- message: UIMessage | CreateUIMessage,
102
+ message: UIMessage<MESSAGE_METADATA> | CreateUIMessage<MESSAGE_METADATA>,
118
103
  { data, headers, body }: ChatRequestOptions = {},
119
104
  ) => {
120
105
  const messages = this.messages.concat({
121
106
  ...message,
122
107
  id: message.id ?? this.#generateId(),
123
- createdAt: message.createdAt ?? this.currentDate(),
124
- parts: message.parts,
125
108
  });
126
109
 
127
110
  return this.#triggerRequest({ messages, headers, body, data });
@@ -177,7 +160,6 @@ export class Chat {
177
160
 
178
161
  const messages = this.messages.concat({
179
162
  id: this.#generateId(),
180
- createdAt: this.currentDate(),
181
163
  role: 'user',
182
164
  parts: [...fileParts, { type: 'text', text: this.input }],
183
165
  });
@@ -185,7 +167,7 @@ export class Chat {
185
167
  const chatRequest: {
186
168
  headers?: Record<string, string> | Headers;
187
169
  body?: object;
188
- messages: UIMessage[];
170
+ messages: UIMessage<MESSAGE_METADATA>[];
189
171
  data?: JSONValue;
190
172
  } = {
191
173
  messages,
@@ -229,7 +211,7 @@ export class Chat {
229
211
  #triggerRequest = async (chatRequest: {
230
212
  headers?: Record<string, string> | Headers;
231
213
  body?: object;
232
- messages: UIMessage[];
214
+ messages: UIMessage<MESSAGE_METADATA>[];
233
215
  data?: JSONValue;
234
216
  }) => {
235
217
  this.#store.status = 'submitted';
@@ -248,7 +230,6 @@ export class Chat {
248
230
  // Optimistically update messages
249
231
  this.messages = messages;
250
232
 
251
- const existingData = this.data ?? [];
252
233
  await callChatApi({
253
234
  api: this.#api,
254
235
  body: {
@@ -266,28 +247,28 @@ export class Chat {
266
247
  },
267
248
  abortController: () => abortController,
268
249
  onResponse: this.#options.onResponse,
269
- onUpdate: ({ message, data, replaceLastMessage }) => {
250
+ onUpdate: ({ message }) => {
270
251
  this.#store.status = 'streaming';
271
252
 
253
+ const replaceLastMessage =
254
+ message.id === messages[messages.length - 1].id;
255
+
272
256
  this.messages = messages;
273
257
  if (replaceLastMessage) {
274
258
  this.messages[this.messages.length - 1] = message;
275
259
  } else {
276
260
  this.messages.push(message);
277
261
  }
278
-
279
- if (data?.length) {
280
- this.data = existingData;
281
- this.data.push(...data);
282
- }
283
262
  },
284
263
  onToolCall: this.#options.onToolCall,
285
264
  onFinish: this.#options.onFinish,
286
265
  generateId: this.#generateId,
287
- getCurrentDate: this.currentDate,
288
266
  fetch: this.#options.fetch,
289
267
  // callChatApi calls structuredClone on the message
290
- lastMessage: $state.snapshot(this.messages[this.messages.length - 1]),
268
+ lastMessage: $state.snapshot(
269
+ this.messages[this.messages.length - 1],
270
+ ) as UIMessage<MESSAGE_METADATA>,
271
+ messageMetadataSchema: this.#messageMetadataSchema,
291
272
  });
292
273
 
293
274
  this.#abortController = undefined;
@@ -2,7 +2,6 @@ import {
2
2
  callCompletionApi,
3
3
  generateId,
4
4
  type CompletionRequestOptions,
5
- type JSONValue,
6
5
  type UseCompletionOptions,
7
6
  } from 'ai';
8
7
  import {
@@ -30,18 +29,6 @@ export class Completion {
30
29
  this.#store.completions.set(this.#id, value);
31
30
  }
32
31
 
33
- /**
34
- * Additional data added on the server via StreamData.
35
- *
36
- * This is writable, so you can use it to transform or clear the chat data.
37
- */
38
- get data() {
39
- return this.#store.data;
40
- }
41
- set data(value: JSONValue[]) {
42
- this.#store.data = value;
43
- }
44
-
45
32
  /** The error object of the API request */
46
33
  get error() {
47
34
  return this.#store.error;
@@ -58,12 +45,9 @@ export class Completion {
58
45
  }
59
46
 
60
47
  constructor(options: CompletionOptions = {}) {
61
- if (hasCompletionContext()) {
62
- this.#keyedStore = getCompletionContext();
63
- } else {
64
- this.#keyedStore = new KeyedCompletionStore();
65
- }
66
-
48
+ this.#keyedStore = hasCompletionContext()
49
+ ? getCompletionContext()
50
+ : new KeyedCompletionStore();
67
51
  this.#options = options;
68
52
  this.completion = options.initialCompletion ?? '';
69
53
  this.input = options.initialInput ?? '';
@@ -116,9 +100,6 @@ export class Completion {
116
100
  setCompletion: completion => {
117
101
  this.completion = completion;
118
102
  },
119
- onData: data => {
120
- this.data.push(...data);
121
- },
122
103
  setLoading: loading => {
123
104
  this.#store.loading = loading;
124
105
  },