@ai-sdk/react 2.0.0-alpha.9 → 2.0.0-beta.2

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,114 @@
1
1
  # @ai-sdk/react
2
2
 
3
+ ## 2.0.0-beta.2
4
+
5
+ ### Patch Changes
6
+
7
+ - d1a034f: feature: using Zod 4 for internal stuff
8
+ - Updated dependencies [0d9583c]
9
+ - Updated dependencies [0571b98]
10
+ - Updated dependencies [c6b64a7]
11
+ - Updated dependencies [39a4fab]
12
+ - Updated dependencies [cb3b9c9]
13
+ - Updated dependencies [d1a034f]
14
+ - ai@5.0.0-beta.2
15
+ - @ai-sdk/provider-utils@3.0.0-beta.2
16
+
17
+ ## 2.0.0-beta.1
18
+
19
+ ### Patch Changes
20
+
21
+ - Updated dependencies [d88455d]
22
+ - Updated dependencies [45c1ea2]
23
+ - Updated dependencies [9ad0484]
24
+ - Updated dependencies [e025824]
25
+ - Updated dependencies [4048ce3]
26
+ - Updated dependencies [f2b041e]
27
+ - Updated dependencies [cb68df0]
28
+ - Updated dependencies [26695a3]
29
+ - Updated dependencies [bfdca8d]
30
+ - Updated dependencies [e7d2ce3]
31
+ - Updated dependencies [102b066]
32
+ - Updated dependencies [71f938d]
33
+ - Updated dependencies [28a5ed5]
34
+ - Updated dependencies [e862b5b]
35
+ - Updated dependencies [7bd025b]
36
+ - ai@5.0.0-beta.1
37
+ - @ai-sdk/provider-utils@3.0.0-beta.1
38
+
39
+ ## 2.0.0-alpha.15
40
+
41
+ ### Patch Changes
42
+
43
+ - ae0dc0a: feat (ui/react): add resume flag to useChat
44
+ - Updated dependencies [b1e3abd]
45
+ - Updated dependencies [8ba77a7]
46
+ - Updated dependencies [04d5063]
47
+ - Updated dependencies [b4b4bb2]
48
+ - Updated dependencies [d884051]
49
+ - Updated dependencies [954aa73]
50
+ - Updated dependencies [142576e]
51
+ - Updated dependencies [395c85e]
52
+ - Updated dependencies [60e2c56]
53
+ - ai@5.0.0-alpha.15
54
+ - @ai-sdk/provider-utils@3.0.0-alpha.15
55
+
56
+ ## 2.0.0-alpha.14
57
+
58
+ ### Patch Changes
59
+
60
+ - 995baa0: fix (react): structuredClone message in replaceMessage
61
+ - Updated dependencies [63f9e9b]
62
+ - ai@5.0.0-alpha.14
63
+ - @ai-sdk/provider-utils@3.0.0-alpha.14
64
+
65
+ ## 2.0.0-alpha.13
66
+
67
+ ### Major Changes
68
+
69
+ - 0a710d8: feat (ui): typed tool parts in ui messages
70
+ - 901df02: feat (ui): use UI_MESSAGE generic
71
+
72
+ ### Patch Changes
73
+
74
+ - Updated dependencies [0a710d8]
75
+ - Updated dependencies [6a83f7d]
76
+ - Updated dependencies [1f55c21]
77
+ - Updated dependencies [33eb499]
78
+ - Updated dependencies [901df02]
79
+ - ai@5.0.0-alpha.13
80
+ - @ai-sdk/provider-utils@3.0.0-alpha.13
81
+
82
+ ## 2.0.0-alpha.12
83
+
84
+ ### Patch Changes
85
+
86
+ - Updated dependencies [da1e6f0]
87
+ - Updated dependencies [4892798]
88
+ - ai@5.0.0-alpha.12
89
+ - @ai-sdk/provider-utils@3.0.0-alpha.12
90
+
91
+ ## 2.0.0-alpha.11
92
+
93
+ ### Patch Changes
94
+
95
+ - Updated dependencies [e8324c5]
96
+ - ai@5.0.0-alpha.11
97
+ - @ai-sdk/provider-utils@3.0.0-alpha.11
98
+
99
+ ## 2.0.0-alpha.10
100
+
101
+ ### Major Changes
102
+
103
+ - 98f25e5: chore (ui): remove managed chat inputs
104
+
105
+ ### Patch Changes
106
+
107
+ - Updated dependencies [98f25e5]
108
+ - Updated dependencies [7bb58d4]
109
+ - ai@5.0.0-alpha.10
110
+ - @ai-sdk/provider-utils@3.0.0-alpha.10
111
+
3
112
  ## 2.0.0-alpha.9
4
113
 
5
114
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -1,14 +1,18 @@
1
- import { UIDataPartSchemas, AbstractChat, BaseChatInit, UIMessage, InferUIDataParts, ChatRequestOptions, FileUIPart, CompletionRequestOptions, UseCompletionOptions, Schema, DeepPartial } from 'ai';
1
+ import { UIMessage, AbstractChat, ChatInit, CompletionRequestOptions, UseCompletionOptions, Schema, DeepPartial } from 'ai';
2
2
  export { CreateUIMessage, UIMessage, UseCompletionOptions } from 'ai';
3
3
  import { FetchFunction, InferSchema } from '@ai-sdk/provider-utils';
4
4
  import * as z3 from 'zod/v3';
5
- import * as z4 from 'zod/v4/core';
5
+ import * as z4 from 'zod/v4';
6
6
 
7
- declare class Chat<MESSAGE_METADATA, UI_DATA_PART_SCHEMAS extends UIDataPartSchemas = UIDataPartSchemas> extends AbstractChat<MESSAGE_METADATA, UI_DATA_PART_SCHEMAS> {
8
- constructor({ messages, ...init }: BaseChatInit<MESSAGE_METADATA, UI_DATA_PART_SCHEMAS>);
7
+ declare class Chat<UI_MESSAGE extends UIMessage> extends AbstractChat<UI_MESSAGE> {
8
+ #private;
9
+ constructor({ messages, ...init }: ChatInit<UI_MESSAGE>);
10
+ '~registerMessagesCallback': (onChange: () => void, throttleWaitMs?: number) => (() => void);
11
+ '~registerStatusCallback': (onChange: () => void) => (() => void);
12
+ '~registerErrorCallback': (onChange: () => void) => (() => void);
9
13
  }
10
14
 
11
- type UseChatHelpers<MESSAGE_METADATA = unknown, DATA_PART_SCHEMAS extends UIDataPartSchemas = UIDataPartSchemas> = {
15
+ type UseChatHelpers<UI_MESSAGE extends UIMessage> = {
12
16
  /**
13
17
  * The id of the chat.
14
18
  */
@@ -18,36 +22,23 @@ type UseChatHelpers<MESSAGE_METADATA = unknown, DATA_PART_SCHEMAS extends UIData
18
22
  * edit the messages on the client, and then trigger the `reload` method
19
23
  * manually to regenerate the AI response.
20
24
  */
21
- setMessages: (messages: UIMessage<MESSAGE_METADATA, InferUIDataParts<DATA_PART_SCHEMAS>>[] | ((messages: UIMessage<MESSAGE_METADATA, InferUIDataParts<DATA_PART_SCHEMAS>>[]) => UIMessage<MESSAGE_METADATA, InferUIDataParts<DATA_PART_SCHEMAS>>[])) => void;
22
- /** The current value of the input */
23
- input: string;
24
- /** setState-powered method to update the input value */
25
- setInput: React.Dispatch<React.SetStateAction<string>>;
26
- /** An input/textarea-ready onChange handler to control the value of the input */
27
- handleInputChange: (e: React.ChangeEvent<HTMLInputElement> | React.ChangeEvent<HTMLTextAreaElement>) => void;
28
- /** Form submission handler to automatically reset input and append a user message */
29
- handleSubmit: (event?: {
30
- preventDefault?: () => void;
31
- }, chatRequestOptions?: ChatRequestOptions & {
32
- files?: FileList | FileUIPart[];
33
- }) => void;
25
+ setMessages: (messages: UI_MESSAGE[] | ((messages: UI_MESSAGE[]) => UI_MESSAGE[])) => void;
34
26
  error: Error | undefined;
35
- } & Pick<AbstractChat<MESSAGE_METADATA, DATA_PART_SCHEMAS>, 'append' | 'reload' | 'stop' | 'experimental_resume' | 'addToolResult' | 'status' | 'messages'>;
36
- type UseChatOptions<MESSAGE_METADATA = unknown, DATA_TYPE_SCHEMAS extends UIDataPartSchemas = UIDataPartSchemas> = ({
37
- chat: Chat<MESSAGE_METADATA, DATA_TYPE_SCHEMAS>;
38
- } | BaseChatInit<MESSAGE_METADATA, DATA_TYPE_SCHEMAS>) & {
39
- /**
40
- /**
41
- * Initial input of the chat.
42
- */
43
- initialInput?: string;
27
+ } & Pick<AbstractChat<UI_MESSAGE>, 'sendMessage' | 'regenerate' | 'stop' | 'resumeStream' | 'addToolResult' | 'status' | 'messages'>;
28
+ type UseChatOptions<UI_MESSAGE extends UIMessage> = ({
29
+ chat: Chat<UI_MESSAGE>;
30
+ } | ChatInit<UI_MESSAGE>) & {
44
31
  /**
45
32
  Custom throttle wait in ms for the chat messages and data updates.
46
33
  Default is undefined, which disables throttling.
47
34
  */
48
35
  experimental_throttle?: number;
36
+ /**
37
+ * Whether to resume an ongoing chat generation stream.
38
+ */
39
+ resume?: boolean;
49
40
  };
50
- declare function useChat<MESSAGE_METADATA = unknown, DATA_PART_SCHEMAS extends UIDataPartSchemas = UIDataPartSchemas>({ initialInput, experimental_throttle: throttleWaitMs, ...options }?: UseChatOptions<MESSAGE_METADATA, DATA_PART_SCHEMAS>): UseChatHelpers<MESSAGE_METADATA, DATA_PART_SCHEMAS>;
41
+ declare function useChat<UI_MESSAGE extends UIMessage = UIMessage>({ experimental_throttle: throttleWaitMs, resume, ...options }?: UseChatOptions<UI_MESSAGE>): UseChatHelpers<UI_MESSAGE>;
51
42
 
52
43
  type UseCompletionHelpers = {
53
44
  /** The current completion result */
@@ -101,7 +92,7 @@ declare function useCompletion({ api, id, initialCompletion, initialInput, crede
101
92
  experimental_throttle?: number;
102
93
  }): UseCompletionHelpers;
103
94
 
104
- type Experimental_UseObjectOptions<SCHEMA extends z4.$ZodType | z3.Schema | Schema, RESULT> = {
95
+ type Experimental_UseObjectOptions<SCHEMA extends z4.ZodType | z3.Schema | Schema, RESULT> = {
105
96
  /**
106
97
  * The API endpoint. It should stream JSON that matches the schema as chunked text.
107
98
  */
@@ -176,7 +167,7 @@ type Experimental_UseObjectHelpers<RESULT, INPUT> = {
176
167
  */
177
168
  stop: () => void;
178
169
  };
179
- declare function useObject<SCHEMA extends z4.$ZodType | z3.Schema | Schema, RESULT = InferSchema<SCHEMA>, INPUT = any>({ api, id, schema, // required, in the future we will use it for validation
170
+ declare function useObject<SCHEMA extends z4.ZodType | z3.Schema | Schema, RESULT = InferSchema<SCHEMA>, INPUT = any>({ api, id, schema, // required, in the future we will use it for validation
180
171
  initialValue, fetch, onError, onFinish, headers, credentials, }: Experimental_UseObjectOptions<SCHEMA, RESULT>): Experimental_UseObjectHelpers<RESULT, INPUT>;
181
172
  declare const experimental_useObject: typeof useObject;
182
173
 
package/dist/index.d.ts CHANGED
@@ -1,14 +1,18 @@
1
- import { UIDataPartSchemas, AbstractChat, BaseChatInit, UIMessage, InferUIDataParts, ChatRequestOptions, FileUIPart, CompletionRequestOptions, UseCompletionOptions, Schema, DeepPartial } from 'ai';
1
+ import { UIMessage, AbstractChat, ChatInit, CompletionRequestOptions, UseCompletionOptions, Schema, DeepPartial } from 'ai';
2
2
  export { CreateUIMessage, UIMessage, UseCompletionOptions } from 'ai';
3
3
  import { FetchFunction, InferSchema } from '@ai-sdk/provider-utils';
4
4
  import * as z3 from 'zod/v3';
5
- import * as z4 from 'zod/v4/core';
5
+ import * as z4 from 'zod/v4';
6
6
 
7
- declare class Chat<MESSAGE_METADATA, UI_DATA_PART_SCHEMAS extends UIDataPartSchemas = UIDataPartSchemas> extends AbstractChat<MESSAGE_METADATA, UI_DATA_PART_SCHEMAS> {
8
- constructor({ messages, ...init }: BaseChatInit<MESSAGE_METADATA, UI_DATA_PART_SCHEMAS>);
7
+ declare class Chat<UI_MESSAGE extends UIMessage> extends AbstractChat<UI_MESSAGE> {
8
+ #private;
9
+ constructor({ messages, ...init }: ChatInit<UI_MESSAGE>);
10
+ '~registerMessagesCallback': (onChange: () => void, throttleWaitMs?: number) => (() => void);
11
+ '~registerStatusCallback': (onChange: () => void) => (() => void);
12
+ '~registerErrorCallback': (onChange: () => void) => (() => void);
9
13
  }
10
14
 
11
- type UseChatHelpers<MESSAGE_METADATA = unknown, DATA_PART_SCHEMAS extends UIDataPartSchemas = UIDataPartSchemas> = {
15
+ type UseChatHelpers<UI_MESSAGE extends UIMessage> = {
12
16
  /**
13
17
  * The id of the chat.
14
18
  */
@@ -18,36 +22,23 @@ type UseChatHelpers<MESSAGE_METADATA = unknown, DATA_PART_SCHEMAS extends UIData
18
22
  * edit the messages on the client, and then trigger the `reload` method
19
23
  * manually to regenerate the AI response.
20
24
  */
21
- setMessages: (messages: UIMessage<MESSAGE_METADATA, InferUIDataParts<DATA_PART_SCHEMAS>>[] | ((messages: UIMessage<MESSAGE_METADATA, InferUIDataParts<DATA_PART_SCHEMAS>>[]) => UIMessage<MESSAGE_METADATA, InferUIDataParts<DATA_PART_SCHEMAS>>[])) => void;
22
- /** The current value of the input */
23
- input: string;
24
- /** setState-powered method to update the input value */
25
- setInput: React.Dispatch<React.SetStateAction<string>>;
26
- /** An input/textarea-ready onChange handler to control the value of the input */
27
- handleInputChange: (e: React.ChangeEvent<HTMLInputElement> | React.ChangeEvent<HTMLTextAreaElement>) => void;
28
- /** Form submission handler to automatically reset input and append a user message */
29
- handleSubmit: (event?: {
30
- preventDefault?: () => void;
31
- }, chatRequestOptions?: ChatRequestOptions & {
32
- files?: FileList | FileUIPart[];
33
- }) => void;
25
+ setMessages: (messages: UI_MESSAGE[] | ((messages: UI_MESSAGE[]) => UI_MESSAGE[])) => void;
34
26
  error: Error | undefined;
35
- } & Pick<AbstractChat<MESSAGE_METADATA, DATA_PART_SCHEMAS>, 'append' | 'reload' | 'stop' | 'experimental_resume' | 'addToolResult' | 'status' | 'messages'>;
36
- type UseChatOptions<MESSAGE_METADATA = unknown, DATA_TYPE_SCHEMAS extends UIDataPartSchemas = UIDataPartSchemas> = ({
37
- chat: Chat<MESSAGE_METADATA, DATA_TYPE_SCHEMAS>;
38
- } | BaseChatInit<MESSAGE_METADATA, DATA_TYPE_SCHEMAS>) & {
39
- /**
40
- /**
41
- * Initial input of the chat.
42
- */
43
- initialInput?: string;
27
+ } & Pick<AbstractChat<UI_MESSAGE>, 'sendMessage' | 'regenerate' | 'stop' | 'resumeStream' | 'addToolResult' | 'status' | 'messages'>;
28
+ type UseChatOptions<UI_MESSAGE extends UIMessage> = ({
29
+ chat: Chat<UI_MESSAGE>;
30
+ } | ChatInit<UI_MESSAGE>) & {
44
31
  /**
45
32
  Custom throttle wait in ms for the chat messages and data updates.
46
33
  Default is undefined, which disables throttling.
47
34
  */
48
35
  experimental_throttle?: number;
36
+ /**
37
+ * Whether to resume an ongoing chat generation stream.
38
+ */
39
+ resume?: boolean;
49
40
  };
50
- declare function useChat<MESSAGE_METADATA = unknown, DATA_PART_SCHEMAS extends UIDataPartSchemas = UIDataPartSchemas>({ initialInput, experimental_throttle: throttleWaitMs, ...options }?: UseChatOptions<MESSAGE_METADATA, DATA_PART_SCHEMAS>): UseChatHelpers<MESSAGE_METADATA, DATA_PART_SCHEMAS>;
41
+ declare function useChat<UI_MESSAGE extends UIMessage = UIMessage>({ experimental_throttle: throttleWaitMs, resume, ...options }?: UseChatOptions<UI_MESSAGE>): UseChatHelpers<UI_MESSAGE>;
51
42
 
52
43
  type UseCompletionHelpers = {
53
44
  /** The current completion result */
@@ -101,7 +92,7 @@ declare function useCompletion({ api, id, initialCompletion, initialInput, crede
101
92
  experimental_throttle?: number;
102
93
  }): UseCompletionHelpers;
103
94
 
104
- type Experimental_UseObjectOptions<SCHEMA extends z4.$ZodType | z3.Schema | Schema, RESULT> = {
95
+ type Experimental_UseObjectOptions<SCHEMA extends z4.ZodType | z3.Schema | Schema, RESULT> = {
105
96
  /**
106
97
  * The API endpoint. It should stream JSON that matches the schema as chunked text.
107
98
  */
@@ -176,7 +167,7 @@ type Experimental_UseObjectHelpers<RESULT, INPUT> = {
176
167
  */
177
168
  stop: () => void;
178
169
  };
179
- declare function useObject<SCHEMA extends z4.$ZodType | z3.Schema | Schema, RESULT = InferSchema<SCHEMA>, INPUT = any>({ api, id, schema, // required, in the future we will use it for validation
170
+ declare function useObject<SCHEMA extends z4.ZodType | z3.Schema | Schema, RESULT = InferSchema<SCHEMA>, INPUT = any>({ api, id, schema, // required, in the future we will use it for validation
180
171
  initialValue, fetch, onError, onFinish, headers, credentials, }: Experimental_UseObjectOptions<SCHEMA, RESULT>): Experimental_UseObjectHelpers<RESULT, INPUT>;
181
172
  declare const experimental_useObject: typeof useObject;
182
173
 
package/dist/index.js CHANGED
@@ -56,101 +56,145 @@ __export(src_exports, {
56
56
  module.exports = __toCommonJS(src_exports);
57
57
 
58
58
  // src/use-chat.ts
59
- var import_ai2 = require("ai");
60
59
  var import_react = require("react");
61
60
 
62
61
  // src/chat.react.ts
63
62
  var import_ai = require("ai");
64
- var _messages;
63
+
64
+ // src/throttle.ts
65
+ var import_throttleit = __toESM(require("throttleit"));
66
+ function throttle(fn, waitMs) {
67
+ return waitMs != null ? (0, import_throttleit.default)(fn, waitMs) : fn;
68
+ }
69
+
70
+ // src/chat.react.ts
71
+ var _messages, _status, _error, _messagesCallbacks, _statusCallbacks, _errorCallbacks, _callMessagesCallbacks, _callStatusCallbacks, _callErrorCallbacks;
65
72
  var ReactChatState = class {
66
- constructor(messages = []) {
73
+ constructor(initialMessages = []) {
67
74
  __privateAdd(this, _messages, void 0);
68
- this.status = "ready";
69
- this.error = void 0;
75
+ __privateAdd(this, _status, "ready");
76
+ __privateAdd(this, _error, void 0);
77
+ __privateAdd(this, _messagesCallbacks, /* @__PURE__ */ new Set());
78
+ __privateAdd(this, _statusCallbacks, /* @__PURE__ */ new Set());
79
+ __privateAdd(this, _errorCallbacks, /* @__PURE__ */ new Set());
70
80
  this.pushMessage = (message) => {
71
- __privateSet(this, _messages, this.messages.concat(message));
81
+ __privateSet(this, _messages, __privateGet(this, _messages).concat(message));
82
+ __privateGet(this, _callMessagesCallbacks).call(this);
72
83
  };
73
84
  this.popMessage = () => {
74
- __privateSet(this, _messages, this.messages.slice(0, -1));
85
+ __privateSet(this, _messages, __privateGet(this, _messages).slice(0, -1));
86
+ __privateGet(this, _callMessagesCallbacks).call(this);
75
87
  };
76
88
  this.replaceMessage = (index, message) => {
77
89
  __privateSet(this, _messages, [
78
90
  ...__privateGet(this, _messages).slice(0, index),
79
- message,
91
+ // We deep clone the message here to ensure the new React Compiler (currently in RC) detects deeply nested parts/metadata changes:
92
+ this.snapshot(message),
80
93
  ...__privateGet(this, _messages).slice(index + 1)
81
94
  ]);
95
+ __privateGet(this, _callMessagesCallbacks).call(this);
82
96
  };
83
97
  this.snapshot = (value) => structuredClone(value);
84
- __privateSet(this, _messages, messages);
98
+ this["~registerMessagesCallback"] = (onChange, throttleWaitMs) => {
99
+ const callback = throttleWaitMs ? throttle(onChange, throttleWaitMs) : onChange;
100
+ __privateGet(this, _messagesCallbacks).add(callback);
101
+ return () => {
102
+ __privateGet(this, _messagesCallbacks).delete(callback);
103
+ };
104
+ };
105
+ this["~registerStatusCallback"] = (onChange) => {
106
+ __privateGet(this, _statusCallbacks).add(onChange);
107
+ return () => {
108
+ __privateGet(this, _statusCallbacks).delete(onChange);
109
+ };
110
+ };
111
+ this["~registerErrorCallback"] = (onChange) => {
112
+ __privateGet(this, _errorCallbacks).add(onChange);
113
+ return () => {
114
+ __privateGet(this, _errorCallbacks).delete(onChange);
115
+ };
116
+ };
117
+ __privateAdd(this, _callMessagesCallbacks, () => {
118
+ __privateGet(this, _messagesCallbacks).forEach((callback) => callback());
119
+ });
120
+ __privateAdd(this, _callStatusCallbacks, () => {
121
+ __privateGet(this, _statusCallbacks).forEach((callback) => callback());
122
+ });
123
+ __privateAdd(this, _callErrorCallbacks, () => {
124
+ __privateGet(this, _errorCallbacks).forEach((callback) => callback());
125
+ });
126
+ __privateSet(this, _messages, initialMessages);
127
+ }
128
+ get status() {
129
+ return __privateGet(this, _status);
130
+ }
131
+ set status(newStatus) {
132
+ __privateSet(this, _status, newStatus);
133
+ __privateGet(this, _callStatusCallbacks).call(this);
134
+ }
135
+ get error() {
136
+ return __privateGet(this, _error);
137
+ }
138
+ set error(newError) {
139
+ __privateSet(this, _error, newError);
140
+ __privateGet(this, _callErrorCallbacks).call(this);
85
141
  }
86
142
  get messages() {
87
143
  return __privateGet(this, _messages);
88
144
  }
89
- set messages(messages) {
90
- __privateSet(this, _messages, [...messages]);
145
+ set messages(newMessages) {
146
+ __privateSet(this, _messages, [...newMessages]);
147
+ __privateGet(this, _callMessagesCallbacks).call(this);
91
148
  }
92
149
  };
93
150
  _messages = new WeakMap();
151
+ _status = new WeakMap();
152
+ _error = new WeakMap();
153
+ _messagesCallbacks = new WeakMap();
154
+ _statusCallbacks = new WeakMap();
155
+ _errorCallbacks = new WeakMap();
156
+ _callMessagesCallbacks = new WeakMap();
157
+ _callStatusCallbacks = new WeakMap();
158
+ _callErrorCallbacks = new WeakMap();
159
+ var _state;
94
160
  var Chat = class extends import_ai.AbstractChat {
95
- constructor({
96
- messages,
97
- ...init
98
- }) {
99
- super({ ...init, state: new ReactChatState(messages) });
161
+ constructor({ messages, ...init }) {
162
+ const state = new ReactChatState(messages);
163
+ super({ ...init, state });
164
+ __privateAdd(this, _state, void 0);
165
+ this["~registerMessagesCallback"] = (onChange, throttleWaitMs) => __privateGet(this, _state)["~registerMessagesCallback"](onChange, throttleWaitMs);
166
+ this["~registerStatusCallback"] = (onChange) => __privateGet(this, _state)["~registerStatusCallback"](onChange);
167
+ this["~registerErrorCallback"] = (onChange) => __privateGet(this, _state)["~registerErrorCallback"](onChange);
168
+ __privateSet(this, _state, state);
100
169
  }
101
170
  };
102
-
103
- // src/throttle.ts
104
- var import_throttleit = __toESM(require("throttleit"));
105
- function throttle(fn, waitMs) {
106
- return waitMs != null ? (0, import_throttleit.default)(fn, waitMs) : fn;
107
- }
171
+ _state = new WeakMap();
108
172
 
109
173
  // src/use-chat.ts
110
174
  function useChat({
111
- initialInput = "",
112
175
  experimental_throttle: throttleWaitMs,
176
+ resume = false,
113
177
  ...options
114
178
  } = {}) {
115
179
  const chatRef = (0, import_react.useRef)("chat" in options ? options.chat : new Chat(options));
116
- const subscribe = (0, import_react.useCallback)(
117
- ({
118
- onStoreChange,
119
- eventType
120
- }) => chatRef.current.subscribe({
121
- onChange: (event) => {
122
- if (event.type !== eventType)
123
- return;
124
- onStoreChange();
125
- }
126
- }),
127
- [chatRef]
180
+ const subscribeToMessages = (0, import_react.useCallback)(
181
+ (update) => chatRef.current["~registerMessagesCallback"](update, throttleWaitMs),
182
+ [throttleWaitMs]
128
183
  );
129
- const addToolResult = (0, import_react.useCallback)(
130
- (options2) => chatRef.current.addToolResult(options2),
131
- [chatRef]
184
+ const messages = (0, import_react.useSyncExternalStore)(
185
+ subscribeToMessages,
186
+ () => chatRef.current.messages,
187
+ () => chatRef.current.messages
132
188
  );
133
189
  const status = (0, import_react.useSyncExternalStore)(
134
- (callback) => subscribe({
135
- onStoreChange: callback,
136
- eventType: "status-changed"
137
- }),
190
+ chatRef.current["~registerStatusCallback"],
138
191
  () => chatRef.current.status,
139
192
  () => chatRef.current.status
140
193
  );
141
- const subscribeToChatStoreForMessages = (0, import_react.useCallback)(
142
- (callback) => {
143
- return subscribe({
144
- onStoreChange: throttleWaitMs ? throttle(callback, throttleWaitMs) : callback,
145
- eventType: "messages-changed"
146
- });
147
- },
148
- [subscribe, throttleWaitMs]
149
- );
150
- const messages = (0, import_react.useSyncExternalStore)(
151
- (callback) => subscribeToChatStoreForMessages(callback),
152
- () => chatRef.current.messages,
153
- () => chatRef.current.messages
194
+ const error = (0, import_react.useSyncExternalStore)(
195
+ chatRef.current["~registerErrorCallback"],
196
+ () => chatRef.current.error,
197
+ () => chatRef.current.error
154
198
  );
155
199
  const setMessages = (0, import_react.useCallback)(
156
200
  (messagesParam) => {
@@ -159,55 +203,29 @@ function useChat({
159
203
  }
160
204
  chatRef.current.messages = messagesParam;
161
205
  },
162
- [chatRef, messages]
163
- );
164
- const [input, setInput] = (0, import_react.useState)(initialInput);
165
- const handleSubmit = (0, import_react.useCallback)(
166
- async (event, options2 = {}) => {
167
- var _a;
168
- (_a = event == null ? void 0 : event.preventDefault) == null ? void 0 : _a.call(event);
169
- const fileParts = Array.isArray(options2 == null ? void 0 : options2.files) ? options2.files : await (0, import_ai2.convertFileListToFileUIParts)(options2 == null ? void 0 : options2.files);
170
- if (!input && fileParts.length === 0)
171
- return;
172
- chatRef.current.append(
173
- {
174
- id: chatRef.current.generateId(),
175
- role: "user",
176
- metadata: void 0,
177
- parts: [...fileParts, { type: "text", text: input }]
178
- },
179
- {
180
- headers: options2.headers,
181
- body: options2.body
182
- }
183
- );
184
- setInput("");
185
- },
186
- [input, chatRef]
206
+ [messages, chatRef]
187
207
  );
188
- const handleInputChange = (e) => {
189
- setInput(e.target.value);
190
- };
208
+ (0, import_react.useEffect)(() => {
209
+ if (resume) {
210
+ chatRef.current.resumeStream();
211
+ }
212
+ }, [resume, chatRef]);
191
213
  return {
192
214
  id: chatRef.current.id,
193
215
  messages,
194
216
  setMessages,
195
- append: chatRef.current.append,
196
- reload: chatRef.current.reload,
217
+ sendMessage: chatRef.current.sendMessage,
218
+ regenerate: chatRef.current.regenerate,
197
219
  stop: chatRef.current.stop,
198
- error: chatRef.current.error,
199
- experimental_resume: chatRef.current.experimental_resume,
200
- input,
201
- setInput,
202
- handleInputChange,
203
- handleSubmit,
220
+ error,
221
+ resumeStream: chatRef.current.resumeStream,
204
222
  status,
205
- addToolResult
223
+ addToolResult: chatRef.current.addToolResult
206
224
  };
207
225
  }
208
226
 
209
227
  // src/use-completion.ts
210
- var import_ai3 = require("ai");
228
+ var import_ai2 = require("ai");
211
229
  var import_react2 = require("react");
212
230
  var import_swr = __toESM(require("swr"));
213
231
  function useCompletion({
@@ -249,7 +267,7 @@ function useCompletion({
249
267
  };
250
268
  }, [credentials, headers, body]);
251
269
  const triggerRequest = (0, import_react2.useCallback)(
252
- async (prompt, options) => (0, import_ai3.callCompletionApi)({
270
+ async (prompt, options) => (0, import_ai2.callCompletionApi)({
253
271
  api,
254
272
  prompt,
255
273
  credentials: extraMetadataRef.current.credentials,
@@ -334,7 +352,7 @@ function useCompletion({
334
352
 
335
353
  // src/use-object.ts
336
354
  var import_provider_utils = require("@ai-sdk/provider-utils");
337
- var import_ai4 = require("ai");
355
+ var import_ai3 = require("ai");
338
356
  var import_react3 = require("react");
339
357
  var import_swr2 = __toESM(require("swr"));
340
358
  var getOriginalFetch = () => fetch;
@@ -403,9 +421,9 @@ function useObject({
403
421
  new WritableStream({
404
422
  async write(chunk) {
405
423
  accumulatedText += chunk;
406
- const { value } = await (0, import_ai4.parsePartialJson)(accumulatedText);
424
+ const { value } = await (0, import_ai3.parsePartialJson)(accumulatedText);
407
425
  const currentObject = value;
408
- if (!(0, import_ai4.isDeepEqualData)(latestObject, currentObject)) {
426
+ if (!(0, import_ai3.isDeepEqualData)(latestObject, currentObject)) {
409
427
  latestObject = currentObject;
410
428
  mutate(currentObject);
411
429
  }
@@ -416,7 +434,7 @@ function useObject({
416
434
  if (onFinish != null) {
417
435
  const validationResult = await (0, import_provider_utils.safeValidateTypes)({
418
436
  value: latestObject,
419
- schema: (0, import_ai4.asSchema)(schema)
437
+ schema: (0, import_ai3.asSchema)(schema)
420
438
  });
421
439
  onFinish(
422
440
  validationResult.success ? { object: validationResult.value, error: void 0 } : { object: void 0, error: validationResult.error }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/use-chat.ts","../src/chat.react.ts","../src/throttle.ts","../src/use-completion.ts","../src/use-object.ts"],"sourcesContent":["export * from './use-chat';\nexport { Chat } from './chat.react';\nexport * from './use-completion';\nexport * from './use-object';\n","import {\n AbstractChat,\n BaseChatInit,\n ChatEvent,\n convertFileListToFileUIParts,\n InferUIDataParts,\n UIDataPartSchemas,\n type ChatRequestOptions,\n type CreateUIMessage,\n type FileUIPart,\n type UIMessage,\n} from 'ai';\nimport { useCallback, useRef, useState, useSyncExternalStore } from 'react';\nimport { Chat } from './chat.react';\nimport { throttle } from './throttle';\n\nexport type { CreateUIMessage, UIMessage };\n\nexport type UseChatHelpers<\n MESSAGE_METADATA = unknown,\n DATA_PART_SCHEMAS extends UIDataPartSchemas = UIDataPartSchemas,\n> = {\n /**\n * The id of the chat.\n */\n readonly id: string;\n\n /**\n * Update the `messages` state locally. This is useful when you want to\n * edit the messages on the client, and then trigger the `reload` method\n * manually to regenerate the AI response.\n */\n setMessages: (\n messages:\n | UIMessage<MESSAGE_METADATA, InferUIDataParts<DATA_PART_SCHEMAS>>[]\n | ((\n messages: UIMessage<\n MESSAGE_METADATA,\n InferUIDataParts<DATA_PART_SCHEMAS>\n >[],\n ) => UIMessage<\n MESSAGE_METADATA,\n InferUIDataParts<DATA_PART_SCHEMAS>\n >[]),\n ) => void;\n\n /** The current value of the input */\n input: string;\n\n /** setState-powered method to update the input value */\n setInput: React.Dispatch<React.SetStateAction<string>>;\n\n /** An input/textarea-ready onChange handler to control the value of the input */\n handleInputChange: (\n e:\n | React.ChangeEvent<HTMLInputElement>\n | React.ChangeEvent<HTMLTextAreaElement>,\n ) => void;\n\n /** Form submission handler to automatically reset input and append a user message */\n handleSubmit: (\n event?: { preventDefault?: () => void },\n chatRequestOptions?: ChatRequestOptions & {\n files?: FileList | FileUIPart[];\n },\n ) => void;\n\n error: Error | undefined;\n} & Pick<\n AbstractChat<MESSAGE_METADATA, DATA_PART_SCHEMAS>,\n | 'append'\n | 'reload'\n | 'stop'\n | 'experimental_resume'\n | 'addToolResult'\n | 'status'\n | 'messages'\n>;\n\nexport type UseChatOptions<\n MESSAGE_METADATA = unknown,\n DATA_TYPE_SCHEMAS extends UIDataPartSchemas = UIDataPartSchemas,\n> = (\n | { chat: Chat<MESSAGE_METADATA, DATA_TYPE_SCHEMAS> }\n | BaseChatInit<MESSAGE_METADATA, DATA_TYPE_SCHEMAS>\n) & {\n /**\n /**\n * Initial input of the chat.\n */\n initialInput?: string;\n\n /**\nCustom throttle wait in ms for the chat messages and data updates.\nDefault is undefined, which disables throttling.\n */\n experimental_throttle?: number;\n};\n\nexport function useChat<\n MESSAGE_METADATA = unknown,\n DATA_PART_SCHEMAS extends UIDataPartSchemas = UIDataPartSchemas,\n>({\n initialInput = '',\n experimental_throttle: throttleWaitMs,\n ...options\n}: UseChatOptions<MESSAGE_METADATA, DATA_PART_SCHEMAS> = {}): UseChatHelpers<\n MESSAGE_METADATA,\n DATA_PART_SCHEMAS\n> {\n const chatRef = useRef('chat' in options ? options.chat : new Chat(options));\n\n const subscribe = useCallback(\n ({\n onStoreChange,\n eventType,\n }: {\n onStoreChange: () => void;\n eventType: ChatEvent['type'];\n }) =>\n chatRef.current.subscribe({\n onChange: event => {\n if (event.type !== eventType) return;\n onStoreChange();\n },\n }),\n [chatRef],\n );\n\n const addToolResult = useCallback(\n (\n options: Parameters<\n Chat<MESSAGE_METADATA, DATA_PART_SCHEMAS>['addToolResult']\n >[0],\n ) => chatRef.current.addToolResult(options),\n [chatRef],\n );\n\n const status = useSyncExternalStore(\n callback =>\n subscribe({\n onStoreChange: callback,\n eventType: 'status-changed',\n }),\n () => chatRef.current.status,\n () => chatRef.current.status,\n );\n\n const subscribeToChatStoreForMessages = useCallback(\n (callback: () => void) => {\n return subscribe({\n onStoreChange: throttleWaitMs\n ? throttle(callback, throttleWaitMs)\n : callback,\n eventType: 'messages-changed',\n });\n },\n [subscribe, throttleWaitMs],\n );\n\n const messages = useSyncExternalStore(\n callback => subscribeToChatStoreForMessages(callback),\n () => chatRef.current.messages,\n () => chatRef.current.messages,\n );\n\n const setMessages = useCallback(\n (\n messagesParam:\n | UIMessage<MESSAGE_METADATA, InferUIDataParts<DATA_PART_SCHEMAS>>[]\n | ((\n messages: UIMessage<\n MESSAGE_METADATA,\n InferUIDataParts<DATA_PART_SCHEMAS>\n >[],\n ) => UIMessage<\n MESSAGE_METADATA,\n InferUIDataParts<DATA_PART_SCHEMAS>\n >[]),\n ) => {\n if (typeof messagesParam === 'function') {\n messagesParam = messagesParam(messages);\n }\n\n chatRef.current.messages = messagesParam;\n },\n [chatRef, messages],\n );\n\n // Input state and handlers.\n const [input, setInput] = useState(initialInput);\n\n const handleSubmit = useCallback(\n async (\n event?: { preventDefault?: () => void },\n options: ChatRequestOptions & {\n files?: FileList | FileUIPart[];\n } = {},\n ) => {\n event?.preventDefault?.();\n\n const fileParts = Array.isArray(options?.files)\n ? options.files\n : await convertFileListToFileUIParts(options?.files);\n\n if (!input && fileParts.length === 0) return;\n\n chatRef.current.append(\n {\n id: chatRef.current.generateId(),\n role: 'user',\n metadata: undefined,\n parts: [...fileParts, { type: 'text', text: input }],\n },\n {\n headers: options.headers,\n body: options.body,\n },\n );\n\n setInput('');\n },\n [input, chatRef],\n );\n\n const handleInputChange = (e: any) => {\n setInput(e.target.value);\n };\n\n return {\n id: chatRef.current.id,\n messages,\n setMessages,\n append: chatRef.current.append,\n reload: chatRef.current.reload,\n stop: chatRef.current.stop,\n error: chatRef.current.error,\n experimental_resume: chatRef.current.experimental_resume,\n input,\n setInput,\n handleInputChange,\n handleSubmit,\n status,\n addToolResult,\n };\n}\n","import {\n AbstractChat,\n BaseChatInit,\n ChatState,\n ChatStatus,\n UIDataPartSchemas,\n UIDataTypes,\n UIMessage,\n} from 'ai';\n\nclass ReactChatState<MESSAGE_METADATA, DATA_TYPES extends UIDataTypes>\n implements ChatState<MESSAGE_METADATA, DATA_TYPES>\n{\n #messages: UIMessage<MESSAGE_METADATA, DATA_TYPES>[];\n status: ChatStatus = 'ready';\n error: Error | undefined = undefined;\n\n constructor(messages: UIMessage<MESSAGE_METADATA, DATA_TYPES>[] = []) {\n this.#messages = messages;\n }\n\n get messages() {\n return this.#messages;\n }\n\n set messages(messages: UIMessage<MESSAGE_METADATA, DATA_TYPES>[]) {\n this.#messages = [...messages];\n }\n\n pushMessage = (message: UIMessage<MESSAGE_METADATA, DATA_TYPES>) => {\n this.#messages = this.messages.concat(message);\n };\n\n popMessage = () => {\n this.#messages = this.messages.slice(0, -1);\n };\n\n replaceMessage = (\n index: number,\n message: UIMessage<MESSAGE_METADATA, DATA_TYPES>,\n ) => {\n this.#messages = [\n ...this.#messages.slice(0, index),\n message,\n ...this.#messages.slice(index + 1),\n ];\n };\n\n snapshot = <T>(value: T): T => structuredClone(value);\n}\n\nexport class Chat<\n MESSAGE_METADATA,\n UI_DATA_PART_SCHEMAS extends UIDataPartSchemas = UIDataPartSchemas,\n> extends AbstractChat<MESSAGE_METADATA, UI_DATA_PART_SCHEMAS> {\n constructor({\n messages,\n ...init\n }: BaseChatInit<MESSAGE_METADATA, UI_DATA_PART_SCHEMAS>) {\n super({ ...init, state: new ReactChatState(messages) });\n }\n}\n","import throttleFunction from 'throttleit';\n\nexport function throttle<T extends (...args: any[]) => any>(\n fn: T,\n waitMs: number | undefined,\n): T {\n return waitMs != null ? throttleFunction(fn, waitMs) : fn;\n}\n","import {\n CompletionRequestOptions,\n UseCompletionOptions,\n callCompletionApi,\n} from 'ai';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\nimport { throttle } from './throttle';\n\nexport type { UseCompletionOptions };\n\nexport type UseCompletionHelpers = {\n /** The current completion result */\n completion: string;\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 /** The error object of the API request */\n error: undefined | Error;\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: string;\n /** setState-powered method to update the input value */\n setInput: React.Dispatch<React.SetStateAction<string>>;\n /**\n * An input/textarea-ready onChange handler to control the value of the input\n * @example\n * ```jsx\n * <input onChange={handleInputChange} value={input} />\n * ```\n */\n handleInputChange: (\n event:\n | React.ChangeEvent<HTMLInputElement>\n | React.ChangeEvent<HTMLTextAreaElement>,\n ) => void;\n\n /**\n * Form submission handler to automatically reset input and append a user message\n * @example\n * ```jsx\n * <form onSubmit={handleSubmit}>\n * <input onChange={handleInputChange} value={input} />\n * </form>\n * ```\n */\n handleSubmit: (event?: { preventDefault?: () => void }) => void;\n\n /** Whether the API request is in progress */\n isLoading: boolean;\n};\n\nexport function useCompletion({\n api = '/api/completion',\n id,\n initialCompletion = '',\n initialInput = '',\n credentials,\n headers,\n body,\n streamProtocol = 'data',\n fetch,\n onFinish,\n onError,\n experimental_throttle: throttleWaitMs,\n}: UseCompletionOptions & {\n /**\n * Custom throttle wait in ms for the completion and data updates.\n * Default is undefined, which disables throttling.\n */\n experimental_throttle?: number;\n} = {}): UseCompletionHelpers {\n // Generate an unique id for the completion if not provided.\n const hookId = useId();\n const completionId = id || hookId;\n\n // Store the completion state in SWR, using the completionId as the key to share states.\n const { data, mutate } = useSWR<string>([api, completionId], null, {\n fallbackData: initialCompletion,\n });\n\n const { data: isLoading = false, mutate: mutateLoading } = useSWR<boolean>(\n [completionId, 'loading'],\n null,\n );\n\n const [error, setError] = useState<undefined | Error>(undefined);\n const completion = data!;\n\n // Abort controller to cancel the current API call.\n const [abortController, setAbortController] =\n useState<AbortController | null>(null);\n\n const extraMetadataRef = useRef({\n credentials,\n headers,\n body,\n });\n\n useEffect(() => {\n extraMetadataRef.current = {\n credentials,\n headers,\n body,\n };\n }, [credentials, headers, body]);\n\n const triggerRequest = useCallback(\n async (prompt: string, options?: CompletionRequestOptions) =>\n callCompletionApi({\n api,\n prompt,\n credentials: extraMetadataRef.current.credentials,\n headers: { ...extraMetadataRef.current.headers, ...options?.headers },\n body: {\n ...extraMetadataRef.current.body,\n ...options?.body,\n },\n streamProtocol,\n fetch,\n // throttle streamed ui updates:\n setCompletion: throttle(\n (completion: string) => mutate(completion, false),\n throttleWaitMs,\n ),\n setLoading: mutateLoading,\n setError,\n setAbortController,\n onFinish,\n onError,\n }),\n [\n mutate,\n mutateLoading,\n api,\n extraMetadataRef,\n setAbortController,\n onFinish,\n onError,\n setError,\n streamProtocol,\n fetch,\n throttleWaitMs,\n ],\n );\n\n const stop = useCallback(() => {\n if (abortController) {\n abortController.abort();\n setAbortController(null);\n }\n }, [abortController]);\n\n const setCompletion = useCallback(\n (completion: string) => {\n mutate(completion, false);\n },\n [mutate],\n );\n\n const complete = useCallback<UseCompletionHelpers['complete']>(\n async (prompt, options) => {\n return triggerRequest(prompt, options);\n },\n [triggerRequest],\n );\n\n const [input, setInput] = useState(initialInput);\n\n const handleSubmit = useCallback(\n (event?: { preventDefault?: () => void }) => {\n event?.preventDefault?.();\n return input ? complete(input) : undefined;\n },\n [input, complete],\n );\n\n const handleInputChange = useCallback(\n (e: any) => {\n setInput(e.target.value);\n },\n [setInput],\n );\n\n return {\n completion,\n complete,\n error,\n setCompletion,\n stop,\n input,\n setInput,\n handleInputChange,\n handleSubmit,\n isLoading,\n };\n}\n","import {\n FetchFunction,\n InferSchema,\n isAbortError,\n safeValidateTypes,\n} from '@ai-sdk/provider-utils';\nimport {\n asSchema,\n DeepPartial,\n isDeepEqualData,\n parsePartialJson,\n Schema,\n} from 'ai';\nimport { useCallback, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\nimport * as z3 from 'zod/v3';\nimport * as z4 from 'zod/v4/core';\n\n// use function to allow for mocking in tests:\nconst getOriginalFetch = () => fetch;\n\nexport type Experimental_UseObjectOptions<\n SCHEMA extends z4.$ZodType | z3.Schema | Schema,\n RESULT,\n> = {\n /**\n * The API endpoint. It should stream JSON that matches the schema as chunked text.\n */\n api: string;\n\n /**\n * A Zod schema that defines the shape of the complete object.\n */\n schema: SCHEMA;\n\n /**\n * An unique identifier. If not provided, a random one will be\n * generated. When provided, the `useObject` hook with the same `id` will\n * have shared states across components.\n */\n id?: string;\n\n /**\n * An optional value for the initial object.\n */\n initialValue?: DeepPartial<RESULT>;\n\n /**\nCustom fetch implementation. You can use it as a middleware to intercept requests,\nor to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n\n /**\nCallback that is called when the stream has finished.\n */\n onFinish?: (event: {\n /**\nThe generated object (typed according to the schema).\nCan be undefined if the final object does not match the schema.\n */\n object: RESULT | undefined;\n\n /**\nOptional error object. This is e.g. a TypeValidationError when the final object does not match the schema.\n */\n error: Error | undefined;\n }) => Promise<void> | void;\n\n /**\n * Callback function to be called when an error is encountered.\n */\n onError?: (error: Error) => void;\n\n /**\n * Additional HTTP headers to be included in the request.\n */\n headers?: Record<string, string> | Headers;\n\n /**\n * The credentials mode to be used for the fetch request.\n * Possible values are: 'omit', 'same-origin', 'include'.\n * Defaults to 'same-origin'.\n */\n credentials?: RequestCredentials;\n};\n\nexport type Experimental_UseObjectHelpers<RESULT, INPUT> = {\n /**\n * Calls the API with the provided input as JSON body.\n */\n submit: (input: INPUT) => void;\n\n /**\n * The current value for the generated object. Updated as the API streams JSON chunks.\n */\n object: DeepPartial<RESULT> | undefined;\n\n /**\n * The error object of the API request if any.\n */\n error: Error | undefined;\n\n /**\n * Flag that indicates whether an API request is in progress.\n */\n isLoading: boolean;\n\n /**\n * Abort the current request immediately, keep the current partial object if any.\n */\n stop: () => void;\n};\n\nfunction useObject<\n SCHEMA extends z4.$ZodType | z3.Schema | Schema,\n RESULT = InferSchema<SCHEMA>,\n INPUT = any,\n>({\n api,\n id,\n schema, // required, in the future we will use it for validation\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 if not provided.\n const hookId = useId();\n const completionId = id ?? hookId;\n\n // Store the completion state in SWR, using the completionId as the key to share states.\n const { data, mutate } = useSWR<DeepPartial<RESULT>>(\n [api, completionId],\n null,\n { fallbackData: initialValue },\n );\n\n const [error, setError] = useState<undefined | Error>(undefined);\n const [isLoading, setIsLoading] = useState(false);\n\n // Abort controller to cancel the current API call.\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const stop = useCallback(() => {\n try {\n abortControllerRef.current?.abort();\n } catch (ignored) {\n } finally {\n setIsLoading(false);\n abortControllerRef.current = null;\n }\n }, []);\n\n const submit = async (input: INPUT) => {\n try {\n mutate(undefined); // reset the data\n setIsLoading(true);\n setError(undefined);\n\n const abortController = new AbortController();\n abortControllerRef.current = 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,\n },\n credentials,\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 == null) {\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\n const { value } = await parsePartialJson(accumulatedText);\n const currentObject = value as DeepPartial<RESULT>;\n\n if (!isDeepEqualData(latestObject, currentObject)) {\n latestObject = currentObject;\n\n mutate(currentObject);\n }\n },\n\n async close() {\n setIsLoading(false);\n abortControllerRef.current = null;\n\n if (onFinish != null) {\n const validationResult = await safeValidateTypes({\n value: latestObject,\n schema: asSchema(schema),\n });\n\n onFinish(\n validationResult.success\n ? { object: validationResult.value, error: undefined }\n : { object: undefined, error: validationResult.error },\n );\n }\n },\n }),\n );\n } catch (error) {\n if (isAbortError(error)) {\n return;\n }\n\n if (onError && error instanceof Error) {\n onError(error);\n }\n\n setIsLoading(false);\n setError(error instanceof Error ? error : new Error(String(error)));\n }\n };\n\n return {\n submit,\n object: data,\n error,\n isLoading,\n stop,\n };\n}\n\nexport const experimental_useObject = useObject;\n"],"mappings":"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","names":["import_ai","throttleFunction","options","import_ai","import_react","fetch","useSWR","completion","import_ai","import_react","import_swr","fetch","useSWR","error"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/use-chat.ts","../src/chat.react.ts","../src/throttle.ts","../src/use-completion.ts","../src/use-object.ts"],"sourcesContent":["export * from './use-chat';\nexport { Chat } from './chat.react';\nexport * from './use-completion';\nexport * from './use-object';\n","import {\n AbstractChat,\n ChatInit,\n type CreateUIMessage,\n type UIMessage,\n} from 'ai';\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from 'react';\nimport { Chat } from './chat.react';\n\nexport type { CreateUIMessage, UIMessage };\n\nexport type UseChatHelpers<UI_MESSAGE extends UIMessage> = {\n /**\n * The id of the chat.\n */\n readonly id: string;\n\n /**\n * Update the `messages` state locally. This is useful when you want to\n * edit the messages on the client, and then trigger the `reload` method\n * manually to regenerate the AI response.\n */\n setMessages: (\n messages: UI_MESSAGE[] | ((messages: UI_MESSAGE[]) => UI_MESSAGE[]),\n ) => void;\n\n error: Error | undefined;\n} & Pick<\n AbstractChat<UI_MESSAGE>,\n | 'sendMessage'\n | 'regenerate'\n | 'stop'\n | 'resumeStream'\n | 'addToolResult'\n | 'status'\n | 'messages'\n>;\n\nexport type UseChatOptions<UI_MESSAGE extends UIMessage> = (\n | { chat: Chat<UI_MESSAGE> }\n | ChatInit<UI_MESSAGE>\n) & {\n /**\nCustom throttle wait in ms for the chat messages and data updates.\nDefault is undefined, which disables throttling.\n */\n experimental_throttle?: number;\n\n /**\n * Whether to resume an ongoing chat generation stream.\n */\n resume?: boolean;\n};\n\nexport function useChat<UI_MESSAGE extends UIMessage = UIMessage>({\n experimental_throttle: throttleWaitMs,\n resume = false,\n ...options\n}: UseChatOptions<UI_MESSAGE> = {}): UseChatHelpers<UI_MESSAGE> {\n const chatRef = useRef('chat' in options ? options.chat : new Chat(options));\n\n const subscribeToMessages = useCallback(\n (update: () => void) =>\n chatRef.current['~registerMessagesCallback'](update, throttleWaitMs),\n [throttleWaitMs],\n );\n\n const messages = useSyncExternalStore(\n subscribeToMessages,\n () => chatRef.current.messages,\n () => chatRef.current.messages,\n );\n\n const status = useSyncExternalStore(\n chatRef.current['~registerStatusCallback'],\n () => chatRef.current.status,\n () => chatRef.current.status,\n );\n\n const error = useSyncExternalStore(\n chatRef.current['~registerErrorCallback'],\n () => chatRef.current.error,\n () => chatRef.current.error,\n );\n\n const setMessages = useCallback(\n (\n messagesParam: UI_MESSAGE[] | ((messages: UI_MESSAGE[]) => UI_MESSAGE[]),\n ) => {\n if (typeof messagesParam === 'function') {\n messagesParam = messagesParam(messages);\n }\n\n chatRef.current.messages = messagesParam;\n },\n [messages, chatRef],\n );\n\n useEffect(() => {\n if (resume) {\n chatRef.current.resumeStream();\n }\n }, [resume, chatRef]);\n\n return {\n id: chatRef.current.id,\n messages,\n setMessages,\n sendMessage: chatRef.current.sendMessage,\n regenerate: chatRef.current.regenerate,\n stop: chatRef.current.stop,\n error,\n resumeStream: chatRef.current.resumeStream,\n status,\n addToolResult: chatRef.current.addToolResult,\n };\n}\n","import { AbstractChat, ChatInit, ChatState, ChatStatus, UIMessage } from 'ai';\nimport { throttle } from './throttle';\n\nclass ReactChatState<UI_MESSAGE extends UIMessage>\n implements ChatState<UI_MESSAGE>\n{\n #messages: UI_MESSAGE[];\n #status: ChatStatus = 'ready';\n #error: Error | undefined = undefined;\n\n #messagesCallbacks = new Set<() => void>();\n #statusCallbacks = new Set<() => void>();\n #errorCallbacks = new Set<() => void>();\n\n constructor(initialMessages: UI_MESSAGE[] = []) {\n this.#messages = initialMessages;\n }\n\n get status(): ChatStatus {\n return this.#status;\n }\n\n set status(newStatus: ChatStatus) {\n this.#status = newStatus;\n this.#callStatusCallbacks();\n }\n\n get error(): Error | undefined {\n return this.#error;\n }\n\n set error(newError: Error | undefined) {\n this.#error = newError;\n this.#callErrorCallbacks();\n }\n\n get messages(): UI_MESSAGE[] {\n return this.#messages;\n }\n\n set messages(newMessages: UI_MESSAGE[]) {\n this.#messages = [...newMessages];\n this.#callMessagesCallbacks();\n }\n\n pushMessage = (message: UI_MESSAGE) => {\n this.#messages = this.#messages.concat(message);\n this.#callMessagesCallbacks();\n };\n\n popMessage = () => {\n this.#messages = this.#messages.slice(0, -1);\n this.#callMessagesCallbacks();\n };\n\n replaceMessage = (index: number, message: UI_MESSAGE) => {\n this.#messages = [\n ...this.#messages.slice(0, index),\n // We deep clone the message here to ensure the new React Compiler (currently in RC) detects deeply nested parts/metadata changes:\n this.snapshot(message),\n ...this.#messages.slice(index + 1),\n ];\n this.#callMessagesCallbacks();\n };\n\n snapshot = <T>(value: T): T => structuredClone(value);\n\n '~registerMessagesCallback' = (\n onChange: () => void,\n throttleWaitMs?: number,\n ): (() => void) => {\n const callback = throttleWaitMs\n ? throttle(onChange, throttleWaitMs)\n : onChange;\n this.#messagesCallbacks.add(callback);\n return () => {\n this.#messagesCallbacks.delete(callback);\n };\n };\n\n '~registerStatusCallback' = (onChange: () => void): (() => void) => {\n this.#statusCallbacks.add(onChange);\n return () => {\n this.#statusCallbacks.delete(onChange);\n };\n };\n\n '~registerErrorCallback' = (onChange: () => void): (() => void) => {\n this.#errorCallbacks.add(onChange);\n return () => {\n this.#errorCallbacks.delete(onChange);\n };\n };\n\n #callMessagesCallbacks = () => {\n this.#messagesCallbacks.forEach(callback => callback());\n };\n\n #callStatusCallbacks = () => {\n this.#statusCallbacks.forEach(callback => callback());\n };\n\n #callErrorCallbacks = () => {\n this.#errorCallbacks.forEach(callback => callback());\n };\n}\n\nexport class Chat<\n UI_MESSAGE extends UIMessage,\n> extends AbstractChat<UI_MESSAGE> {\n #state: ReactChatState<UI_MESSAGE>;\n\n constructor({ messages, ...init }: ChatInit<UI_MESSAGE>) {\n const state = new ReactChatState(messages);\n super({ ...init, state });\n this.#state = state;\n }\n\n '~registerMessagesCallback' = (\n onChange: () => void,\n throttleWaitMs?: number,\n ): (() => void) =>\n this.#state['~registerMessagesCallback'](onChange, throttleWaitMs);\n\n '~registerStatusCallback' = (onChange: () => void): (() => void) =>\n this.#state['~registerStatusCallback'](onChange);\n\n '~registerErrorCallback' = (onChange: () => void): (() => void) =>\n this.#state['~registerErrorCallback'](onChange);\n}\n","import throttleFunction from 'throttleit';\n\nexport function throttle<T extends (...args: any[]) => any>(\n fn: T,\n waitMs: number | undefined,\n): T {\n return waitMs != null ? throttleFunction(fn, waitMs) : fn;\n}\n","import {\n CompletionRequestOptions,\n UseCompletionOptions,\n callCompletionApi,\n} from 'ai';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\nimport { throttle } from './throttle';\n\nexport type { UseCompletionOptions };\n\nexport type UseCompletionHelpers = {\n /** The current completion result */\n completion: string;\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 /** The error object of the API request */\n error: undefined | Error;\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: string;\n /** setState-powered method to update the input value */\n setInput: React.Dispatch<React.SetStateAction<string>>;\n /**\n * An input/textarea-ready onChange handler to control the value of the input\n * @example\n * ```jsx\n * <input onChange={handleInputChange} value={input} />\n * ```\n */\n handleInputChange: (\n event:\n | React.ChangeEvent<HTMLInputElement>\n | React.ChangeEvent<HTMLTextAreaElement>,\n ) => void;\n\n /**\n * Form submission handler to automatically reset input and append a user message\n * @example\n * ```jsx\n * <form onSubmit={handleSubmit}>\n * <input onChange={handleInputChange} value={input} />\n * </form>\n * ```\n */\n handleSubmit: (event?: { preventDefault?: () => void }) => void;\n\n /** Whether the API request is in progress */\n isLoading: boolean;\n};\n\nexport function useCompletion({\n api = '/api/completion',\n id,\n initialCompletion = '',\n initialInput = '',\n credentials,\n headers,\n body,\n streamProtocol = 'data',\n fetch,\n onFinish,\n onError,\n experimental_throttle: throttleWaitMs,\n}: UseCompletionOptions & {\n /**\n * Custom throttle wait in ms for the completion and data updates.\n * Default is undefined, which disables throttling.\n */\n experimental_throttle?: number;\n} = {}): UseCompletionHelpers {\n // Generate an unique id for the completion if not provided.\n const hookId = useId();\n const completionId = id || hookId;\n\n // Store the completion state in SWR, using the completionId as the key to share states.\n const { data, mutate } = useSWR<string>([api, completionId], null, {\n fallbackData: initialCompletion,\n });\n\n const { data: isLoading = false, mutate: mutateLoading } = useSWR<boolean>(\n [completionId, 'loading'],\n null,\n );\n\n const [error, setError] = useState<undefined | Error>(undefined);\n const completion = data!;\n\n // Abort controller to cancel the current API call.\n const [abortController, setAbortController] =\n useState<AbortController | null>(null);\n\n const extraMetadataRef = useRef({\n credentials,\n headers,\n body,\n });\n\n useEffect(() => {\n extraMetadataRef.current = {\n credentials,\n headers,\n body,\n };\n }, [credentials, headers, body]);\n\n const triggerRequest = useCallback(\n async (prompt: string, options?: CompletionRequestOptions) =>\n callCompletionApi({\n api,\n prompt,\n credentials: extraMetadataRef.current.credentials,\n headers: { ...extraMetadataRef.current.headers, ...options?.headers },\n body: {\n ...extraMetadataRef.current.body,\n ...options?.body,\n },\n streamProtocol,\n fetch,\n // throttle streamed ui updates:\n setCompletion: throttle(\n (completion: string) => mutate(completion, false),\n throttleWaitMs,\n ),\n setLoading: mutateLoading,\n setError,\n setAbortController,\n onFinish,\n onError,\n }),\n [\n mutate,\n mutateLoading,\n api,\n extraMetadataRef,\n setAbortController,\n onFinish,\n onError,\n setError,\n streamProtocol,\n fetch,\n throttleWaitMs,\n ],\n );\n\n const stop = useCallback(() => {\n if (abortController) {\n abortController.abort();\n setAbortController(null);\n }\n }, [abortController]);\n\n const setCompletion = useCallback(\n (completion: string) => {\n mutate(completion, false);\n },\n [mutate],\n );\n\n const complete = useCallback<UseCompletionHelpers['complete']>(\n async (prompt, options) => {\n return triggerRequest(prompt, options);\n },\n [triggerRequest],\n );\n\n const [input, setInput] = useState(initialInput);\n\n const handleSubmit = useCallback(\n (event?: { preventDefault?: () => void }) => {\n event?.preventDefault?.();\n return input ? complete(input) : undefined;\n },\n [input, complete],\n );\n\n const handleInputChange = useCallback(\n (e: any) => {\n setInput(e.target.value);\n },\n [setInput],\n );\n\n return {\n completion,\n complete,\n error,\n setCompletion,\n stop,\n input,\n setInput,\n handleInputChange,\n handleSubmit,\n isLoading,\n };\n}\n","import {\n FetchFunction,\n InferSchema,\n isAbortError,\n safeValidateTypes,\n} from '@ai-sdk/provider-utils';\nimport {\n asSchema,\n DeepPartial,\n isDeepEqualData,\n parsePartialJson,\n Schema,\n} from 'ai';\nimport { useCallback, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\nimport * as z3 from 'zod/v3';\nimport * as z4 from 'zod/v4';\n\n// use function to allow for mocking in tests:\nconst getOriginalFetch = () => fetch;\n\nexport type Experimental_UseObjectOptions<\n SCHEMA extends z4.ZodType | z3.Schema | Schema,\n RESULT,\n> = {\n /**\n * The API endpoint. It should stream JSON that matches the schema as chunked text.\n */\n api: string;\n\n /**\n * A Zod schema that defines the shape of the complete object.\n */\n schema: SCHEMA;\n\n /**\n * An unique identifier. If not provided, a random one will be\n * generated. When provided, the `useObject` hook with the same `id` will\n * have shared states across components.\n */\n id?: string;\n\n /**\n * An optional value for the initial object.\n */\n initialValue?: DeepPartial<RESULT>;\n\n /**\nCustom fetch implementation. You can use it as a middleware to intercept requests,\nor to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n\n /**\nCallback that is called when the stream has finished.\n */\n onFinish?: (event: {\n /**\nThe generated object (typed according to the schema).\nCan be undefined if the final object does not match the schema.\n */\n object: RESULT | undefined;\n\n /**\nOptional error object. This is e.g. a TypeValidationError when the final object does not match the schema.\n */\n error: Error | undefined;\n }) => Promise<void> | void;\n\n /**\n * Callback function to be called when an error is encountered.\n */\n onError?: (error: Error) => void;\n\n /**\n * Additional HTTP headers to be included in the request.\n */\n headers?: Record<string, string> | Headers;\n\n /**\n * The credentials mode to be used for the fetch request.\n * Possible values are: 'omit', 'same-origin', 'include'.\n * Defaults to 'same-origin'.\n */\n credentials?: RequestCredentials;\n};\n\nexport type Experimental_UseObjectHelpers<RESULT, INPUT> = {\n /**\n * Calls the API with the provided input as JSON body.\n */\n submit: (input: INPUT) => void;\n\n /**\n * The current value for the generated object. Updated as the API streams JSON chunks.\n */\n object: DeepPartial<RESULT> | undefined;\n\n /**\n * The error object of the API request if any.\n */\n error: Error | undefined;\n\n /**\n * Flag that indicates whether an API request is in progress.\n */\n isLoading: boolean;\n\n /**\n * Abort the current request immediately, keep the current partial object if any.\n */\n stop: () => void;\n};\n\nfunction useObject<\n SCHEMA extends z4.ZodType | z3.Schema | Schema,\n RESULT = InferSchema<SCHEMA>,\n INPUT = any,\n>({\n api,\n id,\n schema, // required, in the future we will use it for validation\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 if not provided.\n const hookId = useId();\n const completionId = id ?? hookId;\n\n // Store the completion state in SWR, using the completionId as the key to share states.\n const { data, mutate } = useSWR<DeepPartial<RESULT>>(\n [api, completionId],\n null,\n { fallbackData: initialValue },\n );\n\n const [error, setError] = useState<undefined | Error>(undefined);\n const [isLoading, setIsLoading] = useState(false);\n\n // Abort controller to cancel the current API call.\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const stop = useCallback(() => {\n try {\n abortControllerRef.current?.abort();\n } catch (ignored) {\n } finally {\n setIsLoading(false);\n abortControllerRef.current = null;\n }\n }, []);\n\n const submit = async (input: INPUT) => {\n try {\n mutate(undefined); // reset the data\n setIsLoading(true);\n setError(undefined);\n\n const abortController = new AbortController();\n abortControllerRef.current = 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,\n },\n credentials,\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 == null) {\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\n const { value } = await parsePartialJson(accumulatedText);\n const currentObject = value as DeepPartial<RESULT>;\n\n if (!isDeepEqualData(latestObject, currentObject)) {\n latestObject = currentObject;\n\n mutate(currentObject);\n }\n },\n\n async close() {\n setIsLoading(false);\n abortControllerRef.current = null;\n\n if (onFinish != null) {\n const validationResult = await safeValidateTypes({\n value: latestObject,\n schema: asSchema(schema),\n });\n\n onFinish(\n validationResult.success\n ? { object: validationResult.value, error: undefined }\n : { object: undefined, error: validationResult.error },\n );\n }\n },\n }),\n );\n } catch (error) {\n if (isAbortError(error)) {\n return;\n }\n\n if (onError && error instanceof Error) {\n onError(error);\n }\n\n setIsLoading(false);\n setError(error instanceof Error ? error : new Error(String(error)));\n }\n };\n\n return {\n submit,\n object: data,\n error,\n isLoading,\n stop,\n };\n}\n\nexport const experimental_useObject = useObject;\n"],"mappings":"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","names":["throttleFunction","import_ai","import_react","fetch","useSWR","completion","import_ai","import_react","import_swr","fetch","useSWR","error"]}
package/dist/index.mjs CHANGED
@@ -18,105 +18,145 @@ var __privateSet = (obj, member, value, setter) => {
18
18
  };
19
19
 
20
20
  // src/use-chat.ts
21
- import {
22
- convertFileListToFileUIParts
23
- } from "ai";
24
- import { useCallback, useRef, useState, useSyncExternalStore } from "react";
21
+ import { useCallback, useEffect, useRef, useSyncExternalStore } from "react";
25
22
 
26
23
  // src/chat.react.ts
27
- import {
28
- AbstractChat
29
- } from "ai";
30
- var _messages;
24
+ import { AbstractChat } from "ai";
25
+
26
+ // src/throttle.ts
27
+ import throttleFunction from "throttleit";
28
+ function throttle(fn, waitMs) {
29
+ return waitMs != null ? throttleFunction(fn, waitMs) : fn;
30
+ }
31
+
32
+ // src/chat.react.ts
33
+ var _messages, _status, _error, _messagesCallbacks, _statusCallbacks, _errorCallbacks, _callMessagesCallbacks, _callStatusCallbacks, _callErrorCallbacks;
31
34
  var ReactChatState = class {
32
- constructor(messages = []) {
35
+ constructor(initialMessages = []) {
33
36
  __privateAdd(this, _messages, void 0);
34
- this.status = "ready";
35
- this.error = void 0;
37
+ __privateAdd(this, _status, "ready");
38
+ __privateAdd(this, _error, void 0);
39
+ __privateAdd(this, _messagesCallbacks, /* @__PURE__ */ new Set());
40
+ __privateAdd(this, _statusCallbacks, /* @__PURE__ */ new Set());
41
+ __privateAdd(this, _errorCallbacks, /* @__PURE__ */ new Set());
36
42
  this.pushMessage = (message) => {
37
- __privateSet(this, _messages, this.messages.concat(message));
43
+ __privateSet(this, _messages, __privateGet(this, _messages).concat(message));
44
+ __privateGet(this, _callMessagesCallbacks).call(this);
38
45
  };
39
46
  this.popMessage = () => {
40
- __privateSet(this, _messages, this.messages.slice(0, -1));
47
+ __privateSet(this, _messages, __privateGet(this, _messages).slice(0, -1));
48
+ __privateGet(this, _callMessagesCallbacks).call(this);
41
49
  };
42
50
  this.replaceMessage = (index, message) => {
43
51
  __privateSet(this, _messages, [
44
52
  ...__privateGet(this, _messages).slice(0, index),
45
- message,
53
+ // We deep clone the message here to ensure the new React Compiler (currently in RC) detects deeply nested parts/metadata changes:
54
+ this.snapshot(message),
46
55
  ...__privateGet(this, _messages).slice(index + 1)
47
56
  ]);
57
+ __privateGet(this, _callMessagesCallbacks).call(this);
48
58
  };
49
59
  this.snapshot = (value) => structuredClone(value);
50
- __privateSet(this, _messages, messages);
60
+ this["~registerMessagesCallback"] = (onChange, throttleWaitMs) => {
61
+ const callback = throttleWaitMs ? throttle(onChange, throttleWaitMs) : onChange;
62
+ __privateGet(this, _messagesCallbacks).add(callback);
63
+ return () => {
64
+ __privateGet(this, _messagesCallbacks).delete(callback);
65
+ };
66
+ };
67
+ this["~registerStatusCallback"] = (onChange) => {
68
+ __privateGet(this, _statusCallbacks).add(onChange);
69
+ return () => {
70
+ __privateGet(this, _statusCallbacks).delete(onChange);
71
+ };
72
+ };
73
+ this["~registerErrorCallback"] = (onChange) => {
74
+ __privateGet(this, _errorCallbacks).add(onChange);
75
+ return () => {
76
+ __privateGet(this, _errorCallbacks).delete(onChange);
77
+ };
78
+ };
79
+ __privateAdd(this, _callMessagesCallbacks, () => {
80
+ __privateGet(this, _messagesCallbacks).forEach((callback) => callback());
81
+ });
82
+ __privateAdd(this, _callStatusCallbacks, () => {
83
+ __privateGet(this, _statusCallbacks).forEach((callback) => callback());
84
+ });
85
+ __privateAdd(this, _callErrorCallbacks, () => {
86
+ __privateGet(this, _errorCallbacks).forEach((callback) => callback());
87
+ });
88
+ __privateSet(this, _messages, initialMessages);
89
+ }
90
+ get status() {
91
+ return __privateGet(this, _status);
92
+ }
93
+ set status(newStatus) {
94
+ __privateSet(this, _status, newStatus);
95
+ __privateGet(this, _callStatusCallbacks).call(this);
96
+ }
97
+ get error() {
98
+ return __privateGet(this, _error);
99
+ }
100
+ set error(newError) {
101
+ __privateSet(this, _error, newError);
102
+ __privateGet(this, _callErrorCallbacks).call(this);
51
103
  }
52
104
  get messages() {
53
105
  return __privateGet(this, _messages);
54
106
  }
55
- set messages(messages) {
56
- __privateSet(this, _messages, [...messages]);
107
+ set messages(newMessages) {
108
+ __privateSet(this, _messages, [...newMessages]);
109
+ __privateGet(this, _callMessagesCallbacks).call(this);
57
110
  }
58
111
  };
59
112
  _messages = new WeakMap();
113
+ _status = new WeakMap();
114
+ _error = new WeakMap();
115
+ _messagesCallbacks = new WeakMap();
116
+ _statusCallbacks = new WeakMap();
117
+ _errorCallbacks = new WeakMap();
118
+ _callMessagesCallbacks = new WeakMap();
119
+ _callStatusCallbacks = new WeakMap();
120
+ _callErrorCallbacks = new WeakMap();
121
+ var _state;
60
122
  var Chat = class extends AbstractChat {
61
- constructor({
62
- messages,
63
- ...init
64
- }) {
65
- super({ ...init, state: new ReactChatState(messages) });
123
+ constructor({ messages, ...init }) {
124
+ const state = new ReactChatState(messages);
125
+ super({ ...init, state });
126
+ __privateAdd(this, _state, void 0);
127
+ this["~registerMessagesCallback"] = (onChange, throttleWaitMs) => __privateGet(this, _state)["~registerMessagesCallback"](onChange, throttleWaitMs);
128
+ this["~registerStatusCallback"] = (onChange) => __privateGet(this, _state)["~registerStatusCallback"](onChange);
129
+ this["~registerErrorCallback"] = (onChange) => __privateGet(this, _state)["~registerErrorCallback"](onChange);
130
+ __privateSet(this, _state, state);
66
131
  }
67
132
  };
68
-
69
- // src/throttle.ts
70
- import throttleFunction from "throttleit";
71
- function throttle(fn, waitMs) {
72
- return waitMs != null ? throttleFunction(fn, waitMs) : fn;
73
- }
133
+ _state = new WeakMap();
74
134
 
75
135
  // src/use-chat.ts
76
136
  function useChat({
77
- initialInput = "",
78
137
  experimental_throttle: throttleWaitMs,
138
+ resume = false,
79
139
  ...options
80
140
  } = {}) {
81
141
  const chatRef = useRef("chat" in options ? options.chat : new Chat(options));
82
- const subscribe = useCallback(
83
- ({
84
- onStoreChange,
85
- eventType
86
- }) => chatRef.current.subscribe({
87
- onChange: (event) => {
88
- if (event.type !== eventType)
89
- return;
90
- onStoreChange();
91
- }
92
- }),
93
- [chatRef]
142
+ const subscribeToMessages = useCallback(
143
+ (update) => chatRef.current["~registerMessagesCallback"](update, throttleWaitMs),
144
+ [throttleWaitMs]
94
145
  );
95
- const addToolResult = useCallback(
96
- (options2) => chatRef.current.addToolResult(options2),
97
- [chatRef]
146
+ const messages = useSyncExternalStore(
147
+ subscribeToMessages,
148
+ () => chatRef.current.messages,
149
+ () => chatRef.current.messages
98
150
  );
99
151
  const status = useSyncExternalStore(
100
- (callback) => subscribe({
101
- onStoreChange: callback,
102
- eventType: "status-changed"
103
- }),
152
+ chatRef.current["~registerStatusCallback"],
104
153
  () => chatRef.current.status,
105
154
  () => chatRef.current.status
106
155
  );
107
- const subscribeToChatStoreForMessages = useCallback(
108
- (callback) => {
109
- return subscribe({
110
- onStoreChange: throttleWaitMs ? throttle(callback, throttleWaitMs) : callback,
111
- eventType: "messages-changed"
112
- });
113
- },
114
- [subscribe, throttleWaitMs]
115
- );
116
- const messages = useSyncExternalStore(
117
- (callback) => subscribeToChatStoreForMessages(callback),
118
- () => chatRef.current.messages,
119
- () => chatRef.current.messages
156
+ const error = useSyncExternalStore(
157
+ chatRef.current["~registerErrorCallback"],
158
+ () => chatRef.current.error,
159
+ () => chatRef.current.error
120
160
  );
121
161
  const setMessages = useCallback(
122
162
  (messagesParam) => {
@@ -125,50 +165,24 @@ function useChat({
125
165
  }
126
166
  chatRef.current.messages = messagesParam;
127
167
  },
128
- [chatRef, messages]
168
+ [messages, chatRef]
129
169
  );
130
- const [input, setInput] = useState(initialInput);
131
- const handleSubmit = useCallback(
132
- async (event, options2 = {}) => {
133
- var _a;
134
- (_a = event == null ? void 0 : event.preventDefault) == null ? void 0 : _a.call(event);
135
- const fileParts = Array.isArray(options2 == null ? void 0 : options2.files) ? options2.files : await convertFileListToFileUIParts(options2 == null ? void 0 : options2.files);
136
- if (!input && fileParts.length === 0)
137
- return;
138
- chatRef.current.append(
139
- {
140
- id: chatRef.current.generateId(),
141
- role: "user",
142
- metadata: void 0,
143
- parts: [...fileParts, { type: "text", text: input }]
144
- },
145
- {
146
- headers: options2.headers,
147
- body: options2.body
148
- }
149
- );
150
- setInput("");
151
- },
152
- [input, chatRef]
153
- );
154
- const handleInputChange = (e) => {
155
- setInput(e.target.value);
156
- };
170
+ useEffect(() => {
171
+ if (resume) {
172
+ chatRef.current.resumeStream();
173
+ }
174
+ }, [resume, chatRef]);
157
175
  return {
158
176
  id: chatRef.current.id,
159
177
  messages,
160
178
  setMessages,
161
- append: chatRef.current.append,
162
- reload: chatRef.current.reload,
179
+ sendMessage: chatRef.current.sendMessage,
180
+ regenerate: chatRef.current.regenerate,
163
181
  stop: chatRef.current.stop,
164
- error: chatRef.current.error,
165
- experimental_resume: chatRef.current.experimental_resume,
166
- input,
167
- setInput,
168
- handleInputChange,
169
- handleSubmit,
182
+ error,
183
+ resumeStream: chatRef.current.resumeStream,
170
184
  status,
171
- addToolResult
185
+ addToolResult: chatRef.current.addToolResult
172
186
  };
173
187
  }
174
188
 
@@ -176,7 +190,7 @@ function useChat({
176
190
  import {
177
191
  callCompletionApi
178
192
  } from "ai";
179
- import { useCallback as useCallback2, useEffect, useId, useRef as useRef2, useState as useState2 } from "react";
193
+ import { useCallback as useCallback2, useEffect as useEffect2, useId, useRef as useRef2, useState } from "react";
180
194
  import useSWR from "swr";
181
195
  function useCompletion({
182
196
  api = "/api/completion",
@@ -201,15 +215,15 @@ function useCompletion({
201
215
  [completionId, "loading"],
202
216
  null
203
217
  );
204
- const [error, setError] = useState2(void 0);
218
+ const [error, setError] = useState(void 0);
205
219
  const completion = data;
206
- const [abortController, setAbortController] = useState2(null);
220
+ const [abortController, setAbortController] = useState(null);
207
221
  const extraMetadataRef = useRef2({
208
222
  credentials,
209
223
  headers,
210
224
  body
211
225
  });
212
- useEffect(() => {
226
+ useEffect2(() => {
213
227
  extraMetadataRef.current = {
214
228
  credentials,
215
229
  headers,
@@ -271,7 +285,7 @@ function useCompletion({
271
285
  },
272
286
  [triggerRequest]
273
287
  );
274
- const [input, setInput] = useState2(initialInput);
288
+ const [input, setInput] = useState(initialInput);
275
289
  const handleSubmit = useCallback2(
276
290
  (event) => {
277
291
  var _a;
@@ -310,7 +324,7 @@ import {
310
324
  isDeepEqualData,
311
325
  parsePartialJson
312
326
  } from "ai";
313
- import { useCallback as useCallback3, useId as useId2, useRef as useRef3, useState as useState3 } from "react";
327
+ import { useCallback as useCallback3, useId as useId2, useRef as useRef3, useState as useState2 } from "react";
314
328
  import useSWR2 from "swr";
315
329
  var getOriginalFetch = () => fetch;
316
330
  function useObject({
@@ -332,8 +346,8 @@ function useObject({
332
346
  null,
333
347
  { fallbackData: initialValue }
334
348
  );
335
- const [error, setError] = useState3(void 0);
336
- const [isLoading, setIsLoading] = useState3(false);
349
+ const [error, setError] = useState2(void 0);
350
+ const [isLoading, setIsLoading] = useState2(false);
337
351
  const abortControllerRef = useRef3(null);
338
352
  const stop = useCallback3(() => {
339
353
  var _a;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/use-chat.ts","../src/chat.react.ts","../src/throttle.ts","../src/use-completion.ts","../src/use-object.ts"],"sourcesContent":["import {\n AbstractChat,\n BaseChatInit,\n ChatEvent,\n convertFileListToFileUIParts,\n InferUIDataParts,\n UIDataPartSchemas,\n type ChatRequestOptions,\n type CreateUIMessage,\n type FileUIPart,\n type UIMessage,\n} from 'ai';\nimport { useCallback, useRef, useState, useSyncExternalStore } from 'react';\nimport { Chat } from './chat.react';\nimport { throttle } from './throttle';\n\nexport type { CreateUIMessage, UIMessage };\n\nexport type UseChatHelpers<\n MESSAGE_METADATA = unknown,\n DATA_PART_SCHEMAS extends UIDataPartSchemas = UIDataPartSchemas,\n> = {\n /**\n * The id of the chat.\n */\n readonly id: string;\n\n /**\n * Update the `messages` state locally. This is useful when you want to\n * edit the messages on the client, and then trigger the `reload` method\n * manually to regenerate the AI response.\n */\n setMessages: (\n messages:\n | UIMessage<MESSAGE_METADATA, InferUIDataParts<DATA_PART_SCHEMAS>>[]\n | ((\n messages: UIMessage<\n MESSAGE_METADATA,\n InferUIDataParts<DATA_PART_SCHEMAS>\n >[],\n ) => UIMessage<\n MESSAGE_METADATA,\n InferUIDataParts<DATA_PART_SCHEMAS>\n >[]),\n ) => void;\n\n /** The current value of the input */\n input: string;\n\n /** setState-powered method to update the input value */\n setInput: React.Dispatch<React.SetStateAction<string>>;\n\n /** An input/textarea-ready onChange handler to control the value of the input */\n handleInputChange: (\n e:\n | React.ChangeEvent<HTMLInputElement>\n | React.ChangeEvent<HTMLTextAreaElement>,\n ) => void;\n\n /** Form submission handler to automatically reset input and append a user message */\n handleSubmit: (\n event?: { preventDefault?: () => void },\n chatRequestOptions?: ChatRequestOptions & {\n files?: FileList | FileUIPart[];\n },\n ) => void;\n\n error: Error | undefined;\n} & Pick<\n AbstractChat<MESSAGE_METADATA, DATA_PART_SCHEMAS>,\n | 'append'\n | 'reload'\n | 'stop'\n | 'experimental_resume'\n | 'addToolResult'\n | 'status'\n | 'messages'\n>;\n\nexport type UseChatOptions<\n MESSAGE_METADATA = unknown,\n DATA_TYPE_SCHEMAS extends UIDataPartSchemas = UIDataPartSchemas,\n> = (\n | { chat: Chat<MESSAGE_METADATA, DATA_TYPE_SCHEMAS> }\n | BaseChatInit<MESSAGE_METADATA, DATA_TYPE_SCHEMAS>\n) & {\n /**\n /**\n * Initial input of the chat.\n */\n initialInput?: string;\n\n /**\nCustom throttle wait in ms for the chat messages and data updates.\nDefault is undefined, which disables throttling.\n */\n experimental_throttle?: number;\n};\n\nexport function useChat<\n MESSAGE_METADATA = unknown,\n DATA_PART_SCHEMAS extends UIDataPartSchemas = UIDataPartSchemas,\n>({\n initialInput = '',\n experimental_throttle: throttleWaitMs,\n ...options\n}: UseChatOptions<MESSAGE_METADATA, DATA_PART_SCHEMAS> = {}): UseChatHelpers<\n MESSAGE_METADATA,\n DATA_PART_SCHEMAS\n> {\n const chatRef = useRef('chat' in options ? options.chat : new Chat(options));\n\n const subscribe = useCallback(\n ({\n onStoreChange,\n eventType,\n }: {\n onStoreChange: () => void;\n eventType: ChatEvent['type'];\n }) =>\n chatRef.current.subscribe({\n onChange: event => {\n if (event.type !== eventType) return;\n onStoreChange();\n },\n }),\n [chatRef],\n );\n\n const addToolResult = useCallback(\n (\n options: Parameters<\n Chat<MESSAGE_METADATA, DATA_PART_SCHEMAS>['addToolResult']\n >[0],\n ) => chatRef.current.addToolResult(options),\n [chatRef],\n );\n\n const status = useSyncExternalStore(\n callback =>\n subscribe({\n onStoreChange: callback,\n eventType: 'status-changed',\n }),\n () => chatRef.current.status,\n () => chatRef.current.status,\n );\n\n const subscribeToChatStoreForMessages = useCallback(\n (callback: () => void) => {\n return subscribe({\n onStoreChange: throttleWaitMs\n ? throttle(callback, throttleWaitMs)\n : callback,\n eventType: 'messages-changed',\n });\n },\n [subscribe, throttleWaitMs],\n );\n\n const messages = useSyncExternalStore(\n callback => subscribeToChatStoreForMessages(callback),\n () => chatRef.current.messages,\n () => chatRef.current.messages,\n );\n\n const setMessages = useCallback(\n (\n messagesParam:\n | UIMessage<MESSAGE_METADATA, InferUIDataParts<DATA_PART_SCHEMAS>>[]\n | ((\n messages: UIMessage<\n MESSAGE_METADATA,\n InferUIDataParts<DATA_PART_SCHEMAS>\n >[],\n ) => UIMessage<\n MESSAGE_METADATA,\n InferUIDataParts<DATA_PART_SCHEMAS>\n >[]),\n ) => {\n if (typeof messagesParam === 'function') {\n messagesParam = messagesParam(messages);\n }\n\n chatRef.current.messages = messagesParam;\n },\n [chatRef, messages],\n );\n\n // Input state and handlers.\n const [input, setInput] = useState(initialInput);\n\n const handleSubmit = useCallback(\n async (\n event?: { preventDefault?: () => void },\n options: ChatRequestOptions & {\n files?: FileList | FileUIPart[];\n } = {},\n ) => {\n event?.preventDefault?.();\n\n const fileParts = Array.isArray(options?.files)\n ? options.files\n : await convertFileListToFileUIParts(options?.files);\n\n if (!input && fileParts.length === 0) return;\n\n chatRef.current.append(\n {\n id: chatRef.current.generateId(),\n role: 'user',\n metadata: undefined,\n parts: [...fileParts, { type: 'text', text: input }],\n },\n {\n headers: options.headers,\n body: options.body,\n },\n );\n\n setInput('');\n },\n [input, chatRef],\n );\n\n const handleInputChange = (e: any) => {\n setInput(e.target.value);\n };\n\n return {\n id: chatRef.current.id,\n messages,\n setMessages,\n append: chatRef.current.append,\n reload: chatRef.current.reload,\n stop: chatRef.current.stop,\n error: chatRef.current.error,\n experimental_resume: chatRef.current.experimental_resume,\n input,\n setInput,\n handleInputChange,\n handleSubmit,\n status,\n addToolResult,\n };\n}\n","import {\n AbstractChat,\n BaseChatInit,\n ChatState,\n ChatStatus,\n UIDataPartSchemas,\n UIDataTypes,\n UIMessage,\n} from 'ai';\n\nclass ReactChatState<MESSAGE_METADATA, DATA_TYPES extends UIDataTypes>\n implements ChatState<MESSAGE_METADATA, DATA_TYPES>\n{\n #messages: UIMessage<MESSAGE_METADATA, DATA_TYPES>[];\n status: ChatStatus = 'ready';\n error: Error | undefined = undefined;\n\n constructor(messages: UIMessage<MESSAGE_METADATA, DATA_TYPES>[] = []) {\n this.#messages = messages;\n }\n\n get messages() {\n return this.#messages;\n }\n\n set messages(messages: UIMessage<MESSAGE_METADATA, DATA_TYPES>[]) {\n this.#messages = [...messages];\n }\n\n pushMessage = (message: UIMessage<MESSAGE_METADATA, DATA_TYPES>) => {\n this.#messages = this.messages.concat(message);\n };\n\n popMessage = () => {\n this.#messages = this.messages.slice(0, -1);\n };\n\n replaceMessage = (\n index: number,\n message: UIMessage<MESSAGE_METADATA, DATA_TYPES>,\n ) => {\n this.#messages = [\n ...this.#messages.slice(0, index),\n message,\n ...this.#messages.slice(index + 1),\n ];\n };\n\n snapshot = <T>(value: T): T => structuredClone(value);\n}\n\nexport class Chat<\n MESSAGE_METADATA,\n UI_DATA_PART_SCHEMAS extends UIDataPartSchemas = UIDataPartSchemas,\n> extends AbstractChat<MESSAGE_METADATA, UI_DATA_PART_SCHEMAS> {\n constructor({\n messages,\n ...init\n }: BaseChatInit<MESSAGE_METADATA, UI_DATA_PART_SCHEMAS>) {\n super({ ...init, state: new ReactChatState(messages) });\n }\n}\n","import throttleFunction from 'throttleit';\n\nexport function throttle<T extends (...args: any[]) => any>(\n fn: T,\n waitMs: number | undefined,\n): T {\n return waitMs != null ? throttleFunction(fn, waitMs) : fn;\n}\n","import {\n CompletionRequestOptions,\n UseCompletionOptions,\n callCompletionApi,\n} from 'ai';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\nimport { throttle } from './throttle';\n\nexport type { UseCompletionOptions };\n\nexport type UseCompletionHelpers = {\n /** The current completion result */\n completion: string;\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 /** The error object of the API request */\n error: undefined | Error;\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: string;\n /** setState-powered method to update the input value */\n setInput: React.Dispatch<React.SetStateAction<string>>;\n /**\n * An input/textarea-ready onChange handler to control the value of the input\n * @example\n * ```jsx\n * <input onChange={handleInputChange} value={input} />\n * ```\n */\n handleInputChange: (\n event:\n | React.ChangeEvent<HTMLInputElement>\n | React.ChangeEvent<HTMLTextAreaElement>,\n ) => void;\n\n /**\n * Form submission handler to automatically reset input and append a user message\n * @example\n * ```jsx\n * <form onSubmit={handleSubmit}>\n * <input onChange={handleInputChange} value={input} />\n * </form>\n * ```\n */\n handleSubmit: (event?: { preventDefault?: () => void }) => void;\n\n /** Whether the API request is in progress */\n isLoading: boolean;\n};\n\nexport function useCompletion({\n api = '/api/completion',\n id,\n initialCompletion = '',\n initialInput = '',\n credentials,\n headers,\n body,\n streamProtocol = 'data',\n fetch,\n onFinish,\n onError,\n experimental_throttle: throttleWaitMs,\n}: UseCompletionOptions & {\n /**\n * Custom throttle wait in ms for the completion and data updates.\n * Default is undefined, which disables throttling.\n */\n experimental_throttle?: number;\n} = {}): UseCompletionHelpers {\n // Generate an unique id for the completion if not provided.\n const hookId = useId();\n const completionId = id || hookId;\n\n // Store the completion state in SWR, using the completionId as the key to share states.\n const { data, mutate } = useSWR<string>([api, completionId], null, {\n fallbackData: initialCompletion,\n });\n\n const { data: isLoading = false, mutate: mutateLoading } = useSWR<boolean>(\n [completionId, 'loading'],\n null,\n );\n\n const [error, setError] = useState<undefined | Error>(undefined);\n const completion = data!;\n\n // Abort controller to cancel the current API call.\n const [abortController, setAbortController] =\n useState<AbortController | null>(null);\n\n const extraMetadataRef = useRef({\n credentials,\n headers,\n body,\n });\n\n useEffect(() => {\n extraMetadataRef.current = {\n credentials,\n headers,\n body,\n };\n }, [credentials, headers, body]);\n\n const triggerRequest = useCallback(\n async (prompt: string, options?: CompletionRequestOptions) =>\n callCompletionApi({\n api,\n prompt,\n credentials: extraMetadataRef.current.credentials,\n headers: { ...extraMetadataRef.current.headers, ...options?.headers },\n body: {\n ...extraMetadataRef.current.body,\n ...options?.body,\n },\n streamProtocol,\n fetch,\n // throttle streamed ui updates:\n setCompletion: throttle(\n (completion: string) => mutate(completion, false),\n throttleWaitMs,\n ),\n setLoading: mutateLoading,\n setError,\n setAbortController,\n onFinish,\n onError,\n }),\n [\n mutate,\n mutateLoading,\n api,\n extraMetadataRef,\n setAbortController,\n onFinish,\n onError,\n setError,\n streamProtocol,\n fetch,\n throttleWaitMs,\n ],\n );\n\n const stop = useCallback(() => {\n if (abortController) {\n abortController.abort();\n setAbortController(null);\n }\n }, [abortController]);\n\n const setCompletion = useCallback(\n (completion: string) => {\n mutate(completion, false);\n },\n [mutate],\n );\n\n const complete = useCallback<UseCompletionHelpers['complete']>(\n async (prompt, options) => {\n return triggerRequest(prompt, options);\n },\n [triggerRequest],\n );\n\n const [input, setInput] = useState(initialInput);\n\n const handleSubmit = useCallback(\n (event?: { preventDefault?: () => void }) => {\n event?.preventDefault?.();\n return input ? complete(input) : undefined;\n },\n [input, complete],\n );\n\n const handleInputChange = useCallback(\n (e: any) => {\n setInput(e.target.value);\n },\n [setInput],\n );\n\n return {\n completion,\n complete,\n error,\n setCompletion,\n stop,\n input,\n setInput,\n handleInputChange,\n handleSubmit,\n isLoading,\n };\n}\n","import {\n FetchFunction,\n InferSchema,\n isAbortError,\n safeValidateTypes,\n} from '@ai-sdk/provider-utils';\nimport {\n asSchema,\n DeepPartial,\n isDeepEqualData,\n parsePartialJson,\n Schema,\n} from 'ai';\nimport { useCallback, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\nimport * as z3 from 'zod/v3';\nimport * as z4 from 'zod/v4/core';\n\n// use function to allow for mocking in tests:\nconst getOriginalFetch = () => fetch;\n\nexport type Experimental_UseObjectOptions<\n SCHEMA extends z4.$ZodType | z3.Schema | Schema,\n RESULT,\n> = {\n /**\n * The API endpoint. It should stream JSON that matches the schema as chunked text.\n */\n api: string;\n\n /**\n * A Zod schema that defines the shape of the complete object.\n */\n schema: SCHEMA;\n\n /**\n * An unique identifier. If not provided, a random one will be\n * generated. When provided, the `useObject` hook with the same `id` will\n * have shared states across components.\n */\n id?: string;\n\n /**\n * An optional value for the initial object.\n */\n initialValue?: DeepPartial<RESULT>;\n\n /**\nCustom fetch implementation. You can use it as a middleware to intercept requests,\nor to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n\n /**\nCallback that is called when the stream has finished.\n */\n onFinish?: (event: {\n /**\nThe generated object (typed according to the schema).\nCan be undefined if the final object does not match the schema.\n */\n object: RESULT | undefined;\n\n /**\nOptional error object. This is e.g. a TypeValidationError when the final object does not match the schema.\n */\n error: Error | undefined;\n }) => Promise<void> | void;\n\n /**\n * Callback function to be called when an error is encountered.\n */\n onError?: (error: Error) => void;\n\n /**\n * Additional HTTP headers to be included in the request.\n */\n headers?: Record<string, string> | Headers;\n\n /**\n * The credentials mode to be used for the fetch request.\n * Possible values are: 'omit', 'same-origin', 'include'.\n * Defaults to 'same-origin'.\n */\n credentials?: RequestCredentials;\n};\n\nexport type Experimental_UseObjectHelpers<RESULT, INPUT> = {\n /**\n * Calls the API with the provided input as JSON body.\n */\n submit: (input: INPUT) => void;\n\n /**\n * The current value for the generated object. Updated as the API streams JSON chunks.\n */\n object: DeepPartial<RESULT> | undefined;\n\n /**\n * The error object of the API request if any.\n */\n error: Error | undefined;\n\n /**\n * Flag that indicates whether an API request is in progress.\n */\n isLoading: boolean;\n\n /**\n * Abort the current request immediately, keep the current partial object if any.\n */\n stop: () => void;\n};\n\nfunction useObject<\n SCHEMA extends z4.$ZodType | z3.Schema | Schema,\n RESULT = InferSchema<SCHEMA>,\n INPUT = any,\n>({\n api,\n id,\n schema, // required, in the future we will use it for validation\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 if not provided.\n const hookId = useId();\n const completionId = id ?? hookId;\n\n // Store the completion state in SWR, using the completionId as the key to share states.\n const { data, mutate } = useSWR<DeepPartial<RESULT>>(\n [api, completionId],\n null,\n { fallbackData: initialValue },\n );\n\n const [error, setError] = useState<undefined | Error>(undefined);\n const [isLoading, setIsLoading] = useState(false);\n\n // Abort controller to cancel the current API call.\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const stop = useCallback(() => {\n try {\n abortControllerRef.current?.abort();\n } catch (ignored) {\n } finally {\n setIsLoading(false);\n abortControllerRef.current = null;\n }\n }, []);\n\n const submit = async (input: INPUT) => {\n try {\n mutate(undefined); // reset the data\n setIsLoading(true);\n setError(undefined);\n\n const abortController = new AbortController();\n abortControllerRef.current = 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,\n },\n credentials,\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 == null) {\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\n const { value } = await parsePartialJson(accumulatedText);\n const currentObject = value as DeepPartial<RESULT>;\n\n if (!isDeepEqualData(latestObject, currentObject)) {\n latestObject = currentObject;\n\n mutate(currentObject);\n }\n },\n\n async close() {\n setIsLoading(false);\n abortControllerRef.current = null;\n\n if (onFinish != null) {\n const validationResult = await safeValidateTypes({\n value: latestObject,\n schema: asSchema(schema),\n });\n\n onFinish(\n validationResult.success\n ? { object: validationResult.value, error: undefined }\n : { object: undefined, error: validationResult.error },\n );\n }\n },\n }),\n );\n } catch (error) {\n if (isAbortError(error)) {\n return;\n }\n\n if (onError && error instanceof Error) {\n onError(error);\n }\n\n setIsLoading(false);\n setError(error instanceof Error ? error : new Error(String(error)));\n }\n };\n\n return {\n submit,\n object: data,\n error,\n isLoading,\n stop,\n };\n}\n\nexport const experimental_useObject = useObject;\n"],"mappings":"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","names":["options","useCallback","useRef","useState","fetch","useState","useRef","useCallback","completion","useCallback","useId","useRef","useState","useSWR","fetch","error"]}
1
+ {"version":3,"sources":["../src/use-chat.ts","../src/chat.react.ts","../src/throttle.ts","../src/use-completion.ts","../src/use-object.ts"],"sourcesContent":["import {\n AbstractChat,\n ChatInit,\n type CreateUIMessage,\n type UIMessage,\n} from 'ai';\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from 'react';\nimport { Chat } from './chat.react';\n\nexport type { CreateUIMessage, UIMessage };\n\nexport type UseChatHelpers<UI_MESSAGE extends UIMessage> = {\n /**\n * The id of the chat.\n */\n readonly id: string;\n\n /**\n * Update the `messages` state locally. This is useful when you want to\n * edit the messages on the client, and then trigger the `reload` method\n * manually to regenerate the AI response.\n */\n setMessages: (\n messages: UI_MESSAGE[] | ((messages: UI_MESSAGE[]) => UI_MESSAGE[]),\n ) => void;\n\n error: Error | undefined;\n} & Pick<\n AbstractChat<UI_MESSAGE>,\n | 'sendMessage'\n | 'regenerate'\n | 'stop'\n | 'resumeStream'\n | 'addToolResult'\n | 'status'\n | 'messages'\n>;\n\nexport type UseChatOptions<UI_MESSAGE extends UIMessage> = (\n | { chat: Chat<UI_MESSAGE> }\n | ChatInit<UI_MESSAGE>\n) & {\n /**\nCustom throttle wait in ms for the chat messages and data updates.\nDefault is undefined, which disables throttling.\n */\n experimental_throttle?: number;\n\n /**\n * Whether to resume an ongoing chat generation stream.\n */\n resume?: boolean;\n};\n\nexport function useChat<UI_MESSAGE extends UIMessage = UIMessage>({\n experimental_throttle: throttleWaitMs,\n resume = false,\n ...options\n}: UseChatOptions<UI_MESSAGE> = {}): UseChatHelpers<UI_MESSAGE> {\n const chatRef = useRef('chat' in options ? options.chat : new Chat(options));\n\n const subscribeToMessages = useCallback(\n (update: () => void) =>\n chatRef.current['~registerMessagesCallback'](update, throttleWaitMs),\n [throttleWaitMs],\n );\n\n const messages = useSyncExternalStore(\n subscribeToMessages,\n () => chatRef.current.messages,\n () => chatRef.current.messages,\n );\n\n const status = useSyncExternalStore(\n chatRef.current['~registerStatusCallback'],\n () => chatRef.current.status,\n () => chatRef.current.status,\n );\n\n const error = useSyncExternalStore(\n chatRef.current['~registerErrorCallback'],\n () => chatRef.current.error,\n () => chatRef.current.error,\n );\n\n const setMessages = useCallback(\n (\n messagesParam: UI_MESSAGE[] | ((messages: UI_MESSAGE[]) => UI_MESSAGE[]),\n ) => {\n if (typeof messagesParam === 'function') {\n messagesParam = messagesParam(messages);\n }\n\n chatRef.current.messages = messagesParam;\n },\n [messages, chatRef],\n );\n\n useEffect(() => {\n if (resume) {\n chatRef.current.resumeStream();\n }\n }, [resume, chatRef]);\n\n return {\n id: chatRef.current.id,\n messages,\n setMessages,\n sendMessage: chatRef.current.sendMessage,\n regenerate: chatRef.current.regenerate,\n stop: chatRef.current.stop,\n error,\n resumeStream: chatRef.current.resumeStream,\n status,\n addToolResult: chatRef.current.addToolResult,\n };\n}\n","import { AbstractChat, ChatInit, ChatState, ChatStatus, UIMessage } from 'ai';\nimport { throttle } from './throttle';\n\nclass ReactChatState<UI_MESSAGE extends UIMessage>\n implements ChatState<UI_MESSAGE>\n{\n #messages: UI_MESSAGE[];\n #status: ChatStatus = 'ready';\n #error: Error | undefined = undefined;\n\n #messagesCallbacks = new Set<() => void>();\n #statusCallbacks = new Set<() => void>();\n #errorCallbacks = new Set<() => void>();\n\n constructor(initialMessages: UI_MESSAGE[] = []) {\n this.#messages = initialMessages;\n }\n\n get status(): ChatStatus {\n return this.#status;\n }\n\n set status(newStatus: ChatStatus) {\n this.#status = newStatus;\n this.#callStatusCallbacks();\n }\n\n get error(): Error | undefined {\n return this.#error;\n }\n\n set error(newError: Error | undefined) {\n this.#error = newError;\n this.#callErrorCallbacks();\n }\n\n get messages(): UI_MESSAGE[] {\n return this.#messages;\n }\n\n set messages(newMessages: UI_MESSAGE[]) {\n this.#messages = [...newMessages];\n this.#callMessagesCallbacks();\n }\n\n pushMessage = (message: UI_MESSAGE) => {\n this.#messages = this.#messages.concat(message);\n this.#callMessagesCallbacks();\n };\n\n popMessage = () => {\n this.#messages = this.#messages.slice(0, -1);\n this.#callMessagesCallbacks();\n };\n\n replaceMessage = (index: number, message: UI_MESSAGE) => {\n this.#messages = [\n ...this.#messages.slice(0, index),\n // We deep clone the message here to ensure the new React Compiler (currently in RC) detects deeply nested parts/metadata changes:\n this.snapshot(message),\n ...this.#messages.slice(index + 1),\n ];\n this.#callMessagesCallbacks();\n };\n\n snapshot = <T>(value: T): T => structuredClone(value);\n\n '~registerMessagesCallback' = (\n onChange: () => void,\n throttleWaitMs?: number,\n ): (() => void) => {\n const callback = throttleWaitMs\n ? throttle(onChange, throttleWaitMs)\n : onChange;\n this.#messagesCallbacks.add(callback);\n return () => {\n this.#messagesCallbacks.delete(callback);\n };\n };\n\n '~registerStatusCallback' = (onChange: () => void): (() => void) => {\n this.#statusCallbacks.add(onChange);\n return () => {\n this.#statusCallbacks.delete(onChange);\n };\n };\n\n '~registerErrorCallback' = (onChange: () => void): (() => void) => {\n this.#errorCallbacks.add(onChange);\n return () => {\n this.#errorCallbacks.delete(onChange);\n };\n };\n\n #callMessagesCallbacks = () => {\n this.#messagesCallbacks.forEach(callback => callback());\n };\n\n #callStatusCallbacks = () => {\n this.#statusCallbacks.forEach(callback => callback());\n };\n\n #callErrorCallbacks = () => {\n this.#errorCallbacks.forEach(callback => callback());\n };\n}\n\nexport class Chat<\n UI_MESSAGE extends UIMessage,\n> extends AbstractChat<UI_MESSAGE> {\n #state: ReactChatState<UI_MESSAGE>;\n\n constructor({ messages, ...init }: ChatInit<UI_MESSAGE>) {\n const state = new ReactChatState(messages);\n super({ ...init, state });\n this.#state = state;\n }\n\n '~registerMessagesCallback' = (\n onChange: () => void,\n throttleWaitMs?: number,\n ): (() => void) =>\n this.#state['~registerMessagesCallback'](onChange, throttleWaitMs);\n\n '~registerStatusCallback' = (onChange: () => void): (() => void) =>\n this.#state['~registerStatusCallback'](onChange);\n\n '~registerErrorCallback' = (onChange: () => void): (() => void) =>\n this.#state['~registerErrorCallback'](onChange);\n}\n","import throttleFunction from 'throttleit';\n\nexport function throttle<T extends (...args: any[]) => any>(\n fn: T,\n waitMs: number | undefined,\n): T {\n return waitMs != null ? throttleFunction(fn, waitMs) : fn;\n}\n","import {\n CompletionRequestOptions,\n UseCompletionOptions,\n callCompletionApi,\n} from 'ai';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\nimport { throttle } from './throttle';\n\nexport type { UseCompletionOptions };\n\nexport type UseCompletionHelpers = {\n /** The current completion result */\n completion: string;\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 /** The error object of the API request */\n error: undefined | Error;\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: string;\n /** setState-powered method to update the input value */\n setInput: React.Dispatch<React.SetStateAction<string>>;\n /**\n * An input/textarea-ready onChange handler to control the value of the input\n * @example\n * ```jsx\n * <input onChange={handleInputChange} value={input} />\n * ```\n */\n handleInputChange: (\n event:\n | React.ChangeEvent<HTMLInputElement>\n | React.ChangeEvent<HTMLTextAreaElement>,\n ) => void;\n\n /**\n * Form submission handler to automatically reset input and append a user message\n * @example\n * ```jsx\n * <form onSubmit={handleSubmit}>\n * <input onChange={handleInputChange} value={input} />\n * </form>\n * ```\n */\n handleSubmit: (event?: { preventDefault?: () => void }) => void;\n\n /** Whether the API request is in progress */\n isLoading: boolean;\n};\n\nexport function useCompletion({\n api = '/api/completion',\n id,\n initialCompletion = '',\n initialInput = '',\n credentials,\n headers,\n body,\n streamProtocol = 'data',\n fetch,\n onFinish,\n onError,\n experimental_throttle: throttleWaitMs,\n}: UseCompletionOptions & {\n /**\n * Custom throttle wait in ms for the completion and data updates.\n * Default is undefined, which disables throttling.\n */\n experimental_throttle?: number;\n} = {}): UseCompletionHelpers {\n // Generate an unique id for the completion if not provided.\n const hookId = useId();\n const completionId = id || hookId;\n\n // Store the completion state in SWR, using the completionId as the key to share states.\n const { data, mutate } = useSWR<string>([api, completionId], null, {\n fallbackData: initialCompletion,\n });\n\n const { data: isLoading = false, mutate: mutateLoading } = useSWR<boolean>(\n [completionId, 'loading'],\n null,\n );\n\n const [error, setError] = useState<undefined | Error>(undefined);\n const completion = data!;\n\n // Abort controller to cancel the current API call.\n const [abortController, setAbortController] =\n useState<AbortController | null>(null);\n\n const extraMetadataRef = useRef({\n credentials,\n headers,\n body,\n });\n\n useEffect(() => {\n extraMetadataRef.current = {\n credentials,\n headers,\n body,\n };\n }, [credentials, headers, body]);\n\n const triggerRequest = useCallback(\n async (prompt: string, options?: CompletionRequestOptions) =>\n callCompletionApi({\n api,\n prompt,\n credentials: extraMetadataRef.current.credentials,\n headers: { ...extraMetadataRef.current.headers, ...options?.headers },\n body: {\n ...extraMetadataRef.current.body,\n ...options?.body,\n },\n streamProtocol,\n fetch,\n // throttle streamed ui updates:\n setCompletion: throttle(\n (completion: string) => mutate(completion, false),\n throttleWaitMs,\n ),\n setLoading: mutateLoading,\n setError,\n setAbortController,\n onFinish,\n onError,\n }),\n [\n mutate,\n mutateLoading,\n api,\n extraMetadataRef,\n setAbortController,\n onFinish,\n onError,\n setError,\n streamProtocol,\n fetch,\n throttleWaitMs,\n ],\n );\n\n const stop = useCallback(() => {\n if (abortController) {\n abortController.abort();\n setAbortController(null);\n }\n }, [abortController]);\n\n const setCompletion = useCallback(\n (completion: string) => {\n mutate(completion, false);\n },\n [mutate],\n );\n\n const complete = useCallback<UseCompletionHelpers['complete']>(\n async (prompt, options) => {\n return triggerRequest(prompt, options);\n },\n [triggerRequest],\n );\n\n const [input, setInput] = useState(initialInput);\n\n const handleSubmit = useCallback(\n (event?: { preventDefault?: () => void }) => {\n event?.preventDefault?.();\n return input ? complete(input) : undefined;\n },\n [input, complete],\n );\n\n const handleInputChange = useCallback(\n (e: any) => {\n setInput(e.target.value);\n },\n [setInput],\n );\n\n return {\n completion,\n complete,\n error,\n setCompletion,\n stop,\n input,\n setInput,\n handleInputChange,\n handleSubmit,\n isLoading,\n };\n}\n","import {\n FetchFunction,\n InferSchema,\n isAbortError,\n safeValidateTypes,\n} from '@ai-sdk/provider-utils';\nimport {\n asSchema,\n DeepPartial,\n isDeepEqualData,\n parsePartialJson,\n Schema,\n} from 'ai';\nimport { useCallback, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\nimport * as z3 from 'zod/v3';\nimport * as z4 from 'zod/v4';\n\n// use function to allow for mocking in tests:\nconst getOriginalFetch = () => fetch;\n\nexport type Experimental_UseObjectOptions<\n SCHEMA extends z4.ZodType | z3.Schema | Schema,\n RESULT,\n> = {\n /**\n * The API endpoint. It should stream JSON that matches the schema as chunked text.\n */\n api: string;\n\n /**\n * A Zod schema that defines the shape of the complete object.\n */\n schema: SCHEMA;\n\n /**\n * An unique identifier. If not provided, a random one will be\n * generated. When provided, the `useObject` hook with the same `id` will\n * have shared states across components.\n */\n id?: string;\n\n /**\n * An optional value for the initial object.\n */\n initialValue?: DeepPartial<RESULT>;\n\n /**\nCustom fetch implementation. You can use it as a middleware to intercept requests,\nor to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n\n /**\nCallback that is called when the stream has finished.\n */\n onFinish?: (event: {\n /**\nThe generated object (typed according to the schema).\nCan be undefined if the final object does not match the schema.\n */\n object: RESULT | undefined;\n\n /**\nOptional error object. This is e.g. a TypeValidationError when the final object does not match the schema.\n */\n error: Error | undefined;\n }) => Promise<void> | void;\n\n /**\n * Callback function to be called when an error is encountered.\n */\n onError?: (error: Error) => void;\n\n /**\n * Additional HTTP headers to be included in the request.\n */\n headers?: Record<string, string> | Headers;\n\n /**\n * The credentials mode to be used for the fetch request.\n * Possible values are: 'omit', 'same-origin', 'include'.\n * Defaults to 'same-origin'.\n */\n credentials?: RequestCredentials;\n};\n\nexport type Experimental_UseObjectHelpers<RESULT, INPUT> = {\n /**\n * Calls the API with the provided input as JSON body.\n */\n submit: (input: INPUT) => void;\n\n /**\n * The current value for the generated object. Updated as the API streams JSON chunks.\n */\n object: DeepPartial<RESULT> | undefined;\n\n /**\n * The error object of the API request if any.\n */\n error: Error | undefined;\n\n /**\n * Flag that indicates whether an API request is in progress.\n */\n isLoading: boolean;\n\n /**\n * Abort the current request immediately, keep the current partial object if any.\n */\n stop: () => void;\n};\n\nfunction useObject<\n SCHEMA extends z4.ZodType | z3.Schema | Schema,\n RESULT = InferSchema<SCHEMA>,\n INPUT = any,\n>({\n api,\n id,\n schema, // required, in the future we will use it for validation\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 if not provided.\n const hookId = useId();\n const completionId = id ?? hookId;\n\n // Store the completion state in SWR, using the completionId as the key to share states.\n const { data, mutate } = useSWR<DeepPartial<RESULT>>(\n [api, completionId],\n null,\n { fallbackData: initialValue },\n );\n\n const [error, setError] = useState<undefined | Error>(undefined);\n const [isLoading, setIsLoading] = useState(false);\n\n // Abort controller to cancel the current API call.\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const stop = useCallback(() => {\n try {\n abortControllerRef.current?.abort();\n } catch (ignored) {\n } finally {\n setIsLoading(false);\n abortControllerRef.current = null;\n }\n }, []);\n\n const submit = async (input: INPUT) => {\n try {\n mutate(undefined); // reset the data\n setIsLoading(true);\n setError(undefined);\n\n const abortController = new AbortController();\n abortControllerRef.current = 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,\n },\n credentials,\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 == null) {\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\n const { value } = await parsePartialJson(accumulatedText);\n const currentObject = value as DeepPartial<RESULT>;\n\n if (!isDeepEqualData(latestObject, currentObject)) {\n latestObject = currentObject;\n\n mutate(currentObject);\n }\n },\n\n async close() {\n setIsLoading(false);\n abortControllerRef.current = null;\n\n if (onFinish != null) {\n const validationResult = await safeValidateTypes({\n value: latestObject,\n schema: asSchema(schema),\n });\n\n onFinish(\n validationResult.success\n ? { object: validationResult.value, error: undefined }\n : { object: undefined, error: validationResult.error },\n );\n }\n },\n }),\n );\n } catch (error) {\n if (isAbortError(error)) {\n return;\n }\n\n if (onError && error instanceof Error) {\n onError(error);\n }\n\n setIsLoading(false);\n setError(error instanceof Error ? error : new Error(String(error)));\n }\n };\n\n return {\n submit,\n object: data,\n error,\n isLoading,\n stop,\n };\n}\n\nexport const experimental_useObject = useObject;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAMA,SAAS,aAAa,WAAW,QAAQ,4BAA4B;;;ACNrE,SAAS,oBAAgE;;;ACAzE,OAAO,sBAAsB;AAEtB,SAAS,SACd,IACA,QACG;AACH,SAAO,UAAU,OAAO,iBAAiB,IAAI,MAAM,IAAI;AACzD;;;ADPA;AAGA,IAAM,iBAAN,MAEA;AAAA,EASE,YAAY,kBAAgC,CAAC,GAAG;AARhD;AACA,gCAAsB;AACtB,+BAA4B;AAE5B,2CAAqB,oBAAI,IAAgB;AACzC,yCAAmB,oBAAI,IAAgB;AACvC,wCAAkB,oBAAI,IAAgB;AAiCtC,uBAAc,CAAC,YAAwB;AACrC,yBAAK,WAAY,mBAAK,WAAU,OAAO,OAAO;AAC9C,yBAAK,wBAAL;AAAA,IACF;AAEA,sBAAa,MAAM;AACjB,yBAAK,WAAY,mBAAK,WAAU,MAAM,GAAG,EAAE;AAC3C,yBAAK,wBAAL;AAAA,IACF;AAEA,0BAAiB,CAAC,OAAe,YAAwB;AACvD,yBAAK,WAAY;AAAA,QACf,GAAG,mBAAK,WAAU,MAAM,GAAG,KAAK;AAAA;AAAA,QAEhC,KAAK,SAAS,OAAO;AAAA,QACrB,GAAG,mBAAK,WAAU,MAAM,QAAQ,CAAC;AAAA,MACnC;AACA,yBAAK,wBAAL;AAAA,IACF;AAEA,oBAAW,CAAI,UAAgB,gBAAgB,KAAK;AAEpD,wCAA8B,CAC5B,UACA,mBACiB;AACjB,YAAM,WAAW,iBACb,SAAS,UAAU,cAAc,IACjC;AACJ,yBAAK,oBAAmB,IAAI,QAAQ;AACpC,aAAO,MAAM;AACX,2BAAK,oBAAmB,OAAO,QAAQ;AAAA,MACzC;AAAA,IACF;AAEA,sCAA4B,CAAC,aAAuC;AAClE,yBAAK,kBAAiB,IAAI,QAAQ;AAClC,aAAO,MAAM;AACX,2BAAK,kBAAiB,OAAO,QAAQ;AAAA,MACvC;AAAA,IACF;AAEA,qCAA2B,CAAC,aAAuC;AACjE,yBAAK,iBAAgB,IAAI,QAAQ;AACjC,aAAO,MAAM;AACX,2BAAK,iBAAgB,OAAO,QAAQ;AAAA,MACtC;AAAA,IACF;AAEA,+CAAyB,MAAM;AAC7B,yBAAK,oBAAmB,QAAQ,cAAY,SAAS,CAAC;AAAA,IACxD;AAEA,6CAAuB,MAAM;AAC3B,yBAAK,kBAAiB,QAAQ,cAAY,SAAS,CAAC;AAAA,IACtD;AAEA,4CAAsB,MAAM;AAC1B,yBAAK,iBAAgB,QAAQ,cAAY,SAAS,CAAC;AAAA,IACrD;AAzFE,uBAAK,WAAY;AAAA,EACnB;AAAA,EAEA,IAAI,SAAqB;AACvB,WAAO,mBAAK;AAAA,EACd;AAAA,EAEA,IAAI,OAAO,WAAuB;AAChC,uBAAK,SAAU;AACf,uBAAK,sBAAL;AAAA,EACF;AAAA,EAEA,IAAI,QAA2B;AAC7B,WAAO,mBAAK;AAAA,EACd;AAAA,EAEA,IAAI,MAAM,UAA6B;AACrC,uBAAK,QAAS;AACd,uBAAK,qBAAL;AAAA,EACF;AAAA,EAEA,IAAI,WAAyB;AAC3B,WAAO,mBAAK;AAAA,EACd;AAAA,EAEA,IAAI,SAAS,aAA2B;AACtC,uBAAK,WAAY,CAAC,GAAG,WAAW;AAChC,uBAAK,wBAAL;AAAA,EACF;AA8DF;AAnGE;AACA;AACA;AAEA;AACA;AACA;AAkFA;AAIA;AAIA;AAtGF;AA2GO,IAAM,OAAN,cAEG,aAAyB;AAAA,EAGjC,YAAY,EAAE,UAAU,GAAG,KAAK,GAAyB;AACvD,UAAM,QAAQ,IAAI,eAAe,QAAQ;AACzC,UAAM,EAAE,GAAG,MAAM,MAAM,CAAC;AAJ1B;AAQA,wCAA8B,CAC5B,UACA,mBAEA,mBAAK,QAAO,2BAA2B,EAAE,UAAU,cAAc;AAEnE,sCAA4B,CAAC,aAC3B,mBAAK,QAAO,yBAAyB,EAAE,QAAQ;AAEjD,qCAA2B,CAAC,aAC1B,mBAAK,QAAO,wBAAwB,EAAE,QAAQ;AAb9C,uBAAK,QAAS;AAAA,EAChB;AAaF;AAnBE;;;ADxDK,SAAS,QAAkD;AAAA,EAChE,uBAAuB;AAAA,EACvB,SAAS;AAAA,EACT,GAAG;AACL,IAAgC,CAAC,GAA+B;AAC9D,QAAM,UAAU,OAAO,UAAU,UAAU,QAAQ,OAAO,IAAI,KAAK,OAAO,CAAC;AAE3E,QAAM,sBAAsB;AAAA,IAC1B,CAAC,WACC,QAAQ,QAAQ,2BAA2B,EAAE,QAAQ,cAAc;AAAA,IACrE,CAAC,cAAc;AAAA,EACjB;AAEA,QAAM,WAAW;AAAA,IACf;AAAA,IACA,MAAM,QAAQ,QAAQ;AAAA,IACtB,MAAM,QAAQ,QAAQ;AAAA,EACxB;AAEA,QAAM,SAAS;AAAA,IACb,QAAQ,QAAQ,yBAAyB;AAAA,IACzC,MAAM,QAAQ,QAAQ;AAAA,IACtB,MAAM,QAAQ,QAAQ;AAAA,EACxB;AAEA,QAAM,QAAQ;AAAA,IACZ,QAAQ,QAAQ,wBAAwB;AAAA,IACxC,MAAM,QAAQ,QAAQ;AAAA,IACtB,MAAM,QAAQ,QAAQ;AAAA,EACxB;AAEA,QAAM,cAAc;AAAA,IAClB,CACE,kBACG;AACH,UAAI,OAAO,kBAAkB,YAAY;AACvC,wBAAgB,cAAc,QAAQ;AAAA,MACxC;AAEA,cAAQ,QAAQ,WAAW;AAAA,IAC7B;AAAA,IACA,CAAC,UAAU,OAAO;AAAA,EACpB;AAEA,YAAU,MAAM;AACd,QAAI,QAAQ;AACV,cAAQ,QAAQ,aAAa;AAAA,IAC/B;AAAA,EACF,GAAG,CAAC,QAAQ,OAAO,CAAC;AAEpB,SAAO;AAAA,IACL,IAAI,QAAQ,QAAQ;AAAA,IACpB;AAAA,IACA;AAAA,IACA,aAAa,QAAQ,QAAQ;AAAA,IAC7B,YAAY,QAAQ,QAAQ;AAAA,IAC5B,MAAM,QAAQ,QAAQ;AAAA,IACtB;AAAA,IACA,cAAc,QAAQ,QAAQ;AAAA,IAC9B;AAAA,IACA,eAAe,QAAQ,QAAQ;AAAA,EACjC;AACF;;;AGpHA;AAAA,EAGE;AAAA,OACK;AACP,SAAS,eAAAA,cAAa,aAAAC,YAAW,OAAO,UAAAC,SAAQ,gBAAgB;AAChE,OAAO,YAAY;AAyDZ,SAAS,cAAc;AAAA,EAC5B,MAAM;AAAA,EACN;AAAA,EACA,oBAAoB;AAAA,EACpB,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB,OAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA,uBAAuB;AACzB,IAMI,CAAC,GAAyB;AAE5B,QAAM,SAAS,MAAM;AACrB,QAAM,eAAe,MAAM;AAG3B,QAAM,EAAE,MAAM,OAAO,IAAI,OAAe,CAAC,KAAK,YAAY,GAAG,MAAM;AAAA,IACjE,cAAc;AAAA,EAChB,CAAC;AAED,QAAM,EAAE,MAAM,YAAY,OAAO,QAAQ,cAAc,IAAI;AAAA,IACzD,CAAC,cAAc,SAAS;AAAA,IACxB;AAAA,EACF;AAEA,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA4B,MAAS;AAC/D,QAAM,aAAa;AAGnB,QAAM,CAAC,iBAAiB,kBAAkB,IACxC,SAAiC,IAAI;AAEvC,QAAM,mBAAmBC,QAAO;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,EAAAC,WAAU,MAAM;AACd,qBAAiB,UAAU;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,GAAG,CAAC,aAAa,SAAS,IAAI,CAAC;AAE/B,QAAM,iBAAiBC;AAAA,IACrB,OAAO,QAAgB,YACrB,kBAAkB;AAAA,MAChB;AAAA,MACA;AAAA,MACA,aAAa,iBAAiB,QAAQ;AAAA,MACtC,SAAS,EAAE,GAAG,iBAAiB,QAAQ,SAAS,GAAG,mCAAS,QAAQ;AAAA,MACpE,MAAM;AAAA,QACJ,GAAG,iBAAiB,QAAQ;AAAA,QAC5B,GAAG,mCAAS;AAAA,MACd;AAAA,MACA;AAAA,MACA,OAAAH;AAAA;AAAA,MAEA,eAAe;AAAA,QACb,CAACI,gBAAuB,OAAOA,aAAY,KAAK;AAAA,QAChD;AAAA,MACF;AAAA,MACA,YAAY;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACAJ;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAOG,aAAY,MAAM;AAC7B,QAAI,iBAAiB;AACnB,sBAAgB,MAAM;AACtB,yBAAmB,IAAI;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,eAAe,CAAC;AAEpB,QAAM,gBAAgBA;AAAA,IACpB,CAACC,gBAAuB;AACtB,aAAOA,aAAY,KAAK;AAAA,IAC1B;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,WAAWD;AAAA,IACf,OAAO,QAAQ,YAAY;AACzB,aAAO,eAAe,QAAQ,OAAO;AAAA,IACvC;AAAA,IACA,CAAC,cAAc;AAAA,EACjB;AAEA,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,YAAY;AAE/C,QAAM,eAAeA;AAAA,IACnB,CAAC,UAA4C;AArLjD;AAsLM,2CAAO,mBAAP;AACA,aAAO,QAAQ,SAAS,KAAK,IAAI;AAAA,IACnC;AAAA,IACA,CAAC,OAAO,QAAQ;AAAA,EAClB;AAEA,QAAM,oBAAoBA;AAAA,IACxB,CAAC,MAAW;AACV,eAAS,EAAE,OAAO,KAAK;AAAA,IACzB;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC/MA;AAAA,EAGE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,eAAAE,cAAa,SAAAC,QAAO,UAAAC,SAAQ,YAAAC,iBAAgB;AACrD,OAAOC,aAAY;AAKnB,IAAM,mBAAmB,MAAM;AA+F/B,SAAS,UAIP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EACA;AAAA,EACA,OAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAGiD;AAE/C,QAAM,SAASJ,OAAM;AACrB,QAAM,eAAe,kBAAM;AAG3B,QAAM,EAAE,MAAM,OAAO,IAAIG;AAAA,IACvB,CAAC,KAAK,YAAY;AAAA,IAClB;AAAA,IACA,EAAE,cAAc,aAAa;AAAA,EAC/B;AAEA,QAAM,CAAC,OAAO,QAAQ,IAAID,UAA4B,MAAS;AAC/D,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,KAAK;AAGhD,QAAM,qBAAqBD,QAA+B,IAAI;AAE9D,QAAM,OAAOF,aAAY,MAAM;AArJjC;AAsJI,QAAI;AACF,+BAAmB,YAAnB,mBAA4B;AAAA,IAC9B,SAAS,SAAS;AAAA,IAClB,UAAE;AACA,mBAAa,KAAK;AAClB,yBAAmB,UAAU;AAAA,IAC/B;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,SAAS,OAAO,UAAiB;AA/JzC;AAgKI,QAAI;AACF,aAAO,MAAS;AAChB,mBAAa,IAAI;AACjB,eAAS,MAAS;AAElB,YAAM,kBAAkB,IAAI,gBAAgB;AAC5C,yBAAmB,UAAU;AAE7B,YAAM,cAAcK,UAAA,OAAAA,SAAS,iBAAiB;AAC9C,YAAM,WAAW,MAAM,YAAY,KAAK;AAAA,QACtC,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,GAAG;AAAA,QACL;AAAA,QACA;AAAA,QACA,QAAQ,gBAAgB;AAAA,QACxB,MAAM,KAAK,UAAU,KAAK;AAAA,MAC5B,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI;AAAA,WACP,WAAM,SAAS,KAAK,MAApB,YAA0B;AAAA,QAC7B;AAAA,MACF;AAEA,UAAI,SAAS,QAAQ,MAAM;AACzB,cAAM,IAAI,MAAM,6BAA6B;AAAA,MAC/C;AAEA,UAAI,kBAAkB;AACtB,UAAI,eAAgD;AAEpD,YAAM,SAAS,KAAK,YAAY,IAAI,kBAAkB,CAAC,EAAE;AAAA,QACvD,IAAI,eAAuB;AAAA,UACzB,MAAM,MAAM,OAAO;AACjB,+BAAmB;AAEnB,kBAAM,EAAE,MAAM,IAAI,MAAM,iBAAiB,eAAe;AACxD,kBAAM,gBAAgB;AAEtB,gBAAI,CAAC,gBAAgB,cAAc,aAAa,GAAG;AACjD,6BAAe;AAEf,qBAAO,aAAa;AAAA,YACtB;AAAA,UACF;AAAA,UAEA,MAAM,QAAQ;AACZ,yBAAa,KAAK;AAClB,+BAAmB,UAAU;AAE7B,gBAAI,YAAY,MAAM;AACpB,oBAAM,mBAAmB,MAAM,kBAAkB;AAAA,gBAC/C,OAAO;AAAA,gBACP,QAAQ,SAAS,MAAM;AAAA,cACzB,CAAC;AAED;AAAA,gBACE,iBAAiB,UACb,EAAE,QAAQ,iBAAiB,OAAO,OAAO,OAAU,IACnD,EAAE,QAAQ,QAAW,OAAO,iBAAiB,MAAM;AAAA,cACzD;AAAA,YACF;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,SAASC,QAAO;AACd,UAAI,aAAaA,MAAK,GAAG;AACvB;AAAA,MACF;AAEA,UAAI,WAAWA,kBAAiB,OAAO;AACrC,gBAAQA,MAAK;AAAA,MACf;AAEA,mBAAa,KAAK;AAClB,eAASA,kBAAiB,QAAQA,SAAQ,IAAI,MAAM,OAAOA,MAAK,CAAC,CAAC;AAAA,IACpE;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,IAAM,yBAAyB;","names":["useCallback","useEffect","useRef","fetch","useRef","useEffect","useCallback","completion","useCallback","useId","useRef","useState","useSWR","fetch","error"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/react",
3
- "version": "2.0.0-alpha.9",
3
+ "version": "2.0.0-beta.2",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -21,8 +21,8 @@
21
21
  "dependencies": {
22
22
  "swr": "^2.2.5",
23
23
  "throttleit": "2.1.0",
24
- "ai": "5.0.0-alpha.9",
25
- "@ai-sdk/provider-utils": "3.0.0-alpha.9"
24
+ "ai": "5.0.0-beta.2",
25
+ "@ai-sdk/provider-utils": "3.0.0-beta.2"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@testing-library/jest-dom": "^6.6.3",