@ai-sdk/react 0.0.15 → 0.0.17
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/.turbo/turbo-build.log +10 -10
- package/.turbo/turbo-clean.log +1 -1
- package/CHANGELOG.md +16 -0
- package/dist/index.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +20 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +20 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/use-chat.ts +16 -10
- package/src/use-chat.ui.test.tsx +78 -0
- package/src/use-object.ts +10 -0
- package/src/use-object.ui.test.tsx +107 -136
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @ai-sdk/react@0.0.
|
|
2
|
+
> @ai-sdk/react@0.0.17 build /home/runner/work/ai/ai/packages/react
|
|
3
3
|
> tsup
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
[34mCLI[39m Target: es2018
|
|
10
10
|
[34mCJS[39m Build start
|
|
11
11
|
[34mESM[39m Build start
|
|
12
|
-
[
|
|
13
|
-
[
|
|
14
|
-
[
|
|
15
|
-
[
|
|
16
|
-
[
|
|
17
|
-
[
|
|
12
|
+
[32mCJS[39m [1mdist/index.js [22m[32m24.41 KB[39m
|
|
13
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m49.29 KB[39m
|
|
14
|
+
[32mCJS[39m ⚡️ Build success in 60ms
|
|
15
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m21.94 KB[39m
|
|
16
|
+
[32mESM[39m [1mdist/index.mjs.map [22m[32m49.21 KB[39m
|
|
17
|
+
[32mESM[39m ⚡️ Build success in 59ms
|
|
18
18
|
[34mDTS[39m Build start
|
|
19
|
-
[32mDTS[39m ⚡️ Build success in
|
|
20
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[
|
|
19
|
+
[32mDTS[39m ⚡️ Build success in 5036ms
|
|
20
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m10.09 KB[39m
|
|
21
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m10.09 KB[39m
|
package/.turbo/turbo-clean.log
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @ai-sdk/react
|
|
2
2
|
|
|
3
|
+
## 0.0.17
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 6a11cfaa: feat (ai/ui): add onError handler to useObject
|
|
8
|
+
- 3db90c3d: allow empty handleSubmit submissions for useChat
|
|
9
|
+
- Updated dependencies [d481729f]
|
|
10
|
+
- @ai-sdk/provider-utils@1.0.1
|
|
11
|
+
- @ai-sdk/ui-utils@0.0.10
|
|
12
|
+
|
|
13
|
+
## 0.0.16
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- 3f756a6b: fix (ai/react): include fetch parameter as part of useChat
|
|
18
|
+
|
|
3
19
|
## 0.0.15
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -105,7 +105,7 @@ type UseChatHelpers = {
|
|
|
105
105
|
/** Additional data added on the server via StreamData */
|
|
106
106
|
data?: JSONValue[];
|
|
107
107
|
};
|
|
108
|
-
declare function useChat({ api, id, initialMessages, initialInput, sendExtraMessageFields, experimental_onFunctionCall, experimental_onToolCall, onToolCall, experimental_prepareRequestBody, experimental_maxAutomaticRoundtrips, maxAutomaticRoundtrips, maxToolRoundtrips, streamMode, onResponse, onFinish, onError, credentials, headers, body, generateId, }?: UseChatOptions & {
|
|
108
|
+
declare function useChat({ api, id, initialMessages, initialInput, sendExtraMessageFields, experimental_onFunctionCall, experimental_onToolCall, onToolCall, experimental_prepareRequestBody, experimental_maxAutomaticRoundtrips, maxAutomaticRoundtrips, maxToolRoundtrips, streamMode, onResponse, onFinish, onError, credentials, headers, body, generateId, fetch, }?: UseChatOptions & {
|
|
109
109
|
key?: string;
|
|
110
110
|
/**
|
|
111
111
|
@deprecated Use `maxToolRoundtrips` instead.
|
|
@@ -228,6 +228,10 @@ type Experimental_UseObjectOptions<RESULT> = {
|
|
|
228
228
|
or to provide a custom fetch implementation for e.g. testing.
|
|
229
229
|
*/
|
|
230
230
|
fetch?: FetchFunction;
|
|
231
|
+
/**
|
|
232
|
+
* Callback function to be called when an error is encountered.
|
|
233
|
+
*/
|
|
234
|
+
onError?: (error: Error) => void;
|
|
231
235
|
};
|
|
232
236
|
type Experimental_UseObjectHelpers<RESULT, INPUT> = {
|
|
233
237
|
/**
|
|
@@ -256,7 +260,7 @@ type Experimental_UseObjectHelpers<RESULT, INPUT> = {
|
|
|
256
260
|
stop: () => void;
|
|
257
261
|
};
|
|
258
262
|
declare function useObject<RESULT, INPUT = any>({ api, id, schema, // required, in the future we will use it for validation
|
|
259
|
-
initialValue, fetch, }: Experimental_UseObjectOptions<RESULT>): Experimental_UseObjectHelpers<RESULT, INPUT>;
|
|
263
|
+
initialValue, fetch, onError, }: Experimental_UseObjectOptions<RESULT>): Experimental_UseObjectHelpers<RESULT, INPUT>;
|
|
260
264
|
declare const experimental_useObject: typeof useObject;
|
|
261
265
|
|
|
262
266
|
export { Experimental_UseObjectHelpers, Experimental_UseObjectOptions, UseAssistantHelpers, UseChatHelpers, UseCompletionHelpers, experimental_useAssistant, experimental_useObject, useAssistant, useChat, useCompletion };
|
package/dist/index.d.ts
CHANGED
|
@@ -105,7 +105,7 @@ type UseChatHelpers = {
|
|
|
105
105
|
/** Additional data added on the server via StreamData */
|
|
106
106
|
data?: JSONValue[];
|
|
107
107
|
};
|
|
108
|
-
declare function useChat({ api, id, initialMessages, initialInput, sendExtraMessageFields, experimental_onFunctionCall, experimental_onToolCall, onToolCall, experimental_prepareRequestBody, experimental_maxAutomaticRoundtrips, maxAutomaticRoundtrips, maxToolRoundtrips, streamMode, onResponse, onFinish, onError, credentials, headers, body, generateId, }?: UseChatOptions & {
|
|
108
|
+
declare function useChat({ api, id, initialMessages, initialInput, sendExtraMessageFields, experimental_onFunctionCall, experimental_onToolCall, onToolCall, experimental_prepareRequestBody, experimental_maxAutomaticRoundtrips, maxAutomaticRoundtrips, maxToolRoundtrips, streamMode, onResponse, onFinish, onError, credentials, headers, body, generateId, fetch, }?: UseChatOptions & {
|
|
109
109
|
key?: string;
|
|
110
110
|
/**
|
|
111
111
|
@deprecated Use `maxToolRoundtrips` instead.
|
|
@@ -228,6 +228,10 @@ type Experimental_UseObjectOptions<RESULT> = {
|
|
|
228
228
|
or to provide a custom fetch implementation for e.g. testing.
|
|
229
229
|
*/
|
|
230
230
|
fetch?: FetchFunction;
|
|
231
|
+
/**
|
|
232
|
+
* Callback function to be called when an error is encountered.
|
|
233
|
+
*/
|
|
234
|
+
onError?: (error: Error) => void;
|
|
231
235
|
};
|
|
232
236
|
type Experimental_UseObjectHelpers<RESULT, INPUT> = {
|
|
233
237
|
/**
|
|
@@ -256,7 +260,7 @@ type Experimental_UseObjectHelpers<RESULT, INPUT> = {
|
|
|
256
260
|
stop: () => void;
|
|
257
261
|
};
|
|
258
262
|
declare function useObject<RESULT, INPUT = any>({ api, id, schema, // required, in the future we will use it for validation
|
|
259
|
-
initialValue, fetch, }: Experimental_UseObjectOptions<RESULT>): Experimental_UseObjectHelpers<RESULT, INPUT>;
|
|
263
|
+
initialValue, fetch, onError, }: Experimental_UseObjectOptions<RESULT>): Experimental_UseObjectHelpers<RESULT, INPUT>;
|
|
260
264
|
declare const experimental_useObject: typeof useObject;
|
|
261
265
|
|
|
262
266
|
export { Experimental_UseObjectHelpers, Experimental_UseObjectOptions, UseAssistantHelpers, UseChatHelpers, UseCompletionHelpers, experimental_useAssistant, experimental_useObject, useAssistant, useChat, useCompletion };
|
package/dist/index.js
CHANGED
|
@@ -301,7 +301,8 @@ function useChat({
|
|
|
301
301
|
credentials,
|
|
302
302
|
headers,
|
|
303
303
|
body,
|
|
304
|
-
generateId: generateId2 = import_ui_utils2.generateId
|
|
304
|
+
generateId: generateId2 = import_ui_utils2.generateId,
|
|
305
|
+
fetch: fetch2
|
|
305
306
|
} = {}) {
|
|
306
307
|
const hookId = (0, import_react2.useId)();
|
|
307
308
|
const idKey = id != null ? id : hookId;
|
|
@@ -360,7 +361,7 @@ function useChat({
|
|
|
360
361
|
onToolCall,
|
|
361
362
|
sendExtraMessageFields,
|
|
362
363
|
experimental_prepareRequestBody,
|
|
363
|
-
|
|
364
|
+
fetch2
|
|
364
365
|
),
|
|
365
366
|
experimental_onFunctionCall,
|
|
366
367
|
experimental_onToolCall,
|
|
@@ -415,7 +416,8 @@ function useChat({
|
|
|
415
416
|
maxToolRoundtrips,
|
|
416
417
|
messagesRef,
|
|
417
418
|
abortControllerRef,
|
|
418
|
-
generateId2
|
|
419
|
+
generateId2,
|
|
420
|
+
fetch2
|
|
419
421
|
]
|
|
420
422
|
);
|
|
421
423
|
const append = (0, import_react2.useCallback)(
|
|
@@ -501,19 +503,19 @@ function useChat({
|
|
|
501
503
|
};
|
|
502
504
|
}
|
|
503
505
|
(_a = event == null ? void 0 : event.preventDefault) == null ? void 0 : _a.call(event);
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
{
|
|
508
|
-
content: input,
|
|
506
|
+
const chatRequest = {
|
|
507
|
+
messages: input ? messagesRef.current.concat({
|
|
508
|
+
id: generateId2(),
|
|
509
509
|
role: "user",
|
|
510
|
-
|
|
511
|
-
},
|
|
512
|
-
options
|
|
513
|
-
|
|
510
|
+
content: input
|
|
511
|
+
}) : messagesRef.current,
|
|
512
|
+
options: options.options,
|
|
513
|
+
data: options.data
|
|
514
|
+
};
|
|
515
|
+
triggerRequest(chatRequest);
|
|
514
516
|
setInput("");
|
|
515
517
|
},
|
|
516
|
-
[input,
|
|
518
|
+
[input, generateId2, triggerRequest]
|
|
517
519
|
);
|
|
518
520
|
const handleInputChange = (e) => {
|
|
519
521
|
setInput(e.target.value);
|
|
@@ -710,7 +712,8 @@ function useObject({
|
|
|
710
712
|
schema,
|
|
711
713
|
// required, in the future we will use it for validation
|
|
712
714
|
initialValue,
|
|
713
|
-
fetch: fetch2
|
|
715
|
+
fetch: fetch2,
|
|
716
|
+
onError
|
|
714
717
|
}) {
|
|
715
718
|
const hookId = (0, import_react4.useId)();
|
|
716
719
|
const completionId = id != null ? id : hookId;
|
|
@@ -778,6 +781,9 @@ function useObject({
|
|
|
778
781
|
if ((0, import_provider_utils2.isAbortError)(error2)) {
|
|
779
782
|
return;
|
|
780
783
|
}
|
|
784
|
+
if (onError && error2 instanceof Error) {
|
|
785
|
+
onError(error2);
|
|
786
|
+
}
|
|
781
787
|
setError(error2);
|
|
782
788
|
}
|
|
783
789
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/use-assistant.ts","../src/use-chat.ts","../src/use-completion.ts","../src/use-object.ts"],"sourcesContent":["export * from './use-assistant';\nexport * from './use-chat';\nexport * from './use-completion';\nexport * from './use-object';\n","import { isAbortError } from '@ai-sdk/provider-utils';\nimport {\n AssistantStatus,\n CreateMessage,\n Message,\n UseAssistantOptions,\n generateId,\n readDataStream,\n} from '@ai-sdk/ui-utils';\nimport { useCallback, useRef, useState } from 'react';\n\n// use function to allow for mocking in tests:\nconst getOriginalFetch = () => fetch;\n\nexport type UseAssistantHelpers = {\n /**\n * The current array of chat messages.\n */\n messages: Message[];\n\n /**\n * Update the message store with a new array of messages.\n */\n setMessages: React.Dispatch<React.SetStateAction<Message[]>>;\n\n /**\n * The current thread ID.\n */\n threadId: string | undefined;\n\n /**\n * The current value of the input field.\n */\n input: string;\n\n /**\n * Append a user message to the chat list. This triggers the API call to fetch\n * the assistant's response.\n * @param message The message to append\n * @param requestOptions Additional options to pass to the API call\n */\n append: (\n message: Message | CreateMessage,\n requestOptions?: {\n data?: Record<string, string>;\n },\n ) => Promise<void>;\n\n /**\nAbort the current request immediately, keep the generated tokens if any.\n */\n stop: () => void;\n\n /**\n * setState-powered method to update the input value.\n */\n setInput: React.Dispatch<React.SetStateAction<string>>;\n\n /**\n * Handler for the `onChange` event of the input field to control the input's value.\n */\n handleInputChange: (\n event:\n | React.ChangeEvent<HTMLInputElement>\n | React.ChangeEvent<HTMLTextAreaElement>,\n ) => void;\n\n /**\n * Form submission handler that automatically resets the input field and appends a user message.\n */\n submitMessage: (\n event?: React.FormEvent<HTMLFormElement>,\n requestOptions?: {\n data?: Record<string, string>;\n },\n ) => Promise<void>;\n\n /**\n * The current status of the assistant. This can be used to show a loading indicator.\n */\n status: AssistantStatus;\n\n /**\n * The error thrown during the assistant message processing, if any.\n */\n error: undefined | Error;\n};\n\nexport function useAssistant({\n api,\n threadId: threadIdParam,\n credentials,\n headers,\n body,\n onError,\n fetch,\n}: UseAssistantOptions): UseAssistantHelpers {\n const [messages, setMessages] = useState<Message[]>([]);\n const [input, setInput] = useState('');\n const [threadId, setThreadId] = useState<string | undefined>(undefined);\n const [status, setStatus] = useState<AssistantStatus>('awaiting_message');\n const [error, setError] = useState<undefined | Error>(undefined);\n\n const handleInputChange = (\n event:\n | React.ChangeEvent<HTMLInputElement>\n | React.ChangeEvent<HTMLTextAreaElement>,\n ) => {\n setInput(event.target.value);\n };\n\n // Abort controller to cancel the current API call.\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const stop = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n }, []);\n\n const append = async (\n message: Message | CreateMessage,\n requestOptions?: {\n data?: Record<string, string>;\n },\n ) => {\n setStatus('in_progress');\n\n setMessages(messages => [\n ...messages,\n {\n ...message,\n id: message.id ?? generateId(),\n },\n ]);\n\n setInput('');\n\n const abortController = new AbortController();\n\n try {\n abortControllerRef.current = abortController;\n\n const actualFetch = fetch ?? getOriginalFetch();\n const response = await actualFetch(api, {\n method: 'POST',\n credentials,\n signal: abortController.signal,\n headers: { 'Content-Type': 'application/json', ...headers },\n body: JSON.stringify({\n ...body,\n // always use user-provided threadId when available:\n threadId: threadIdParam ?? threadId ?? null,\n message: message.content,\n\n // optional request data:\n data: requestOptions?.data,\n }),\n });\n\n if (!response.ok) {\n throw new Error(\n (await response.text()) ?? 'Failed to fetch the assistant response.',\n );\n }\n\n if (response.body == null) {\n throw new Error('The response body is empty.');\n }\n\n for await (const { type, value } of readDataStream(\n response.body.getReader(),\n )) {\n switch (type) {\n case 'assistant_message': {\n setMessages(messages => [\n ...messages,\n {\n id: value.id,\n role: value.role,\n content: value.content[0].text.value,\n },\n ]);\n break;\n }\n\n case 'text': {\n // text delta - add to last message:\n setMessages(messages => {\n const lastMessage = messages[messages.length - 1];\n return [\n ...messages.slice(0, messages.length - 1),\n {\n id: lastMessage.id,\n role: lastMessage.role,\n content: lastMessage.content + value,\n },\n ];\n });\n\n break;\n }\n\n case 'data_message': {\n setMessages(messages => [\n ...messages,\n {\n id: value.id ?? generateId(),\n role: 'data',\n content: '',\n data: value.data,\n },\n ]);\n break;\n }\n\n case 'assistant_control_data': {\n setThreadId(value.threadId);\n\n // set id of last message:\n setMessages(messages => {\n const lastMessage = messages[messages.length - 1];\n lastMessage.id = value.messageId;\n return [...messages.slice(0, messages.length - 1), lastMessage];\n });\n\n break;\n }\n\n case 'error': {\n setError(new Error(value));\n break;\n }\n }\n }\n } catch (error) {\n // Ignore abort errors as they are expected when the user cancels the request:\n if (isAbortError(error) && abortController.signal.aborted) {\n abortControllerRef.current = null;\n return;\n }\n\n if (onError && error instanceof Error) {\n onError(error);\n }\n\n setError(error as Error);\n } finally {\n abortControllerRef.current = null;\n setStatus('awaiting_message');\n }\n };\n\n const submitMessage = async (\n event?: React.FormEvent<HTMLFormElement>,\n requestOptions?: {\n data?: Record<string, string>;\n },\n ) => {\n event?.preventDefault?.();\n\n if (input === '') {\n return;\n }\n\n append({ role: 'user', content: input }, requestOptions);\n };\n\n return {\n append,\n messages,\n setMessages,\n threadId,\n input,\n setInput,\n handleInputChange,\n submitMessage,\n status,\n error,\n stop,\n };\n}\n\n/**\n@deprecated Use `useAssistant` instead.\n */\nexport const experimental_useAssistant = useAssistant;\n","import type {\n ChatRequest,\n ChatRequestOptions,\n CreateMessage,\n FetchFunction,\n IdGenerator,\n JSONValue,\n Message,\n UseChatOptions,\n} from '@ai-sdk/ui-utils';\nimport {\n callChatApi,\n generateId as generateIdFunc,\n processChatStream,\n} from '@ai-sdk/ui-utils';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport useSWR, { KeyedMutator } from 'swr';\n\nexport type { CreateMessage, Message, UseChatOptions };\n\nexport type UseChatHelpers = {\n /** Current messages in the chat */\n messages: Message[];\n /** The error object of the API request */\n error: undefined | Error;\n /**\n * Append a user message to the chat list. This triggers the API call to fetch\n * the assistant's response.\n * @param message The message to append\n * @param options Additional options to pass to the API call\n */\n append: (\n message: Message | CreateMessage,\n chatRequestOptions?: ChatRequestOptions,\n ) => Promise<string | null | undefined>;\n /**\n * Reload the last AI chat response for the given chat history. If the last\n * message isn't from the assistant, it will request the API to generate a\n * new response.\n */\n reload: (\n chatRequestOptions?: ChatRequestOptions,\n ) => Promise<string | null | undefined>;\n /**\n * Abort the current request immediately, keep the generated tokens if any.\n */\n stop: () => void;\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: (messages: Message[]) => 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 /** 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 /** Form submission handler to automatically reset input and append a user message */\n handleSubmit: (\n event?: { preventDefault?: () => void },\n chatRequestOptions?: ChatRequestOptions,\n ) => void;\n metadata?: Object;\n /** Whether the API request is in progress */\n isLoading: boolean;\n /** Additional data added on the server via StreamData */\n data?: JSONValue[];\n};\n\nconst getStreamedResponse = async (\n api: string,\n chatRequest: ChatRequest,\n mutate: KeyedMutator<Message[]>,\n mutateStreamData: KeyedMutator<JSONValue[] | undefined>,\n existingData: JSONValue[] | undefined,\n extraMetadataRef: React.MutableRefObject<any>,\n messagesRef: React.MutableRefObject<Message[]>,\n abortControllerRef: React.MutableRefObject<AbortController | null>,\n generateId: IdGenerator,\n streamMode: 'stream-data' | 'text' | undefined,\n onFinish: ((message: Message) => void) | undefined,\n onResponse: ((response: Response) => void | Promise<void>) | undefined,\n onToolCall: UseChatOptions['onToolCall'] | undefined,\n sendExtraMessageFields: boolean | undefined,\n experimental_prepareRequestBody:\n | ((options: {\n messages: Message[];\n requestData?: JSONValue;\n requestBody?: object;\n }) => JSONValue)\n | undefined,\n fetch: FetchFunction | undefined,\n) => {\n // Do an optimistic update to the chat state to show the updated messages\n // immediately.\n const previousMessages = messagesRef.current;\n mutate(chatRequest.messages, false);\n\n const constructedMessagesPayload = sendExtraMessageFields\n ? chatRequest.messages\n : chatRequest.messages.map(\n ({\n role,\n content,\n name,\n data,\n annotations,\n toolInvocations,\n function_call,\n tool_calls,\n tool_call_id,\n }) => ({\n role,\n content,\n ...(name !== undefined && { name }),\n ...(data !== undefined && { data }),\n ...(annotations !== undefined && { annotations }),\n ...(toolInvocations !== undefined && { toolInvocations }),\n // outdated function/tool call handling (TODO deprecate):\n tool_call_id,\n ...(function_call !== undefined && { function_call }),\n ...(tool_calls !== undefined && { tool_calls }),\n }),\n );\n\n return await callChatApi({\n api,\n body: experimental_prepareRequestBody?.({\n messages: chatRequest.messages,\n requestData: chatRequest.data,\n requestBody: chatRequest.options?.body,\n }) ?? {\n messages: constructedMessagesPayload,\n data: chatRequest.data,\n ...extraMetadataRef.current.body,\n ...chatRequest.options?.body,\n ...(chatRequest.functions !== undefined && {\n functions: chatRequest.functions,\n }),\n ...(chatRequest.function_call !== undefined && {\n function_call: chatRequest.function_call,\n }),\n ...(chatRequest.tools !== undefined && {\n tools: chatRequest.tools,\n }),\n ...(chatRequest.tool_choice !== undefined && {\n tool_choice: chatRequest.tool_choice,\n }),\n },\n streamMode,\n credentials: extraMetadataRef.current.credentials,\n headers: {\n ...extraMetadataRef.current.headers,\n ...chatRequest.options?.headers,\n },\n abortController: () => abortControllerRef.current,\n restoreMessagesOnFailure() {\n mutate(previousMessages, false);\n },\n onResponse,\n onUpdate(merged, data) {\n mutate([...chatRequest.messages, ...merged], false);\n mutateStreamData([...(existingData || []), ...(data || [])], false);\n },\n onToolCall,\n onFinish,\n generateId,\n fetch,\n });\n};\n\nexport function useChat({\n api = '/api/chat',\n id,\n initialMessages,\n initialInput = '',\n sendExtraMessageFields,\n experimental_onFunctionCall,\n experimental_onToolCall,\n onToolCall,\n experimental_prepareRequestBody,\n experimental_maxAutomaticRoundtrips = 0,\n maxAutomaticRoundtrips = experimental_maxAutomaticRoundtrips,\n maxToolRoundtrips = maxAutomaticRoundtrips,\n streamMode,\n onResponse,\n onFinish,\n onError,\n credentials,\n headers,\n body,\n generateId = generateIdFunc,\n}: UseChatOptions & {\n key?: string;\n\n /**\n@deprecated Use `maxToolRoundtrips` instead.\n */\n experimental_maxAutomaticRoundtrips?: number;\n\n /**\n@deprecated Use `maxToolRoundtrips` instead.\n */\n maxAutomaticRoundtrips?: number;\n\n /**\n * Experimental (React only). When a function is provided, it will be used\n * to prepare the request body for the chat API. This can be useful for\n * customizing the request body based on the messages and data in the chat.\n *\n * @param messages The current messages in the chat.\n * @param requestData The data object passed in the chat request.\n * @param requestBody The request body object passed in the chat request.\n */\n experimental_prepareRequestBody?: (options: {\n messages: Message[];\n requestData?: JSONValue;\n requestBody?: object;\n }) => JSONValue;\n\n /**\nMaximal number of automatic roundtrips for tool calls.\n\nAn automatic tool call roundtrip is a call to the server with the \ntool call results when all tool calls in the last assistant \nmessage have results.\n\nA maximum number is required to prevent infinite loops in the\ncase of misconfigured tools.\n\nBy default, it's set to 0, which will disable the feature.\n */\n maxToolRoundtrips?: number;\n} = {}): UseChatHelpers & {\n /**\n * @deprecated Use `addToolResult` instead.\n */\n experimental_addToolResult: ({\n toolCallId,\n result,\n }: {\n toolCallId: string;\n result: any;\n }) => void;\n addToolResult: ({\n toolCallId,\n result,\n }: {\n toolCallId: string;\n result: any;\n }) => void;\n} {\n // Generate a unique id for the chat if not provided.\n const hookId = useId();\n const idKey = id ?? hookId;\n const chatKey = typeof api === 'string' ? [api, idKey] : idKey;\n\n // Store a empty array as the initial messages\n // (instead of using a default parameter value that gets re-created each time)\n // to avoid re-renders:\n const [initialMessagesFallback] = useState([]);\n\n // Store the chat state in SWR, using the chatId as the key to share states.\n const { data: messages, mutate } = useSWR<Message[]>(\n [chatKey, 'messages'],\n null,\n { fallbackData: initialMessages ?? initialMessagesFallback },\n );\n\n // We store loading state in another hook to sync loading states across hook invocations\n const { data: isLoading = false, mutate: mutateLoading } = useSWR<boolean>(\n [chatKey, 'loading'],\n null,\n );\n\n const { data: streamData, mutate: mutateStreamData } = useSWR<\n JSONValue[] | undefined\n >([chatKey, 'streamData'], null);\n\n const { data: error = undefined, mutate: setError } = useSWR<\n undefined | Error\n >([chatKey, 'error'], null);\n\n // Keep the latest messages in a ref.\n const messagesRef = useRef<Message[]>(messages || []);\n useEffect(() => {\n messagesRef.current = messages || [];\n }, [messages]);\n\n // Abort controller to cancel the current API call.\n const abortControllerRef = useRef<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 (chatRequest: ChatRequest) => {\n const messageCount = messagesRef.current.length;\n\n try {\n mutateLoading(true);\n setError(undefined);\n\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n\n await processChatStream({\n getStreamedResponse: () =>\n getStreamedResponse(\n api,\n chatRequest,\n mutate,\n mutateStreamData,\n streamData!,\n extraMetadataRef,\n messagesRef,\n abortControllerRef,\n generateId,\n streamMode,\n onFinish,\n onResponse,\n onToolCall,\n sendExtraMessageFields,\n experimental_prepareRequestBody,\n fetch,\n ),\n experimental_onFunctionCall,\n experimental_onToolCall,\n updateChatRequest: chatRequestParam => {\n chatRequest = chatRequestParam;\n },\n getCurrentMessages: () => messagesRef.current,\n });\n\n abortControllerRef.current = null;\n } catch (err) {\n // Ignore abort errors as they are expected.\n if ((err as any).name === 'AbortError') {\n abortControllerRef.current = null;\n return null;\n }\n\n if (onError && err instanceof Error) {\n onError(err);\n }\n\n setError(err as Error);\n } finally {\n mutateLoading(false);\n }\n\n // auto-submit when all tool calls in the last assistant message have results:\n const messages = messagesRef.current;\n const lastMessage = messages[messages.length - 1];\n if (\n // ensure we actually have new messages (to prevent infinite loops in case of errors):\n messages.length > messageCount &&\n // ensure there is a last message:\n lastMessage != null &&\n // check if the feature is enabled:\n maxToolRoundtrips > 0 &&\n // check that roundtrip is possible:\n isAssistantMessageWithCompletedToolCalls(lastMessage) &&\n // limit the number of automatic roundtrips:\n countTrailingAssistantMessages(messages) <= maxToolRoundtrips\n ) {\n await triggerRequest({ messages });\n }\n },\n [\n mutate,\n mutateLoading,\n api,\n extraMetadataRef,\n onResponse,\n onFinish,\n onError,\n setError,\n mutateStreamData,\n streamData,\n streamMode,\n sendExtraMessageFields,\n experimental_onFunctionCall,\n experimental_onToolCall,\n experimental_prepareRequestBody,\n onToolCall,\n maxToolRoundtrips,\n messagesRef,\n abortControllerRef,\n generateId,\n ],\n );\n\n const append = useCallback(\n async (\n message: Message | CreateMessage,\n {\n options,\n functions,\n function_call,\n tools,\n tool_choice,\n data,\n }: ChatRequestOptions = {},\n ) => {\n if (!message.id) {\n message.id = generateId();\n }\n\n const chatRequest: ChatRequest = {\n messages: messagesRef.current.concat(message as Message),\n options,\n data,\n ...(functions !== undefined && { functions }),\n ...(function_call !== undefined && { function_call }),\n ...(tools !== undefined && { tools }),\n ...(tool_choice !== undefined && { tool_choice }),\n };\n\n return triggerRequest(chatRequest);\n },\n [triggerRequest, generateId],\n );\n\n const reload = useCallback(\n async ({\n options,\n functions,\n function_call,\n tools,\n tool_choice,\n }: ChatRequestOptions = {}) => {\n if (messagesRef.current.length === 0) return null;\n\n // Remove last assistant message and retry last user message.\n const lastMessage = messagesRef.current[messagesRef.current.length - 1];\n if (lastMessage.role === 'assistant') {\n const chatRequest: ChatRequest = {\n messages: messagesRef.current.slice(0, -1),\n options,\n ...(functions !== undefined && { functions }),\n ...(function_call !== undefined && { function_call }),\n ...(tools !== undefined && { tools }),\n ...(tool_choice !== undefined && { tool_choice }),\n };\n\n return triggerRequest(chatRequest);\n }\n\n const chatRequest: ChatRequest = {\n messages: messagesRef.current,\n options,\n ...(functions !== undefined && { functions }),\n ...(function_call !== undefined && { function_call }),\n ...(tools !== undefined && { tools }),\n ...(tool_choice !== undefined && { tool_choice }),\n };\n\n return triggerRequest(chatRequest);\n },\n [triggerRequest],\n );\n\n const stop = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n }, []);\n\n const setMessages = useCallback(\n (messages: Message[]) => {\n mutate(messages, false);\n messagesRef.current = messages;\n },\n [mutate],\n );\n\n // Input state and handlers.\n const [input, setInput] = useState(initialInput);\n\n const handleSubmit = useCallback(\n (\n event?: { preventDefault?: () => void },\n options: ChatRequestOptions = {},\n metadata?: Object,\n ) => {\n if (metadata) {\n extraMetadataRef.current = {\n ...extraMetadataRef.current,\n ...metadata,\n };\n }\n\n event?.preventDefault?.();\n\n if (!input) return;\n\n append(\n {\n content: input,\n role: 'user',\n createdAt: new Date(),\n },\n options,\n );\n setInput('');\n },\n [input, append],\n );\n\n const handleInputChange = (e: any) => {\n setInput(e.target.value);\n };\n\n const addToolResult = ({\n toolCallId,\n result,\n }: {\n toolCallId: string;\n result: any;\n }) => {\n const updatedMessages = messagesRef.current.map((message, index, arr) =>\n // update the tool calls in the last assistant message:\n index === arr.length - 1 &&\n message.role === 'assistant' &&\n message.toolInvocations\n ? {\n ...message,\n toolInvocations: message.toolInvocations.map(toolInvocation =>\n toolInvocation.toolCallId === toolCallId\n ? { ...toolInvocation, result }\n : toolInvocation,\n ),\n }\n : message,\n );\n\n mutate(updatedMessages, false);\n\n // auto-submit when all tool calls in the last assistant message have results:\n const lastMessage = updatedMessages[updatedMessages.length - 1];\n if (isAssistantMessageWithCompletedToolCalls(lastMessage)) {\n triggerRequest({ messages: updatedMessages });\n }\n };\n\n return {\n messages: messages || [],\n error,\n append,\n reload,\n stop,\n setMessages,\n input,\n setInput,\n handleInputChange,\n handleSubmit,\n isLoading,\n data: streamData,\n addToolResult,\n experimental_addToolResult: addToolResult,\n };\n}\n\n/**\nCheck if the message is an assistant message with completed tool calls. \nThe message must have at least one tool invocation and all tool invocations\nmust have a result.\n */\nfunction isAssistantMessageWithCompletedToolCalls(message: Message) {\n return (\n message.role === 'assistant' &&\n message.toolInvocations &&\n message.toolInvocations.length > 0 &&\n message.toolInvocations.every(toolInvocation => 'result' in toolInvocation)\n );\n}\n\n/**\nReturns the number of trailing assistant messages in the array.\n */\nfunction countTrailingAssistantMessages(messages: Message[]) {\n let count = 0;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === 'assistant') {\n count++;\n } else {\n break;\n }\n }\n return count;\n}\n","import {\n JSONValue,\n RequestOptions,\n UseCompletionOptions,\n callCompletionApi,\n} from '@ai-sdk/ui-utils';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\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?: RequestOptions,\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 /** Additional data added on the server via StreamData */\n data?: JSONValue[];\n};\n\nexport function useCompletion({\n api = '/api/completion',\n id,\n initialCompletion = '',\n initialInput = '',\n credentials,\n headers,\n body,\n streamMode,\n fetch,\n onResponse,\n onFinish,\n onError,\n}: UseCompletionOptions = {}): 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 { data: streamData, mutate: mutateStreamData } = useSWR<\n JSONValue[] | undefined\n >([completionId, 'streamData'], null);\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 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?: RequestOptions) =>\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 streamMode,\n fetch,\n setCompletion: completion => mutate(completion, false),\n setLoading: mutateLoading,\n setError,\n setAbortController,\n onResponse,\n onFinish,\n onError,\n onData: data => {\n mutateStreamData([...(streamData || []), ...(data || [])], false);\n },\n }),\n [\n mutate,\n mutateLoading,\n api,\n extraMetadataRef,\n setAbortController,\n onResponse,\n onFinish,\n onError,\n setError,\n streamData,\n streamMode,\n fetch,\n mutateStreamData,\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 = (e: any) => {\n setInput(e.target.value);\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 data: streamData,\n };\n}\n","import { isAbortError } from '@ai-sdk/provider-utils';\nimport {\n DeepPartial,\n FetchFunction,\n isDeepEqualData,\n parsePartialJson,\n} from '@ai-sdk/ui-utils';\nimport { useCallback, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\nimport z from 'zod';\n\n// use function to allow for mocking in tests:\nconst getOriginalFetch = () => fetch;\n\nexport type Experimental_UseObjectOptions<RESULT> = {\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: z.Schema<RESULT>;\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\nexport type Experimental_UseObjectHelpers<RESULT, INPUT> = {\n /**\n * @deprecated Use `submit` instead.\n */\n setInput: (input: INPUT) => void;\n\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: undefined | unknown;\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<RESULT, INPUT = any>({\n api,\n id,\n schema, // required, in the future we will use it for validation\n initialValue,\n fetch,\n}: Experimental_UseObjectOptions<RESULT>): Experimental_UseObjectHelpers<\n RESULT,\n INPUT\n> {\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 | unknown>(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 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: { 'Content-Type': 'application/json' },\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 write(chunk) {\n accumulatedText += chunk;\n\n const currentObject = parsePartialJson(\n accumulatedText,\n ) as DeepPartial<RESULT>;\n\n if (!isDeepEqualData(latestObject, currentObject)) {\n latestObject = currentObject;\n\n mutate(currentObject);\n }\n },\n\n close() {\n setIsLoading(false);\n abortControllerRef.current = null;\n },\n }),\n );\n } catch (error) {\n if (isAbortError(error)) {\n return;\n }\n\n setError(error);\n }\n };\n\n return {\n setInput: submit, // Deprecated\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":["fetch","messages","_a","error","import_ui_utils","import_react","generateId","fetch","generateIdFunc","useSWR","messages","chatRequest","import_ui_utils","import_react","import_swr","fetch","useSWR","completion","data","import_provider_utils","import_ui_utils","import_react","import_swr","getOriginalFetch","fetch","useSWR","error"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/use-assistant.ts","../src/use-chat.ts","../src/use-completion.ts","../src/use-object.ts"],"sourcesContent":["export * from './use-assistant';\nexport * from './use-chat';\nexport * from './use-completion';\nexport * from './use-object';\n","import { isAbortError } from '@ai-sdk/provider-utils';\nimport {\n AssistantStatus,\n CreateMessage,\n Message,\n UseAssistantOptions,\n generateId,\n readDataStream,\n} from '@ai-sdk/ui-utils';\nimport { useCallback, useRef, useState } from 'react';\n\n// use function to allow for mocking in tests:\nconst getOriginalFetch = () => fetch;\n\nexport type UseAssistantHelpers = {\n /**\n * The current array of chat messages.\n */\n messages: Message[];\n\n /**\n * Update the message store with a new array of messages.\n */\n setMessages: React.Dispatch<React.SetStateAction<Message[]>>;\n\n /**\n * The current thread ID.\n */\n threadId: string | undefined;\n\n /**\n * The current value of the input field.\n */\n input: string;\n\n /**\n * Append a user message to the chat list. This triggers the API call to fetch\n * the assistant's response.\n * @param message The message to append\n * @param requestOptions Additional options to pass to the API call\n */\n append: (\n message: Message | CreateMessage,\n requestOptions?: {\n data?: Record<string, string>;\n },\n ) => Promise<void>;\n\n /**\nAbort the current request immediately, keep the generated tokens if any.\n */\n stop: () => void;\n\n /**\n * setState-powered method to update the input value.\n */\n setInput: React.Dispatch<React.SetStateAction<string>>;\n\n /**\n * Handler for the `onChange` event of the input field to control the input's value.\n */\n handleInputChange: (\n event:\n | React.ChangeEvent<HTMLInputElement>\n | React.ChangeEvent<HTMLTextAreaElement>,\n ) => void;\n\n /**\n * Form submission handler that automatically resets the input field and appends a user message.\n */\n submitMessage: (\n event?: React.FormEvent<HTMLFormElement>,\n requestOptions?: {\n data?: Record<string, string>;\n },\n ) => Promise<void>;\n\n /**\n * The current status of the assistant. This can be used to show a loading indicator.\n */\n status: AssistantStatus;\n\n /**\n * The error thrown during the assistant message processing, if any.\n */\n error: undefined | Error;\n};\n\nexport function useAssistant({\n api,\n threadId: threadIdParam,\n credentials,\n headers,\n body,\n onError,\n fetch,\n}: UseAssistantOptions): UseAssistantHelpers {\n const [messages, setMessages] = useState<Message[]>([]);\n const [input, setInput] = useState('');\n const [threadId, setThreadId] = useState<string | undefined>(undefined);\n const [status, setStatus] = useState<AssistantStatus>('awaiting_message');\n const [error, setError] = useState<undefined | Error>(undefined);\n\n const handleInputChange = (\n event:\n | React.ChangeEvent<HTMLInputElement>\n | React.ChangeEvent<HTMLTextAreaElement>,\n ) => {\n setInput(event.target.value);\n };\n\n // Abort controller to cancel the current API call.\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const stop = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n }, []);\n\n const append = async (\n message: Message | CreateMessage,\n requestOptions?: {\n data?: Record<string, string>;\n },\n ) => {\n setStatus('in_progress');\n\n setMessages(messages => [\n ...messages,\n {\n ...message,\n id: message.id ?? generateId(),\n },\n ]);\n\n setInput('');\n\n const abortController = new AbortController();\n\n try {\n abortControllerRef.current = abortController;\n\n const actualFetch = fetch ?? getOriginalFetch();\n const response = await actualFetch(api, {\n method: 'POST',\n credentials,\n signal: abortController.signal,\n headers: { 'Content-Type': 'application/json', ...headers },\n body: JSON.stringify({\n ...body,\n // always use user-provided threadId when available:\n threadId: threadIdParam ?? threadId ?? null,\n message: message.content,\n\n // optional request data:\n data: requestOptions?.data,\n }),\n });\n\n if (!response.ok) {\n throw new Error(\n (await response.text()) ?? 'Failed to fetch the assistant response.',\n );\n }\n\n if (response.body == null) {\n throw new Error('The response body is empty.');\n }\n\n for await (const { type, value } of readDataStream(\n response.body.getReader(),\n )) {\n switch (type) {\n case 'assistant_message': {\n setMessages(messages => [\n ...messages,\n {\n id: value.id,\n role: value.role,\n content: value.content[0].text.value,\n },\n ]);\n break;\n }\n\n case 'text': {\n // text delta - add to last message:\n setMessages(messages => {\n const lastMessage = messages[messages.length - 1];\n return [\n ...messages.slice(0, messages.length - 1),\n {\n id: lastMessage.id,\n role: lastMessage.role,\n content: lastMessage.content + value,\n },\n ];\n });\n\n break;\n }\n\n case 'data_message': {\n setMessages(messages => [\n ...messages,\n {\n id: value.id ?? generateId(),\n role: 'data',\n content: '',\n data: value.data,\n },\n ]);\n break;\n }\n\n case 'assistant_control_data': {\n setThreadId(value.threadId);\n\n // set id of last message:\n setMessages(messages => {\n const lastMessage = messages[messages.length - 1];\n lastMessage.id = value.messageId;\n return [...messages.slice(0, messages.length - 1), lastMessage];\n });\n\n break;\n }\n\n case 'error': {\n setError(new Error(value));\n break;\n }\n }\n }\n } catch (error) {\n // Ignore abort errors as they are expected when the user cancels the request:\n if (isAbortError(error) && abortController.signal.aborted) {\n abortControllerRef.current = null;\n return;\n }\n\n if (onError && error instanceof Error) {\n onError(error);\n }\n\n setError(error as Error);\n } finally {\n abortControllerRef.current = null;\n setStatus('awaiting_message');\n }\n };\n\n const submitMessage = async (\n event?: React.FormEvent<HTMLFormElement>,\n requestOptions?: {\n data?: Record<string, string>;\n },\n ) => {\n event?.preventDefault?.();\n\n if (input === '') {\n return;\n }\n\n append({ role: 'user', content: input }, requestOptions);\n };\n\n return {\n append,\n messages,\n setMessages,\n threadId,\n input,\n setInput,\n handleInputChange,\n submitMessage,\n status,\n error,\n stop,\n };\n}\n\n/**\n@deprecated Use `useAssistant` instead.\n */\nexport const experimental_useAssistant = useAssistant;\n","import type {\n ChatRequest,\n ChatRequestOptions,\n CreateMessage,\n FetchFunction,\n IdGenerator,\n JSONValue,\n Message,\n UseChatOptions,\n} from '@ai-sdk/ui-utils';\nimport {\n callChatApi,\n generateId as generateIdFunc,\n processChatStream,\n} from '@ai-sdk/ui-utils';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport useSWR, { KeyedMutator } from 'swr';\n\nexport type { CreateMessage, Message, UseChatOptions };\n\nexport type UseChatHelpers = {\n /** Current messages in the chat */\n messages: Message[];\n /** The error object of the API request */\n error: undefined | Error;\n /**\n * Append a user message to the chat list. This triggers the API call to fetch\n * the assistant's response.\n * @param message The message to append\n * @param options Additional options to pass to the API call\n */\n append: (\n message: Message | CreateMessage,\n chatRequestOptions?: ChatRequestOptions,\n ) => Promise<string | null | undefined>;\n /**\n * Reload the last AI chat response for the given chat history. If the last\n * message isn't from the assistant, it will request the API to generate a\n * new response.\n */\n reload: (\n chatRequestOptions?: ChatRequestOptions,\n ) => Promise<string | null | undefined>;\n /**\n * Abort the current request immediately, keep the generated tokens if any.\n */\n stop: () => void;\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: (messages: Message[]) => 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 /** 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 /** Form submission handler to automatically reset input and append a user message */\n handleSubmit: (\n event?: { preventDefault?: () => void },\n chatRequestOptions?: ChatRequestOptions,\n ) => void;\n metadata?: Object;\n /** Whether the API request is in progress */\n isLoading: boolean;\n /** Additional data added on the server via StreamData */\n data?: JSONValue[];\n};\n\nconst getStreamedResponse = async (\n api: string,\n chatRequest: ChatRequest,\n mutate: KeyedMutator<Message[]>,\n mutateStreamData: KeyedMutator<JSONValue[] | undefined>,\n existingData: JSONValue[] | undefined,\n extraMetadataRef: React.MutableRefObject<any>,\n messagesRef: React.MutableRefObject<Message[]>,\n abortControllerRef: React.MutableRefObject<AbortController | null>,\n generateId: IdGenerator,\n streamMode: 'stream-data' | 'text' | undefined,\n onFinish: ((message: Message) => void) | undefined,\n onResponse: ((response: Response) => void | Promise<void>) | undefined,\n onToolCall: UseChatOptions['onToolCall'] | undefined,\n sendExtraMessageFields: boolean | undefined,\n experimental_prepareRequestBody:\n | ((options: {\n messages: Message[];\n requestData?: JSONValue;\n requestBody?: object;\n }) => JSONValue)\n | undefined,\n fetch: FetchFunction | undefined,\n) => {\n // Do an optimistic update to the chat state to show the updated messages\n // immediately.\n const previousMessages = messagesRef.current;\n mutate(chatRequest.messages, false);\n\n const constructedMessagesPayload = sendExtraMessageFields\n ? chatRequest.messages\n : chatRequest.messages.map(\n ({\n role,\n content,\n name,\n data,\n annotations,\n toolInvocations,\n function_call,\n tool_calls,\n tool_call_id,\n }) => ({\n role,\n content,\n ...(name !== undefined && { name }),\n ...(data !== undefined && { data }),\n ...(annotations !== undefined && { annotations }),\n ...(toolInvocations !== undefined && { toolInvocations }),\n // outdated function/tool call handling (TODO deprecate):\n tool_call_id,\n ...(function_call !== undefined && { function_call }),\n ...(tool_calls !== undefined && { tool_calls }),\n }),\n );\n\n return await callChatApi({\n api,\n body: experimental_prepareRequestBody?.({\n messages: chatRequest.messages,\n requestData: chatRequest.data,\n requestBody: chatRequest.options?.body,\n }) ?? {\n messages: constructedMessagesPayload,\n data: chatRequest.data,\n ...extraMetadataRef.current.body,\n ...chatRequest.options?.body,\n ...(chatRequest.functions !== undefined && {\n functions: chatRequest.functions,\n }),\n ...(chatRequest.function_call !== undefined && {\n function_call: chatRequest.function_call,\n }),\n ...(chatRequest.tools !== undefined && {\n tools: chatRequest.tools,\n }),\n ...(chatRequest.tool_choice !== undefined && {\n tool_choice: chatRequest.tool_choice,\n }),\n },\n streamMode,\n credentials: extraMetadataRef.current.credentials,\n headers: {\n ...extraMetadataRef.current.headers,\n ...chatRequest.options?.headers,\n },\n abortController: () => abortControllerRef.current,\n restoreMessagesOnFailure() {\n mutate(previousMessages, false);\n },\n onResponse,\n onUpdate(merged, data) {\n mutate([...chatRequest.messages, ...merged], false);\n mutateStreamData([...(existingData || []), ...(data || [])], false);\n },\n onToolCall,\n onFinish,\n generateId,\n fetch,\n });\n};\n\nexport function useChat({\n api = '/api/chat',\n id,\n initialMessages,\n initialInput = '',\n sendExtraMessageFields,\n experimental_onFunctionCall,\n experimental_onToolCall,\n onToolCall,\n experimental_prepareRequestBody,\n experimental_maxAutomaticRoundtrips = 0,\n maxAutomaticRoundtrips = experimental_maxAutomaticRoundtrips,\n maxToolRoundtrips = maxAutomaticRoundtrips,\n streamMode,\n onResponse,\n onFinish,\n onError,\n credentials,\n headers,\n body,\n generateId = generateIdFunc,\n fetch,\n}: UseChatOptions & {\n key?: string;\n\n /**\n@deprecated Use `maxToolRoundtrips` instead.\n */\n experimental_maxAutomaticRoundtrips?: number;\n\n /**\n@deprecated Use `maxToolRoundtrips` instead.\n */\n maxAutomaticRoundtrips?: number;\n\n /**\n * Experimental (React only). When a function is provided, it will be used\n * to prepare the request body for the chat API. This can be useful for\n * customizing the request body based on the messages and data in the chat.\n *\n * @param messages The current messages in the chat.\n * @param requestData The data object passed in the chat request.\n * @param requestBody The request body object passed in the chat request.\n */\n experimental_prepareRequestBody?: (options: {\n messages: Message[];\n requestData?: JSONValue;\n requestBody?: object;\n }) => JSONValue;\n\n /**\nMaximal number of automatic roundtrips for tool calls.\n\nAn automatic tool call roundtrip is a call to the server with the \ntool call results when all tool calls in the last assistant \nmessage have results.\n\nA maximum number is required to prevent infinite loops in the\ncase of misconfigured tools.\n\nBy default, it's set to 0, which will disable the feature.\n */\n maxToolRoundtrips?: number;\n} = {}): UseChatHelpers & {\n /**\n * @deprecated Use `addToolResult` instead.\n */\n experimental_addToolResult: ({\n toolCallId,\n result,\n }: {\n toolCallId: string;\n result: any;\n }) => void;\n addToolResult: ({\n toolCallId,\n result,\n }: {\n toolCallId: string;\n result: any;\n }) => void;\n} {\n // Generate a unique id for the chat if not provided.\n const hookId = useId();\n const idKey = id ?? hookId;\n const chatKey = typeof api === 'string' ? [api, idKey] : idKey;\n\n // Store a empty array as the initial messages\n // (instead of using a default parameter value that gets re-created each time)\n // to avoid re-renders:\n const [initialMessagesFallback] = useState([]);\n\n // Store the chat state in SWR, using the chatId as the key to share states.\n const { data: messages, mutate } = useSWR<Message[]>(\n [chatKey, 'messages'],\n null,\n { fallbackData: initialMessages ?? initialMessagesFallback },\n );\n\n // We store loading state in another hook to sync loading states across hook invocations\n const { data: isLoading = false, mutate: mutateLoading } = useSWR<boolean>(\n [chatKey, 'loading'],\n null,\n );\n\n const { data: streamData, mutate: mutateStreamData } = useSWR<\n JSONValue[] | undefined\n >([chatKey, 'streamData'], null);\n\n const { data: error = undefined, mutate: setError } = useSWR<\n undefined | Error\n >([chatKey, 'error'], null);\n\n // Keep the latest messages in a ref.\n const messagesRef = useRef<Message[]>(messages || []);\n useEffect(() => {\n messagesRef.current = messages || [];\n }, [messages]);\n\n // Abort controller to cancel the current API call.\n const abortControllerRef = useRef<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 (chatRequest: ChatRequest) => {\n const messageCount = messagesRef.current.length;\n\n try {\n mutateLoading(true);\n setError(undefined);\n\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n\n await processChatStream({\n getStreamedResponse: () =>\n getStreamedResponse(\n api,\n chatRequest,\n mutate,\n mutateStreamData,\n streamData!,\n extraMetadataRef,\n messagesRef,\n abortControllerRef,\n generateId,\n streamMode,\n onFinish,\n onResponse,\n onToolCall,\n sendExtraMessageFields,\n experimental_prepareRequestBody,\n fetch,\n ),\n experimental_onFunctionCall,\n experimental_onToolCall,\n updateChatRequest: chatRequestParam => {\n chatRequest = chatRequestParam;\n },\n getCurrentMessages: () => messagesRef.current,\n });\n\n abortControllerRef.current = null;\n } catch (err) {\n // Ignore abort errors as they are expected.\n if ((err as any).name === 'AbortError') {\n abortControllerRef.current = null;\n return null;\n }\n\n if (onError && err instanceof Error) {\n onError(err);\n }\n\n setError(err as Error);\n } finally {\n mutateLoading(false);\n }\n\n // auto-submit when all tool calls in the last assistant message have results:\n const messages = messagesRef.current;\n const lastMessage = messages[messages.length - 1];\n if (\n // ensure we actually have new messages (to prevent infinite loops in case of errors):\n messages.length > messageCount &&\n // ensure there is a last message:\n lastMessage != null &&\n // check if the feature is enabled:\n maxToolRoundtrips > 0 &&\n // check that roundtrip is possible:\n isAssistantMessageWithCompletedToolCalls(lastMessage) &&\n // limit the number of automatic roundtrips:\n countTrailingAssistantMessages(messages) <= maxToolRoundtrips\n ) {\n await triggerRequest({ messages });\n }\n },\n [\n mutate,\n mutateLoading,\n api,\n extraMetadataRef,\n onResponse,\n onFinish,\n onError,\n setError,\n mutateStreamData,\n streamData,\n streamMode,\n sendExtraMessageFields,\n experimental_onFunctionCall,\n experimental_onToolCall,\n experimental_prepareRequestBody,\n onToolCall,\n maxToolRoundtrips,\n messagesRef,\n abortControllerRef,\n generateId,\n fetch,\n ],\n );\n\n const append = useCallback(\n async (\n message: Message | CreateMessage,\n {\n options,\n functions,\n function_call,\n tools,\n tool_choice,\n data,\n }: ChatRequestOptions = {},\n ) => {\n if (!message.id) {\n message.id = generateId();\n }\n\n const chatRequest: ChatRequest = {\n messages: messagesRef.current.concat(message as Message),\n options,\n data,\n ...(functions !== undefined && { functions }),\n ...(function_call !== undefined && { function_call }),\n ...(tools !== undefined && { tools }),\n ...(tool_choice !== undefined && { tool_choice }),\n };\n\n return triggerRequest(chatRequest);\n },\n [triggerRequest, generateId],\n );\n\n const reload = useCallback(\n async ({\n options,\n functions,\n function_call,\n tools,\n tool_choice,\n }: ChatRequestOptions = {}) => {\n if (messagesRef.current.length === 0) return null;\n\n // Remove last assistant message and retry last user message.\n const lastMessage = messagesRef.current[messagesRef.current.length - 1];\n if (lastMessage.role === 'assistant') {\n const chatRequest: ChatRequest = {\n messages: messagesRef.current.slice(0, -1),\n options,\n ...(functions !== undefined && { functions }),\n ...(function_call !== undefined && { function_call }),\n ...(tools !== undefined && { tools }),\n ...(tool_choice !== undefined && { tool_choice }),\n };\n\n return triggerRequest(chatRequest);\n }\n\n const chatRequest: ChatRequest = {\n messages: messagesRef.current,\n options,\n ...(functions !== undefined && { functions }),\n ...(function_call !== undefined && { function_call }),\n ...(tools !== undefined && { tools }),\n ...(tool_choice !== undefined && { tool_choice }),\n };\n\n return triggerRequest(chatRequest);\n },\n [triggerRequest],\n );\n\n const stop = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n }, []);\n\n const setMessages = useCallback(\n (messages: Message[]) => {\n mutate(messages, false);\n messagesRef.current = messages;\n },\n [mutate],\n );\n\n // Input state and handlers.\n const [input, setInput] = useState(initialInput);\n\n const handleSubmit = useCallback(\n (\n event?: { preventDefault?: () => void },\n options: ChatRequestOptions = {},\n metadata?: Object,\n ) => {\n if (metadata) {\n extraMetadataRef.current = {\n ...extraMetadataRef.current,\n ...metadata,\n };\n }\n\n event?.preventDefault?.();\n\n const chatRequest: ChatRequest = {\n messages: input\n ? messagesRef.current.concat({\n id: generateId(),\n role: 'user',\n content: input,\n })\n : messagesRef.current,\n options: options.options,\n data: options.data,\n };\n\n triggerRequest(chatRequest);\n\n setInput('');\n },\n [input, generateId, triggerRequest],\n );\n\n const handleInputChange = (e: any) => {\n setInput(e.target.value);\n };\n\n const addToolResult = ({\n toolCallId,\n result,\n }: {\n toolCallId: string;\n result: any;\n }) => {\n const updatedMessages = messagesRef.current.map((message, index, arr) =>\n // update the tool calls in the last assistant message:\n index === arr.length - 1 &&\n message.role === 'assistant' &&\n message.toolInvocations\n ? {\n ...message,\n toolInvocations: message.toolInvocations.map(toolInvocation =>\n toolInvocation.toolCallId === toolCallId\n ? { ...toolInvocation, result }\n : toolInvocation,\n ),\n }\n : message,\n );\n\n mutate(updatedMessages, false);\n\n // auto-submit when all tool calls in the last assistant message have results:\n const lastMessage = updatedMessages[updatedMessages.length - 1];\n if (isAssistantMessageWithCompletedToolCalls(lastMessage)) {\n triggerRequest({ messages: updatedMessages });\n }\n };\n\n return {\n messages: messages || [],\n error,\n append,\n reload,\n stop,\n setMessages,\n input,\n setInput,\n handleInputChange,\n handleSubmit,\n isLoading,\n data: streamData,\n addToolResult,\n experimental_addToolResult: addToolResult,\n };\n}\n\n/**\nCheck if the message is an assistant message with completed tool calls. \nThe message must have at least one tool invocation and all tool invocations\nmust have a result.\n */\nfunction isAssistantMessageWithCompletedToolCalls(message: Message) {\n return (\n message.role === 'assistant' &&\n message.toolInvocations &&\n message.toolInvocations.length > 0 &&\n message.toolInvocations.every(toolInvocation => 'result' in toolInvocation)\n );\n}\n\n/**\nReturns the number of trailing assistant messages in the array.\n */\nfunction countTrailingAssistantMessages(messages: Message[]) {\n let count = 0;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === 'assistant') {\n count++;\n } else {\n break;\n }\n }\n return count;\n}\n","import {\n JSONValue,\n RequestOptions,\n UseCompletionOptions,\n callCompletionApi,\n} from '@ai-sdk/ui-utils';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\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?: RequestOptions,\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 /** Additional data added on the server via StreamData */\n data?: JSONValue[];\n};\n\nexport function useCompletion({\n api = '/api/completion',\n id,\n initialCompletion = '',\n initialInput = '',\n credentials,\n headers,\n body,\n streamMode,\n fetch,\n onResponse,\n onFinish,\n onError,\n}: UseCompletionOptions = {}): 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 { data: streamData, mutate: mutateStreamData } = useSWR<\n JSONValue[] | undefined\n >([completionId, 'streamData'], null);\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 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?: RequestOptions) =>\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 streamMode,\n fetch,\n setCompletion: completion => mutate(completion, false),\n setLoading: mutateLoading,\n setError,\n setAbortController,\n onResponse,\n onFinish,\n onError,\n onData: data => {\n mutateStreamData([...(streamData || []), ...(data || [])], false);\n },\n }),\n [\n mutate,\n mutateLoading,\n api,\n extraMetadataRef,\n setAbortController,\n onResponse,\n onFinish,\n onError,\n setError,\n streamData,\n streamMode,\n fetch,\n mutateStreamData,\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 = (e: any) => {\n setInput(e.target.value);\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 data: streamData,\n };\n}\n","import { isAbortError } from '@ai-sdk/provider-utils';\nimport {\n DeepPartial,\n FetchFunction,\n isDeepEqualData,\n parsePartialJson,\n} from '@ai-sdk/ui-utils';\nimport { useCallback, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\nimport z from 'zod';\n\n// use function to allow for mocking in tests:\nconst getOriginalFetch = () => fetch;\n\nexport type Experimental_UseObjectOptions<RESULT> = {\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: z.Schema<RESULT>;\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 /**\n * Callback function to be called when an error is encountered.\n */\n onError?: (error: Error) => void;\n};\n\nexport type Experimental_UseObjectHelpers<RESULT, INPUT> = {\n /**\n * @deprecated Use `submit` instead.\n */\n setInput: (input: INPUT) => void;\n\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: undefined | unknown;\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<RESULT, INPUT = any>({\n api,\n id,\n schema, // required, in the future we will use it for validation\n initialValue,\n fetch,\n onError,\n}: Experimental_UseObjectOptions<RESULT>): Experimental_UseObjectHelpers<\n RESULT,\n INPUT\n> {\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 | unknown>(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 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: { 'Content-Type': 'application/json' },\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 write(chunk) {\n accumulatedText += chunk;\n\n const currentObject = parsePartialJson(\n accumulatedText,\n ) as DeepPartial<RESULT>;\n\n if (!isDeepEqualData(latestObject, currentObject)) {\n latestObject = currentObject;\n\n mutate(currentObject);\n }\n },\n\n close() {\n setIsLoading(false);\n abortControllerRef.current = null;\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 setError(error);\n }\n };\n\n return {\n setInput: submit, // Deprecated\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":["fetch","messages","_a","error","import_ui_utils","import_react","generateId","fetch","generateIdFunc","useSWR","messages","chatRequest","import_ui_utils","import_react","import_swr","fetch","useSWR","completion","data","import_provider_utils","import_ui_utils","import_react","import_swr","getOriginalFetch","fetch","useSWR","error"]}
|
package/dist/index.mjs
CHANGED
|
@@ -268,7 +268,8 @@ function useChat({
|
|
|
268
268
|
credentials,
|
|
269
269
|
headers,
|
|
270
270
|
body,
|
|
271
|
-
generateId: generateId2 = generateIdFunc
|
|
271
|
+
generateId: generateId2 = generateIdFunc,
|
|
272
|
+
fetch: fetch2
|
|
272
273
|
} = {}) {
|
|
273
274
|
const hookId = useId();
|
|
274
275
|
const idKey = id != null ? id : hookId;
|
|
@@ -327,7 +328,7 @@ function useChat({
|
|
|
327
328
|
onToolCall,
|
|
328
329
|
sendExtraMessageFields,
|
|
329
330
|
experimental_prepareRequestBody,
|
|
330
|
-
|
|
331
|
+
fetch2
|
|
331
332
|
),
|
|
332
333
|
experimental_onFunctionCall,
|
|
333
334
|
experimental_onToolCall,
|
|
@@ -382,7 +383,8 @@ function useChat({
|
|
|
382
383
|
maxToolRoundtrips,
|
|
383
384
|
messagesRef,
|
|
384
385
|
abortControllerRef,
|
|
385
|
-
generateId2
|
|
386
|
+
generateId2,
|
|
387
|
+
fetch2
|
|
386
388
|
]
|
|
387
389
|
);
|
|
388
390
|
const append = useCallback2(
|
|
@@ -468,19 +470,19 @@ function useChat({
|
|
|
468
470
|
};
|
|
469
471
|
}
|
|
470
472
|
(_a = event == null ? void 0 : event.preventDefault) == null ? void 0 : _a.call(event);
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
{
|
|
475
|
-
content: input,
|
|
473
|
+
const chatRequest = {
|
|
474
|
+
messages: input ? messagesRef.current.concat({
|
|
475
|
+
id: generateId2(),
|
|
476
476
|
role: "user",
|
|
477
|
-
|
|
478
|
-
},
|
|
479
|
-
options
|
|
480
|
-
|
|
477
|
+
content: input
|
|
478
|
+
}) : messagesRef.current,
|
|
479
|
+
options: options.options,
|
|
480
|
+
data: options.data
|
|
481
|
+
};
|
|
482
|
+
triggerRequest(chatRequest);
|
|
481
483
|
setInput("");
|
|
482
484
|
},
|
|
483
|
-
[input,
|
|
485
|
+
[input, generateId2, triggerRequest]
|
|
484
486
|
);
|
|
485
487
|
const handleInputChange = (e) => {
|
|
486
488
|
setInput(e.target.value);
|
|
@@ -682,7 +684,8 @@ function useObject({
|
|
|
682
684
|
schema,
|
|
683
685
|
// required, in the future we will use it for validation
|
|
684
686
|
initialValue,
|
|
685
|
-
fetch: fetch2
|
|
687
|
+
fetch: fetch2,
|
|
688
|
+
onError
|
|
686
689
|
}) {
|
|
687
690
|
const hookId = useId3();
|
|
688
691
|
const completionId = id != null ? id : hookId;
|
|
@@ -750,6 +753,9 @@ function useObject({
|
|
|
750
753
|
if (isAbortError2(error2)) {
|
|
751
754
|
return;
|
|
752
755
|
}
|
|
756
|
+
if (onError && error2 instanceof Error) {
|
|
757
|
+
onError(error2);
|
|
758
|
+
}
|
|
753
759
|
setError(error2);
|
|
754
760
|
}
|
|
755
761
|
};
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/use-assistant.ts","../src/use-chat.ts","../src/use-completion.ts","../src/use-object.ts"],"sourcesContent":["import { isAbortError } from '@ai-sdk/provider-utils';\nimport {\n AssistantStatus,\n CreateMessage,\n Message,\n UseAssistantOptions,\n generateId,\n readDataStream,\n} from '@ai-sdk/ui-utils';\nimport { useCallback, useRef, useState } from 'react';\n\n// use function to allow for mocking in tests:\nconst getOriginalFetch = () => fetch;\n\nexport type UseAssistantHelpers = {\n /**\n * The current array of chat messages.\n */\n messages: Message[];\n\n /**\n * Update the message store with a new array of messages.\n */\n setMessages: React.Dispatch<React.SetStateAction<Message[]>>;\n\n /**\n * The current thread ID.\n */\n threadId: string | undefined;\n\n /**\n * The current value of the input field.\n */\n input: string;\n\n /**\n * Append a user message to the chat list. This triggers the API call to fetch\n * the assistant's response.\n * @param message The message to append\n * @param requestOptions Additional options to pass to the API call\n */\n append: (\n message: Message | CreateMessage,\n requestOptions?: {\n data?: Record<string, string>;\n },\n ) => Promise<void>;\n\n /**\nAbort the current request immediately, keep the generated tokens if any.\n */\n stop: () => void;\n\n /**\n * setState-powered method to update the input value.\n */\n setInput: React.Dispatch<React.SetStateAction<string>>;\n\n /**\n * Handler for the `onChange` event of the input field to control the input's value.\n */\n handleInputChange: (\n event:\n | React.ChangeEvent<HTMLInputElement>\n | React.ChangeEvent<HTMLTextAreaElement>,\n ) => void;\n\n /**\n * Form submission handler that automatically resets the input field and appends a user message.\n */\n submitMessage: (\n event?: React.FormEvent<HTMLFormElement>,\n requestOptions?: {\n data?: Record<string, string>;\n },\n ) => Promise<void>;\n\n /**\n * The current status of the assistant. This can be used to show a loading indicator.\n */\n status: AssistantStatus;\n\n /**\n * The error thrown during the assistant message processing, if any.\n */\n error: undefined | Error;\n};\n\nexport function useAssistant({\n api,\n threadId: threadIdParam,\n credentials,\n headers,\n body,\n onError,\n fetch,\n}: UseAssistantOptions): UseAssistantHelpers {\n const [messages, setMessages] = useState<Message[]>([]);\n const [input, setInput] = useState('');\n const [threadId, setThreadId] = useState<string | undefined>(undefined);\n const [status, setStatus] = useState<AssistantStatus>('awaiting_message');\n const [error, setError] = useState<undefined | Error>(undefined);\n\n const handleInputChange = (\n event:\n | React.ChangeEvent<HTMLInputElement>\n | React.ChangeEvent<HTMLTextAreaElement>,\n ) => {\n setInput(event.target.value);\n };\n\n // Abort controller to cancel the current API call.\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const stop = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n }, []);\n\n const append = async (\n message: Message | CreateMessage,\n requestOptions?: {\n data?: Record<string, string>;\n },\n ) => {\n setStatus('in_progress');\n\n setMessages(messages => [\n ...messages,\n {\n ...message,\n id: message.id ?? generateId(),\n },\n ]);\n\n setInput('');\n\n const abortController = new AbortController();\n\n try {\n abortControllerRef.current = abortController;\n\n const actualFetch = fetch ?? getOriginalFetch();\n const response = await actualFetch(api, {\n method: 'POST',\n credentials,\n signal: abortController.signal,\n headers: { 'Content-Type': 'application/json', ...headers },\n body: JSON.stringify({\n ...body,\n // always use user-provided threadId when available:\n threadId: threadIdParam ?? threadId ?? null,\n message: message.content,\n\n // optional request data:\n data: requestOptions?.data,\n }),\n });\n\n if (!response.ok) {\n throw new Error(\n (await response.text()) ?? 'Failed to fetch the assistant response.',\n );\n }\n\n if (response.body == null) {\n throw new Error('The response body is empty.');\n }\n\n for await (const { type, value } of readDataStream(\n response.body.getReader(),\n )) {\n switch (type) {\n case 'assistant_message': {\n setMessages(messages => [\n ...messages,\n {\n id: value.id,\n role: value.role,\n content: value.content[0].text.value,\n },\n ]);\n break;\n }\n\n case 'text': {\n // text delta - add to last message:\n setMessages(messages => {\n const lastMessage = messages[messages.length - 1];\n return [\n ...messages.slice(0, messages.length - 1),\n {\n id: lastMessage.id,\n role: lastMessage.role,\n content: lastMessage.content + value,\n },\n ];\n });\n\n break;\n }\n\n case 'data_message': {\n setMessages(messages => [\n ...messages,\n {\n id: value.id ?? generateId(),\n role: 'data',\n content: '',\n data: value.data,\n },\n ]);\n break;\n }\n\n case 'assistant_control_data': {\n setThreadId(value.threadId);\n\n // set id of last message:\n setMessages(messages => {\n const lastMessage = messages[messages.length - 1];\n lastMessage.id = value.messageId;\n return [...messages.slice(0, messages.length - 1), lastMessage];\n });\n\n break;\n }\n\n case 'error': {\n setError(new Error(value));\n break;\n }\n }\n }\n } catch (error) {\n // Ignore abort errors as they are expected when the user cancels the request:\n if (isAbortError(error) && abortController.signal.aborted) {\n abortControllerRef.current = null;\n return;\n }\n\n if (onError && error instanceof Error) {\n onError(error);\n }\n\n setError(error as Error);\n } finally {\n abortControllerRef.current = null;\n setStatus('awaiting_message');\n }\n };\n\n const submitMessage = async (\n event?: React.FormEvent<HTMLFormElement>,\n requestOptions?: {\n data?: Record<string, string>;\n },\n ) => {\n event?.preventDefault?.();\n\n if (input === '') {\n return;\n }\n\n append({ role: 'user', content: input }, requestOptions);\n };\n\n return {\n append,\n messages,\n setMessages,\n threadId,\n input,\n setInput,\n handleInputChange,\n submitMessage,\n status,\n error,\n stop,\n };\n}\n\n/**\n@deprecated Use `useAssistant` instead.\n */\nexport const experimental_useAssistant = useAssistant;\n","import type {\n ChatRequest,\n ChatRequestOptions,\n CreateMessage,\n FetchFunction,\n IdGenerator,\n JSONValue,\n Message,\n UseChatOptions,\n} from '@ai-sdk/ui-utils';\nimport {\n callChatApi,\n generateId as generateIdFunc,\n processChatStream,\n} from '@ai-sdk/ui-utils';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport useSWR, { KeyedMutator } from 'swr';\n\nexport type { CreateMessage, Message, UseChatOptions };\n\nexport type UseChatHelpers = {\n /** Current messages in the chat */\n messages: Message[];\n /** The error object of the API request */\n error: undefined | Error;\n /**\n * Append a user message to the chat list. This triggers the API call to fetch\n * the assistant's response.\n * @param message The message to append\n * @param options Additional options to pass to the API call\n */\n append: (\n message: Message | CreateMessage,\n chatRequestOptions?: ChatRequestOptions,\n ) => Promise<string | null | undefined>;\n /**\n * Reload the last AI chat response for the given chat history. If the last\n * message isn't from the assistant, it will request the API to generate a\n * new response.\n */\n reload: (\n chatRequestOptions?: ChatRequestOptions,\n ) => Promise<string | null | undefined>;\n /**\n * Abort the current request immediately, keep the generated tokens if any.\n */\n stop: () => void;\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: (messages: Message[]) => 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 /** 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 /** Form submission handler to automatically reset input and append a user message */\n handleSubmit: (\n event?: { preventDefault?: () => void },\n chatRequestOptions?: ChatRequestOptions,\n ) => void;\n metadata?: Object;\n /** Whether the API request is in progress */\n isLoading: boolean;\n /** Additional data added on the server via StreamData */\n data?: JSONValue[];\n};\n\nconst getStreamedResponse = async (\n api: string,\n chatRequest: ChatRequest,\n mutate: KeyedMutator<Message[]>,\n mutateStreamData: KeyedMutator<JSONValue[] | undefined>,\n existingData: JSONValue[] | undefined,\n extraMetadataRef: React.MutableRefObject<any>,\n messagesRef: React.MutableRefObject<Message[]>,\n abortControllerRef: React.MutableRefObject<AbortController | null>,\n generateId: IdGenerator,\n streamMode: 'stream-data' | 'text' | undefined,\n onFinish: ((message: Message) => void) | undefined,\n onResponse: ((response: Response) => void | Promise<void>) | undefined,\n onToolCall: UseChatOptions['onToolCall'] | undefined,\n sendExtraMessageFields: boolean | undefined,\n experimental_prepareRequestBody:\n | ((options: {\n messages: Message[];\n requestData?: JSONValue;\n requestBody?: object;\n }) => JSONValue)\n | undefined,\n fetch: FetchFunction | undefined,\n) => {\n // Do an optimistic update to the chat state to show the updated messages\n // immediately.\n const previousMessages = messagesRef.current;\n mutate(chatRequest.messages, false);\n\n const constructedMessagesPayload = sendExtraMessageFields\n ? chatRequest.messages\n : chatRequest.messages.map(\n ({\n role,\n content,\n name,\n data,\n annotations,\n toolInvocations,\n function_call,\n tool_calls,\n tool_call_id,\n }) => ({\n role,\n content,\n ...(name !== undefined && { name }),\n ...(data !== undefined && { data }),\n ...(annotations !== undefined && { annotations }),\n ...(toolInvocations !== undefined && { toolInvocations }),\n // outdated function/tool call handling (TODO deprecate):\n tool_call_id,\n ...(function_call !== undefined && { function_call }),\n ...(tool_calls !== undefined && { tool_calls }),\n }),\n );\n\n return await callChatApi({\n api,\n body: experimental_prepareRequestBody?.({\n messages: chatRequest.messages,\n requestData: chatRequest.data,\n requestBody: chatRequest.options?.body,\n }) ?? {\n messages: constructedMessagesPayload,\n data: chatRequest.data,\n ...extraMetadataRef.current.body,\n ...chatRequest.options?.body,\n ...(chatRequest.functions !== undefined && {\n functions: chatRequest.functions,\n }),\n ...(chatRequest.function_call !== undefined && {\n function_call: chatRequest.function_call,\n }),\n ...(chatRequest.tools !== undefined && {\n tools: chatRequest.tools,\n }),\n ...(chatRequest.tool_choice !== undefined && {\n tool_choice: chatRequest.tool_choice,\n }),\n },\n streamMode,\n credentials: extraMetadataRef.current.credentials,\n headers: {\n ...extraMetadataRef.current.headers,\n ...chatRequest.options?.headers,\n },\n abortController: () => abortControllerRef.current,\n restoreMessagesOnFailure() {\n mutate(previousMessages, false);\n },\n onResponse,\n onUpdate(merged, data) {\n mutate([...chatRequest.messages, ...merged], false);\n mutateStreamData([...(existingData || []), ...(data || [])], false);\n },\n onToolCall,\n onFinish,\n generateId,\n fetch,\n });\n};\n\nexport function useChat({\n api = '/api/chat',\n id,\n initialMessages,\n initialInput = '',\n sendExtraMessageFields,\n experimental_onFunctionCall,\n experimental_onToolCall,\n onToolCall,\n experimental_prepareRequestBody,\n experimental_maxAutomaticRoundtrips = 0,\n maxAutomaticRoundtrips = experimental_maxAutomaticRoundtrips,\n maxToolRoundtrips = maxAutomaticRoundtrips,\n streamMode,\n onResponse,\n onFinish,\n onError,\n credentials,\n headers,\n body,\n generateId = generateIdFunc,\n}: UseChatOptions & {\n key?: string;\n\n /**\n@deprecated Use `maxToolRoundtrips` instead.\n */\n experimental_maxAutomaticRoundtrips?: number;\n\n /**\n@deprecated Use `maxToolRoundtrips` instead.\n */\n maxAutomaticRoundtrips?: number;\n\n /**\n * Experimental (React only). When a function is provided, it will be used\n * to prepare the request body for the chat API. This can be useful for\n * customizing the request body based on the messages and data in the chat.\n *\n * @param messages The current messages in the chat.\n * @param requestData The data object passed in the chat request.\n * @param requestBody The request body object passed in the chat request.\n */\n experimental_prepareRequestBody?: (options: {\n messages: Message[];\n requestData?: JSONValue;\n requestBody?: object;\n }) => JSONValue;\n\n /**\nMaximal number of automatic roundtrips for tool calls.\n\nAn automatic tool call roundtrip is a call to the server with the \ntool call results when all tool calls in the last assistant \nmessage have results.\n\nA maximum number is required to prevent infinite loops in the\ncase of misconfigured tools.\n\nBy default, it's set to 0, which will disable the feature.\n */\n maxToolRoundtrips?: number;\n} = {}): UseChatHelpers & {\n /**\n * @deprecated Use `addToolResult` instead.\n */\n experimental_addToolResult: ({\n toolCallId,\n result,\n }: {\n toolCallId: string;\n result: any;\n }) => void;\n addToolResult: ({\n toolCallId,\n result,\n }: {\n toolCallId: string;\n result: any;\n }) => void;\n} {\n // Generate a unique id for the chat if not provided.\n const hookId = useId();\n const idKey = id ?? hookId;\n const chatKey = typeof api === 'string' ? [api, idKey] : idKey;\n\n // Store a empty array as the initial messages\n // (instead of using a default parameter value that gets re-created each time)\n // to avoid re-renders:\n const [initialMessagesFallback] = useState([]);\n\n // Store the chat state in SWR, using the chatId as the key to share states.\n const { data: messages, mutate } = useSWR<Message[]>(\n [chatKey, 'messages'],\n null,\n { fallbackData: initialMessages ?? initialMessagesFallback },\n );\n\n // We store loading state in another hook to sync loading states across hook invocations\n const { data: isLoading = false, mutate: mutateLoading } = useSWR<boolean>(\n [chatKey, 'loading'],\n null,\n );\n\n const { data: streamData, mutate: mutateStreamData } = useSWR<\n JSONValue[] | undefined\n >([chatKey, 'streamData'], null);\n\n const { data: error = undefined, mutate: setError } = useSWR<\n undefined | Error\n >([chatKey, 'error'], null);\n\n // Keep the latest messages in a ref.\n const messagesRef = useRef<Message[]>(messages || []);\n useEffect(() => {\n messagesRef.current = messages || [];\n }, [messages]);\n\n // Abort controller to cancel the current API call.\n const abortControllerRef = useRef<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 (chatRequest: ChatRequest) => {\n const messageCount = messagesRef.current.length;\n\n try {\n mutateLoading(true);\n setError(undefined);\n\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n\n await processChatStream({\n getStreamedResponse: () =>\n getStreamedResponse(\n api,\n chatRequest,\n mutate,\n mutateStreamData,\n streamData!,\n extraMetadataRef,\n messagesRef,\n abortControllerRef,\n generateId,\n streamMode,\n onFinish,\n onResponse,\n onToolCall,\n sendExtraMessageFields,\n experimental_prepareRequestBody,\n fetch,\n ),\n experimental_onFunctionCall,\n experimental_onToolCall,\n updateChatRequest: chatRequestParam => {\n chatRequest = chatRequestParam;\n },\n getCurrentMessages: () => messagesRef.current,\n });\n\n abortControllerRef.current = null;\n } catch (err) {\n // Ignore abort errors as they are expected.\n if ((err as any).name === 'AbortError') {\n abortControllerRef.current = null;\n return null;\n }\n\n if (onError && err instanceof Error) {\n onError(err);\n }\n\n setError(err as Error);\n } finally {\n mutateLoading(false);\n }\n\n // auto-submit when all tool calls in the last assistant message have results:\n const messages = messagesRef.current;\n const lastMessage = messages[messages.length - 1];\n if (\n // ensure we actually have new messages (to prevent infinite loops in case of errors):\n messages.length > messageCount &&\n // ensure there is a last message:\n lastMessage != null &&\n // check if the feature is enabled:\n maxToolRoundtrips > 0 &&\n // check that roundtrip is possible:\n isAssistantMessageWithCompletedToolCalls(lastMessage) &&\n // limit the number of automatic roundtrips:\n countTrailingAssistantMessages(messages) <= maxToolRoundtrips\n ) {\n await triggerRequest({ messages });\n }\n },\n [\n mutate,\n mutateLoading,\n api,\n extraMetadataRef,\n onResponse,\n onFinish,\n onError,\n setError,\n mutateStreamData,\n streamData,\n streamMode,\n sendExtraMessageFields,\n experimental_onFunctionCall,\n experimental_onToolCall,\n experimental_prepareRequestBody,\n onToolCall,\n maxToolRoundtrips,\n messagesRef,\n abortControllerRef,\n generateId,\n ],\n );\n\n const append = useCallback(\n async (\n message: Message | CreateMessage,\n {\n options,\n functions,\n function_call,\n tools,\n tool_choice,\n data,\n }: ChatRequestOptions = {},\n ) => {\n if (!message.id) {\n message.id = generateId();\n }\n\n const chatRequest: ChatRequest = {\n messages: messagesRef.current.concat(message as Message),\n options,\n data,\n ...(functions !== undefined && { functions }),\n ...(function_call !== undefined && { function_call }),\n ...(tools !== undefined && { tools }),\n ...(tool_choice !== undefined && { tool_choice }),\n };\n\n return triggerRequest(chatRequest);\n },\n [triggerRequest, generateId],\n );\n\n const reload = useCallback(\n async ({\n options,\n functions,\n function_call,\n tools,\n tool_choice,\n }: ChatRequestOptions = {}) => {\n if (messagesRef.current.length === 0) return null;\n\n // Remove last assistant message and retry last user message.\n const lastMessage = messagesRef.current[messagesRef.current.length - 1];\n if (lastMessage.role === 'assistant') {\n const chatRequest: ChatRequest = {\n messages: messagesRef.current.slice(0, -1),\n options,\n ...(functions !== undefined && { functions }),\n ...(function_call !== undefined && { function_call }),\n ...(tools !== undefined && { tools }),\n ...(tool_choice !== undefined && { tool_choice }),\n };\n\n return triggerRequest(chatRequest);\n }\n\n const chatRequest: ChatRequest = {\n messages: messagesRef.current,\n options,\n ...(functions !== undefined && { functions }),\n ...(function_call !== undefined && { function_call }),\n ...(tools !== undefined && { tools }),\n ...(tool_choice !== undefined && { tool_choice }),\n };\n\n return triggerRequest(chatRequest);\n },\n [triggerRequest],\n );\n\n const stop = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n }, []);\n\n const setMessages = useCallback(\n (messages: Message[]) => {\n mutate(messages, false);\n messagesRef.current = messages;\n },\n [mutate],\n );\n\n // Input state and handlers.\n const [input, setInput] = useState(initialInput);\n\n const handleSubmit = useCallback(\n (\n event?: { preventDefault?: () => void },\n options: ChatRequestOptions = {},\n metadata?: Object,\n ) => {\n if (metadata) {\n extraMetadataRef.current = {\n ...extraMetadataRef.current,\n ...metadata,\n };\n }\n\n event?.preventDefault?.();\n\n if (!input) return;\n\n append(\n {\n content: input,\n role: 'user',\n createdAt: new Date(),\n },\n options,\n );\n setInput('');\n },\n [input, append],\n );\n\n const handleInputChange = (e: any) => {\n setInput(e.target.value);\n };\n\n const addToolResult = ({\n toolCallId,\n result,\n }: {\n toolCallId: string;\n result: any;\n }) => {\n const updatedMessages = messagesRef.current.map((message, index, arr) =>\n // update the tool calls in the last assistant message:\n index === arr.length - 1 &&\n message.role === 'assistant' &&\n message.toolInvocations\n ? {\n ...message,\n toolInvocations: message.toolInvocations.map(toolInvocation =>\n toolInvocation.toolCallId === toolCallId\n ? { ...toolInvocation, result }\n : toolInvocation,\n ),\n }\n : message,\n );\n\n mutate(updatedMessages, false);\n\n // auto-submit when all tool calls in the last assistant message have results:\n const lastMessage = updatedMessages[updatedMessages.length - 1];\n if (isAssistantMessageWithCompletedToolCalls(lastMessage)) {\n triggerRequest({ messages: updatedMessages });\n }\n };\n\n return {\n messages: messages || [],\n error,\n append,\n reload,\n stop,\n setMessages,\n input,\n setInput,\n handleInputChange,\n handleSubmit,\n isLoading,\n data: streamData,\n addToolResult,\n experimental_addToolResult: addToolResult,\n };\n}\n\n/**\nCheck if the message is an assistant message with completed tool calls. \nThe message must have at least one tool invocation and all tool invocations\nmust have a result.\n */\nfunction isAssistantMessageWithCompletedToolCalls(message: Message) {\n return (\n message.role === 'assistant' &&\n message.toolInvocations &&\n message.toolInvocations.length > 0 &&\n message.toolInvocations.every(toolInvocation => 'result' in toolInvocation)\n );\n}\n\n/**\nReturns the number of trailing assistant messages in the array.\n */\nfunction countTrailingAssistantMessages(messages: Message[]) {\n let count = 0;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === 'assistant') {\n count++;\n } else {\n break;\n }\n }\n return count;\n}\n","import {\n JSONValue,\n RequestOptions,\n UseCompletionOptions,\n callCompletionApi,\n} from '@ai-sdk/ui-utils';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\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?: RequestOptions,\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 /** Additional data added on the server via StreamData */\n data?: JSONValue[];\n};\n\nexport function useCompletion({\n api = '/api/completion',\n id,\n initialCompletion = '',\n initialInput = '',\n credentials,\n headers,\n body,\n streamMode,\n fetch,\n onResponse,\n onFinish,\n onError,\n}: UseCompletionOptions = {}): 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 { data: streamData, mutate: mutateStreamData } = useSWR<\n JSONValue[] | undefined\n >([completionId, 'streamData'], null);\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 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?: RequestOptions) =>\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 streamMode,\n fetch,\n setCompletion: completion => mutate(completion, false),\n setLoading: mutateLoading,\n setError,\n setAbortController,\n onResponse,\n onFinish,\n onError,\n onData: data => {\n mutateStreamData([...(streamData || []), ...(data || [])], false);\n },\n }),\n [\n mutate,\n mutateLoading,\n api,\n extraMetadataRef,\n setAbortController,\n onResponse,\n onFinish,\n onError,\n setError,\n streamData,\n streamMode,\n fetch,\n mutateStreamData,\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 = (e: any) => {\n setInput(e.target.value);\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 data: streamData,\n };\n}\n","import { isAbortError } from '@ai-sdk/provider-utils';\nimport {\n DeepPartial,\n FetchFunction,\n isDeepEqualData,\n parsePartialJson,\n} from '@ai-sdk/ui-utils';\nimport { useCallback, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\nimport z from 'zod';\n\n// use function to allow for mocking in tests:\nconst getOriginalFetch = () => fetch;\n\nexport type Experimental_UseObjectOptions<RESULT> = {\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: z.Schema<RESULT>;\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\nexport type Experimental_UseObjectHelpers<RESULT, INPUT> = {\n /**\n * @deprecated Use `submit` instead.\n */\n setInput: (input: INPUT) => void;\n\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: undefined | unknown;\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<RESULT, INPUT = any>({\n api,\n id,\n schema, // required, in the future we will use it for validation\n initialValue,\n fetch,\n}: Experimental_UseObjectOptions<RESULT>): Experimental_UseObjectHelpers<\n RESULT,\n INPUT\n> {\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 | unknown>(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 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: { 'Content-Type': 'application/json' },\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 write(chunk) {\n accumulatedText += chunk;\n\n const currentObject = parsePartialJson(\n accumulatedText,\n ) as DeepPartial<RESULT>;\n\n if (!isDeepEqualData(latestObject, currentObject)) {\n latestObject = currentObject;\n\n mutate(currentObject);\n }\n },\n\n close() {\n setIsLoading(false);\n abortControllerRef.current = null;\n },\n }),\n );\n } catch (error) {\n if (isAbortError(error)) {\n return;\n }\n\n setError(error);\n }\n };\n\n return {\n setInput: submit, // Deprecated\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":["fetch","messages","_a","error","useCallback","useRef","useState","generateId","fetch","messages","chatRequest","useCallback","useEffect","useId","useRef","useState","useSWR","fetch","completion","data","isAbortError","useCallback","useId","useRef","useState","useSWR","getOriginalFetch","fetch","error"]}
|
|
1
|
+
{"version":3,"sources":["../src/use-assistant.ts","../src/use-chat.ts","../src/use-completion.ts","../src/use-object.ts"],"sourcesContent":["import { isAbortError } from '@ai-sdk/provider-utils';\nimport {\n AssistantStatus,\n CreateMessage,\n Message,\n UseAssistantOptions,\n generateId,\n readDataStream,\n} from '@ai-sdk/ui-utils';\nimport { useCallback, useRef, useState } from 'react';\n\n// use function to allow for mocking in tests:\nconst getOriginalFetch = () => fetch;\n\nexport type UseAssistantHelpers = {\n /**\n * The current array of chat messages.\n */\n messages: Message[];\n\n /**\n * Update the message store with a new array of messages.\n */\n setMessages: React.Dispatch<React.SetStateAction<Message[]>>;\n\n /**\n * The current thread ID.\n */\n threadId: string | undefined;\n\n /**\n * The current value of the input field.\n */\n input: string;\n\n /**\n * Append a user message to the chat list. This triggers the API call to fetch\n * the assistant's response.\n * @param message The message to append\n * @param requestOptions Additional options to pass to the API call\n */\n append: (\n message: Message | CreateMessage,\n requestOptions?: {\n data?: Record<string, string>;\n },\n ) => Promise<void>;\n\n /**\nAbort the current request immediately, keep the generated tokens if any.\n */\n stop: () => void;\n\n /**\n * setState-powered method to update the input value.\n */\n setInput: React.Dispatch<React.SetStateAction<string>>;\n\n /**\n * Handler for the `onChange` event of the input field to control the input's value.\n */\n handleInputChange: (\n event:\n | React.ChangeEvent<HTMLInputElement>\n | React.ChangeEvent<HTMLTextAreaElement>,\n ) => void;\n\n /**\n * Form submission handler that automatically resets the input field and appends a user message.\n */\n submitMessage: (\n event?: React.FormEvent<HTMLFormElement>,\n requestOptions?: {\n data?: Record<string, string>;\n },\n ) => Promise<void>;\n\n /**\n * The current status of the assistant. This can be used to show a loading indicator.\n */\n status: AssistantStatus;\n\n /**\n * The error thrown during the assistant message processing, if any.\n */\n error: undefined | Error;\n};\n\nexport function useAssistant({\n api,\n threadId: threadIdParam,\n credentials,\n headers,\n body,\n onError,\n fetch,\n}: UseAssistantOptions): UseAssistantHelpers {\n const [messages, setMessages] = useState<Message[]>([]);\n const [input, setInput] = useState('');\n const [threadId, setThreadId] = useState<string | undefined>(undefined);\n const [status, setStatus] = useState<AssistantStatus>('awaiting_message');\n const [error, setError] = useState<undefined | Error>(undefined);\n\n const handleInputChange = (\n event:\n | React.ChangeEvent<HTMLInputElement>\n | React.ChangeEvent<HTMLTextAreaElement>,\n ) => {\n setInput(event.target.value);\n };\n\n // Abort controller to cancel the current API call.\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const stop = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n }, []);\n\n const append = async (\n message: Message | CreateMessage,\n requestOptions?: {\n data?: Record<string, string>;\n },\n ) => {\n setStatus('in_progress');\n\n setMessages(messages => [\n ...messages,\n {\n ...message,\n id: message.id ?? generateId(),\n },\n ]);\n\n setInput('');\n\n const abortController = new AbortController();\n\n try {\n abortControllerRef.current = abortController;\n\n const actualFetch = fetch ?? getOriginalFetch();\n const response = await actualFetch(api, {\n method: 'POST',\n credentials,\n signal: abortController.signal,\n headers: { 'Content-Type': 'application/json', ...headers },\n body: JSON.stringify({\n ...body,\n // always use user-provided threadId when available:\n threadId: threadIdParam ?? threadId ?? null,\n message: message.content,\n\n // optional request data:\n data: requestOptions?.data,\n }),\n });\n\n if (!response.ok) {\n throw new Error(\n (await response.text()) ?? 'Failed to fetch the assistant response.',\n );\n }\n\n if (response.body == null) {\n throw new Error('The response body is empty.');\n }\n\n for await (const { type, value } of readDataStream(\n response.body.getReader(),\n )) {\n switch (type) {\n case 'assistant_message': {\n setMessages(messages => [\n ...messages,\n {\n id: value.id,\n role: value.role,\n content: value.content[0].text.value,\n },\n ]);\n break;\n }\n\n case 'text': {\n // text delta - add to last message:\n setMessages(messages => {\n const lastMessage = messages[messages.length - 1];\n return [\n ...messages.slice(0, messages.length - 1),\n {\n id: lastMessage.id,\n role: lastMessage.role,\n content: lastMessage.content + value,\n },\n ];\n });\n\n break;\n }\n\n case 'data_message': {\n setMessages(messages => [\n ...messages,\n {\n id: value.id ?? generateId(),\n role: 'data',\n content: '',\n data: value.data,\n },\n ]);\n break;\n }\n\n case 'assistant_control_data': {\n setThreadId(value.threadId);\n\n // set id of last message:\n setMessages(messages => {\n const lastMessage = messages[messages.length - 1];\n lastMessage.id = value.messageId;\n return [...messages.slice(0, messages.length - 1), lastMessage];\n });\n\n break;\n }\n\n case 'error': {\n setError(new Error(value));\n break;\n }\n }\n }\n } catch (error) {\n // Ignore abort errors as they are expected when the user cancels the request:\n if (isAbortError(error) && abortController.signal.aborted) {\n abortControllerRef.current = null;\n return;\n }\n\n if (onError && error instanceof Error) {\n onError(error);\n }\n\n setError(error as Error);\n } finally {\n abortControllerRef.current = null;\n setStatus('awaiting_message');\n }\n };\n\n const submitMessage = async (\n event?: React.FormEvent<HTMLFormElement>,\n requestOptions?: {\n data?: Record<string, string>;\n },\n ) => {\n event?.preventDefault?.();\n\n if (input === '') {\n return;\n }\n\n append({ role: 'user', content: input }, requestOptions);\n };\n\n return {\n append,\n messages,\n setMessages,\n threadId,\n input,\n setInput,\n handleInputChange,\n submitMessage,\n status,\n error,\n stop,\n };\n}\n\n/**\n@deprecated Use `useAssistant` instead.\n */\nexport const experimental_useAssistant = useAssistant;\n","import type {\n ChatRequest,\n ChatRequestOptions,\n CreateMessage,\n FetchFunction,\n IdGenerator,\n JSONValue,\n Message,\n UseChatOptions,\n} from '@ai-sdk/ui-utils';\nimport {\n callChatApi,\n generateId as generateIdFunc,\n processChatStream,\n} from '@ai-sdk/ui-utils';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport useSWR, { KeyedMutator } from 'swr';\n\nexport type { CreateMessage, Message, UseChatOptions };\n\nexport type UseChatHelpers = {\n /** Current messages in the chat */\n messages: Message[];\n /** The error object of the API request */\n error: undefined | Error;\n /**\n * Append a user message to the chat list. This triggers the API call to fetch\n * the assistant's response.\n * @param message The message to append\n * @param options Additional options to pass to the API call\n */\n append: (\n message: Message | CreateMessage,\n chatRequestOptions?: ChatRequestOptions,\n ) => Promise<string | null | undefined>;\n /**\n * Reload the last AI chat response for the given chat history. If the last\n * message isn't from the assistant, it will request the API to generate a\n * new response.\n */\n reload: (\n chatRequestOptions?: ChatRequestOptions,\n ) => Promise<string | null | undefined>;\n /**\n * Abort the current request immediately, keep the generated tokens if any.\n */\n stop: () => void;\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: (messages: Message[]) => 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 /** 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 /** Form submission handler to automatically reset input and append a user message */\n handleSubmit: (\n event?: { preventDefault?: () => void },\n chatRequestOptions?: ChatRequestOptions,\n ) => void;\n metadata?: Object;\n /** Whether the API request is in progress */\n isLoading: boolean;\n /** Additional data added on the server via StreamData */\n data?: JSONValue[];\n};\n\nconst getStreamedResponse = async (\n api: string,\n chatRequest: ChatRequest,\n mutate: KeyedMutator<Message[]>,\n mutateStreamData: KeyedMutator<JSONValue[] | undefined>,\n existingData: JSONValue[] | undefined,\n extraMetadataRef: React.MutableRefObject<any>,\n messagesRef: React.MutableRefObject<Message[]>,\n abortControllerRef: React.MutableRefObject<AbortController | null>,\n generateId: IdGenerator,\n streamMode: 'stream-data' | 'text' | undefined,\n onFinish: ((message: Message) => void) | undefined,\n onResponse: ((response: Response) => void | Promise<void>) | undefined,\n onToolCall: UseChatOptions['onToolCall'] | undefined,\n sendExtraMessageFields: boolean | undefined,\n experimental_prepareRequestBody:\n | ((options: {\n messages: Message[];\n requestData?: JSONValue;\n requestBody?: object;\n }) => JSONValue)\n | undefined,\n fetch: FetchFunction | undefined,\n) => {\n // Do an optimistic update to the chat state to show the updated messages\n // immediately.\n const previousMessages = messagesRef.current;\n mutate(chatRequest.messages, false);\n\n const constructedMessagesPayload = sendExtraMessageFields\n ? chatRequest.messages\n : chatRequest.messages.map(\n ({\n role,\n content,\n name,\n data,\n annotations,\n toolInvocations,\n function_call,\n tool_calls,\n tool_call_id,\n }) => ({\n role,\n content,\n ...(name !== undefined && { name }),\n ...(data !== undefined && { data }),\n ...(annotations !== undefined && { annotations }),\n ...(toolInvocations !== undefined && { toolInvocations }),\n // outdated function/tool call handling (TODO deprecate):\n tool_call_id,\n ...(function_call !== undefined && { function_call }),\n ...(tool_calls !== undefined && { tool_calls }),\n }),\n );\n\n return await callChatApi({\n api,\n body: experimental_prepareRequestBody?.({\n messages: chatRequest.messages,\n requestData: chatRequest.data,\n requestBody: chatRequest.options?.body,\n }) ?? {\n messages: constructedMessagesPayload,\n data: chatRequest.data,\n ...extraMetadataRef.current.body,\n ...chatRequest.options?.body,\n ...(chatRequest.functions !== undefined && {\n functions: chatRequest.functions,\n }),\n ...(chatRequest.function_call !== undefined && {\n function_call: chatRequest.function_call,\n }),\n ...(chatRequest.tools !== undefined && {\n tools: chatRequest.tools,\n }),\n ...(chatRequest.tool_choice !== undefined && {\n tool_choice: chatRequest.tool_choice,\n }),\n },\n streamMode,\n credentials: extraMetadataRef.current.credentials,\n headers: {\n ...extraMetadataRef.current.headers,\n ...chatRequest.options?.headers,\n },\n abortController: () => abortControllerRef.current,\n restoreMessagesOnFailure() {\n mutate(previousMessages, false);\n },\n onResponse,\n onUpdate(merged, data) {\n mutate([...chatRequest.messages, ...merged], false);\n mutateStreamData([...(existingData || []), ...(data || [])], false);\n },\n onToolCall,\n onFinish,\n generateId,\n fetch,\n });\n};\n\nexport function useChat({\n api = '/api/chat',\n id,\n initialMessages,\n initialInput = '',\n sendExtraMessageFields,\n experimental_onFunctionCall,\n experimental_onToolCall,\n onToolCall,\n experimental_prepareRequestBody,\n experimental_maxAutomaticRoundtrips = 0,\n maxAutomaticRoundtrips = experimental_maxAutomaticRoundtrips,\n maxToolRoundtrips = maxAutomaticRoundtrips,\n streamMode,\n onResponse,\n onFinish,\n onError,\n credentials,\n headers,\n body,\n generateId = generateIdFunc,\n fetch,\n}: UseChatOptions & {\n key?: string;\n\n /**\n@deprecated Use `maxToolRoundtrips` instead.\n */\n experimental_maxAutomaticRoundtrips?: number;\n\n /**\n@deprecated Use `maxToolRoundtrips` instead.\n */\n maxAutomaticRoundtrips?: number;\n\n /**\n * Experimental (React only). When a function is provided, it will be used\n * to prepare the request body for the chat API. This can be useful for\n * customizing the request body based on the messages and data in the chat.\n *\n * @param messages The current messages in the chat.\n * @param requestData The data object passed in the chat request.\n * @param requestBody The request body object passed in the chat request.\n */\n experimental_prepareRequestBody?: (options: {\n messages: Message[];\n requestData?: JSONValue;\n requestBody?: object;\n }) => JSONValue;\n\n /**\nMaximal number of automatic roundtrips for tool calls.\n\nAn automatic tool call roundtrip is a call to the server with the \ntool call results when all tool calls in the last assistant \nmessage have results.\n\nA maximum number is required to prevent infinite loops in the\ncase of misconfigured tools.\n\nBy default, it's set to 0, which will disable the feature.\n */\n maxToolRoundtrips?: number;\n} = {}): UseChatHelpers & {\n /**\n * @deprecated Use `addToolResult` instead.\n */\n experimental_addToolResult: ({\n toolCallId,\n result,\n }: {\n toolCallId: string;\n result: any;\n }) => void;\n addToolResult: ({\n toolCallId,\n result,\n }: {\n toolCallId: string;\n result: any;\n }) => void;\n} {\n // Generate a unique id for the chat if not provided.\n const hookId = useId();\n const idKey = id ?? hookId;\n const chatKey = typeof api === 'string' ? [api, idKey] : idKey;\n\n // Store a empty array as the initial messages\n // (instead of using a default parameter value that gets re-created each time)\n // to avoid re-renders:\n const [initialMessagesFallback] = useState([]);\n\n // Store the chat state in SWR, using the chatId as the key to share states.\n const { data: messages, mutate } = useSWR<Message[]>(\n [chatKey, 'messages'],\n null,\n { fallbackData: initialMessages ?? initialMessagesFallback },\n );\n\n // We store loading state in another hook to sync loading states across hook invocations\n const { data: isLoading = false, mutate: mutateLoading } = useSWR<boolean>(\n [chatKey, 'loading'],\n null,\n );\n\n const { data: streamData, mutate: mutateStreamData } = useSWR<\n JSONValue[] | undefined\n >([chatKey, 'streamData'], null);\n\n const { data: error = undefined, mutate: setError } = useSWR<\n undefined | Error\n >([chatKey, 'error'], null);\n\n // Keep the latest messages in a ref.\n const messagesRef = useRef<Message[]>(messages || []);\n useEffect(() => {\n messagesRef.current = messages || [];\n }, [messages]);\n\n // Abort controller to cancel the current API call.\n const abortControllerRef = useRef<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 (chatRequest: ChatRequest) => {\n const messageCount = messagesRef.current.length;\n\n try {\n mutateLoading(true);\n setError(undefined);\n\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n\n await processChatStream({\n getStreamedResponse: () =>\n getStreamedResponse(\n api,\n chatRequest,\n mutate,\n mutateStreamData,\n streamData!,\n extraMetadataRef,\n messagesRef,\n abortControllerRef,\n generateId,\n streamMode,\n onFinish,\n onResponse,\n onToolCall,\n sendExtraMessageFields,\n experimental_prepareRequestBody,\n fetch,\n ),\n experimental_onFunctionCall,\n experimental_onToolCall,\n updateChatRequest: chatRequestParam => {\n chatRequest = chatRequestParam;\n },\n getCurrentMessages: () => messagesRef.current,\n });\n\n abortControllerRef.current = null;\n } catch (err) {\n // Ignore abort errors as they are expected.\n if ((err as any).name === 'AbortError') {\n abortControllerRef.current = null;\n return null;\n }\n\n if (onError && err instanceof Error) {\n onError(err);\n }\n\n setError(err as Error);\n } finally {\n mutateLoading(false);\n }\n\n // auto-submit when all tool calls in the last assistant message have results:\n const messages = messagesRef.current;\n const lastMessage = messages[messages.length - 1];\n if (\n // ensure we actually have new messages (to prevent infinite loops in case of errors):\n messages.length > messageCount &&\n // ensure there is a last message:\n lastMessage != null &&\n // check if the feature is enabled:\n maxToolRoundtrips > 0 &&\n // check that roundtrip is possible:\n isAssistantMessageWithCompletedToolCalls(lastMessage) &&\n // limit the number of automatic roundtrips:\n countTrailingAssistantMessages(messages) <= maxToolRoundtrips\n ) {\n await triggerRequest({ messages });\n }\n },\n [\n mutate,\n mutateLoading,\n api,\n extraMetadataRef,\n onResponse,\n onFinish,\n onError,\n setError,\n mutateStreamData,\n streamData,\n streamMode,\n sendExtraMessageFields,\n experimental_onFunctionCall,\n experimental_onToolCall,\n experimental_prepareRequestBody,\n onToolCall,\n maxToolRoundtrips,\n messagesRef,\n abortControllerRef,\n generateId,\n fetch,\n ],\n );\n\n const append = useCallback(\n async (\n message: Message | CreateMessage,\n {\n options,\n functions,\n function_call,\n tools,\n tool_choice,\n data,\n }: ChatRequestOptions = {},\n ) => {\n if (!message.id) {\n message.id = generateId();\n }\n\n const chatRequest: ChatRequest = {\n messages: messagesRef.current.concat(message as Message),\n options,\n data,\n ...(functions !== undefined && { functions }),\n ...(function_call !== undefined && { function_call }),\n ...(tools !== undefined && { tools }),\n ...(tool_choice !== undefined && { tool_choice }),\n };\n\n return triggerRequest(chatRequest);\n },\n [triggerRequest, generateId],\n );\n\n const reload = useCallback(\n async ({\n options,\n functions,\n function_call,\n tools,\n tool_choice,\n }: ChatRequestOptions = {}) => {\n if (messagesRef.current.length === 0) return null;\n\n // Remove last assistant message and retry last user message.\n const lastMessage = messagesRef.current[messagesRef.current.length - 1];\n if (lastMessage.role === 'assistant') {\n const chatRequest: ChatRequest = {\n messages: messagesRef.current.slice(0, -1),\n options,\n ...(functions !== undefined && { functions }),\n ...(function_call !== undefined && { function_call }),\n ...(tools !== undefined && { tools }),\n ...(tool_choice !== undefined && { tool_choice }),\n };\n\n return triggerRequest(chatRequest);\n }\n\n const chatRequest: ChatRequest = {\n messages: messagesRef.current,\n options,\n ...(functions !== undefined && { functions }),\n ...(function_call !== undefined && { function_call }),\n ...(tools !== undefined && { tools }),\n ...(tool_choice !== undefined && { tool_choice }),\n };\n\n return triggerRequest(chatRequest);\n },\n [triggerRequest],\n );\n\n const stop = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n }, []);\n\n const setMessages = useCallback(\n (messages: Message[]) => {\n mutate(messages, false);\n messagesRef.current = messages;\n },\n [mutate],\n );\n\n // Input state and handlers.\n const [input, setInput] = useState(initialInput);\n\n const handleSubmit = useCallback(\n (\n event?: { preventDefault?: () => void },\n options: ChatRequestOptions = {},\n metadata?: Object,\n ) => {\n if (metadata) {\n extraMetadataRef.current = {\n ...extraMetadataRef.current,\n ...metadata,\n };\n }\n\n event?.preventDefault?.();\n\n const chatRequest: ChatRequest = {\n messages: input\n ? messagesRef.current.concat({\n id: generateId(),\n role: 'user',\n content: input,\n })\n : messagesRef.current,\n options: options.options,\n data: options.data,\n };\n\n triggerRequest(chatRequest);\n\n setInput('');\n },\n [input, generateId, triggerRequest],\n );\n\n const handleInputChange = (e: any) => {\n setInput(e.target.value);\n };\n\n const addToolResult = ({\n toolCallId,\n result,\n }: {\n toolCallId: string;\n result: any;\n }) => {\n const updatedMessages = messagesRef.current.map((message, index, arr) =>\n // update the tool calls in the last assistant message:\n index === arr.length - 1 &&\n message.role === 'assistant' &&\n message.toolInvocations\n ? {\n ...message,\n toolInvocations: message.toolInvocations.map(toolInvocation =>\n toolInvocation.toolCallId === toolCallId\n ? { ...toolInvocation, result }\n : toolInvocation,\n ),\n }\n : message,\n );\n\n mutate(updatedMessages, false);\n\n // auto-submit when all tool calls in the last assistant message have results:\n const lastMessage = updatedMessages[updatedMessages.length - 1];\n if (isAssistantMessageWithCompletedToolCalls(lastMessage)) {\n triggerRequest({ messages: updatedMessages });\n }\n };\n\n return {\n messages: messages || [],\n error,\n append,\n reload,\n stop,\n setMessages,\n input,\n setInput,\n handleInputChange,\n handleSubmit,\n isLoading,\n data: streamData,\n addToolResult,\n experimental_addToolResult: addToolResult,\n };\n}\n\n/**\nCheck if the message is an assistant message with completed tool calls. \nThe message must have at least one tool invocation and all tool invocations\nmust have a result.\n */\nfunction isAssistantMessageWithCompletedToolCalls(message: Message) {\n return (\n message.role === 'assistant' &&\n message.toolInvocations &&\n message.toolInvocations.length > 0 &&\n message.toolInvocations.every(toolInvocation => 'result' in toolInvocation)\n );\n}\n\n/**\nReturns the number of trailing assistant messages in the array.\n */\nfunction countTrailingAssistantMessages(messages: Message[]) {\n let count = 0;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === 'assistant') {\n count++;\n } else {\n break;\n }\n }\n return count;\n}\n","import {\n JSONValue,\n RequestOptions,\n UseCompletionOptions,\n callCompletionApi,\n} from '@ai-sdk/ui-utils';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\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?: RequestOptions,\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 /** Additional data added on the server via StreamData */\n data?: JSONValue[];\n};\n\nexport function useCompletion({\n api = '/api/completion',\n id,\n initialCompletion = '',\n initialInput = '',\n credentials,\n headers,\n body,\n streamMode,\n fetch,\n onResponse,\n onFinish,\n onError,\n}: UseCompletionOptions = {}): 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 { data: streamData, mutate: mutateStreamData } = useSWR<\n JSONValue[] | undefined\n >([completionId, 'streamData'], null);\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 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?: RequestOptions) =>\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 streamMode,\n fetch,\n setCompletion: completion => mutate(completion, false),\n setLoading: mutateLoading,\n setError,\n setAbortController,\n onResponse,\n onFinish,\n onError,\n onData: data => {\n mutateStreamData([...(streamData || []), ...(data || [])], false);\n },\n }),\n [\n mutate,\n mutateLoading,\n api,\n extraMetadataRef,\n setAbortController,\n onResponse,\n onFinish,\n onError,\n setError,\n streamData,\n streamMode,\n fetch,\n mutateStreamData,\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 = (e: any) => {\n setInput(e.target.value);\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 data: streamData,\n };\n}\n","import { isAbortError } from '@ai-sdk/provider-utils';\nimport {\n DeepPartial,\n FetchFunction,\n isDeepEqualData,\n parsePartialJson,\n} from '@ai-sdk/ui-utils';\nimport { useCallback, useId, useRef, useState } from 'react';\nimport useSWR from 'swr';\nimport z from 'zod';\n\n// use function to allow for mocking in tests:\nconst getOriginalFetch = () => fetch;\n\nexport type Experimental_UseObjectOptions<RESULT> = {\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: z.Schema<RESULT>;\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 /**\n * Callback function to be called when an error is encountered.\n */\n onError?: (error: Error) => void;\n};\n\nexport type Experimental_UseObjectHelpers<RESULT, INPUT> = {\n /**\n * @deprecated Use `submit` instead.\n */\n setInput: (input: INPUT) => void;\n\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: undefined | unknown;\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<RESULT, INPUT = any>({\n api,\n id,\n schema, // required, in the future we will use it for validation\n initialValue,\n fetch,\n onError,\n}: Experimental_UseObjectOptions<RESULT>): Experimental_UseObjectHelpers<\n RESULT,\n INPUT\n> {\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 | unknown>(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 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: { 'Content-Type': 'application/json' },\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 write(chunk) {\n accumulatedText += chunk;\n\n const currentObject = parsePartialJson(\n accumulatedText,\n ) as DeepPartial<RESULT>;\n\n if (!isDeepEqualData(latestObject, currentObject)) {\n latestObject = currentObject;\n\n mutate(currentObject);\n }\n },\n\n close() {\n setIsLoading(false);\n abortControllerRef.current = null;\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 setError(error);\n }\n };\n\n return {\n setInput: submit, // Deprecated\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":["fetch","messages","_a","error","useCallback","useRef","useState","generateId","fetch","messages","chatRequest","useCallback","useEffect","useId","useRef","useState","useSWR","fetch","completion","data","isAbortError","useCallback","useId","useRef","useState","useSWR","getOriginalFetch","fetch","error"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@ai-sdk/provider-utils": "1.0.
|
|
19
|
-
"@ai-sdk/ui-utils": "0.0.
|
|
18
|
+
"@ai-sdk/provider-utils": "1.0.1",
|
|
19
|
+
"@ai-sdk/ui-utils": "0.0.10",
|
|
20
20
|
"swr": "2.2.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"@types/react-dom": "^18",
|
|
29
29
|
"eslint": "^7.32.0",
|
|
30
30
|
"jsdom": "^24.0.0",
|
|
31
|
-
"msw": "2.
|
|
31
|
+
"msw": "2.3.1",
|
|
32
32
|
"react-dom": "^18",
|
|
33
33
|
"tsup": "^7.2.0",
|
|
34
34
|
"typescript": "5.1.3",
|
package/src/use-chat.ts
CHANGED
|
@@ -196,6 +196,7 @@ export function useChat({
|
|
|
196
196
|
headers,
|
|
197
197
|
body,
|
|
198
198
|
generateId = generateIdFunc,
|
|
199
|
+
fetch,
|
|
199
200
|
}: UseChatOptions & {
|
|
200
201
|
key?: string;
|
|
201
202
|
|
|
@@ -405,6 +406,7 @@ By default, it's set to 0, which will disable the feature.
|
|
|
405
406
|
messagesRef,
|
|
406
407
|
abortControllerRef,
|
|
407
408
|
generateId,
|
|
409
|
+
fetch,
|
|
408
410
|
],
|
|
409
411
|
);
|
|
410
412
|
|
|
@@ -511,19 +513,23 @@ By default, it's set to 0, which will disable the feature.
|
|
|
511
513
|
|
|
512
514
|
event?.preventDefault?.();
|
|
513
515
|
|
|
514
|
-
|
|
516
|
+
const chatRequest: ChatRequest = {
|
|
517
|
+
messages: input
|
|
518
|
+
? messagesRef.current.concat({
|
|
519
|
+
id: generateId(),
|
|
520
|
+
role: 'user',
|
|
521
|
+
content: input,
|
|
522
|
+
})
|
|
523
|
+
: messagesRef.current,
|
|
524
|
+
options: options.options,
|
|
525
|
+
data: options.data,
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
triggerRequest(chatRequest);
|
|
515
529
|
|
|
516
|
-
append(
|
|
517
|
-
{
|
|
518
|
-
content: input,
|
|
519
|
-
role: 'user',
|
|
520
|
-
createdAt: new Date(),
|
|
521
|
-
},
|
|
522
|
-
options,
|
|
523
|
-
);
|
|
524
530
|
setInput('');
|
|
525
531
|
},
|
|
526
|
-
[input,
|
|
532
|
+
[input, generateId, triggerRequest],
|
|
527
533
|
);
|
|
528
534
|
|
|
529
535
|
const handleInputChange = (e: any) => {
|
package/src/use-chat.ui.test.tsx
CHANGED
|
@@ -205,6 +205,84 @@ describe('text stream', () => {
|
|
|
205
205
|
});
|
|
206
206
|
});
|
|
207
207
|
|
|
208
|
+
describe('form actions', () => {
|
|
209
|
+
const TestComponent = () => {
|
|
210
|
+
const {
|
|
211
|
+
messages,
|
|
212
|
+
append,
|
|
213
|
+
handleSubmit,
|
|
214
|
+
handleInputChange,
|
|
215
|
+
isLoading,
|
|
216
|
+
input,
|
|
217
|
+
} = useChat({
|
|
218
|
+
streamMode: 'text',
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
return (
|
|
222
|
+
<div>
|
|
223
|
+
{messages.map((m, idx) => (
|
|
224
|
+
<div data-testid={`message-${idx}`} key={m.id}>
|
|
225
|
+
{m.role === 'user' ? 'User: ' : 'AI: '}
|
|
226
|
+
{m.content}
|
|
227
|
+
</div>
|
|
228
|
+
))}
|
|
229
|
+
|
|
230
|
+
<form onSubmit={handleSubmit} className="fixed bottom-0 p-2 w-full">
|
|
231
|
+
<input
|
|
232
|
+
value={input}
|
|
233
|
+
placeholder="Send message..."
|
|
234
|
+
onChange={handleInputChange}
|
|
235
|
+
className="bg-zinc-100 w-full p-2"
|
|
236
|
+
disabled={isLoading}
|
|
237
|
+
data-testid="do-input"
|
|
238
|
+
/>
|
|
239
|
+
</form>
|
|
240
|
+
</div>
|
|
241
|
+
);
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
beforeEach(() => {
|
|
245
|
+
render(<TestComponent />);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
afterEach(() => {
|
|
249
|
+
vi.restoreAllMocks();
|
|
250
|
+
cleanup();
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('should show streamed response using handleSubmit', async () => {
|
|
254
|
+
mockFetchDataStream({
|
|
255
|
+
url: 'https://example.com/api/chat',
|
|
256
|
+
chunks: ['Hello', ',', ' world', '.'],
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
const firstInput = screen.getByTestId('do-input');
|
|
260
|
+
await userEvent.type(firstInput, 'hi');
|
|
261
|
+
await userEvent.keyboard('{Enter}');
|
|
262
|
+
|
|
263
|
+
await screen.findByTestId('message-0');
|
|
264
|
+
expect(screen.getByTestId('message-0')).toHaveTextContent('User: hi');
|
|
265
|
+
|
|
266
|
+
await screen.findByTestId('message-1');
|
|
267
|
+
expect(screen.getByTestId('message-1')).toHaveTextContent(
|
|
268
|
+
'AI: Hello, world.',
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
mockFetchDataStream({
|
|
272
|
+
url: 'https://example.com/api/chat',
|
|
273
|
+
chunks: ['How', ' can', ' I', ' help', ' you', '?'],
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
const secondInput = screen.getByTestId('do-input');
|
|
277
|
+
await userEvent.type(secondInput, '{Enter}');
|
|
278
|
+
|
|
279
|
+
await screen.findByTestId('message-2');
|
|
280
|
+
expect(screen.getByTestId('message-2')).toHaveTextContent(
|
|
281
|
+
'AI: How can I help you?',
|
|
282
|
+
);
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
|
|
208
286
|
describe('prepareRequestBody', () => {
|
|
209
287
|
let bodyOptions: any;
|
|
210
288
|
|
package/src/use-object.ts
CHANGED
|
@@ -40,6 +40,11 @@ Custom fetch implementation. You can use it as a middleware to intercept request
|
|
|
40
40
|
or to provide a custom fetch implementation for e.g. testing.
|
|
41
41
|
*/
|
|
42
42
|
fetch?: FetchFunction;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Callback function to be called when an error is encountered.
|
|
46
|
+
*/
|
|
47
|
+
onError?: (error: Error) => void;
|
|
43
48
|
};
|
|
44
49
|
|
|
45
50
|
export type Experimental_UseObjectHelpers<RESULT, INPUT> = {
|
|
@@ -80,6 +85,7 @@ function useObject<RESULT, INPUT = any>({
|
|
|
80
85
|
schema, // required, in the future we will use it for validation
|
|
81
86
|
initialValue,
|
|
82
87
|
fetch,
|
|
88
|
+
onError,
|
|
83
89
|
}: Experimental_UseObjectOptions<RESULT>): Experimental_UseObjectHelpers<
|
|
84
90
|
RESULT,
|
|
85
91
|
INPUT
|
|
@@ -167,6 +173,10 @@ function useObject<RESULT, INPUT = any>({
|
|
|
167
173
|
return;
|
|
168
174
|
}
|
|
169
175
|
|
|
176
|
+
if (onError && error instanceof Error) {
|
|
177
|
+
onError(error);
|
|
178
|
+
}
|
|
179
|
+
|
|
170
180
|
setError(error);
|
|
171
181
|
}
|
|
172
182
|
};
|
|
@@ -1,17 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
describeWithTestServer,
|
|
3
|
+
withTestServer,
|
|
4
|
+
} from '@ai-sdk/provider-utils/test';
|
|
2
5
|
import '@testing-library/jest-dom/vitest';
|
|
3
6
|
import { cleanup, render, screen, waitFor } from '@testing-library/react';
|
|
4
7
|
import userEvent from '@testing-library/user-event';
|
|
5
|
-
import { HttpResponse, http } from 'msw';
|
|
6
|
-
import { SetupServer, setupServer } from 'msw/node';
|
|
7
8
|
import { z } from 'zod';
|
|
8
9
|
import { experimental_useObject } from './use-object';
|
|
9
10
|
|
|
10
11
|
describe('text stream', () => {
|
|
12
|
+
let onErrorResult: Error | undefined;
|
|
13
|
+
|
|
11
14
|
const TestComponent = () => {
|
|
12
15
|
const { object, error, submit, isLoading, stop } = experimental_useObject({
|
|
13
16
|
api: '/api/use-object',
|
|
14
17
|
schema: z.object({ content: z.string() }),
|
|
18
|
+
onError(error) {
|
|
19
|
+
onErrorResult = error;
|
|
20
|
+
},
|
|
15
21
|
});
|
|
16
22
|
|
|
17
23
|
return (
|
|
@@ -34,6 +40,7 @@ describe('text stream', () => {
|
|
|
34
40
|
|
|
35
41
|
beforeEach(() => {
|
|
36
42
|
render(<TestComponent />);
|
|
43
|
+
onErrorResult = undefined;
|
|
37
44
|
});
|
|
38
45
|
|
|
39
46
|
afterEach(() => {
|
|
@@ -41,159 +48,123 @@ describe('text stream', () => {
|
|
|
41
48
|
cleanup();
|
|
42
49
|
});
|
|
43
50
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
describeWithTestServer(
|
|
52
|
+
"when the API returns 'Hello, world!'",
|
|
53
|
+
{
|
|
54
|
+
url: '/api/use-object',
|
|
55
|
+
type: 'stream-values',
|
|
56
|
+
content: ['{ ', '"content": "Hello, ', 'world', '!"'],
|
|
57
|
+
},
|
|
58
|
+
({ call }) => {
|
|
59
|
+
beforeEach(async () => {
|
|
60
|
+
await userEvent.click(screen.getByTestId('submit-button'));
|
|
51
61
|
});
|
|
52
62
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
JSON.stringify({ content: 'Hello, world!' }),
|
|
60
|
-
);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it("should send 'test' to the API", async () => {
|
|
64
|
-
expect(await mockFetch.requestBody).toBe(JSON.stringify('test-input'));
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('should not have an error', async () => {
|
|
68
|
-
await screen.findByTestId('error');
|
|
69
|
-
expect(screen.getByTestId('error')).toBeEmptyDOMElement();
|
|
70
|
-
});
|
|
71
|
-
});
|
|
63
|
+
it('should render stream', async () => {
|
|
64
|
+
await screen.findByTestId('object');
|
|
65
|
+
expect(screen.getByTestId('object')).toHaveTextContent(
|
|
66
|
+
JSON.stringify({ content: 'Hello, world!' }),
|
|
67
|
+
);
|
|
68
|
+
});
|
|
72
69
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
it("should send 'test' to the API", async () => {
|
|
71
|
+
expect(await call(0).getRequestBodyJson()).toBe('test-input');
|
|
72
|
+
});
|
|
76
73
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
},
|
|
74
|
+
it('should not have an error', async () => {
|
|
75
|
+
await screen.findByTestId('error');
|
|
76
|
+
expect(screen.getByTestId('error')).toBeEmptyDOMElement();
|
|
77
|
+
expect(onErrorResult).toBeUndefined();
|
|
82
78
|
});
|
|
79
|
+
},
|
|
80
|
+
);
|
|
83
81
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
82
|
+
describe('isLoading', async () => {
|
|
83
|
+
it(
|
|
84
|
+
'should be true while loading',
|
|
85
|
+
withTestServer(
|
|
86
|
+
{ url: '/api/use-object', type: 'controlled-stream' },
|
|
87
|
+
async ({ streamController }) => {
|
|
88
|
+
streamController.enqueue('{"content": ');
|
|
89
|
+
|
|
90
|
+
await userEvent.click(screen.getByTestId('submit-button'));
|
|
91
|
+
|
|
92
|
+
// wait for element "loading" to have text content "true":
|
|
93
|
+
await waitFor(() => {
|
|
94
|
+
expect(screen.getByTestId('loading')).toHaveTextContent('true');
|
|
93
95
|
});
|
|
94
|
-
}),
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
server.listen();
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
afterEach(() => {
|
|
101
|
-
server.close();
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it('should be true when loading', async () => {
|
|
105
|
-
streamController.enqueue('{"content": ');
|
|
106
96
|
|
|
107
|
-
|
|
97
|
+
streamController.enqueue('"Hello, world!"}');
|
|
98
|
+
streamController.close();
|
|
108
99
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
// wait for element "loading" to have text content "false":
|
|
118
|
-
await waitFor(() => {
|
|
119
|
-
expect(screen.getByTestId('loading')).toHaveTextContent('false');
|
|
120
|
-
});
|
|
121
|
-
});
|
|
100
|
+
// wait for element "loading" to have text content "false":
|
|
101
|
+
await waitFor(() => {
|
|
102
|
+
expect(screen.getByTestId('loading')).toHaveTextContent('false');
|
|
103
|
+
});
|
|
104
|
+
},
|
|
105
|
+
),
|
|
106
|
+
);
|
|
122
107
|
});
|
|
123
108
|
|
|
124
109
|
describe('stop', async () => {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
'
|
|
141
|
-
|
|
142
|
-
Connection: 'keep-alive',
|
|
143
|
-
},
|
|
110
|
+
it(
|
|
111
|
+
'should abort the stream and not consume any more data',
|
|
112
|
+
withTestServer(
|
|
113
|
+
{ url: '/api/use-object', type: 'controlled-stream' },
|
|
114
|
+
async ({ streamController }) => {
|
|
115
|
+
streamController.enqueue('{"content": "h');
|
|
116
|
+
|
|
117
|
+
userEvent.click(screen.getByTestId('submit-button'));
|
|
118
|
+
|
|
119
|
+
// wait for element "loading" and "object" to have text content:
|
|
120
|
+
await waitFor(() => {
|
|
121
|
+
expect(screen.getByTestId('loading')).toHaveTextContent('true');
|
|
122
|
+
});
|
|
123
|
+
await waitFor(() => {
|
|
124
|
+
expect(screen.getByTestId('object')).toHaveTextContent(
|
|
125
|
+
'{"content":"h"}',
|
|
126
|
+
);
|
|
144
127
|
});
|
|
145
|
-
}),
|
|
146
|
-
);
|
|
147
|
-
|
|
148
|
-
server.listen();
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
afterEach(() => {
|
|
152
|
-
server.close();
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it('should be true when loading', async () => {
|
|
156
|
-
streamController.enqueue('{"content": "h');
|
|
157
|
-
|
|
158
|
-
userEvent.click(screen.getByTestId('submit-button'));
|
|
159
|
-
|
|
160
|
-
// wait for element "loading" and "object" to have text content:
|
|
161
|
-
await waitFor(() => {
|
|
162
|
-
expect(screen.getByTestId('loading')).toHaveTextContent('true');
|
|
163
|
-
});
|
|
164
|
-
await waitFor(() => {
|
|
165
|
-
expect(screen.getByTestId('object')).toHaveTextContent(
|
|
166
|
-
'{"content":"h"}',
|
|
167
|
-
);
|
|
168
|
-
});
|
|
169
128
|
|
|
170
|
-
|
|
171
|
-
|
|
129
|
+
// click stop button:
|
|
130
|
+
await userEvent.click(screen.getByTestId('stop-button'));
|
|
172
131
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
132
|
+
// wait for element "loading" to have text content "false":
|
|
133
|
+
await waitFor(() => {
|
|
134
|
+
expect(screen.getByTestId('loading')).toHaveTextContent('false');
|
|
135
|
+
});
|
|
177
136
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
137
|
+
// this should not be consumed any more:
|
|
138
|
+
streamController.enqueue('ello, world!"}');
|
|
139
|
+
streamController.close();
|
|
181
140
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
141
|
+
// should only show start of object:
|
|
142
|
+
expect(screen.getByTestId('object')).toHaveTextContent(
|
|
143
|
+
'{"content":"h"}',
|
|
144
|
+
);
|
|
145
|
+
},
|
|
146
|
+
),
|
|
147
|
+
);
|
|
185
148
|
});
|
|
186
149
|
|
|
187
150
|
describe('when the API returns a 404', () => {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
151
|
+
it(
|
|
152
|
+
'should render error',
|
|
153
|
+
withTestServer(
|
|
154
|
+
{
|
|
155
|
+
url: '/api/use-object',
|
|
156
|
+
type: 'error',
|
|
157
|
+
status: 404,
|
|
158
|
+
content: 'Not found',
|
|
159
|
+
},
|
|
160
|
+
async () => {
|
|
161
|
+
await userEvent.click(screen.getByTestId('submit-button'));
|
|
193
162
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
163
|
+
await screen.findByTestId('error');
|
|
164
|
+
expect(screen.getByTestId('error')).toHaveTextContent('Not found');
|
|
165
|
+
expect(onErrorResult).toBeInstanceOf(Error);
|
|
166
|
+
},
|
|
167
|
+
),
|
|
168
|
+
);
|
|
198
169
|
});
|
|
199
170
|
});
|