Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ai-sdk/react

Package Overview
Dependencies
Maintainers
2
Versions
75
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ai-sdk/react - npm Package Compare versions

Comparing version 0.0.3 to 0.0.4

src/use-object.ts

8

CHANGELOG.md
# @ai-sdk/react
## 0.0.4
### Patch Changes
- 008725ec: feat (@ai-sdk/react): add experimental_useObject to @ai-sdk/react
- Updated dependencies [008725ec]
- @ai-sdk/ui-utils@0.0.4
## 0.0.3

@@ -4,0 +12,0 @@

127

dist/index.d.ts

@@ -1,4 +0,64 @@

import { Message, CreateMessage, ChatRequestOptions, JSONValue, UseChatOptions, RequestOptions, UseCompletionOptions, AssistantStatus, UseAssistantOptions } from '@ai-sdk/ui-utils';
import { Message, CreateMessage, AssistantStatus, UseAssistantOptions, ChatRequestOptions, JSONValue, UseChatOptions, RequestOptions, UseCompletionOptions, DeepPartial } from '@ai-sdk/ui-utils';
export { CreateMessage, Message, UseChatOptions, UseCompletionOptions } from '@ai-sdk/ui-utils';
import z from 'zod';
type UseAssistantHelpers = {
/**
* The current array of chat messages.
*/
messages: Message[];
/**
* Update the message store with a new array of messages.
*/
setMessages: React.Dispatch<React.SetStateAction<Message[]>>;
/**
* The current thread ID.
*/
threadId: string | undefined;
/**
* The current value of the input field.
*/
input: string;
/**
* Append a user message to the chat list. This triggers the API call to fetch
* the assistant's response.
* @param message The message to append
* @param requestOptions Additional options to pass to the API call
*/
append: (message: Message | CreateMessage, requestOptions?: {
data?: Record<string, string>;
}) => Promise<void>;
/**
Abort the current request immediately, keep the generated tokens if any.
*/
stop: () => void;
/**
* setState-powered method to update the input value.
*/
setInput: React.Dispatch<React.SetStateAction<string>>;
/**
* Handler for the `onChange` event of the input field to control the input's value.
*/
handleInputChange: (event: React.ChangeEvent<HTMLInputElement> | React.ChangeEvent<HTMLTextAreaElement>) => void;
/**
* Form submission handler that automatically resets the input field and appends a user message.
*/
submitMessage: (event?: React.FormEvent<HTMLFormElement>, requestOptions?: {
data?: Record<string, string>;
}) => Promise<void>;
/**
* The current status of the assistant. This can be used to show a loading indicator.
*/
status: AssistantStatus;
/**
* The error thrown during the assistant message processing, if any.
*/
error: undefined | unknown;
};
declare function useAssistant({ api, threadId: threadIdParam, credentials, headers, body, onError, }: UseAssistantOptions): UseAssistantHelpers;
/**
@deprecated Use `useAssistant` instead.
*/
declare const experimental_useAssistant: typeof useAssistant;
type UseChatHelpers = {

@@ -130,61 +190,40 @@ /** Current messages in the chat */

type UseAssistantHelpers = {
type Experimental_UseObjectOptions<RESULT> = {
/**
* The current array of chat messages.
* The API endpoint. It should stream JSON that matches the schema as chunked text.
*/
messages: Message[];
api: string;
/**
* Update the message store with a new array of messages.
* A Zod schema that defines the shape of the complete object.
*/
setMessages: React.Dispatch<React.SetStateAction<Message[]>>;
schema: z.Schema<RESULT>;
/**
* The current thread ID.
* An unique identifier. If not provided, a random one will be
* generated. When provided, the `useObject` hook with the same `id` will
* have shared states across components.
*/
threadId: string | undefined;
id?: string;
/**
* The current value of the input field.
* An optional value for the initial object.
*/
input: string;
initialValue?: DeepPartial<RESULT>;
};
type Experimental_UseObjectHelpers<RESULT, INPUT> = {
/**
* Append a user message to the chat list. This triggers the API call to fetch
* the assistant's response.
* @param message The message to append
* @param requestOptions Additional options to pass to the API call
* Calls the API with the provided input as JSON body.
*/
append: (message: Message | CreateMessage, requestOptions?: {
data?: Record<string, string>;
}) => Promise<void>;
setInput: (input: INPUT) => void;
/**
Abort the current request immediately, keep the generated tokens if any.
* The current value for the generated object. Updated as the API streams JSON chunks.
*/
stop: () => void;
object: DeepPartial<RESULT> | undefined;
/**
* setState-powered method to update the input value.
* The error object of the API request if any.
*/
setInput: React.Dispatch<React.SetStateAction<string>>;
/**
* Handler for the `onChange` event of the input field to control the input's value.
*/
handleInputChange: (event: React.ChangeEvent<HTMLInputElement> | React.ChangeEvent<HTMLTextAreaElement>) => void;
/**
* Form submission handler that automatically resets the input field and appends a user message.
*/
submitMessage: (event?: React.FormEvent<HTMLFormElement>, requestOptions?: {
data?: Record<string, string>;
}) => Promise<void>;
/**
* The current status of the assistant. This can be used to show a loading indicator.
*/
status: AssistantStatus;
/**
* The error thrown during the assistant message processing, if any.
*/
error: undefined | unknown;
};
declare function useAssistant({ api, threadId: threadIdParam, credentials, headers, body, onError, }: UseAssistantOptions): UseAssistantHelpers;
/**
@deprecated Use `useAssistant` instead.
*/
declare const experimental_useAssistant: typeof useAssistant;
declare function useObject<RESULT, INPUT = any>({ api, id, schema, // required, in the future we will use it for validation
initialValue, }: Experimental_UseObjectOptions<RESULT>): Experimental_UseObjectHelpers<RESULT, INPUT>;
declare const experimental_useObject: typeof useObject;
export { UseAssistantHelpers, UseChatHelpers, UseCompletionHelpers, experimental_useAssistant, useAssistant, useChat, useCompletion };
export { Experimental_UseObjectHelpers, Experimental_UseObjectOptions, UseAssistantHelpers, UseChatHelpers, UseCompletionHelpers, experimental_useAssistant, experimental_useObject, useAssistant, useChat, useCompletion };

@@ -34,2 +34,3 @@ "use strict";

experimental_useAssistant: () => experimental_useAssistant,
experimental_useObject: () => experimental_useObject,
useAssistant: () => useAssistant,

@@ -41,5 +42,163 @@ useChat: () => useChat,

// src/use-chat.ts
// src/use-assistant.ts
var import_provider_utils = require("@ai-sdk/provider-utils");
var import_ui_utils = require("@ai-sdk/ui-utils");
var import_react = require("react");
function useAssistant({
api,
threadId: threadIdParam,
credentials,
headers,
body,
onError
}) {
const [messages, setMessages] = (0, import_react.useState)([]);
const [input, setInput] = (0, import_react.useState)("");
const [threadId, setThreadId] = (0, import_react.useState)(void 0);
const [status, setStatus] = (0, import_react.useState)("awaiting_message");
const [error, setError] = (0, import_react.useState)(void 0);
const handleInputChange = (event) => {
setInput(event.target.value);
};
const abortControllerRef = (0, import_react.useRef)(null);
const stop = (0, import_react.useCallback)(() => {
if (abortControllerRef.current) {
abortControllerRef.current.abort();
abortControllerRef.current = null;
}
}, []);
const append = async (message, requestOptions) => {
var _a;
setStatus("in_progress");
setMessages((messages2) => {
var _a2;
return [
...messages2,
{
...message,
id: (_a2 = message.id) != null ? _a2 : (0, import_ui_utils.generateId)()
}
];
});
setInput("");
const abortController = new AbortController();
try {
abortControllerRef.current = abortController;
const result = await fetch(api, {
method: "POST",
credentials,
signal: abortController.signal,
headers: { "Content-Type": "application/json", ...headers },
body: JSON.stringify({
...body,
// always use user-provided threadId when available:
threadId: (_a = threadIdParam != null ? threadIdParam : threadId) != null ? _a : null,
message: message.content,
// optional request data:
data: requestOptions == null ? void 0 : requestOptions.data
})
});
if (result.body == null) {
throw new Error("The response body is empty.");
}
for await (const { type, value } of (0, import_ui_utils.readDataStream)(
result.body.getReader()
)) {
switch (type) {
case "assistant_message": {
setMessages((messages2) => [
...messages2,
{
id: value.id,
role: value.role,
content: value.content[0].text.value
}
]);
break;
}
case "text": {
setMessages((messages2) => {
const lastMessage = messages2[messages2.length - 1];
return [
...messages2.slice(0, messages2.length - 1),
{
id: lastMessage.id,
role: lastMessage.role,
content: lastMessage.content + value
}
];
});
break;
}
case "data_message": {
setMessages((messages2) => {
var _a2;
return [
...messages2,
{
id: (_a2 = value.id) != null ? _a2 : (0, import_ui_utils.generateId)(),
role: "data",
content: "",
data: value.data
}
];
});
break;
}
case "assistant_control_data": {
setThreadId(value.threadId);
setMessages((messages2) => {
const lastMessage = messages2[messages2.length - 1];
lastMessage.id = value.messageId;
return [...messages2.slice(0, messages2.length - 1), lastMessage];
});
break;
}
case "error": {
setError(new Error(value));
break;
}
}
}
} catch (error2) {
if ((0, import_provider_utils.isAbortError)(error2) && abortController.signal.aborted) {
abortControllerRef.current = null;
return;
}
if (onError && error2 instanceof Error) {
onError(error2);
}
setError(error2);
} finally {
abortControllerRef.current = null;
setStatus("awaiting_message");
}
};
const submitMessage = async (event, requestOptions) => {
var _a;
(_a = event == null ? void 0 : event.preventDefault) == null ? void 0 : _a.call(event);
if (input === "") {
return;
}
append({ role: "user", content: input }, requestOptions);
};
return {
append,
messages,
setMessages,
threadId,
input,
setInput,
handleInputChange,
submitMessage,
status,
error,
stop
};
}
var experimental_useAssistant = useAssistant;
// src/use-chat.ts
var import_ui_utils2 = require("@ai-sdk/ui-utils");
var import_react2 = require("react");
var import_swr = __toESM(require("swr"));

@@ -74,3 +233,3 @@ var getStreamedResponse = async (api, chatRequest, mutate, mutateStreamData, existingData, extraMetadataRef, messagesRef, abortControllerRef, generateId2, streamMode, onFinish, onResponse, onToolCall, sendExtraMessageFields) => {

);
return await (0, import_ui_utils.callChatApi)({
return await (0, import_ui_utils2.callChatApi)({
api,

@@ -134,8 +293,8 @@ messages: constructedMessagesPayload,

body,
generateId: generateId2 = import_ui_utils.generateId
generateId: generateId2 = import_ui_utils2.generateId
} = {}) {
const hookId = (0, import_react.useId)();
const hookId = (0, import_react2.useId)();
const idKey = id != null ? id : hookId;
const chatKey = typeof api === "string" ? [api, idKey] : idKey;
const [initialMessagesFallback] = (0, import_react.useState)([]);
const [initialMessagesFallback] = (0, import_react2.useState)([]);
const { data: messages, mutate } = (0, import_swr.default)(

@@ -152,8 +311,8 @@ [chatKey, "messages"],

const { data: error = void 0, mutate: setError } = (0, import_swr.default)([chatKey, "error"], null);
const messagesRef = (0, import_react.useRef)(messages || []);
(0, import_react.useEffect)(() => {
const messagesRef = (0, import_react2.useRef)(messages || []);
(0, import_react2.useEffect)(() => {
messagesRef.current = messages || [];
}, [messages]);
const abortControllerRef = (0, import_react.useRef)(null);
const extraMetadataRef = (0, import_react.useRef)({
const abortControllerRef = (0, import_react2.useRef)(null);
const extraMetadataRef = (0, import_react2.useRef)({
credentials,

@@ -163,3 +322,3 @@ headers,

});
(0, import_react.useEffect)(() => {
(0, import_react2.useEffect)(() => {
extraMetadataRef.current = {

@@ -171,3 +330,3 @@ credentials,

}, [credentials, headers, body]);
const triggerRequest = (0, import_react.useCallback)(
const triggerRequest = (0, import_react2.useCallback)(
async (chatRequest) => {

@@ -179,3 +338,3 @@ try {

abortControllerRef.current = abortController;
await (0, import_ui_utils.processChatStream)({
await (0, import_ui_utils2.processChatStream)({
getStreamedResponse: () => getStreamedResponse(

@@ -251,3 +410,3 @@ api,

);
const append = (0, import_react.useCallback)(
const append = (0, import_react2.useCallback)(
async (message, {

@@ -277,3 +436,3 @@ options,

);
const reload = (0, import_react.useCallback)(
const reload = (0, import_react2.useCallback)(
async ({

@@ -312,3 +471,3 @@ options,

);
const stop = (0, import_react.useCallback)(() => {
const stop = (0, import_react2.useCallback)(() => {
if (abortControllerRef.current) {

@@ -319,3 +478,3 @@ abortControllerRef.current.abort();

}, []);
const setMessages = (0, import_react.useCallback)(
const setMessages = (0, import_react2.useCallback)(
(messages2) => {

@@ -327,4 +486,4 @@ mutate(messages2, false);

);
const [input, setInput] = (0, import_react.useState)(initialInput);
const handleSubmit = (0, import_react.useCallback)(
const [input, setInput] = (0, import_react2.useState)(initialInput);
const handleSubmit = (0, import_react2.useCallback)(
(e, options = {}, metadata) => {

@@ -409,4 +568,4 @@ if (metadata) {

// src/use-completion.ts
var import_ui_utils2 = require("@ai-sdk/ui-utils");
var import_react2 = require("react");
var import_ui_utils3 = require("@ai-sdk/ui-utils");
var import_react3 = require("react");
var import_swr2 = __toESM(require("swr"));

@@ -426,3 +585,3 @@ function useCompletion({

} = {}) {
const hookId = (0, import_react2.useId)();
const hookId = (0, import_react3.useId)();
const completionId = id || hookId;

@@ -437,6 +596,6 @@ const { data, mutate } = (0, import_swr2.default)([api, completionId], null, {

const { data: streamData, mutate: mutateStreamData } = (0, import_swr2.default)([completionId, "streamData"], null);
const [error, setError] = (0, import_react2.useState)(void 0);
const [error, setError] = (0, import_react3.useState)(void 0);
const completion = data;
const [abortController, setAbortController] = (0, import_react2.useState)(null);
const extraMetadataRef = (0, import_react2.useRef)({
const [abortController, setAbortController] = (0, import_react3.useState)(null);
const extraMetadataRef = (0, import_react3.useRef)({
credentials,

@@ -446,3 +605,3 @@ headers,

});
(0, import_react2.useEffect)(() => {
(0, import_react3.useEffect)(() => {
extraMetadataRef.current = {

@@ -454,4 +613,4 @@ credentials,

}, [credentials, headers, body]);
const triggerRequest = (0, import_react2.useCallback)(
async (prompt, options) => (0, import_ui_utils2.callCompletionApi)({
const triggerRequest = (0, import_react3.useCallback)(
async (prompt, options) => (0, import_ui_utils3.callCompletionApi)({
api,

@@ -492,3 +651,3 @@ prompt,

);
const stop = (0, import_react2.useCallback)(() => {
const stop = (0, import_react3.useCallback)(() => {
if (abortController) {

@@ -499,3 +658,3 @@ abortController.abort();

}, [abortController]);
const setCompletion = (0, import_react2.useCallback)(
const setCompletion = (0, import_react3.useCallback)(
(completion2) => {

@@ -506,3 +665,3 @@ mutate(completion2, false);

);
const complete = (0, import_react2.useCallback)(
const complete = (0, import_react3.useCallback)(
async (prompt, options) => {

@@ -513,4 +672,4 @@ return triggerRequest(prompt, options);

);
const [input, setInput] = (0, import_react2.useState)(initialInput);
const handleSubmit = (0, import_react2.useCallback)(
const [input, setInput] = (0, import_react3.useState)(initialInput);
const handleSubmit = (0, import_react3.useCallback)(
(e) => {

@@ -542,162 +701,68 @@ e.preventDefault();

// src/use-assistant.ts
var import_provider_utils = require("@ai-sdk/provider-utils");
var import_ui_utils3 = require("@ai-sdk/ui-utils");
var import_react3 = require("react");
function useAssistant({
// src/use-object.ts
var import_ui_utils4 = require("@ai-sdk/ui-utils");
var import_react4 = require("react");
var import_swr3 = __toESM(require("swr"));
function useObject({
api,
threadId: threadIdParam,
credentials,
headers,
body,
onError
id,
schema,
// required, in the future we will use it for validation
initialValue
}) {
const [messages, setMessages] = (0, import_react3.useState)([]);
const [input, setInput] = (0, import_react3.useState)("");
const [threadId, setThreadId] = (0, import_react3.useState)(void 0);
const [status, setStatus] = (0, import_react3.useState)("awaiting_message");
const [error, setError] = (0, import_react3.useState)(void 0);
const handleInputChange = (event) => {
setInput(event.target.value);
};
const abortControllerRef = (0, import_react3.useRef)(null);
const stop = (0, import_react3.useCallback)(() => {
if (abortControllerRef.current) {
abortControllerRef.current.abort();
abortControllerRef.current = null;
}
}, []);
const append = async (message, requestOptions) => {
var _a;
setStatus("in_progress");
setMessages((messages2) => {
var _a2;
return [
...messages2,
{
...message,
id: (_a2 = message.id) != null ? _a2 : (0, import_ui_utils3.generateId)()
const hookId = (0, import_react4.useId)();
const completionId = id != null ? id : hookId;
const { data, mutate } = (0, import_swr3.default)(
[api, completionId],
null,
{ fallbackData: initialValue }
);
const [error, setError] = (0, import_react4.useState)(void 0);
return {
async setInput(input) {
var _a;
try {
const response = await fetch(api, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(input)
});
if (!response.ok) {
throw new Error(
(_a = await response.text()) != null ? _a : "Failed to fetch the response."
);
}
];
});
setInput("");
const abortController = new AbortController();
try {
abortControllerRef.current = abortController;
const result = await fetch(api, {
method: "POST",
credentials,
signal: abortController.signal,
headers: { "Content-Type": "application/json", ...headers },
body: JSON.stringify({
...body,
// always use user-provided threadId when available:
threadId: (_a = threadIdParam != null ? threadIdParam : threadId) != null ? _a : null,
message: message.content,
// optional request data:
data: requestOptions == null ? void 0 : requestOptions.data
})
});
if (result.body == null) {
throw new Error("The response body is empty.");
}
for await (const { type, value } of (0, import_ui_utils3.readDataStream)(
result.body.getReader()
)) {
switch (type) {
case "assistant_message": {
setMessages((messages2) => [
...messages2,
{
id: value.id,
role: value.role,
content: value.content[0].text.value
if (response.body == null) {
throw new Error("The response body is empty.");
}
let accumulatedText = "";
let latestObject = void 0;
response.body.pipeThrough(new TextDecoderStream()).pipeTo(
new WritableStream({
write(chunk) {
accumulatedText += chunk;
const currentObject = (0, import_ui_utils4.parsePartialJson)(
accumulatedText
);
if (!(0, import_ui_utils4.isDeepEqualData)(latestObject, currentObject)) {
latestObject = currentObject;
mutate(currentObject);
}
]);
break;
}
case "text": {
setMessages((messages2) => {
const lastMessage = messages2[messages2.length - 1];
return [
...messages2.slice(0, messages2.length - 1),
{
id: lastMessage.id,
role: lastMessage.role,
content: lastMessage.content + value
}
];
});
break;
}
case "data_message": {
setMessages((messages2) => {
var _a2;
return [
...messages2,
{
id: (_a2 = value.id) != null ? _a2 : (0, import_ui_utils3.generateId)(),
role: "data",
content: "",
data: value.data
}
];
});
break;
}
case "assistant_control_data": {
setThreadId(value.threadId);
setMessages((messages2) => {
const lastMessage = messages2[messages2.length - 1];
lastMessage.id = value.messageId;
return [...messages2.slice(0, messages2.length - 1), lastMessage];
});
break;
}
case "error": {
setError(new Error(value));
break;
}
}
}
})
);
setError(void 0);
} catch (error2) {
setError(error2);
}
} catch (error2) {
if ((0, import_provider_utils.isAbortError)(error2) && abortController.signal.aborted) {
abortControllerRef.current = null;
return;
}
if (onError && error2 instanceof Error) {
onError(error2);
}
setError(error2);
} finally {
abortControllerRef.current = null;
setStatus("awaiting_message");
}
},
object: data,
error
};
const submitMessage = async (event, requestOptions) => {
var _a;
(_a = event == null ? void 0 : event.preventDefault) == null ? void 0 : _a.call(event);
if (input === "") {
return;
}
append({ role: "user", content: input }, requestOptions);
};
return {
append,
messages,
setMessages,
threadId,
input,
setInput,
handleInputChange,
submitMessage,
status,
error,
stop
};
}
var experimental_useAssistant = useAssistant;
var experimental_useObject = useObject;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
experimental_useAssistant,
experimental_useObject,
useAssistant,

@@ -704,0 +769,0 @@ useChat,

{
"name": "@ai-sdk/react",
"version": "0.0.3",
"version": "0.0.4",
"license": "Apache-2.0",

@@ -19,3 +19,3 @@ "sideEffects": false,

"@ai-sdk/provider-utils": "0.0.15",
"@ai-sdk/ui-utils": "0.0.3",
"@ai-sdk/ui-utils": "0.0.4",
"swr": "2.2.0"

@@ -36,2 +36,3 @@ },

"typescript": "5.1.3",
"zod": "3.23.8",
"@vercel/ai-tsconfig": "0.0.0",

@@ -41,3 +42,4 @@ "eslint-config-vercel-ai": "0.0.0"

"peerDependencies": {
"react": "^18 || ^19"
"react": "^18 || ^19",
"zod": "^3.0.0"
},

@@ -47,2 +49,5 @@ "peerDependenciesMeta": {

"optional": true
},
"zod": {
"optional": true
}

@@ -49,0 +54,0 @@ },

@@ -0,3 +1,4 @@

export * from './use-assistant';
export * from './use-chat';
export * from './use-completion';
export * from './use-assistant';
export * from './use-object';

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc