@ai-sdk/react 0.0.14 → 0.0.15

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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @ai-sdk/react@0.0.14 build /home/runner/work/ai/ai/packages/react
2
+ > @ai-sdk/react@0.0.15 build /home/runner/work/ai/ai/packages/react
3
3
  > tsup
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -9,13 +9,13 @@
9
9
  CLI Target: es2018
10
10
  CJS Build start
11
11
  ESM Build start
12
- CJS dist/index.js 23.93 KB
13
- CJS dist/index.js.map 48.31 KB
14
- CJS ⚡️ Build success in 56ms
15
- ESM dist/index.mjs 21.47 KB
16
- ESM dist/index.mjs.map 48.24 KB
17
- ESM ⚡️ Build success in 57ms
12
+ ESM dist/index.mjs 21.69 KB
13
+ ESM dist/index.mjs.map 48.60 KB
14
+ ESM ⚡️ Build success in 48ms
15
+ CJS dist/index.js 24.17 KB
16
+ CJS dist/index.js.map 48.68 KB
17
+ CJS ⚡️ Build success in 50ms
18
18
  DTS Build start
19
- DTS ⚡️ Build success in 5320ms
19
+ DTS ⚡️ Build success in 5222ms
20
20
  DTS dist/index.d.ts 9.95 KB
21
21
  DTS dist/index.d.mts 9.95 KB
@@ -1,4 +1,4 @@
1
1
 
2
- > @ai-sdk/react@0.0.14 clean /home/runner/work/ai/ai/packages/react
2
+ > @ai-sdk/react@0.0.15 clean /home/runner/work/ai/ai/packages/react
3
3
  > rm -rf dist
4
4
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @ai-sdk/react
2
2
 
3
+ ## 0.0.15
4
+
5
+ ### Patch Changes
6
+
7
+ - 6c99581e: fix (ai/react): stop() on useObject does not throw error and clears isLoading
8
+
3
9
  ## 0.0.14
4
10
 
5
11
  ### Patch Changes
package/dist/index.js CHANGED
@@ -699,6 +699,7 @@ function useCompletion({
699
699
  }
700
700
 
701
701
  // src/use-object.ts
702
+ var import_provider_utils2 = require("@ai-sdk/provider-utils");
702
703
  var import_ui_utils4 = require("@ai-sdk/ui-utils");
703
704
  var import_react4 = require("react");
704
705
  var import_swr3 = __toESM(require("swr"));
@@ -723,13 +724,19 @@ function useObject({
723
724
  const abortControllerRef = (0, import_react4.useRef)(null);
724
725
  const stop = (0, import_react4.useCallback)(() => {
725
726
  var _a;
726
- (_a = abortControllerRef.current) == null ? void 0 : _a.abort();
727
- abortControllerRef.current = null;
727
+ try {
728
+ (_a = abortControllerRef.current) == null ? void 0 : _a.abort();
729
+ } catch (ignored) {
730
+ } finally {
731
+ setIsLoading(false);
732
+ abortControllerRef.current = null;
733
+ }
728
734
  }, []);
729
735
  const submit = async (input) => {
730
736
  var _a;
731
737
  try {
732
738
  setIsLoading(true);
739
+ setError(void 0);
733
740
  const abortController = new AbortController();
734
741
  abortControllerRef.current = abortController;
735
742
  const actualFetch = fetch2 != null ? fetch2 : getOriginalFetch2();
@@ -749,7 +756,7 @@ function useObject({
749
756
  }
750
757
  let accumulatedText = "";
751
758
  let latestObject = void 0;
752
- response.body.pipeThrough(new TextDecoderStream()).pipeTo(
759
+ await response.body.pipeThrough(new TextDecoderStream()).pipeTo(
753
760
  new WritableStream({
754
761
  write(chunk) {
755
762
  accumulatedText += chunk;
@@ -767,8 +774,10 @@ function useObject({
767
774
  }
768
775
  })
769
776
  );
770
- setError(void 0);
771
777
  } catch (error2) {
778
+ if ((0, import_provider_utils2.isAbortError)(error2)) {
779
+ return;
780
+ }
772
781
  setError(error2);
773
782
  }
774
783
  };
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 {\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 abortControllerRef.current?.abort();\n abortControllerRef.current = null;\n }, []);\n\n const submit = async (input: INPUT) => {\n try {\n setIsLoading(true);\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 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\n setError(undefined);\n } catch (error) {\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_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}: 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"]}
package/dist/index.mjs CHANGED
@@ -668,6 +668,7 @@ function useCompletion({
668
668
  }
669
669
 
670
670
  // src/use-object.ts
671
+ import { isAbortError as isAbortError2 } from "@ai-sdk/provider-utils";
671
672
  import {
672
673
  isDeepEqualData,
673
674
  parsePartialJson
@@ -695,13 +696,19 @@ function useObject({
695
696
  const abortControllerRef = useRef4(null);
696
697
  const stop = useCallback4(() => {
697
698
  var _a;
698
- (_a = abortControllerRef.current) == null ? void 0 : _a.abort();
699
- abortControllerRef.current = null;
699
+ try {
700
+ (_a = abortControllerRef.current) == null ? void 0 : _a.abort();
701
+ } catch (ignored) {
702
+ } finally {
703
+ setIsLoading(false);
704
+ abortControllerRef.current = null;
705
+ }
700
706
  }, []);
701
707
  const submit = async (input) => {
702
708
  var _a;
703
709
  try {
704
710
  setIsLoading(true);
711
+ setError(void 0);
705
712
  const abortController = new AbortController();
706
713
  abortControllerRef.current = abortController;
707
714
  const actualFetch = fetch2 != null ? fetch2 : getOriginalFetch2();
@@ -721,7 +728,7 @@ function useObject({
721
728
  }
722
729
  let accumulatedText = "";
723
730
  let latestObject = void 0;
724
- response.body.pipeThrough(new TextDecoderStream()).pipeTo(
731
+ await response.body.pipeThrough(new TextDecoderStream()).pipeTo(
725
732
  new WritableStream({
726
733
  write(chunk) {
727
734
  accumulatedText += chunk;
@@ -739,8 +746,10 @@ function useObject({
739
746
  }
740
747
  })
741
748
  );
742
- setError(void 0);
743
749
  } catch (error2) {
750
+ if (isAbortError2(error2)) {
751
+ return;
752
+ }
744
753
  setError(error2);
745
754
  }
746
755
  };
@@ -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 {\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 abortControllerRef.current?.abort();\n abortControllerRef.current = null;\n }, []);\n\n const submit = async (input: INPUT) => {\n try {\n setIsLoading(true);\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 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\n setError(undefined);\n } catch (error) {\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","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}: 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/react",
3
- "version": "0.0.14",
3
+ "version": "0.0.15",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
package/src/use-object.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { isAbortError } from '@ai-sdk/provider-utils';
1
2
  import {
2
3
  DeepPartial,
3
4
  FetchFunction,
@@ -101,13 +102,19 @@ function useObject<RESULT, INPUT = any>({
101
102
  const abortControllerRef = useRef<AbortController | null>(null);
102
103
 
103
104
  const stop = useCallback(() => {
104
- abortControllerRef.current?.abort();
105
- abortControllerRef.current = null;
105
+ try {
106
+ abortControllerRef.current?.abort();
107
+ } catch (ignored) {
108
+ } finally {
109
+ setIsLoading(false);
110
+ abortControllerRef.current = null;
111
+ }
106
112
  }, []);
107
113
 
108
114
  const submit = async (input: INPUT) => {
109
115
  try {
110
116
  setIsLoading(true);
117
+ setError(undefined);
111
118
 
112
119
  const abortController = new AbortController();
113
120
  abortControllerRef.current = abortController;
@@ -133,7 +140,7 @@ function useObject<RESULT, INPUT = any>({
133
140
  let accumulatedText = '';
134
141
  let latestObject: DeepPartial<RESULT> | undefined = undefined;
135
142
 
136
- response.body.pipeThrough(new TextDecoderStream()).pipeTo(
143
+ await response.body.pipeThrough(new TextDecoderStream()).pipeTo(
137
144
  new WritableStream<string>({
138
145
  write(chunk) {
139
146
  accumulatedText += chunk;
@@ -155,9 +162,11 @@ function useObject<RESULT, INPUT = any>({
155
162
  },
156
163
  }),
157
164
  );
158
-
159
- setError(undefined);
160
165
  } catch (error) {
166
+ if (isAbortError(error)) {
167
+ return;
168
+ }
169
+
161
170
  setError(error);
162
171
  }
163
172
  };
@@ -9,7 +9,7 @@ import { experimental_useObject } from './use-object';
9
9
 
10
10
  describe('text stream', () => {
11
11
  const TestComponent = () => {
12
- const { object, error, submit, isLoading } = experimental_useObject({
12
+ const { object, error, submit, isLoading, stop } = experimental_useObject({
13
13
  api: '/api/use-object',
14
14
  schema: z.object({ content: z.string() }),
15
15
  });
@@ -25,6 +25,9 @@ describe('text stream', () => {
25
25
  >
26
26
  Generate
27
27
  </button>
28
+ <button data-testid="stop-button" onClick={stop}>
29
+ Stop
30
+ </button>
28
31
  </div>
29
32
  );
30
33
  };
@@ -79,7 +82,7 @@ describe('text stream', () => {
79
82
  });
80
83
 
81
84
  server = setupServer(
82
- http.post('https://example.com/api/use-object', ({ request }) => {
85
+ http.post('/api/use-object', ({ request }) => {
83
86
  return new HttpResponse(stream.pipeThrough(new TextEncoderStream()), {
84
87
  status: 200,
85
88
  headers: {
@@ -101,7 +104,7 @@ describe('text stream', () => {
101
104
  it('should be true when loading', async () => {
102
105
  streamController.enqueue('{"content": ');
103
106
 
104
- userEvent.click(screen.getByTestId('submit-button'));
107
+ await userEvent.click(screen.getByTestId('submit-button'));
105
108
 
106
109
  // wait for element "loading" to have text content "true":
107
110
  await waitFor(() => {
@@ -112,9 +115,72 @@ describe('text stream', () => {
112
115
  streamController.close();
113
116
 
114
117
  // wait for element "loading" to have text content "false":
118
+ await waitFor(() => {
119
+ expect(screen.getByTestId('loading')).toHaveTextContent('false');
120
+ });
121
+ });
122
+ });
123
+
124
+ describe('stop', async () => {
125
+ let streamController: ReadableStreamDefaultController<string>;
126
+ let server: SetupServer;
127
+
128
+ beforeEach(() => {
129
+ const stream = new ReadableStream({
130
+ start(controller) {
131
+ streamController = controller;
132
+ },
133
+ });
134
+
135
+ server = setupServer(
136
+ http.post('/api/use-object', ({ request }) => {
137
+ return new HttpResponse(stream.pipeThrough(new TextEncoderStream()), {
138
+ status: 200,
139
+ headers: {
140
+ 'Content-Type': 'text/event-stream',
141
+ 'Cache-Control': 'no-cache',
142
+ Connection: 'keep-alive',
143
+ },
144
+ });
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:
115
161
  await waitFor(() => {
116
162
  expect(screen.getByTestId('loading')).toHaveTextContent('true');
117
163
  });
164
+ await waitFor(() => {
165
+ expect(screen.getByTestId('object')).toHaveTextContent(
166
+ '{"content":"h"}',
167
+ );
168
+ });
169
+
170
+ // click stop button:
171
+ await userEvent.click(screen.getByTestId('stop-button'));
172
+
173
+ // wait for element "loading" to have text content "false":
174
+ await waitFor(() => {
175
+ expect(screen.getByTestId('loading')).toHaveTextContent('false');
176
+ });
177
+
178
+ // this should not be consumed any more:
179
+ streamController.enqueue('ello, world!"}');
180
+ streamController.close();
181
+
182
+ // should only show start of object:
183
+ expect(screen.getByTestId('object')).toHaveTextContent('{"content":"h"}');
118
184
  });
119
185
  });
120
186