@ai-sdk/solid
Version:
> **Warning** `@ai-sdk/solid` has been deprecated and will be removed in AI SDK 5
1 lines • 58.6 kB
Source Map (JSON)
{"version":3,"sources":["../src/use-chat.ts","../src/utils/convert-to-accessor-options.ts","../src/utils/reactive-lru.ts","../src/use-completion.ts","../src/use-object.ts","../src/use-assistant.ts"],"sourcesContent":["import { FetchFunction } from '@ai-sdk/provider-utils';\nimport type {\n ChatRequest,\n ChatRequestOptions,\n CreateMessage,\n JSONValue,\n Message,\n UseChatOptions as SharedUseChatOptions,\n UIMessage,\n} from '@ai-sdk/ui-utils';\nimport {\n callChatApi,\n extractMaxToolInvocationStep,\n fillMessageParts,\n generateId as generateIdFunc,\n getMessageParts,\n isAssistantMessageWithCompletedToolCalls,\n prepareAttachmentsForRequest,\n shouldResubmitMessages,\n updateToolCallResult,\n} from '@ai-sdk/ui-utils';\nimport {\n Accessor,\n createEffect,\n createMemo,\n createSignal,\n JSX,\n Setter,\n} from 'solid-js';\nimport { createStore, reconcile, Store } from 'solid-js/store';\nimport { convertToAccessorOptions } from './utils/convert-to-accessor-options';\nimport { ReactiveLRU } from './utils/reactive-lru';\n\nexport type { CreateMessage, Message };\n\nexport type UseChatHelpers = {\n /**\n * Current messages in the chat as a SolidJS store.\n */\n messages: () => Store<UIMessage[]>;\n\n /** The error object of the API request */\n error: Accessor<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: (\n messages: Message[] | ((messages: Message[]) => Message[]),\n ) => void;\n /** The current value of the input */\n input: Accessor<string>;\n /** Signal setter to update the input value */\n setInput: Setter<string>;\n /** An input/textarea-ready onChange handler to control the value of the input */\n handleInputChange: JSX.ChangeEventHandlerUnion<\n HTMLInputElement | HTMLTextAreaElement,\n Event\n >;\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\n /**\n * Whether the API request is in progress\n *\n * @deprecated use `status` instead\n */\n isLoading: Accessor<boolean>;\n\n /**\n * Hook status:\n *\n * - `submitted`: The message has been sent to the API and we're awaiting the start of the response stream.\n * - `streaming`: The response is actively streaming in from the API, receiving chunks of data.\n * - `ready`: The full response has been received and processed; a new user message can be submitted.\n * - `error`: An error occurred during the API request, preventing successful completion.\n */\n status: Accessor<'submitted' | 'streaming' | 'ready' | 'error'>;\n\n /** Additional data added on the server via StreamData */\n data: Accessor<JSONValue[] | undefined>;\n /** Set the data of the chat. You can use this to transform or clear the chat data. */\n setData: (\n data:\n | JSONValue[]\n | undefined\n | ((data: JSONValue[] | undefined) => JSONValue[] | undefined),\n ) => void;\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 addToolResult: ({\n toolCallId,\n result,\n }: {\n toolCallId: string;\n result: any;\n }) => void;\n\n /** The id of the chat */\n id: string;\n};\n\nconst chatCache = new ReactiveLRU<string, Message[]>();\n\nexport type UseChatOptions = SharedUseChatOptions & {\n /**\nMaximum number of sequential LLM calls (steps), e.g. when you use tool calls. Must be at least 1.\n\nA maximum number is required to prevent infinite loops in the case of misconfigured tools.\n\nBy default, it's set to 1, which means that only a single LLM call is made.\n*/\n maxSteps?: number;\n\n /**\n * Experimental (SolidJS 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 id The chat ID\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 id: string;\n messages: UIMessage[];\n requestData?: JSONValue;\n requestBody?: object;\n }) => unknown;\n};\n\n/**\n * @deprecated `@ai-sdk/solid` has been deprecated and will be removed in AI SDK 5.\n */\nexport function useChat(\n rawUseChatOptions: UseChatOptions | Accessor<UseChatOptions> = {},\n): UseChatHelpers {\n const resolvedOptions = createMemo(() =>\n convertToAccessorOptions(rawUseChatOptions),\n );\n const prepareFn = createMemo(() => {\n const opts = resolvedOptions();\n return opts.experimental_prepareRequestBody?.();\n });\n const useChatOptions = createMemo(() => ({\n ...resolvedOptions(),\n experimental_prepareRequestBody: prepareFn,\n }));\n\n const api = createMemo(() => useChatOptions().api?.() ?? '/api/chat');\n const generateId = createMemo(\n () => useChatOptions().generateId?.() ?? generateIdFunc,\n );\n const chatId = createMemo(() => useChatOptions().id?.() ?? generateId()());\n const chatKey = createMemo(() => `${api()}|${chatId()}|messages`);\n\n const _messages = createMemo(\n () =>\n chatCache.get(chatKey()) ?? useChatOptions().initialMessages?.() ?? [],\n );\n\n const [messagesStore, setMessagesStore] = createStore<UIMessage[]>(\n fillMessageParts(_messages()),\n );\n createEffect(() => {\n setMessagesStore(reconcile(fillMessageParts(_messages()), { merge: true }));\n });\n\n const mutate = (messages: UIMessage[]) => {\n chatCache.set(chatKey(), messages);\n };\n\n const [error, setError] = createSignal<undefined | Error>(undefined);\n const [streamData, setStreamData] = createSignal<JSONValue[] | undefined>(\n undefined,\n );\n const [status, setStatus] = createSignal<\n 'submitted' | 'streaming' | 'ready' | 'error'\n >('ready');\n\n let messagesRef: UIMessage[] = fillMessageParts(_messages()) || [];\n createEffect(() => {\n messagesRef = fillMessageParts(_messages()) || [];\n });\n\n let abortController: AbortController | null = null;\n\n let extraMetadata = {\n credentials: useChatOptions().credentials?.(),\n headers: useChatOptions().headers?.(),\n body: useChatOptions().body?.(),\n };\n createEffect(() => {\n extraMetadata = {\n credentials: useChatOptions().credentials?.(),\n headers: useChatOptions().headers?.(),\n body: useChatOptions().body?.(),\n };\n });\n\n const triggerRequest = async (chatRequest: ChatRequest) => {\n setError(undefined);\n setStatus('submitted');\n\n const messageCount = messagesRef.length;\n const maxStep = extractMaxToolInvocationStep(\n chatRequest.messages[chatRequest.messages.length - 1]?.toolInvocations,\n );\n\n try {\n abortController = new AbortController();\n\n const streamProtocol = useChatOptions().streamProtocol?.() ?? 'data';\n\n const onFinish = useChatOptions().onFinish?.();\n const onResponse = useChatOptions().onResponse?.();\n const onToolCall = useChatOptions().onToolCall?.();\n\n const sendExtraMessageFields =\n useChatOptions().sendExtraMessageFields?.();\n\n const keepLastMessageOnError =\n useChatOptions().keepLastMessageOnError?.() ?? true;\n\n const experimental_prepareRequestBody =\n useChatOptions().experimental_prepareRequestBody?.();\n\n // Do an optimistic update to the chat state to show the updated messages\n // immediately.\n const previousMessages = messagesRef;\n const chatMessages = fillMessageParts(chatRequest.messages);\n\n mutate(chatMessages);\n\n const existingStreamData = streamData() ?? [];\n\n const constructedMessagesPayload = sendExtraMessageFields\n ? chatMessages\n : chatMessages.map(\n ({\n role,\n content,\n experimental_attachments,\n data,\n annotations,\n toolInvocations,\n parts,\n }) => ({\n role,\n content,\n ...(experimental_attachments !== undefined && {\n experimental_attachments,\n }),\n ...(data !== undefined && { data }),\n ...(annotations !== undefined && { annotations }),\n ...(toolInvocations !== undefined && { toolInvocations }),\n ...(parts !== undefined && { parts }),\n }),\n );\n\n await callChatApi({\n api: api(),\n body: experimental_prepareRequestBody?.({\n id: chatId(),\n messages: chatMessages,\n requestData: chatRequest.data,\n requestBody: chatRequest.body,\n }) ?? {\n id: chatId(),\n messages: constructedMessagesPayload,\n data: chatRequest.data,\n ...extraMetadata.body,\n ...chatRequest.body,\n },\n streamProtocol,\n credentials: extraMetadata.credentials,\n headers: {\n ...extraMetadata.headers,\n ...chatRequest.headers,\n },\n abortController: () => abortController,\n restoreMessagesOnFailure() {\n if (!keepLastMessageOnError) {\n mutate(previousMessages);\n }\n },\n onResponse,\n onUpdate({ message, data, replaceLastMessage }) {\n setStatus('streaming');\n\n mutate([\n ...(replaceLastMessage\n ? chatMessages.slice(0, chatMessages.length - 1)\n : chatMessages),\n message,\n ]);\n\n if (data?.length) {\n setStreamData([...existingStreamData, ...data]);\n }\n },\n onToolCall,\n onFinish,\n generateId: generateId(),\n fetch: useChatOptions().fetch?.(),\n lastMessage: chatMessages[chatMessages.length - 1],\n });\n\n abortController = null;\n setStatus('ready');\n } catch (err) {\n // Ignore abort errors as they are expected.\n if ((err as any).name === 'AbortError') {\n abortController = null;\n setStatus('ready');\n return null;\n }\n\n const onError = useChatOptions().onError?.();\n if (onError && err instanceof Error) {\n onError(err);\n }\n\n setError(err as Error);\n setStatus('error');\n }\n\n const maxSteps = useChatOptions().maxSteps?.() ?? 1;\n\n // auto-submit when all tool calls in the last assistant message have results:\n const messages = messagesRef;\n if (\n shouldResubmitMessages({\n originalMaxToolInvocationStep: maxStep,\n originalMessageCount: messageCount,\n maxSteps,\n messages,\n })\n ) {\n await triggerRequest({ messages });\n }\n };\n\n const append: UseChatHelpers['append'] = async (\n message,\n {\n data,\n headers,\n body,\n experimental_attachments = message.experimental_attachments,\n } = {},\n ) => {\n const attachmentsForRequest = await prepareAttachmentsForRequest(\n experimental_attachments,\n );\n\n const messages = messagesRef.concat({\n ...message,\n id: message.id ?? generateId()(),\n createdAt: message.createdAt ?? new Date(),\n experimental_attachments:\n attachmentsForRequest.length > 0 ? attachmentsForRequest : undefined,\n parts: getMessageParts(message),\n });\n\n return triggerRequest({\n messages,\n headers,\n body,\n data,\n });\n };\n\n const reload: UseChatHelpers['reload'] = async ({\n data,\n headers,\n body,\n } = {}) => {\n if (messagesRef.length === 0) {\n return null;\n }\n\n // Remove last assistant message and retry last user message.\n const lastMessage = messagesRef[messagesRef.length - 1];\n return triggerRequest({\n messages:\n lastMessage.role === 'assistant'\n ? messagesRef.slice(0, -1)\n : messagesRef,\n headers,\n body,\n data,\n });\n };\n\n const stop = () => {\n if (abortController) {\n abortController.abort();\n abortController = null;\n }\n };\n\n const setMessages = (\n messagesArg: Message[] | ((messages: Message[]) => Message[]),\n ) => {\n if (typeof messagesArg === 'function') {\n messagesArg = messagesArg(messagesRef);\n }\n\n const messagesWithParts = fillMessageParts(messagesArg);\n mutate(messagesWithParts);\n messagesRef = messagesWithParts;\n };\n\n const setData = (\n dataArg:\n | JSONValue[]\n | undefined\n | ((data: JSONValue[] | undefined) => JSONValue[] | undefined),\n ) => {\n if (typeof dataArg === 'function') {\n dataArg = dataArg(streamData());\n }\n\n setStreamData(dataArg);\n };\n\n const [input, setInput] = createSignal(\n useChatOptions().initialInput?.() || '',\n );\n\n const handleSubmit: UseChatHelpers['handleSubmit'] = async (\n event,\n options = {},\n metadata?: Object,\n ) => {\n event?.preventDefault?.();\n const inputValue = input();\n\n if (!inputValue && !options.allowEmptySubmit) return;\n\n const attachmentsForRequest = await prepareAttachmentsForRequest(\n options.experimental_attachments,\n );\n\n if (metadata) {\n extraMetadata = {\n ...extraMetadata,\n ...metadata,\n };\n }\n\n triggerRequest({\n messages: messagesRef.concat({\n id: generateId()(),\n role: 'user',\n content: inputValue,\n createdAt: new Date(),\n experimental_attachments:\n attachmentsForRequest.length > 0 ? attachmentsForRequest : undefined,\n parts: [{ type: 'text', text: inputValue }],\n }),\n headers: options.headers,\n body: options.body,\n data: options.data,\n });\n\n setInput('');\n };\n\n const handleInputChange: UseChatHelpers['handleInputChange'] = e => {\n setInput(e.target.value);\n };\n\n const addToolResult = ({\n toolCallId,\n result,\n }: {\n toolCallId: string;\n result: any;\n }) => {\n const currentMessages = messagesRef ?? [];\n\n updateToolCallResult({\n messages: currentMessages,\n toolCallId,\n toolResult: result,\n });\n\n mutate(currentMessages);\n\n // when the request is ongoing, the auto-submit will be triggered after the request is finished\n if (status() === 'submitted' || status() === 'streaming') {\n return;\n }\n\n // auto-submit when all tool calls in the last assistant message have results:\n const lastMessage = currentMessages[currentMessages.length - 1];\n if (isAssistantMessageWithCompletedToolCalls(lastMessage)) {\n triggerRequest({ messages: currentMessages });\n }\n };\n\n const isLoading = createMemo(\n () => status() === 'submitted' || status() === 'streaming',\n );\n\n return {\n // TODO next major release: replace with direct message store access (breaking change)\n messages: () => messagesStore,\n id: chatId(),\n append,\n error,\n reload,\n stop,\n setMessages,\n input,\n setInput,\n handleInputChange,\n handleSubmit,\n isLoading,\n status,\n data: streamData,\n setData,\n addToolResult,\n };\n}\n","import { Accessor, createMemo } from 'solid-js';\n\n/**\n * Handle reactive and non-reactive useChatOptions\n */\nexport function convertToAccessorOptions<T extends object>(\n options: T | Accessor<T>,\n) {\n const resolvedOptions = typeof options === 'function' ? options() : options;\n\n return Object.entries(resolvedOptions).reduce(\n (reactiveOptions, [key, value]) => {\n reactiveOptions[key as keyof T] = createMemo(() => value) as any;\n return reactiveOptions;\n },\n {} as {\n [K in keyof T]: Accessor<T[K]>;\n },\n );\n}\n","import { batch } from 'solid-js';\nimport { TriggerCache } from '@solid-primitives/trigger';\n\nconst $KEYS = Symbol('track-keys');\n\n/**\n * A reactive LRU (Least Recently Used) cache implementation based on Map.\n * All reads and writes are reactive signals.\n * @param maxSize maximum number of entries to store before evicting least recently used\n * @param initial initial entries of the reactive LRU cache\n */\nexport class ReactiveLRU<K, V> extends Map<K, V> {\n #keyTriggers = new TriggerCache<K | typeof $KEYS>();\n #valueTriggers = new TriggerCache<K>();\n #maxSize: number;\n #accessList: K[] = [];\n\n constructor(maxSize = 10, initial?: Iterable<readonly [K, V]> | null) {\n super();\n this.#maxSize = maxSize;\n if (initial) {\n for (const [key, value] of initial) {\n this.set(key, value);\n }\n }\n }\n\n #recordAccess(key: K) {\n const index = this.#accessList.indexOf(key);\n if (index > -1) {\n this.#accessList.splice(index, 1);\n }\n this.#accessList.push(key);\n if (this.#accessList.length > this.#maxSize) {\n const lru = this.#accessList.shift()!;\n this.delete(lru);\n }\n }\n\n // reads\n has(key: K): boolean {\n this.#keyTriggers.track(key);\n const exists = super.has(key);\n if (exists) {\n this.#recordAccess(key);\n }\n return exists;\n }\n\n get(key: K): V | undefined {\n this.#valueTriggers.track(key);\n const value = super.get(key);\n if (value !== undefined) {\n this.#recordAccess(key);\n }\n return value;\n }\n\n get size(): number {\n this.#keyTriggers.track($KEYS);\n return super.size;\n }\n\n *keys(): MapIterator<K> {\n for (const key of super.keys()) {\n this.#keyTriggers.track(key);\n yield key;\n }\n this.#keyTriggers.track($KEYS);\n }\n\n *values(): MapIterator<V> {\n for (const [key, v] of super.entries()) {\n this.#valueTriggers.track(key);\n yield v;\n }\n this.#keyTriggers.track($KEYS);\n }\n\n *entries(): MapIterator<[K, V]> {\n for (const entry of super.entries()) {\n this.#valueTriggers.track(entry[0]);\n yield entry;\n }\n this.#keyTriggers.track($KEYS);\n }\n\n // writes\n set(key: K, value: V): this {\n batch(() => {\n if (super.has(key)) {\n if (super.get(key)! === value) {\n this.#recordAccess(key);\n return;\n }\n } else {\n this.#keyTriggers.dirty(key);\n this.#keyTriggers.dirty($KEYS);\n }\n this.#valueTriggers.dirty(key);\n super.set(key, value);\n this.#recordAccess(key);\n });\n return this;\n }\n\n delete(key: K): boolean {\n const r = super.delete(key);\n if (r) {\n batch(() => {\n this.#keyTriggers.dirty(key);\n this.#keyTriggers.dirty($KEYS);\n this.#valueTriggers.dirty(key);\n const index = this.#accessList.indexOf(key);\n if (index > -1) {\n this.#accessList.splice(index, 1);\n }\n });\n }\n return r;\n }\n\n clear(): void {\n if (super.size) {\n batch(() => {\n for (const v of super.keys()) {\n this.#keyTriggers.dirty(v);\n this.#valueTriggers.dirty(v);\n }\n super.clear();\n this.#accessList = [];\n this.#keyTriggers.dirty($KEYS);\n });\n }\n }\n\n // callback\n forEach(callbackfn: (value: V, key: K, map: this) => void) {\n this.#keyTriggers.track($KEYS);\n for (const [key, v] of super.entries()) {\n this.#valueTriggers.track(key);\n this.#recordAccess(key);\n callbackfn(v, key, this);\n }\n }\n\n [Symbol.iterator](): MapIterator<[K, V]> {\n return this.entries();\n }\n}\n","import { FetchFunction } from '@ai-sdk/provider-utils';\nimport type {\n JSONValue,\n Message,\n RequestOptions,\n UseCompletionOptions,\n} from '@ai-sdk/ui-utils';\nimport { callCompletionApi } from '@ai-sdk/ui-utils';\nimport {\n Accessor,\n JSX,\n Setter,\n createEffect,\n createMemo,\n createSignal,\n createUniqueId,\n} from 'solid-js';\nimport { ReactiveLRU } from './utils/reactive-lru';\nimport { convertToAccessorOptions } from './utils/convert-to-accessor-options';\n\nexport type { UseCompletionOptions };\n\nexport type UseCompletionHelpers = {\n /** The current completion result */\n completion: Accessor<string>;\n /** The error object of the API request */\n error: Accessor<undefined | Error>;\n /**\n * Send a new prompt to the API endpoint and update the completion state.\n */\n complete: (\n prompt: string,\n options?: RequestOptions,\n ) => Promise<string | null | undefined>;\n /**\n * Abort the current API request but keep the generated tokens.\n */\n stop: () => void;\n /**\n * Update the `completion` state locally.\n */\n setCompletion: (completion: string) => void;\n /** The current value of the input */\n input: Accessor<string>;\n /** Signal Setter to update the input value */\n setInput: Setter<string>;\n\n /** An input/textarea-ready onChange handler to control the value of the input */\n handleInputChange: JSX.ChangeEventHandlerUnion<\n HTMLInputElement | HTMLTextAreaElement,\n Event\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 value={input()} />\n * </form>\n * ```\n */\n handleSubmit: (event?: { preventDefault?: () => void }) => void;\n /** Whether the API request is in progress */\n isLoading: Accessor<boolean>;\n /** Additional data added on the server via StreamData */\n data: Accessor<JSONValue[] | undefined>;\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\nconst completionCache = new ReactiveLRU<string, string>();\n\n/**\n * @deprecated `@ai-sdk/solid` has been deprecated and will be removed in AI SDK 5.\n */\nexport function useCompletion(\n rawUseCompletionOptions:\n | UseCompletionOptions\n | Accessor<UseCompletionOptions> = {},\n): UseCompletionHelpers {\n const useCompletionOptions = createMemo(() =>\n convertToAccessorOptions(rawUseCompletionOptions),\n );\n\n const api = createMemo(\n () => useCompletionOptions().api?.() ?? '/api/completion',\n );\n // Generate an unique id for the completion if not provided.\n const idKey = createMemo(\n () => useCompletionOptions().id?.() ?? `completion-${createUniqueId()}`,\n );\n const completionKey = createMemo(() => `${api()}|${idKey()}|completion`);\n\n const completion = createMemo(\n () =>\n completionCache.get(completionKey()) ??\n useCompletionOptions().initialCompletion?.() ??\n '',\n );\n\n const mutate = (data: string) => {\n completionCache.set(completionKey(), data);\n };\n\n const [error, setError] = createSignal<undefined | Error>(undefined);\n const [streamData, setStreamData] = createSignal<JSONValue[] | undefined>(\n undefined,\n );\n const [isLoading, setIsLoading] = createSignal(false);\n\n const [abortController, setAbortController] =\n createSignal<AbortController | null>(null);\n\n let extraMetadata = {\n credentials: useCompletionOptions().credentials?.(),\n headers: useCompletionOptions().headers?.(),\n body: useCompletionOptions().body?.(),\n };\n createEffect(() => {\n extraMetadata = {\n credentials: useCompletionOptions().credentials?.(),\n headers: useCompletionOptions().headers?.(),\n body: useCompletionOptions().body?.(),\n };\n });\n\n const complete: UseCompletionHelpers['complete'] = async (\n prompt: string,\n options?: RequestOptions,\n ) => {\n const existingData = streamData() ?? [];\n return callCompletionApi({\n api: api(),\n prompt,\n credentials: useCompletionOptions().credentials?.(),\n headers: { ...extraMetadata.headers, ...options?.headers },\n body: {\n ...extraMetadata.body,\n ...options?.body,\n },\n streamProtocol: useCompletionOptions().streamProtocol?.(),\n setCompletion: mutate,\n setLoading: setIsLoading,\n setError,\n setAbortController,\n onResponse: useCompletionOptions().onResponse?.(),\n onFinish: useCompletionOptions().onFinish?.(),\n onError: useCompletionOptions().onError?.(),\n onData: data => {\n setStreamData([...existingData, ...(data ?? [])]);\n },\n fetch: useCompletionOptions().fetch?.(),\n });\n };\n\n const stop = () => {\n if (abortController()) {\n abortController()!.abort();\n }\n };\n\n const setCompletion = (completion: string) => {\n mutate(completion);\n };\n\n const [input, setInput] = createSignal(\n useCompletionOptions().initialInput?.() ?? '',\n );\n\n const handleInputChange: UseCompletionHelpers['handleInputChange'] =\n event => {\n setInput(event.target.value);\n };\n\n const handleSubmit: UseCompletionHelpers['handleSubmit'] = event => {\n event?.preventDefault?.();\n\n const inputValue = input();\n return inputValue ? complete(inputValue) : undefined;\n };\n\n return {\n completion,\n complete,\n error,\n stop,\n setCompletion,\n input,\n setInput,\n handleInputChange,\n handleSubmit,\n isLoading,\n data: streamData,\n };\n}\n","import {\n FetchFunction,\n isAbortError,\n safeValidateTypes,\n} from '@ai-sdk/provider-utils';\nimport {\n asSchema,\n DeepPartial,\n isDeepEqualData,\n parsePartialJson,\n Schema,\n} from '@ai-sdk/ui-utils';\nimport { Accessor, createMemo, createSignal, createUniqueId } from 'solid-js';\nimport z from 'zod';\nimport { convertToAccessorOptions } from './utils/convert-to-accessor-options';\nimport { ReactiveLRU } from './utils/reactive-lru';\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, z.ZodTypeDef, any> | 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 /**\n Custom fetch implementation. You can use it as a middleware to intercept requests,\n or to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n\n /**\n Callback that is called when the stream has finished.\n */\n onFinish?: (event: {\n /**\n The generated object (typed according to the schema).\n Can be undefined if the final object does not match the schema.\n */\n object: RESULT | undefined;\n\n /**\n Optional error object. This is e.g. a TypeValidationError when the final object does not match the schema.\n */\n error: Error | undefined;\n }) => Promise<void> | void;\n\n /**\n * Callback function to be called when an error is encountered.\n */\n onError?: (error: Error) => void;\n\n /**\n * Additional HTTP headers to be included in the request.\n */\n headers?: Record<string, string> | Headers;\n\n /**\n * The credentials mode to be used for the fetch request.\n * Possible values are: 'omit', 'same-origin', 'include'.\n * Defaults to 'same-origin'.\n */\n credentials?: RequestCredentials;\n};\n\nexport type Experimental_UseObjectHelpers<RESULT, INPUT> = {\n /**\n * Calls the API with the provided input as JSON body.\n */\n submit: (input: INPUT) => void;\n\n /**\n * The current value for the generated object. Updated as the API streams JSON chunks.\n */\n object: Accessor<DeepPartial<RESULT> | undefined>;\n\n /**\n * The error object of the API request if any.\n */\n error: Accessor<Error | undefined>;\n\n /**\n * Flag that indicates whether an API request is in progress.\n */\n isLoading: Accessor<boolean>;\n\n /**\n * Abort the current request immediately, keep the current partial object if any.\n */\n stop: () => void;\n};\n\nconst objectCache = new ReactiveLRU<string, DeepPartial<any>>();\n\n/**\n * @deprecated `@ai-sdk/solid` has been deprecated and will be removed in AI SDK 5.\n */\nfunction useObject<RESULT, INPUT = any>(\n rawUseObjectOptions:\n | Experimental_UseObjectOptions<RESULT>\n | Accessor<Experimental_UseObjectOptions<RESULT>>,\n): Experimental_UseObjectHelpers<RESULT, INPUT> {\n const useObjectOptions = createMemo(() =>\n convertToAccessorOptions(rawUseObjectOptions),\n );\n\n // Generate an unique id for the completion if not provided.\n const idKey = createMemo(\n () => useObjectOptions().id?.() ?? `object-${createUniqueId()}`,\n );\n\n const data = createMemo(\n () =>\n (objectCache.get(idKey()) ?? useObjectOptions().initialValue?.()) as\n | DeepPartial<RESULT>\n | undefined,\n );\n\n const mutate = (value: DeepPartial<RESULT> | undefined) => {\n objectCache.set(idKey(), value);\n };\n\n const [error, setError] = createSignal<Error>();\n const [isLoading, setIsLoading] = createSignal(false);\n\n // Abort controller to cancel the current API call.\n let abortControllerRef: AbortController | null = null;\n\n const stop = () => {\n try {\n abortControllerRef?.abort();\n } catch (ignored) {\n } finally {\n setIsLoading(false);\n abortControllerRef = null;\n }\n };\n\n const submit = async (input: INPUT) => {\n try {\n mutate(undefined); // reset the data\n setIsLoading(true);\n setError(undefined);\n\n const abortController = new AbortController();\n abortControllerRef = abortController;\n\n const actualFetch = fetch ?? getOriginalFetch();\n const response = await actualFetch(useObjectOptions().api(), {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...useObjectOptions().headers?.(),\n },\n credentials: useObjectOptions().credentials?.(),\n signal: abortController.signal,\n body: JSON.stringify(input),\n });\n\n if (!response.ok) {\n throw new Error(\n (await response.text()) ?? 'Failed to fetch the response.',\n );\n }\n\n if (response.body == null) {\n throw new Error('The response body is empty.');\n }\n\n let accumulatedText = '';\n let latestObject: DeepPartial<RESULT> | undefined = undefined;\n\n await response.body.pipeThrough(new TextDecoderStream()).pipeTo(\n new WritableStream<string>({\n write(chunk) {\n accumulatedText += chunk;\n\n const { value } = parsePartialJson(accumulatedText);\n const currentObject = value as DeepPartial<RESULT>;\n\n if (!isDeepEqualData(latestObject, currentObject)) {\n latestObject = currentObject;\n\n mutate(currentObject);\n }\n },\n\n close() {\n setIsLoading(false);\n abortControllerRef = null;\n\n const onFinish = useObjectOptions().onFinish?.();\n if (onFinish != null) {\n const validationResult = safeValidateTypes({\n value: latestObject,\n schema: asSchema(useObjectOptions().schema()),\n });\n\n onFinish(\n validationResult.success\n ? { object: validationResult.value, error: undefined }\n : { object: undefined, error: validationResult.error },\n );\n }\n },\n }),\n );\n } catch (error) {\n if (isAbortError(error)) {\n return;\n }\n\n const onError = useObjectOptions().onError?.();\n if (onError && error instanceof Error) {\n onError(error);\n }\n\n setIsLoading(false);\n setError(error instanceof Error ? error : new Error(String(error)));\n }\n };\n\n return {\n submit,\n object: data,\n error,\n isLoading,\n stop,\n };\n}\n\nexport const experimental_useObject = useObject;\n","import { isAbortError } from '@ai-sdk/provider-utils';\nimport {\n AssistantStatus,\n CreateMessage,\n generateId,\n Message,\n processAssistantStream,\n UseAssistantOptions,\n} from '@ai-sdk/ui-utils';\nimport { Accessor, createMemo, createSignal, JSX, Setter } from 'solid-js';\nimport { createStore, SetStoreFunction, Store } from 'solid-js/store';\nimport { convertToAccessorOptions } from './utils/convert-to-accessor-options';\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: Store<Message[]>;\n\n /**\n * Update the message store with a new array of messages.\n */\n setMessages: SetStoreFunction<Message[]>;\n\n /**\n * The current thread ID.\n */\n threadId: Accessor<string | undefined>;\n\n /**\n * Set the current thread ID. Specifying a thread ID will switch to that thread, if it exists. If set to 'undefined', a new thread will be created. For both cases, `threadId` will be updated with the new value and `messages` will be cleared.\n */\n setThreadId: (threadId: string | undefined) => void;\n\n /**\n * The current value of the input field.\n */\n input: Accessor<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: Setter<string>;\n\n /**\n * Handler for the `onChange` event of the input field to control the input's value.\n */\n handleInputChange: JSX.ChangeEventHandlerUnion<\n HTMLInputElement | HTMLTextAreaElement,\n Event\n >;\n\n /**\n * Form submission handler that automatically resets the input field and appends a user message.\n */\n submitMessage: (\n event?: SubmitEvent,\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: Accessor<AssistantStatus>;\n\n /**\n * The error thrown during the assistant message processing, if any.\n */\n error: Accessor<undefined | Error>;\n};\n\n/**\n * @deprecated `@ai-sdk/solid` has been deprecated and will be removed in AI SDK 5.\n */\nexport function useAssistant(\n rawUseAssistantOptions: UseAssistantOptions | Accessor<UseAssistantOptions>,\n): UseAssistantHelpers {\n const useAssistantOptions = createMemo(() =>\n convertToAccessorOptions(rawUseAssistantOptions),\n );\n\n const [messages, setMessages] = createStore<Message[]>([]);\n const [input, setInput] = createSignal('');\n const [currentThreadId, setCurrentThreadId] = createSignal<string>();\n const [status, setStatus] = createSignal<AssistantStatus>('awaiting_message');\n const [error, setError] = createSignal<Error>();\n\n const handleInputChange: JSX.ChangeEventHandlerUnion<\n HTMLInputElement | HTMLTextAreaElement,\n Event\n > = event => {\n setInput(event.target.value);\n };\n\n // Abort controller to cancel the current API call.\n let abortControllerRef: AbortController | null = null;\n\n const stop = () => {\n if (abortControllerRef) {\n abortControllerRef?.abort();\n abortControllerRef = 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 = abortController;\n\n const actualFetch = fetch ?? getOriginalFetch();\n const response = await actualFetch(useAssistantOptions().api(), {\n method: 'POST',\n credentials: useAssistantOptions().credentials?.(),\n signal: abortController.signal,\n headers: {\n 'Content-Type': 'application/json',\n ...useAssistantOptions().headers?.(),\n },\n body: JSON.stringify({\n ...useAssistantOptions().body?.(),\n // always use user-provided threadId when available:\n threadId: useAssistantOptions().threadId?.() ?? currentThreadId(),\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 await processAssistantStream({\n stream: response.body,\n onAssistantMessagePart(value) {\n setMessages(messages => [\n ...messages,\n {\n id: value.id,\n role: value.role,\n content: value.content[0].text.value,\n parts: [],\n },\n ]);\n },\n onTextPart(value) {\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 parts: lastMessage.parts,\n },\n ];\n });\n },\n onAssistantControlDataPart(value) {\n setCurrentThreadId(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 onDataMessagePart(value) {\n setMessages(messages => [\n ...messages,\n {\n id: value.id ?? generateId(),\n role: 'data',\n content: '',\n data: value.data,\n parts: [],\n },\n ]);\n },\n onErrorPart(value) {\n setError(new Error(value));\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 = null;\n return;\n }\n\n const onError = useAssistantOptions().onError?.();\n if (onError && error instanceof Error) {\n onError(error);\n }\n\n setError(error as Error);\n } finally {\n abortControllerRef = null;\n setStatus('awaiting_message');\n }\n };\n\n const submitMessage = async (\n event?: SubmitEvent,\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(), parts: [] }, requestOptions);\n };\n\n const setThreadId = (threadId: string | undefined) => {\n setCurrentThreadId(threadId);\n setMessages([]);\n };\n\n return {\n append,\n messages,\n setMessages,\n threadId: currentThreadId,\n setThreadId,\n input,\n setInput,\n handleInputChange,\n submitMessage,\n status,\n error,\n stop,\n };\n}\n"],"mappings":"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