diff --git a/apps/builder/package.json b/apps/builder/package.json index ff59b75f0..c45ab1402 100644 --- a/apps/builder/package.json +++ b/apps/builder/package.json @@ -128,7 +128,7 @@ "eslint-config-custom": "workspace:*", "next-runtime-env": "1.6.2", "superjson": "1.12.4", - "typescript": "5.3.2", + "typescript": "5.4.5", "zod": "3.22.4" } } diff --git a/apps/chat-api/package.json b/apps/chat-api/package.json index 9e34fa493..f4dcdd6d8 100644 --- a/apps/chat-api/package.json +++ b/apps/chat-api/package.json @@ -22,9 +22,9 @@ "@typebot.io/prisma": "workspace:*", "@typebot.io/schemas": "workspace:*", "@typebot.io/variables": "workspace:*", - "ai": "3.0.12", + "ai": "3.0.31", "hono": "4.0.5", - "openai": "4.28.4", + "openai": "4.38.3", "prom-client": "15.1.0" }, "devDependencies": { diff --git a/apps/docs/openapi/builder.json b/apps/docs/openapi/builder.json index 34ac47a85..26ac32c05 100644 --- a/apps/docs/openapi/builder.json +++ b/apps/docs/openapi/builder.json @@ -19149,7 +19149,7 @@ "assistantId": { "type": "string" }, - "threadId": { + "threadVariableId": { "type": "string" }, "message": { @@ -19186,6 +19186,9 @@ } } } + }, + "threadId": { + "type": "string" } }, "required": [ diff --git a/apps/docs/openapi/viewer.json b/apps/docs/openapi/viewer.json index 6bde40df2..0131bb47c 100644 --- a/apps/docs/openapi/viewer.json +++ b/apps/docs/openapi/viewer.json @@ -9977,7 +9977,7 @@ "assistantId": { "type": "string" }, - "threadId": { + "threadVariableId": { "type": "string" }, "message": { @@ -10014,6 +10014,9 @@ } } } + }, + "threadId": { + "type": "string" } }, "required": [ @@ -12480,18 +12483,10 @@ } } } - }, - "runtime": { - "type": "string", - "enum": [ - "edge", - "nodejs" - ] } }, "required": [ - "messages", - "runtime" + "messages" ] }, "lastBubbleBlockId": { @@ -12768,13 +12763,6 @@ true ] }, - "runtime": { - "type": "string", - "enum": [ - "edge", - "nodejs" - ] - }, "lastBubbleBlockId": { "type": "string" }, @@ -12784,8 +12772,7 @@ }, "required": [ "type", - "stream", - "runtime" + "stream" ], "title": "Exec stream" }, diff --git a/apps/landing-page/package.json b/apps/landing-page/package.json index 243f6d8ba..faad068af 100644 --- a/apps/landing-page/package.json +++ b/apps/landing-page/package.json @@ -48,6 +48,6 @@ "postcss": "8.4.26", "prettier": "3.0.0", "tailwindcss": "3.3.3", - "typescript": "5.3.2" + "typescript": "5.4.5" } } diff --git a/apps/viewer/package.json b/apps/viewer/package.json index fc04ff46a..30a725630 100644 --- a/apps/viewer/package.json +++ b/apps/viewer/package.json @@ -21,7 +21,7 @@ "@typebot.io/js": "workspace:*", "@typebot.io/nextjs": "workspace:*", "@typebot.io/prisma": "workspace:*", - "ai": "3.0.12", + "ai": "3.0.31", "bot-engine": "workspace:*", "cors": "2.8.5", "google-spreadsheet": "4.1.1", @@ -30,7 +30,7 @@ "next": "14.1.0", "nextjs-cors": "2.1.2", "nodemailer": "6.9.8", - "openai": "4.28.4", + "openai": "4.38.3", "qs": "6.11.2", "react": "18.2.0", "react-dom": "18.2.0", @@ -62,7 +62,7 @@ "next-runtime-env": "1.6.2", "papaparse": "5.4.1", "superjson": "1.12.4", - "typescript": "5.3.2", + "typescript": "5.4.5", "zod": "3.22.4", "@typebot.io/playwright": "workspace:*", "@typebot.io/results": "workspace:*" diff --git a/apps/viewer/src/app/api/integrations/openai/streamer/route.ts b/apps/viewer/src/app/api/integrations/openai/streamer/route.ts index 13ad0da60..d8571b549 100644 --- a/apps/viewer/src/app/api/integrations/openai/streamer/route.ts +++ b/apps/viewer/src/app/api/integrations/openai/streamer/route.ts @@ -7,7 +7,7 @@ import { NextResponse } from 'next/dist/server/web/spec-extension/response' import { getBlockById } from '@typebot.io/schemas/helpers' import { forgedBlocks } from '@typebot.io/forge-repository/definitions' import { decryptV2 } from '@typebot.io/lib/api/encryption/decryptV2' -import { ReadOnlyVariableStore } from '@typebot.io/forge' +import { VariableStore } from '@typebot.io/forge' import { ParseVariablesOptions, parseVariables, @@ -38,6 +38,7 @@ export async function OPTIONS() { }) } +// Deprecated in favor of `/api/v1/sessions/:sessionId/streamMessage`. export async function POST(req: Request) { const { sessionId, messages } = (await req.json()) as { messages: OpenAI.Chat.ChatCompletionMessage[] | undefined @@ -140,7 +141,7 @@ export async function POST(req: Request) { credentials.data, credentials.iv ) - const variables: ReadOnlyVariableStore = { + const variables: VariableStore = { list: () => state.typebotsQueue[0].typebot.variables, get: (id: string) => { const variable = state.typebotsQueue[0].typebot.variables.find( @@ -150,6 +151,8 @@ export async function POST(req: Request) { }, parse: (text: string, params?: ParseVariablesOptions) => parseVariables(state.typebotsQueue[0].typebot.variables, params)(text), + // eslint-disable-next-line @typescript-eslint/no-unused-vars + set: (_1: string, _2: unknown) => {}, } const stream = await action.run.stream.run({ credentials: decryptedCredentials, diff --git a/apps/viewer/src/app/api/v1/sessions/[sessionId]/streamMessage/route.ts b/apps/viewer/src/app/api/v1/sessions/[sessionId]/streamMessage/route.ts index 4f4fa49ff..47f8edf85 100644 --- a/apps/viewer/src/app/api/v1/sessions/[sessionId]/streamMessage/route.ts +++ b/apps/viewer/src/app/api/v1/sessions/[sessionId]/streamMessage/route.ts @@ -26,11 +26,6 @@ export async function POST( req: Request, { params }: { params: { sessionId: string } } ) { - if (process.env.VERCEL_ENV) - return NextResponse.json( - { message: "Can't get streaming if hosted on Vercel" }, - { status: 400, headers: responseHeaders } - ) const messages = typeof req.body === 'string' ? JSON.parse(req.body) : req.body const { stream, status, message } = await getMessageStream({ @@ -39,7 +34,22 @@ export async function POST( }) if (!stream) return NextResponse.json({ message }, { status, headers: responseHeaders }) - return new StreamingTextResponse(stream, { - headers: responseHeaders, + return new StreamingTextResponse( + stream.pipeThrough(createStreamDataTransformer()), + { + headers: responseHeaders, + } + ) +} + +const createStreamDataTransformer = () => { + const encoder = new TextEncoder() + const decoder = new TextDecoder() + return new TransformStream({ + transform: async (chunk, controller) => { + const decodedChunk = decoder.decode(chunk) + if (decodedChunk[0] !== '0') return + controller.enqueue(encoder.encode(JSON.parse(decodedChunk.slice(2)))) + }, }) } diff --git a/apps/viewer/src/app/api/v2/sessions/[sessionId]/streamMessage/route.ts b/apps/viewer/src/app/api/v2/sessions/[sessionId]/streamMessage/route.ts new file mode 100644 index 000000000..ce2c18f62 --- /dev/null +++ b/apps/viewer/src/app/api/v2/sessions/[sessionId]/streamMessage/route.ts @@ -0,0 +1,40 @@ +import { getMessageStream } from '@typebot.io/bot-engine/apiHandlers/getMessageStream' +import { StreamingTextResponse } from 'ai' +import { NextResponse } from 'next/server' + +export const dynamic = 'force-dynamic' + +const responseHeaders = { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'POST, OPTIONS', + 'Access-Control-Expose-Headers': 'Content-Length, X-JSON', + 'Access-Control-Allow-Headers': '*', +} + +export async function OPTIONS() { + return new Response('ok', { + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'POST', + 'Access-Control-Expose-Headers': 'Content-Length, X-JSON', + 'Access-Control-Allow-Headers': '*', + }, + }) +} + +export async function POST( + req: Request, + { params }: { params: { sessionId: string } } +) { + const messages = + typeof req.body === 'string' ? JSON.parse(req.body) : req.body + const { stream, status, message } = await getMessageStream({ + sessionId: params.sessionId, + messages, + }) + if (!stream) + return NextResponse.json({ message }, { status, headers: responseHeaders }) + return new StreamingTextResponse(stream, { + headers: responseHeaders, + }) +} diff --git a/packages/bot-engine/apiHandlers/getMessageStream.ts b/packages/bot-engine/apiHandlers/getMessageStream.ts index 13baa0e92..57d590200 100644 --- a/packages/bot-engine/apiHandlers/getMessageStream.ts +++ b/packages/bot-engine/apiHandlers/getMessageStream.ts @@ -3,7 +3,7 @@ import { ChatCompletionOpenAIOptions } from '@typebot.io/schemas/features/blocks import { OpenAI } from 'openai' import { decryptV2 } from '@typebot.io/lib/api/encryption/decryptV2' import { forgedBlocks } from '@typebot.io/forge-repository/definitions' -import { ReadOnlyVariableStore } from '@typebot.io/forge' +import { VariableStore } from '@typebot.io/forge' import { ParseVariablesOptions, parseVariables, @@ -13,6 +13,9 @@ import { getCredentials } from '../queries/getCredentials' import { getSession } from '../queries/getSession' import { getBlockById } from '@typebot.io/schemas/helpers' import { isForgedBlockType } from '@typebot.io/schemas/features/blocks/forged/helpers' +import { updateVariablesInSession } from '@typebot.io/variables/updateVariablesInSession' +import { updateSession } from '../queries/updateSession' +import { deepParseVariables } from '@typebot.io/variables/deepParseVariables' type Props = { sessionId: string @@ -92,7 +95,8 @@ export const getMessageStream = async ({ sessionId, messages }: Props) => { credentials.data, credentials.iv ) - const variables: ReadOnlyVariableStore = { + + const variables: VariableStore = { list: () => session.state.typebotsQueue[0].typebot.variables, get: (id: string) => { const variable = session.state.typebotsQueue[0].typebot.variables.find( @@ -105,10 +109,25 @@ export const getMessageStream = async ({ sessionId, messages }: Props) => { session.state.typebotsQueue[0].typebot.variables, params )(text), + set: async (id: string, value: unknown) => { + const variable = session.state.typebotsQueue[0].typebot.variables.find( + (variable) => variable.id === id + ) + if (!variable) return + await updateSession({ + id: session.id, + state: updateVariablesInSession(session.state)([ + { ...variable, value }, + ]), + isReplying: undefined, + }) + }, } const stream = await action.run.stream.run({ credentials: decryptedCredentials, - options: block.options, + options: deepParseVariables( + session.state.typebotsQueue[0].typebot.variables + )(block.options), variables, }) if (!stream) return { status: 500, message: 'Could not create stream' } diff --git a/packages/bot-engine/blocks/integrations/legacy/openai/createChatCompletionOpenAI.ts b/packages/bot-engine/blocks/integrations/legacy/openai/createChatCompletionOpenAI.ts index 5a2ff31ac..6e142399c 100644 --- a/packages/bot-engine/blocks/integrations/legacy/openai/createChatCompletionOpenAI.ts +++ b/packages/bot-engine/blocks/integrations/legacy/openai/createChatCompletionOpenAI.ts @@ -89,9 +89,7 @@ export const createChatCompletionOpenAI = async ( isNextBubbleMessageWithAssistantMessage(typebot)( blockId, assistantMessageVariableName - ) && - (!process.env.VERCEL_ENV || - (isPlaneteScale() && credentials && isCredentialsV2(credentials))) + ) ) { return { clientSideActions: [ @@ -102,7 +100,6 @@ export const createChatCompletionOpenAI = async ( content?: string role: (typeof chatCompletionMessageRoles)[number] }[], - runtime: process.env.VERCEL_ENV ? 'edge' : 'nodejs', }, expectsDedicatedReply: true, }, diff --git a/packages/bot-engine/forge/executeForgedBlock.ts b/packages/bot-engine/forge/executeForgedBlock.ts index ea44781b1..993b091f1 100644 --- a/packages/bot-engine/forge/executeForgedBlock.ts +++ b/packages/bot-engine/forge/executeForgedBlock.ts @@ -58,9 +58,7 @@ export const executeForgedBlock = async ( action.run.stream.getStreamVariableId(block.options) ) && state.isStreamEnabled && - !state.whatsApp && - (!process.env.VERCEL_ENV || - (isPlaneteScale() && credentials && isCredentialsV2(credentials))) + !state.whatsApp ) { return { outgoingEdgeId: block.outgoingEdgeId, @@ -69,7 +67,6 @@ export const executeForgedBlock = async ( type: 'stream', expectsDedicatedReply: true, stream: true, - runtime: process.env.VERCEL_ENV ? 'edge' : 'nodejs', }, ], } diff --git a/packages/bot-engine/package.json b/packages/bot-engine/package.json index ddc968e18..446d724e1 100644 --- a/packages/bot-engine/package.json +++ b/packages/bot-engine/package.json @@ -19,7 +19,7 @@ "@typebot.io/tsconfig": "workspace:*", "@typebot.io/variables": "workspace:*", "@udecode/plate-common": "30.4.5", - "ai": "3.0.12", + "ai": "3.0.31", "chrono-node": "2.7.5", "date-fns": "2.30.0", "date-fns-tz": "2.0.0", @@ -29,7 +29,7 @@ "libphonenumber-js": "1.10.37", "node-html-parser": "6.1.5", "nodemailer": "6.9.8", - "openai": "4.28.4", + "openai": "4.38.3", "qs": "6.11.2", "stripe": "12.13.0" }, diff --git a/packages/bot-engine/queries/updateSession.ts b/packages/bot-engine/queries/updateSession.ts index 37f4c4dde..6c0a6ceda 100644 --- a/packages/bot-engine/queries/updateSession.ts +++ b/packages/bot-engine/queries/updateSession.ts @@ -5,7 +5,7 @@ import { SessionState } from '@typebot.io/schemas' type Props = { id: string state: SessionState - isReplying: boolean + isReplying: boolean | undefined } export const updateSession = ({ diff --git a/packages/deprecated/bot-engine/package.json b/packages/deprecated/bot-engine/package.json index cb557b33b..0d73d6ab5 100644 --- a/packages/deprecated/bot-engine/package.json +++ b/packages/deprecated/bot-engine/package.json @@ -6,7 +6,7 @@ "main": "dist/index.js", "module": "dist/index.mjs", "scripts": { - "build": "pnpm tsc --noEmit && tsup", + "build": "tsup", "dev": "tsup --watch" }, "dependencies": { @@ -40,7 +40,7 @@ "@typebot.io/tsconfig": "workspace:*", "tsup": "6.5.0", "typebot-js": "workspace:*", - "typescript": "5.3.2", + "typescript": "5.4.5", "@typebot.io/lib": "workspace:*", "@typebot.io/env": "workspace:*" }, diff --git a/packages/deprecated/typebot-js/package.json b/packages/deprecated/typebot-js/package.json index 54ef9341b..52d26b148 100644 --- a/packages/deprecated/typebot-js/package.json +++ b/packages/deprecated/typebot-js/package.json @@ -18,7 +18,7 @@ "jest-environment-jsdom": "29.4.1", "prettier": "2.8.3", "ts-jest": "29.0.5", - "typescript": "5.3.2", + "typescript": "5.4.5", "@typebot.io/tsconfig": "workspace:*" } } diff --git a/packages/embeds/js/package.json b/packages/embeds/js/package.json index 6061cbb40..642962ed6 100644 --- a/packages/embeds/js/package.json +++ b/packages/embeds/js/package.json @@ -1,6 +1,6 @@ { "name": "@typebot.io/js", - "version": "0.2.77", + "version": "0.2.78", "description": "Javascript library to display typebots on your website", "type": "module", "main": "dist/index.js", @@ -46,6 +46,6 @@ "rollup-plugin-postcss": "4.0.2", "rollup-plugin-typescript-paths": "1.4.0", "tailwindcss": "3.3.3", - "typescript": "5.3.2" + "typescript": "5.4.5" } } diff --git a/packages/embeds/js/src/components/ConversationContainer/ChatChunk.tsx b/packages/embeds/js/src/components/ConversationContainer/ChatChunk.tsx index cc776c916..d8a4ef5bf 100644 --- a/packages/embeds/js/src/components/ConversationContainer/ChatChunk.tsx +++ b/packages/embeds/js/src/components/ConversationContainer/ChatChunk.tsx @@ -165,8 +165,8 @@ export const ChatChunk = (props: Props) => { class="flex flex-col flex-1 gap-2" style={{ 'max-width': - props.theme.chat?.hostAvatar?.isEnabled ?? - defaultHostAvatarIsEnabled + props.theme.chat?.guestAvatar?.isEnabled ?? + defaultGuestAvatarIsEnabled ? isMobile() ? 'calc(100% - 32px - 32px)' : 'calc(100% - 48px - 48px)' diff --git a/packages/embeds/js/src/components/bubbles/StreamingBubble.tsx b/packages/embeds/js/src/components/bubbles/StreamingBubble.tsx index 6eb66c494..1eda692b1 100644 --- a/packages/embeds/js/src/components/bubbles/StreamingBubble.tsx +++ b/packages/embeds/js/src/components/bubbles/StreamingBubble.tsx @@ -27,7 +27,7 @@ export const StreamingBubble = (props: Props) => { .map((block, index) => { if (index % 2 === 0) { return block.split('\n\n').map((line) => - domPurify.sanitize(marked.parse(line), { + domPurify.sanitize(marked.parse(line.replace(/【.+】/g, '')), { ADD_ATTR: ['target'], }) ) diff --git a/packages/embeds/js/src/features/blocks/integrations/openai/streamChat.ts b/packages/embeds/js/src/features/blocks/integrations/openai/streamChat.ts index 087f96f33..9f1f82336 100644 --- a/packages/embeds/js/src/features/blocks/integrations/openai/streamChat.ts +++ b/packages/embeds/js/src/features/blocks/integrations/openai/streamChat.ts @@ -1,4 +1,5 @@ import { ClientSideActionContext } from '@/types' +import { readDataStream } from '@/utils/ai/readDataStream' import { guessApiHost } from '@/utils/guessApiHost' import { isNotEmpty } from '@typebot.io/lib/utils' import { createUniqueId } from 'solid-js' @@ -7,22 +8,16 @@ let abortController: AbortController | null = null const secondsToWaitBeforeRetries = 3 const maxRetryAttempts = 3 -const edgeRuntimePath = '/api/integrations/openai/streamer' -const nodejsRuntimePath = (sessionId: string) => - `/api/v1/sessions/${sessionId}/streamMessage` - export const streamChat = (context: ClientSideActionContext & { retryAttempt?: number }) => async ({ messages, - runtime, onMessageStream, }: { messages?: { content?: string | undefined role?: 'system' | 'user' | 'assistant' | undefined }[] - runtime: 'edge' | 'nodejs' onMessageStream?: (props: { id: string; message: string }) => void }): Promise<{ message?: string; error?: object }> => { try { @@ -31,12 +26,8 @@ export const streamChat = const apiHost = context.apiHost const res = await fetch( - isNotEmpty(apiHost) - ? apiHost - : guessApiHost() + - (runtime === 'edge' - ? edgeRuntimePath - : nodejsRuntimePath(context.sessionId)), + (isNotEmpty(apiHost) ? apiHost : guessApiHost()) + + `/api/v2/sessions/${context.sessionId}/streamMessage`, { method: 'POST', headers: { @@ -44,7 +35,6 @@ export const streamChat = }, body: JSON.stringify({ messages, - sessionId: runtime === 'edge' ? context.sessionId : undefined, }), signal: abortController.signal, } @@ -61,7 +51,7 @@ export const streamChat = return streamChat({ ...context, retryAttempt: (context.retryAttempt ?? 0) + 1, - })({ messages, onMessageStream, runtime }) + })({ messages, onMessageStream }) } return { error: (await res.json()) || 'Failed to fetch the chat response.', @@ -75,22 +65,15 @@ export const streamChat = let message = '' const reader = res.body.getReader() - const decoder = new TextDecoder() const id = createUniqueId() - // eslint-disable-next-line no-constant-condition - while (true) { - const { done, value } = await reader.read() - if (done) { - break - } - const chunk = decoder.decode(value) - message += chunk - if (onMessageStream) onMessageStream({ id, message }) - if (abortController === null) { - reader.cancel() - break + for await (const { type, value } of readDataStream(reader, { + isAborted: () => abortController === null, + })) { + if (type === 'text') { + message += value + if (onMessageStream) onMessageStream({ id, message }) } } diff --git a/packages/embeds/js/src/utils/ai/readDataStream.ts b/packages/embeds/js/src/utils/ai/readDataStream.ts new file mode 100644 index 000000000..3a58098ed --- /dev/null +++ b/packages/embeds/js/src/utils/ai/readDataStream.ts @@ -0,0 +1,80 @@ +import { StreamPartType, parseStreamPart } from './streamParts' + +const NEWLINE = '\n'.charCodeAt(0) + +// concatenates all the chunks into a single Uint8Array +function concatChunks(chunks: Uint8Array[], totalLength: number) { + const concatenatedChunks = new Uint8Array(totalLength) + + let offset = 0 + for (const chunk of chunks) { + concatenatedChunks.set(chunk, offset) + offset += chunk.length + } + chunks.length = 0 + + return concatenatedChunks +} + +/** +Converts a ReadableStreamDefaultReader into an async generator that yields +StreamPart objects. + +@param reader + Reader for the stream to read from. +@param isAborted + Optional function that returns true if the request has been aborted. + If the function returns true, the generator will stop reading the stream. + If the function is not provided, the generator will not stop reading the stream. + */ +export async function* readDataStream( + reader: ReadableStreamDefaultReader, + { + isAborted, + }: { + isAborted?: () => boolean + } = {} +): AsyncGenerator { + // implementation note: this slightly more complex algorithm is required + // to pass the tests in the edge environment. + + const decoder = new TextDecoder() + const chunks: Uint8Array[] = [] + let totalLength = 0 + + while (true) { + const { value } = await reader.read() + + if (value) { + chunks.push(value) + totalLength += value.length + if (value[value.length - 1] !== NEWLINE) { + // if the last character is not a newline, we have not read the whole JSON value + continue + } + } + + if (chunks.length === 0) { + break // we have reached the end of the stream + } + + const concatenatedChunks = concatChunks(chunks, totalLength) + totalLength = 0 + + const streamParts = decoder + .decode(concatenatedChunks, { stream: true }) + .split('\n') + .filter((line) => line !== '') // splitting leaves an empty string at the end + .map(parseStreamPart) + + for (const streamPart of streamParts) { + yield streamPart + } + + // The request has been aborted, stop reading the stream. + if (isAborted?.()) { + reader.cancel() + break + } + } +} diff --git a/packages/embeds/js/src/utils/ai/streamParts.ts b/packages/embeds/js/src/utils/ai/streamParts.ts new file mode 100644 index 000000000..7c37d34f0 --- /dev/null +++ b/packages/embeds/js/src/utils/ai/streamParts.ts @@ -0,0 +1,377 @@ +import { + AssistantMessage, + DataMessage, + FunctionCall, + JSONValue, + ToolCall, +} from './types' + +type StreamString = + `${(typeof StreamStringPrefixes)[keyof typeof StreamStringPrefixes]}:${string}\n` + +export interface StreamPart { + code: CODE + name: NAME + parse: (value: JSONValue) => { type: NAME; value: TYPE } +} + +const textStreamPart: StreamPart<'0', 'text', string> = { + code: '0', + name: 'text', + parse: (value: JSONValue) => { + if (typeof value !== 'string') { + throw new Error('"text" parts expect a string value.') + } + return { type: 'text', value } + }, +} + +const functionCallStreamPart: StreamPart< + '1', + 'function_call', + { function_call: FunctionCall } +> = { + code: '1', + name: 'function_call', + parse: (value: JSONValue) => { + if ( + value == null || + typeof value !== 'object' || + !('function_call' in value) || + typeof value.function_call !== 'object' || + value.function_call == null || + !('name' in value.function_call) || + !('arguments' in value.function_call) || + typeof value.function_call.name !== 'string' || + typeof value.function_call.arguments !== 'string' + ) { + throw new Error( + '"function_call" parts expect an object with a "function_call" property.' + ) + } + + return { + type: 'function_call', + value: value as unknown as { function_call: FunctionCall }, + } + }, +} + +const dataStreamPart: StreamPart<'2', 'data', Array> = { + code: '2', + name: 'data', + parse: (value: JSONValue) => { + if (!Array.isArray(value)) { + throw new Error('"data" parts expect an array value.') + } + + return { type: 'data', value } + }, +} + +const errorStreamPart: StreamPart<'3', 'error', string> = { + code: '3', + name: 'error', + parse: (value: JSONValue) => { + if (typeof value !== 'string') { + throw new Error('"error" parts expect a string value.') + } + return { type: 'error', value } + }, +} + +const assistantMessageStreamPart: StreamPart< + '4', + 'assistant_message', + AssistantMessage +> = { + code: '4', + name: 'assistant_message', + parse: (value: JSONValue) => { + if ( + value == null || + typeof value !== 'object' || + !('id' in value) || + !('role' in value) || + !('content' in value) || + typeof value.id !== 'string' || + typeof value.role !== 'string' || + value.role !== 'assistant' || + !Array.isArray(value.content) || + !value.content.every( + (item) => + item != null && + typeof item === 'object' && + 'type' in item && + item.type === 'text' && + 'text' in item && + item.text != null && + typeof item.text === 'object' && + 'value' in item.text && + typeof item.text.value === 'string' + ) + ) { + throw new Error( + '"assistant_message" parts expect an object with an "id", "role", and "content" property.' + ) + } + + return { + type: 'assistant_message', + value: value as AssistantMessage, + } + }, +} + +const assistantControlDataStreamPart: StreamPart< + '5', + 'assistant_control_data', + { + threadId: string + messageId: string + } +> = { + code: '5', + name: 'assistant_control_data', + parse: (value: JSONValue) => { + if ( + value == null || + typeof value !== 'object' || + !('threadId' in value) || + !('messageId' in value) || + typeof value.threadId !== 'string' || + typeof value.messageId !== 'string' + ) { + throw new Error( + '"assistant_control_data" parts expect an object with a "threadId" and "messageId" property.' + ) + } + + return { + type: 'assistant_control_data', + value: { + threadId: value.threadId, + messageId: value.messageId, + }, + } + }, +} + +const dataMessageStreamPart: StreamPart<'6', 'data_message', DataMessage> = { + code: '6', + name: 'data_message', + parse: (value: JSONValue) => { + if ( + value == null || + typeof value !== 'object' || + !('role' in value) || + !('data' in value) || + typeof value.role !== 'string' || + value.role !== 'data' + ) { + throw new Error( + '"data_message" parts expect an object with a "role" and "data" property.' + ) + } + + return { + type: 'data_message', + value: value as DataMessage, + } + }, +} + +const toolCallStreamPart: StreamPart< + '7', + 'tool_calls', + { tool_calls: ToolCall[] } +> = { + code: '7', + name: 'tool_calls', + parse: (value: JSONValue) => { + if ( + value == null || + typeof value !== 'object' || + !('tool_calls' in value) || + typeof value.tool_calls !== 'object' || + value.tool_calls == null || + !Array.isArray(value.tool_calls) || + value.tool_calls.some( + (tc) => + tc == null || + typeof tc !== 'object' || + !('id' in tc) || + typeof tc.id !== 'string' || + !('type' in tc) || + typeof tc.type !== 'string' || + !('function' in tc) || + tc.function == null || + typeof tc.function !== 'object' || + !('arguments' in tc.function) || + typeof tc.function.name !== 'string' || + typeof tc.function.arguments !== 'string' + ) + ) { + throw new Error( + '"tool_calls" parts expect an object with a ToolCallPayload.' + ) + } + + return { + type: 'tool_calls', + value: value as unknown as { tool_calls: ToolCall[] }, + } + }, +} + +const messageAnnotationsStreamPart: StreamPart< + '8', + 'message_annotations', + Array +> = { + code: '8', + name: 'message_annotations', + parse: (value: JSONValue) => { + if (!Array.isArray(value)) { + throw new Error('"message_annotations" parts expect an array value.') + } + + return { type: 'message_annotations', value } + }, +} + +const streamParts = [ + textStreamPart, + functionCallStreamPart, + dataStreamPart, + errorStreamPart, + assistantMessageStreamPart, + assistantControlDataStreamPart, + dataMessageStreamPart, + toolCallStreamPart, + messageAnnotationsStreamPart, +] as const + +// union type of all stream parts +type StreamParts = + | typeof textStreamPart + | typeof functionCallStreamPart + | typeof dataStreamPart + | typeof errorStreamPart + | typeof assistantMessageStreamPart + | typeof assistantControlDataStreamPart + | typeof dataMessageStreamPart + | typeof toolCallStreamPart + | typeof messageAnnotationsStreamPart +/** + * Maps the type of a stream part to its value type. + */ +type StreamPartValueType = { + [P in StreamParts as P['name']]: ReturnType['value'] +} + +export type StreamPartType = + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + +export const streamPartsByCode = { + [textStreamPart.code]: textStreamPart, + [functionCallStreamPart.code]: functionCallStreamPart, + [dataStreamPart.code]: dataStreamPart, + [errorStreamPart.code]: errorStreamPart, + [assistantMessageStreamPart.code]: assistantMessageStreamPart, + [assistantControlDataStreamPart.code]: assistantControlDataStreamPart, + [dataMessageStreamPart.code]: dataMessageStreamPart, + [toolCallStreamPart.code]: toolCallStreamPart, + [messageAnnotationsStreamPart.code]: messageAnnotationsStreamPart, +} as const + +/** + * The map of prefixes for data in the stream + * + * - 0: Text from the LLM response + * - 1: (OpenAI) function_call responses + * - 2: custom JSON added by the user using `Data` + * - 6: (OpenAI) tool_call responses + * + * Example: + * ``` + * 0:Vercel + * 0:'s + * 0: AI + * 0: AI + * 0: SDK + * 0: is great + * 0:! + * 2: { "someJson": "value" } + * 1: {"function_call": {"name": "get_current_weather", "arguments": "{\\n\\"location\\": \\"Charlottesville, Virginia\\",\\n\\"format\\": \\"celsius\\"\\n}"}} + * 6: {"tool_call": {"id": "tool_0", "type": "function", "function": {"name": "get_current_weather", "arguments": "{\\n\\"location\\": \\"Charlottesville, Virginia\\",\\n\\"format\\": \\"celsius\\"\\n}"}}} + *``` + */ +export const StreamStringPrefixes = { + [textStreamPart.name]: textStreamPart.code, + [functionCallStreamPart.name]: functionCallStreamPart.code, + [dataStreamPart.name]: dataStreamPart.code, + [errorStreamPart.name]: errorStreamPart.code, + [assistantMessageStreamPart.name]: assistantMessageStreamPart.code, + [assistantControlDataStreamPart.name]: assistantControlDataStreamPart.code, + [dataMessageStreamPart.name]: dataMessageStreamPart.code, + [toolCallStreamPart.name]: toolCallStreamPart.code, + [messageAnnotationsStreamPart.name]: messageAnnotationsStreamPart.code, +} as const + +export const validCodes = streamParts.map((part) => part.code) + +/** +Parses a stream part from a string. + +@param line The string to parse. +@returns The parsed stream part. +@throws An error if the string cannot be parsed. + */ +export const parseStreamPart = (line: string): StreamPartType => { + const firstSeparatorIndex = line.indexOf(':') + + if (firstSeparatorIndex === -1) { + throw new Error('Failed to parse stream string. No separator found.') + } + + const prefix = line.slice(0, firstSeparatorIndex) + + if (!validCodes.includes(prefix as keyof typeof streamPartsByCode)) { + throw new Error(`Failed to parse stream string. Invalid code ${prefix}.`) + } + + const code = prefix as keyof typeof streamPartsByCode + + const textValue = line.slice(firstSeparatorIndex + 1) + const jsonValue: JSONValue = JSON.parse(textValue) + + return streamPartsByCode[code].parse(jsonValue) +} + +/** +Prepends a string with a prefix from the `StreamChunkPrefixes`, JSON-ifies it, +and appends a new line. + +It ensures type-safety for the part type and value. + */ +export function formatStreamPart( + type: T, + value: StreamPartValueType[T] +): StreamString { + const streamPart = streamParts.find((part) => part.name === type) + + if (!streamPart) { + throw new Error(`Invalid stream part type: ${type}`) + } + + return `${streamPart.code}:${JSON.stringify(value)}\n` +} diff --git a/packages/embeds/js/src/utils/ai/types.ts b/packages/embeds/js/src/utils/ai/types.ts new file mode 100644 index 000000000..6a844e953 --- /dev/null +++ b/packages/embeds/js/src/utils/ai/types.ts @@ -0,0 +1,355 @@ +/* eslint-disable @typescript-eslint/ban-types */ +// https://github.com/openai/openai-node/blob/07b3504e1c40fd929f4aae1651b83afc19e3baf8/src/resources/chat/completions.ts#L146-L159 +export interface FunctionCall { + /** + * The arguments to call the function with, as generated by the model in JSON + * format. Note that the model does not always generate valid JSON, and may + * hallucinate parameters not defined by your function schema. Validate the + * arguments in your code before calling your function. + */ + arguments?: string + + /** + * The name of the function to call. + */ + name?: string +} + +/** + * The tool calls generated by the model, such as function calls. + */ +export interface ToolCall { + // The ID of the tool call. + id: string + + // The type of the tool. Currently, only `function` is supported. + type: string + + // The function that the model called. + function: { + // The name of the function. + name: string + + // The arguments to call the function with, as generated by the model in JSON + arguments: string + } +} + +/** + * Controls which (if any) function is called by the model. + * - none means the model will not call a function and instead generates a message. + * - auto means the model can pick between generating a message or calling a function. + * - Specifying a particular function via {"type: "function", "function": {"name": "my_function"}} forces the model to call that function. + * none is the default when no functions are present. auto is the default if functions are present. + */ +export type ToolChoice = + | 'none' + | 'auto' + | { type: 'function'; function: { name: string } } + +/** + * A list of tools the model may call. Currently, only functions are supported as a tool. + * Use this to provide a list of functions the model may generate JSON inputs for. + */ +export interface Tool { + type: 'function' + function: Function +} + +export interface Function { + /** + * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain + * underscores and dashes, with a maximum length of 64. + */ + name: string + + /** + * The parameters the functions accepts, described as a JSON Schema object. See the + * [guide](/docs/guides/gpt/function-calling) for examples, and the + * [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for + * documentation about the format. + * + * To describe a function that accepts no parameters, provide the value + * `{"type": "object", "properties": {}}`. + */ + parameters: Record + + /** + * A description of what the function does, used by the model to choose when and + * how to call the function. + */ + description?: string +} + +export type IdGenerator = () => string + +/** + * Shared types between the API and UI packages. + */ +export interface Message { + id: string + tool_call_id?: string + createdAt?: Date + content: string + ui?: string | JSX.Element | JSX.Element[] | null | undefined + role: 'system' | 'user' | 'assistant' | 'function' | 'data' | 'tool' + /** + * If the message has a role of `function`, the `name` field is the name of the function. + * Otherwise, the name field should not be set. + */ + name?: string + /** + * If the assistant role makes a function call, the `function_call` field + * contains the function call name and arguments. Otherwise, the field should + * not be set. (Deprecated and replaced by tool_calls.) + */ + function_call?: string | FunctionCall + + data?: JSONValue + /** + * If the assistant role makes a tool call, the `tool_calls` field contains + * the tool call name and arguments. Otherwise, the field should not be set. + */ + tool_calls?: string | ToolCall[] + + /** + * Additional message-specific information added on the server via StreamData + */ + annotations?: JSONValue[] | undefined +} + +export type CreateMessage = Omit & { + id?: Message['id'] +} + +export type ChatRequest = { + messages: Message[] + options?: RequestOptions + // @deprecated + functions?: Array + // @deprecated + function_call?: FunctionCall + data?: Record + tools?: Array + tool_choice?: ToolChoice +} + +export type FunctionCallHandler = ( + chatMessages: Message[], + functionCall: FunctionCall +) => Promise + +export type ToolCallHandler = ( + chatMessages: Message[], + toolCalls: ToolCall[] +) => Promise + +export type RequestOptions = { + headers?: Record | Headers + body?: object +} + +export type ChatRequestOptions = { + options?: RequestOptions + functions?: Array + function_call?: FunctionCall + tools?: Array + tool_choice?: ToolChoice + data?: Record +} + +export type UseChatOptions = { + /** + * The API endpoint that accepts a `{ messages: Message[] }` object and returns + * a stream of tokens of the AI chat response. Defaults to `/api/chat`. + */ + api?: string + + /** + * A unique identifier for the chat. If not provided, a random one will be + * generated. When provided, the `useChat` hook with the same `id` will + * have shared states across components. + */ + id?: string + + /** + * Initial messages of the chat. Useful to load an existing chat history. + */ + initialMessages?: Message[] + + /** + * Initial input of the chat. + */ + initialInput?: string + + /** + * Callback function to be called when a function call is received. + * If the function returns a `ChatRequest` object, the request will be sent + * automatically to the API and will be used to update the chat. + */ + experimental_onFunctionCall?: FunctionCallHandler + + /** + * Callback function to be called when a tool call is received. + * If the function returns a `ChatRequest` object, the request will be sent + * automatically to the API and will be used to update the chat. + */ + experimental_onToolCall?: ToolCallHandler + + /** + * Callback function to be called when the API response is received. + */ + onResponse?: (response: Response) => void | Promise + + /** + * Callback function to be called when the chat is finished streaming. + */ + onFinish?: (message: Message) => void + + /** + * Callback function to be called when an error is encountered. + */ + onError?: (error: Error) => void + + /** + * A way to provide a function that is going to be used for ids for messages. + * If not provided nanoid is used by default. + */ + generateId?: IdGenerator + + /** + * The credentials mode to be used for the fetch request. + * Possible values are: 'omit', 'same-origin', 'include'. + * Defaults to 'same-origin'. + */ + credentials?: RequestCredentials + + /** + * HTTP headers to be sent with the API request. + */ + headers?: Record | Headers + + /** + * Extra body object to be sent with the API request. + * @example + * Send a `sessionId` to the API along with the messages. + * ```js + * useChat({ + * body: { + * sessionId: '123', + * } + * }) + * ``` + */ + body?: object + + /** + * Whether to send extra message fields such as `message.id` and `message.createdAt` to the API. + * Defaults to `false`. When set to `true`, the API endpoint might need to + * handle the extra fields before forwarding the request to the AI service. + */ + sendExtraMessageFields?: boolean + + /** Stream mode (default to "stream-data") */ + streamMode?: 'stream-data' | 'text' +} + +export type UseCompletionOptions = { + /** + * The API endpoint that accepts a `{ prompt: string }` object and returns + * a stream of tokens of the AI completion response. Defaults to `/api/completion`. + */ + api?: string + /** + * An unique identifier for the chat. If not provided, a random one will be + * generated. When provided, the `useChat` hook with the same `id` will + * have shared states across components. + */ + id?: string + + /** + * Initial prompt input of the completion. + */ + initialInput?: string + + /** + * Initial completion result. Useful to load an existing history. + */ + initialCompletion?: string + + /** + * Callback function to be called when the API response is received. + */ + onResponse?: (response: Response) => void | Promise + + /** + * Callback function to be called when the completion is finished streaming. + */ + onFinish?: (prompt: string, completion: string) => void + + /** + * Callback function to be called when an error is encountered. + */ + onError?: (error: Error) => void + + /** + * The credentials mode to be used for the fetch request. + * Possible values are: 'omit', 'same-origin', 'include'. + * Defaults to 'same-origin'. + */ + credentials?: RequestCredentials + + /** + * HTTP headers to be sent with the API request. + */ + headers?: Record | Headers + + /** + * Extra body object to be sent with the API request. + * @example + * Send a `sessionId` to the API along with the prompt. + * ```js + * useChat({ + * body: { + * sessionId: '123', + * } + * }) + * ``` + */ + body?: object + + /** Stream mode (default to "stream-data") */ + streamMode?: 'stream-data' | 'text' +} + +export type JSONValue = + | null + | string + | number + | boolean + | { [x: string]: JSONValue } + | Array + +export type AssistantMessage = { + id: string + role: 'assistant' + content: Array<{ + type: 'text' + text: { + value: string + } + }> +} + +/* + * A data message is an application-specific message from the assistant + * that should be shown in order with the other messages. + * + * It can trigger other operations on the frontend, such as annotating + * a map. + */ +export type DataMessage = { + id?: string // optional id, implement if needed (e.g. for persistance) + role: 'data' + data: JSONValue // application-specific data +} diff --git a/packages/embeds/js/src/utils/executeClientSideActions.ts b/packages/embeds/js/src/utils/executeClientSideActions.ts index f0c7811f8..051233730 100644 --- a/packages/embeds/js/src/utils/executeClientSideActions.ts +++ b/packages/embeds/js/src/utils/executeClientSideActions.ts @@ -54,17 +54,12 @@ export const executeClientSideAction = async ({ 'streamOpenAiChatCompletion' in clientSideAction || 'stream' in clientSideAction ) { - const runtime = - 'streamOpenAiChatCompletion' in clientSideAction - ? clientSideAction.streamOpenAiChatCompletion.runtime - : clientSideAction.runtime const { error, message } = await streamChat(context)({ messages: 'streamOpenAiChatCompletion' in clientSideAction ? clientSideAction.streamOpenAiChatCompletion?.messages : undefined, onMessageStream, - runtime, }) if (error) return { diff --git a/packages/embeds/nextjs/package.json b/packages/embeds/nextjs/package.json index d96555da5..6d1bff6bc 100644 --- a/packages/embeds/nextjs/package.json +++ b/packages/embeds/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@typebot.io/nextjs", - "version": "0.2.77", + "version": "0.2.78", "description": "Convenient library to display typebots on your Next.js website", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -35,7 +35,7 @@ "rollup-plugin-typescript-paths": "1.4.0", "tslib": "2.6.0", "tsx": "3.12.7", - "typescript": "5.3.2", + "typescript": "5.4.5", "@rollup/plugin-typescript": "11.1.2" }, "peerDependencies": { diff --git a/packages/embeds/react/package.json b/packages/embeds/react/package.json index 47deb172a..44e81e43f 100644 --- a/packages/embeds/react/package.json +++ b/packages/embeds/react/package.json @@ -1,6 +1,6 @@ { "name": "@typebot.io/react", - "version": "0.2.77", + "version": "0.2.78", "description": "Convenient library to display typebots on your React app", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -39,7 +39,7 @@ "rollup-plugin-typescript-paths": "1.4.0", "tslib": "2.6.0", "tsx": "3.12.7", - "typescript": "5.3.2", + "typescript": "5.4.5", "@rollup/plugin-typescript": "11.1.2" }, "peerDependencies": { diff --git a/packages/forge/blocks/anthropic/helpers/parseChatMessages.ts b/packages/forge/blocks/anthropic/helpers/parseChatMessages.ts index 68a5029b4..fdc276d55 100644 --- a/packages/forge/blocks/anthropic/helpers/parseChatMessages.ts +++ b/packages/forge/blocks/anthropic/helpers/parseChatMessages.ts @@ -1,6 +1,6 @@ import { Anthropic } from '@anthropic-ai/sdk' import { options as createMessageOptions } from '../actions/createChatMessage' -import { ReadOnlyVariableStore } from '@typebot.io/forge' +import { VariableStore } from '@typebot.io/forge' import { isNotEmpty } from '@typebot.io/lib' import { z } from '@typebot.io/forge/zod' @@ -9,7 +9,7 @@ export const parseChatMessages = ({ variables, }: { options: Pick, 'messages'> - variables: ReadOnlyVariableStore + variables: VariableStore }): Anthropic.Messages.MessageParam[] => { const parsedMessages = messages ?.flatMap((message) => { diff --git a/packages/forge/blocks/anthropic/package.json b/packages/forge/blocks/anthropic/package.json index ef0934634..1012ffba7 100644 --- a/packages/forge/blocks/anthropic/package.json +++ b/packages/forge/blocks/anthropic/package.json @@ -11,10 +11,10 @@ "@typebot.io/lib": "workspace:*", "@typebot.io/tsconfig": "workspace:*", "@types/react": "18.2.15", - "typescript": "5.3.2" + "typescript": "5.4.5" }, "dependencies": { - "@anthropic-ai/sdk": "0.18.0", - "ai": "3.0.12" + "@anthropic-ai/sdk": "0.20.6", + "ai": "3.0.31" } } diff --git a/packages/forge/blocks/calCom/package.json b/packages/forge/blocks/calCom/package.json index b4e4ef7f9..a0a3ab43a 100644 --- a/packages/forge/blocks/calCom/package.json +++ b/packages/forge/blocks/calCom/package.json @@ -9,7 +9,7 @@ "@typebot.io/forge": "workspace:*", "@typebot.io/tsconfig": "workspace:*", "@types/react": "18.2.15", - "typescript": "5.3.2", + "typescript": "5.4.5", "@typebot.io/lib": "workspace:*" } } diff --git a/packages/forge/blocks/chatNode/package.json b/packages/forge/blocks/chatNode/package.json index 2e697d07d..69bb7d286 100644 --- a/packages/forge/blocks/chatNode/package.json +++ b/packages/forge/blocks/chatNode/package.json @@ -10,7 +10,7 @@ "@typebot.io/lib": "workspace:*", "@typebot.io/tsconfig": "workspace:*", "@types/react": "18.2.15", - "typescript": "5.3.2", + "typescript": "5.4.5", "ky": "1.2.3" } } diff --git a/packages/forge/blocks/difyAi/package.json b/packages/forge/blocks/difyAi/package.json index 2174ee540..92558715d 100644 --- a/packages/forge/blocks/difyAi/package.json +++ b/packages/forge/blocks/difyAi/package.json @@ -11,6 +11,6 @@ "@typebot.io/tsconfig": "workspace:*", "@types/react": "18.2.15", "ky": "1.2.3", - "typescript": "5.3.2" + "typescript": "5.4.5" } } diff --git a/packages/forge/blocks/elevenlabs/package.json b/packages/forge/blocks/elevenlabs/package.json index f97412dc1..e4734d218 100644 --- a/packages/forge/blocks/elevenlabs/package.json +++ b/packages/forge/blocks/elevenlabs/package.json @@ -10,7 +10,7 @@ "@typebot.io/lib": "workspace:*", "@typebot.io/tsconfig": "workspace:*", "@types/react": "18.2.15", - "typescript": "5.3.2" + "typescript": "5.4.5" }, "dependencies": { "ky": "1.2.3", diff --git a/packages/forge/blocks/mistral/actions/createChatCompletion.ts b/packages/forge/blocks/mistral/actions/createChatCompletion.ts index 6e2c3c364..3befa72ce 100644 --- a/packages/forge/blocks/mistral/actions/createChatCompletion.ts +++ b/packages/forge/blocks/mistral/actions/createChatCompletion.ts @@ -80,6 +80,7 @@ export const createChatCompletion = createAction({ blockId: 'anthropic', transform: (options) => ({ ...options, + model: undefined, action: 'Create Chat Message', responseMapping: options.responseMapping?.map((res: any) => res.item === 'Message content' diff --git a/packages/forge/blocks/mistral/helpers/parseMessages.ts b/packages/forge/blocks/mistral/helpers/parseMessages.ts index c56ecea52..089cb29f6 100644 --- a/packages/forge/blocks/mistral/helpers/parseMessages.ts +++ b/packages/forge/blocks/mistral/helpers/parseMessages.ts @@ -1,5 +1,5 @@ import { options as createChatCompletionOption } from '../actions/createChatCompletion' -import { ReadOnlyVariableStore } from '@typebot.io/forge' +import { VariableStore } from '@typebot.io/forge' import { isDefined, isNotEmpty } from '@typebot.io/lib' import { z } from '@typebot.io/forge/zod' @@ -8,7 +8,7 @@ export const parseMessages = ({ variables, }: { options: Pick, 'messages'> - variables: ReadOnlyVariableStore + variables: VariableStore }) => messages ?.flatMap((message) => { diff --git a/packages/forge/blocks/mistral/package.json b/packages/forge/blocks/mistral/package.json index 945555861..611a3fccc 100644 --- a/packages/forge/blocks/mistral/package.json +++ b/packages/forge/blocks/mistral/package.json @@ -11,9 +11,9 @@ "@typebot.io/tsconfig": "workspace:*", "@types/node": "^20.12.4", "@types/react": "18.2.15", - "typescript": "5.3.2" + "typescript": "5.4.5" }, "dependencies": { - "ai": "3.0.12" + "ai": "3.0.31" } } diff --git a/packages/forge/blocks/openRouter/actions/createChatCompletion.tsx b/packages/forge/blocks/openRouter/actions/createChatCompletion.tsx index fdaabbf9b..06cdb565d 100644 --- a/packages/forge/blocks/openRouter/actions/createChatCompletion.tsx +++ b/packages/forge/blocks/openRouter/actions/createChatCompletion.tsx @@ -24,6 +24,7 @@ export const createChatCompletion = createAction({ blockId: 'anthropic', transform: (options) => ({ ...options, + model: undefined, action: 'Create Chat Message', responseMapping: options.responseMapping?.map((res: any) => res.item === 'Message content' diff --git a/packages/forge/blocks/openRouter/package.json b/packages/forge/blocks/openRouter/package.json index 6b1067b4e..1735c3672 100644 --- a/packages/forge/blocks/openRouter/package.json +++ b/packages/forge/blocks/openRouter/package.json @@ -9,7 +9,7 @@ "@typebot.io/forge": "workspace:*", "@typebot.io/tsconfig": "workspace:*", "@types/react": "18.2.15", - "typescript": "5.3.2", + "typescript": "5.4.5", "@typebot.io/lib": "workspace:*", "@typebot.io/openai-block": "workspace:*", "ky": "1.2.3" diff --git a/packages/forge/blocks/openai/actions/askAssistant.tsx b/packages/forge/blocks/openai/actions/askAssistant.tsx index 35a054233..d414c4d5a 100644 --- a/packages/forge/blocks/openai/actions/askAssistant.tsx +++ b/packages/forge/blocks/openai/actions/askAssistant.tsx @@ -1,54 +1,68 @@ -import { createAction, option } from '@typebot.io/forge' -import { isDefined, isEmpty } from '@typebot.io/lib' +import { + LogsStore, + VariableStore, + createAction, + option, +} from '@typebot.io/forge' +import { isDefined, isEmpty, isNotEmpty } from '@typebot.io/lib' import { auth } from '../auth' import { ClientOptions, OpenAI } from 'openai' import { baseOptions } from '../baseOptions' import { executeFunction } from '@typebot.io/variables/executeFunction' +import { readDataStream } from 'ai' +import { deprecatedAskAssistantOptions } from '../deprecated' +import { OpenAIAssistantStream } from '../helpers/OpenAIAssistantStream' export const askAssistant = createAction({ auth, baseOptions, name: 'Ask Assistant', - options: option.object({ - assistantId: option.string.layout({ - label: 'Assistant ID', - placeholder: 'Select an assistant', - moreInfoTooltip: 'The OpenAI assistant you want to ask question to.', - fetcher: 'fetchAssistants', - }), - threadId: option.string.layout({ - label: 'Thread ID', - moreInfoTooltip: - 'Used to remember the conversation with the user. If empty, a new thread is created.', - }), - message: option.string.layout({ - label: 'Message', - inputType: 'textarea', - }), - functions: option - .array( - option.object({ - name: option.string.layout({ - fetcher: 'fetchAssistantFunctions', - label: 'Name', - }), - code: option.string.layout({ - inputType: 'code', - label: 'Code', - lang: 'javascript', - moreInfoTooltip: - 'A javascript code snippet that can use the defined parameters. It should return a value.', - withVariableButton: false, - }), - }) - ) - .layout({ accordion: 'Functions', itemLabel: 'function' }), - responseMapping: option - .saveResponseArray(['Message', 'Thread ID'] as const) - .layout({ - accordion: 'Save response', + options: option + .object({ + assistantId: option.string.layout({ + label: 'Assistant ID', + placeholder: 'Select an assistant', + moreInfoTooltip: 'The OpenAI assistant you want to ask question to.', + fetcher: 'fetchAssistants', }), - }), + threadVariableId: option.string.layout({ + label: 'Thread ID', + moreInfoTooltip: + 'Used to remember the conversation with the user. If empty, a new thread is created.', + inputType: 'variableDropdown', + }), + + message: option.string.layout({ + label: 'Message', + inputType: 'textarea', + }), + functions: option + .array( + option.object({ + name: option.string.layout({ + fetcher: 'fetchAssistantFunctions', + label: 'Name', + }), + code: option.string.layout({ + inputType: 'code', + label: 'Code', + lang: 'javascript', + moreInfoTooltip: + 'A javascript code snippet that can use the defined parameters. It should return a value.', + withVariableButton: false, + }), + }) + ) + .layout({ accordion: 'Functions', itemLabel: 'function' }), + responseMapping: option + .saveResponseArray(['Message', 'Thread ID'] as const, { + item: { hiddenItems: ['Thread ID'] }, + }) + .layout({ + accordion: 'Save response', + }), + }) + .merge(deprecatedAskAssistantOptions), fetchers: [ { id: 'fetchAssistants', @@ -121,6 +135,23 @@ export const askAssistant = createAction({ getSetVariableIds: ({ responseMapping }) => responseMapping?.map((r) => r.variableId).filter(isDefined) ?? [], run: { + stream: { + getStreamVariableId: ({ responseMapping }) => + responseMapping?.find((m) => !m.item || m.item === 'Message') + ?.variableId, + run: async ({ credentials, options, variables }) => + createAssistantStream({ + apiKey: credentials.apiKey, + assistantId: options.assistantId, + message: options.message, + baseUrl: options.baseUrl, + apiVersion: options.apiVersion, + threadVariableId: options.threadVariableId, + variables, + functions: options.functions, + responseMapping: options.responseMapping, + }), + }, server: async ({ credentials: { apiKey }, options: { @@ -130,143 +161,188 @@ export const askAssistant = createAction({ message, responseMapping, threadId, + threadVariableId, functions, }, variables, logs, }) => { - if (isEmpty(assistantId)) { - logs.add('Assistant ID is empty') - return - } - if (isEmpty(message)) { - logs.add('Message is empty') - return - } - const config = { + const stream = await createAssistantStream({ apiKey, - baseURL: baseUrl, - defaultHeaders: { - 'api-key': apiKey, - }, - defaultQuery: apiVersion - ? { - 'api-version': apiVersion, - } - : undefined, - } satisfies ClientOptions - - const openai = new OpenAI(config) - - // Create a thread if needed - const currentThreadId = isEmpty(threadId) - ? (await openai.beta.threads.create({})).id - : threadId - - // Add a message to the thread - const createdMessage = await openai.beta.threads.messages.create( - currentThreadId, - { - role: 'user', - content: message, - } - ) - - const run = await openai.beta.threads.runs.create(currentThreadId, { - assistant_id: assistantId, + assistantId, + logs, + message, + baseUrl, + apiVersion, + threadVariableId, + variables, + threadId, + functions, }) - async function waitForRun(run: OpenAI.Beta.Threads.Runs.Run) { - // Poll for status change - while (run.status === 'queued' || run.status === 'in_progress') { - await new Promise((resolve) => setTimeout(resolve, 500)) + if (!stream) return - run = await openai.beta.threads.runs.retrieve(currentThreadId, run.id) - } + let writingMessage = '' - // Check the run status - if ( - run.status === 'cancelled' || - run.status === 'cancelling' || - run.status === 'failed' || - run.status === 'expired' - ) { - throw new Error(run.status) - } - if (run.status === 'requires_action') { - if (run.required_action?.type === 'submit_tool_outputs') { - const tool_outputs = ( - await Promise.all( - run.required_action.submit_tool_outputs.tool_calls.map( - async (toolCall) => { - const parameters = JSON.parse(toolCall.function.arguments) - - const functionToExecute = functions?.find( - (f) => f.name === toolCall.function.name - ) - if (!functionToExecute) return - - const name = toolCall.function.name - if (!name || !functionToExecute.code) return - - const { output, newVariables } = await executeFunction({ - variables: variables.list(), - body: functionToExecute.code, - args: parameters, - }) - - newVariables?.forEach((variable) => { - variables.set(variable.id, variable.value) - }) - - return { - tool_call_id: toolCall.id, - output, - } - } - ) - ) - ).filter(isDefined) - - run = await openai.beta.threads.runs.submitToolOutputs( - currentThreadId, - run.id, - { tool_outputs } - ) - - await waitForRun(run) - } + for await (const { type, value } of readDataStream(stream.getReader())) { + if (type === 'text') { + writingMessage += value } } - await waitForRun(run) - - const responseMessages = ( - await openai.beta.threads.messages.list(currentThreadId, { - after: createdMessage.id, - order: 'asc', - }) - ).data - responseMapping?.forEach((mapping) => { if (!mapping.variableId) return if (!mapping.item || mapping.item === 'Message') { - let message = '' - const messageContents = responseMessages[0].content - for (const content of messageContents) { - switch (content.type) { - case 'text': - message += - (message !== '' ? '\n\n' : '') + - content.text.value.replace(/【.+】/g, '') - break - } - } - variables.set(mapping.variableId, message) + variables.set( + mapping.variableId, + writingMessage.replace(/【.+】/g, '') + ) } - if (mapping.item === 'Thread ID') - variables.set(mapping.variableId, currentThreadId) }) }, }, }) + +const createAssistantStream = async ({ + apiKey, + assistantId, + logs, + message, + baseUrl, + apiVersion, + threadVariableId, + variables, + threadId, + functions, + responseMapping, +}: { + apiKey?: string + assistantId?: string + message?: string + baseUrl?: string + apiVersion?: string + threadVariableId?: string + threadId?: string + functions?: { name?: string; code?: string }[] + responseMapping?: { + item?: 'Thread ID' | 'Message' | undefined + variableId?: string | undefined + }[] + logs?: LogsStore + variables: VariableStore +}): Promise => { + if (isEmpty(assistantId)) { + logs?.add('Assistant ID is empty') + return + } + if (isEmpty(message)) { + logs?.add('Message is empty') + return + } + const config = { + apiKey, + baseURL: baseUrl, + defaultHeaders: { + 'api-key': apiKey, + }, + defaultQuery: apiVersion + ? { + 'api-version': apiVersion, + } + : undefined, + } satisfies ClientOptions + + const openai = new OpenAI(config) + + let currentThreadId: string | undefined + + if ( + threadVariableId && + isNotEmpty(variables.get(threadVariableId)?.toString()) + ) { + currentThreadId = variables.get(threadVariableId)?.toString() + } else if (isNotEmpty(threadId)) { + currentThreadId = threadId + } else { + currentThreadId = (await openai.beta.threads.create({})).id + const threadIdResponseMapping = responseMapping?.find( + (mapping) => mapping.item === 'Thread ID' + ) + if (threadIdResponseMapping?.variableId) + variables.set(threadIdResponseMapping.variableId, currentThreadId) + + if (threadVariableId) variables.set(threadVariableId, currentThreadId) + } + + if (!currentThreadId) { + logs?.add('Could not get thread ID') + return + } + + // Add a message to the thread + const createdMessage = await openai.beta.threads.messages.create( + currentThreadId, + { + role: 'user', + content: message, + } + ) + return OpenAIAssistantStream( + { threadId: currentThreadId, messageId: createdMessage.id }, + async ({ forwardStream }) => { + const runStream = openai.beta.threads.runs.createAndStream( + currentThreadId, + { + assistant_id: assistantId, + } + ) + + let runResult = await forwardStream(runStream) + + while ( + runResult?.status === 'requires_action' && + runResult.required_action?.type === 'submit_tool_outputs' + ) { + const tool_outputs = ( + await Promise.all( + runResult.required_action.submit_tool_outputs.tool_calls.map( + async (toolCall) => { + const parameters = JSON.parse(toolCall.function.arguments) + + const functionToExecute = functions?.find( + (f) => f.name === toolCall.function.name + ) + if (!functionToExecute) return + + const name = toolCall.function.name + if (!name || !functionToExecute.code) return + + const { output, newVariables } = await executeFunction({ + variables: variables.list(), + body: functionToExecute.code, + args: parameters, + }) + + newVariables?.forEach((variable) => { + variables.set(variable.id, variable.value) + }) + + return { + tool_call_id: toolCall.id, + output, + } + } + ) + ) + ).filter(isDefined) + runResult = await forwardStream( + openai.beta.threads.runs.submitToolOutputsStream( + currentThreadId, + runResult.id, + { tool_outputs } + ) + ) + } + } + ) +} diff --git a/packages/forge/blocks/openai/actions/createChatCompletion.tsx b/packages/forge/blocks/openai/actions/createChatCompletion.tsx index 663576fed..e01eb4cba 100644 --- a/packages/forge/blocks/openai/actions/createChatCompletion.tsx +++ b/packages/forge/blocks/openai/actions/createChatCompletion.tsx @@ -31,6 +31,7 @@ export const createChatCompletion = createAction({ blockId: 'anthropic', transform: (options) => ({ ...options, + model: undefined, action: 'Create Chat Message', responseMapping: options.responseMapping?.map((res: any) => res.item === 'Message content' diff --git a/packages/forge/blocks/openai/deprecated.ts b/packages/forge/blocks/openai/deprecated.ts new file mode 100644 index 000000000..83ee01479 --- /dev/null +++ b/packages/forge/blocks/openai/deprecated.ts @@ -0,0 +1,10 @@ +import { option } from '@typebot.io/forge' + +export const deprecatedAskAssistantOptions = option.object({ + threadId: option.string.layout({ + label: 'Thread ID', + moreInfoTooltip: + 'Used to remember the conversation with the user. If empty, a new thread is created.', + isHidden: true, + }), +}) diff --git a/packages/forge/blocks/openai/helpers/OpenAIAssistantStream.ts b/packages/forge/blocks/openai/helpers/OpenAIAssistantStream.ts new file mode 100644 index 000000000..0cd2cb68f --- /dev/null +++ b/packages/forge/blocks/openai/helpers/OpenAIAssistantStream.ts @@ -0,0 +1,145 @@ +import { AssistantMessage, DataMessage, formatStreamPart } from 'ai' +import { AssistantStream } from 'openai/lib/AssistantStream' +import { Run } from 'openai/resources/beta/threads/runs/runs' + +/** +You can pass the thread and the latest message into the `AssistantResponse`. This establishes the context for the response. + */ +type AssistantResponseSettings = { + /** +The thread ID that the response is associated with. + */ + threadId: string + + /** +The ID of the latest message that the response is associated with. + */ + messageId: string +} + +/** +The process parameter is a callback in which you can run the assistant on threads, and send messages and data messages to the client. + */ +type AssistantResponseCallback = (options: { + /** +@deprecated use variable from outer scope instead. + */ + threadId: string + + /** +@deprecated use variable from outer scope instead. + */ + messageId: string + + /** +Forwards an assistant message (non-streaming) to the client. + */ + sendMessage: (message: AssistantMessage) => void + + /** +Send a data message to the client. You can use this to provide information for rendering custom UIs while the assistant is processing the thread. + */ + sendDataMessage: (message: DataMessage) => void + + /** +Forwards the assistant response stream to the client. Returns the `Run` object after it completes, or when it requires an action. + */ + forwardStream: (stream: AssistantStream) => Promise +}) => Promise + +export const OpenAIAssistantStream = ( + { threadId, messageId }: AssistantResponseSettings, + process: AssistantResponseCallback +) => + new ReadableStream({ + async start(controller) { + const textEncoder = new TextEncoder() + + const sendMessage = (message: AssistantMessage) => { + controller.enqueue( + textEncoder.encode(formatStreamPart('assistant_message', message)) + ) + } + + const sendDataMessage = (message: DataMessage) => { + controller.enqueue( + textEncoder.encode(formatStreamPart('data_message', message)) + ) + } + + const sendError = (errorMessage: string) => { + controller.enqueue( + textEncoder.encode(formatStreamPart('error', errorMessage)) + ) + } + + const forwardStream = async (stream: AssistantStream) => { + let result: Run | undefined = undefined + + for await (const value of stream) { + switch (value.event) { + case 'thread.message.created': { + controller.enqueue( + textEncoder.encode( + formatStreamPart('assistant_message', { + id: value.data.id, + role: 'assistant', + content: [{ type: 'text', text: { value: '' } }], + }) + ) + ) + break + } + + case 'thread.message.delta': { + const content = value.data.delta.content?.[0] + + if (content?.type === 'text' && content.text?.value != null) { + controller.enqueue( + textEncoder.encode( + formatStreamPart('text', content.text.value) + ) + ) + } + + break + } + + case 'thread.run.completed': + case 'thread.run.requires_action': { + result = value.data + break + } + } + } + + return result + } + + // send the threadId and messageId as the first message: + controller.enqueue( + textEncoder.encode( + formatStreamPart('assistant_control_data', { + threadId, + messageId, + }) + ) + ) + + try { + await process({ + threadId, + messageId, + sendMessage, + sendDataMessage, + forwardStream, + }) + } catch (error) { + sendError((error as any).message ?? `${error}`) + } finally { + controller.close() + } + }, + pull(controller) {}, + cancel() {}, + }) diff --git a/packages/forge/blocks/openai/helpers/parseChatCompletionMessages.ts b/packages/forge/blocks/openai/helpers/parseChatCompletionMessages.ts index c7d75939f..b2e310521 100644 --- a/packages/forge/blocks/openai/helpers/parseChatCompletionMessages.ts +++ b/packages/forge/blocks/openai/helpers/parseChatCompletionMessages.ts @@ -1,5 +1,5 @@ import type { OpenAI } from 'openai' -import { ReadOnlyVariableStore } from '@typebot.io/forge' +import { VariableStore } from '@typebot.io/forge' import { isNotEmpty } from '@typebot.io/lib' import { ChatCompletionOptions } from '../shared/parseChatCompletionOptions' @@ -8,7 +8,7 @@ export const parseChatCompletionMessages = ({ variables, }: { options: ChatCompletionOptions - variables: ReadOnlyVariableStore + variables: VariableStore }): OpenAI.Chat.ChatCompletionMessageParam[] => { const parsedMessages = messages ?.flatMap((message) => { diff --git a/packages/forge/blocks/openai/package.json b/packages/forge/blocks/openai/package.json index 5e1045712..1339feb90 100644 --- a/packages/forge/blocks/openai/package.json +++ b/packages/forge/blocks/openai/package.json @@ -7,14 +7,14 @@ "author": "Baptiste Arnaud", "license": "ISC", "dependencies": { - "ai": "3.0.12", - "openai": "4.28.4" + "ai": "3.0.31", + "openai": "4.38.3" }, "devDependencies": { "@typebot.io/forge": "workspace:*", "@typebot.io/tsconfig": "workspace:*", "@types/react": "18.2.15", - "typescript": "5.3.2", + "typescript": "5.4.5", "@typebot.io/lib": "workspace:*", "@typebot.io/variables": "workspace:*" } diff --git a/packages/forge/blocks/openai/shared/runChatCompletionStream.ts b/packages/forge/blocks/openai/shared/runChatCompletionStream.ts index 75abf595f..4777d82c2 100644 --- a/packages/forge/blocks/openai/shared/runChatCompletionStream.ts +++ b/packages/forge/blocks/openai/shared/runChatCompletionStream.ts @@ -1,4 +1,4 @@ -import { LogsStore, ReadOnlyVariableStore } from '@typebot.io/forge/types' +import { VariableStore } from '@typebot.io/forge/types' import { ChatCompletionOptions } from './parseChatCompletionOptions' import { executeFunction } from '@typebot.io/variables/executeFunction' import { OpenAIStream, ToolCallPayload } from 'ai' @@ -10,7 +10,7 @@ import { parseToolParameters } from '../helpers/parseToolParameters' type Props = { credentials: { apiKey?: string } options: ChatCompletionOptions - variables: ReadOnlyVariableStore + variables: VariableStore config: { baseUrl: string; defaultModel?: string } } export const runChatCompletionStream = async ({ diff --git a/packages/forge/blocks/qrcode/package.json b/packages/forge/blocks/qrcode/package.json index 04cc52984..80395a980 100644 --- a/packages/forge/blocks/qrcode/package.json +++ b/packages/forge/blocks/qrcode/package.json @@ -11,9 +11,9 @@ "@typebot.io/tsconfig": "workspace:*", "@types/react": "18.2.15", "@types/qrcode": "^1.5.3", - "typescript": "5.3.2" + "typescript": "5.4.5" }, "dependencies": { "qrcode": "^1.5.3" } -} \ No newline at end of file +} diff --git a/packages/forge/blocks/togetherAi/actions/createChatCompletion.tsx b/packages/forge/blocks/togetherAi/actions/createChatCompletion.tsx index 1ceefe686..ff9191e35 100644 --- a/packages/forge/blocks/togetherAi/actions/createChatCompletion.tsx +++ b/packages/forge/blocks/togetherAi/actions/createChatCompletion.tsx @@ -26,6 +26,7 @@ export const createChatCompletion = createAction({ blockId: 'anthropic', transform: (options) => ({ ...options, + model: undefined, action: 'Create Chat Message', responseMapping: options.responseMapping?.map((res: any) => res.item === 'Message content' diff --git a/packages/forge/blocks/togetherAi/package.json b/packages/forge/blocks/togetherAi/package.json index 6c65e1a3c..b36e0dca3 100644 --- a/packages/forge/blocks/togetherAi/package.json +++ b/packages/forge/blocks/togetherAi/package.json @@ -12,6 +12,6 @@ "@typebot.io/variables": "workspace:*", "@typebot.io/openai-block": "workspace:*", "@types/react": "18.2.15", - "typescript": "5.3.2" + "typescript": "5.4.5" } } diff --git a/packages/forge/blocks/zemanticAi/package.json b/packages/forge/blocks/zemanticAi/package.json index 1db95535e..edb6fbae5 100644 --- a/packages/forge/blocks/zemanticAi/package.json +++ b/packages/forge/blocks/zemanticAi/package.json @@ -9,7 +9,7 @@ "@typebot.io/forge": "workspace:*", "@typebot.io/tsconfig": "workspace:*", "@types/react": "18.2.15", - "typescript": "5.3.2", + "typescript": "5.4.5", "@typebot.io/lib": "workspace:*", "ky": "1.2.3" } diff --git a/packages/forge/core/types.ts b/packages/forge/core/types.ts index 7e5a96778..c302a14ee 100644 --- a/packages/forge/core/types.ts +++ b/packages/forge/core/types.ts @@ -30,8 +30,6 @@ export type FunctionToExecute = { content: string } -export type ReadOnlyVariableStore = Omit - export type TurnableIntoParam = { blockId: string /** @@ -65,7 +63,7 @@ export type ActionDefinition< run: (params: { credentials: CredentialsFromAuthDef options: z.infer & z.infer - variables: ReadOnlyVariableStore + variables: VariableStore }) => Promise | undefined> } web?: { diff --git a/packages/lib/package.json b/packages/lib/package.json index 52f188f90..0220f204c 100644 --- a/packages/lib/package.json +++ b/packages/lib/package.json @@ -17,7 +17,7 @@ "next": "14.1.0", "nodemailer": "6.9.8", "tslib": "2.6.0", - "typescript": "5.3.2" + "typescript": "5.4.5" }, "peerDependencies": { "next": "14.0.0", diff --git a/packages/prisma/package.json b/packages/prisma/package.json index 21bfce5e6..1d2cf9a87 100644 --- a/packages/prisma/package.json +++ b/packages/prisma/package.json @@ -22,6 +22,6 @@ "prisma": "5.12.1", "@typebot.io/tsconfig": "workspace:*", "tsx": "3.12.7", - "typescript": "5.3.2" + "typescript": "5.4.5" } } diff --git a/packages/radar/package.json b/packages/radar/package.json index ec0ce7bad..71717122a 100644 --- a/packages/radar/package.json +++ b/packages/radar/package.json @@ -13,6 +13,6 @@ "@typebot.io/prisma": "workspace:*", "@typebot.io/tsconfig": "workspace:*", "@typebot.io/env": "workspace:*", - "typescript": "5.3.2" + "typescript": "5.4.5" } } diff --git a/packages/schemas/features/chat/clientSideAction.ts b/packages/schemas/features/chat/clientSideAction.ts index 8b48726c7..0964816c4 100644 --- a/packages/schemas/features/chat/clientSideAction.ts +++ b/packages/schemas/features/chat/clientSideAction.ts @@ -110,7 +110,6 @@ export const clientSideActionSchema = z.discriminatedUnion('type', [ messages: z.array( nativeMessageSchema.pick({ content: true, role: true }) ), - runtime: z.enum(['edge', 'nodejs']), }), }) .merge(clientSideActionBaseSchema) @@ -152,7 +151,6 @@ export const clientSideActionSchema = z.discriminatedUnion('type', [ .object({ type: z.literal('stream'), stream: z.literal(true), - runtime: z.enum(['edge', 'nodejs']), }) .merge(clientSideActionBaseSchema) .openapi({ diff --git a/packages/schemas/package.json b/packages/schemas/package.json index 5f4465819..a8ce6c116 100644 --- a/packages/schemas/package.json +++ b/packages/schemas/package.json @@ -14,6 +14,6 @@ "@typebot.io/forge-repository": "workspace:*", "@typebot.io/prisma": "workspace:*", "@typebot.io/tsconfig": "workspace:*", - "typescript": "5.3.2" + "typescript": "5.4.5" } } diff --git a/packages/scripts/inspectTypebot.ts b/packages/scripts/inspectTypebot.ts index 63e2182fd..a7cf666c7 100644 --- a/packages/scripts/inspectTypebot.ts +++ b/packages/scripts/inspectTypebot.ts @@ -38,6 +38,7 @@ const inspectTypebot = async () => { customDomain: true, createdAt: true, isArchived: true, + isClosed: true, publishedTypebot: { select: { id: true, diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 7cc2d54cc..658895cb3 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -46,7 +46,7 @@ "prompts": "2.4.2", "stripe": "12.13.0", "tsx": "3.12.7", - "typescript": "5.3.2", + "typescript": "5.4.5", "zod": "3.22.4" }, "dependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c256a3759..289584e91 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -370,8 +370,8 @@ importers: specifier: 1.12.4 version: 1.12.4 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 zod: specifier: 3.22.4 version: 3.22.4 @@ -418,14 +418,14 @@ importers: specifier: workspace:* version: link:../../packages/variables ai: - specifier: 3.0.12 - version: 3.0.12(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4) + specifier: 3.0.31 + version: 3.0.31(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4) hono: specifier: 4.0.5 version: 4.0.5 openai: - specifier: 4.28.4 - version: 4.28.4 + specifier: 4.38.3 + version: 4.38.3 prom-client: specifier: 15.1.0 version: 15.1.0 @@ -570,8 +570,8 @@ importers: specifier: 3.3.3 version: 3.3.3 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 apps/viewer: dependencies: @@ -600,8 +600,8 @@ importers: specifier: workspace:* version: link:../../packages/prisma ai: - specifier: 3.0.12 - version: 3.0.12(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4) + specifier: 3.0.31 + version: 3.0.31(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4) bot-engine: specifier: workspace:* version: link:../../packages/deprecated/bot-engine @@ -627,8 +627,8 @@ importers: specifier: 6.9.8 version: 6.9.8 openai: - specifier: 4.28.4 - version: 4.28.4 + specifier: 4.38.3 + version: 4.38.3 qs: specifier: 6.11.2 version: 6.11.2 @@ -724,8 +724,8 @@ importers: specifier: 1.12.4 version: 1.12.4 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 zod: specifier: 3.22.4 version: 3.22.4 @@ -788,8 +788,8 @@ importers: specifier: 30.4.5 version: 30.4.5(@types/react@18.2.15)(immer@10.0.2)(react-dom@18.2.0)(react@18.2.0)(scheduler@0.23.0)(slate-history@0.100.0)(slate-hyperscript@0.100.0)(slate-react@0.102.0)(slate@0.102.0) ai: - specifier: 3.0.12 - version: 3.0.12(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4) + specifier: 3.0.31 + version: 3.0.31(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4) chrono-node: specifier: 2.7.5 version: 2.7.5 @@ -818,8 +818,8 @@ importers: specifier: 6.9.8 version: 6.9.8 openai: - specifier: 4.28.4 - version: 4.28.4 + specifier: 4.38.3 + version: 4.38.3 qs: specifier: 6.11.2 version: 6.11.2 @@ -932,13 +932,13 @@ importers: version: 3.2.4(postcss@8.4.21) tsup: specifier: 6.5.0 - version: 6.5.0(postcss@8.4.21)(typescript@5.3.2) + version: 6.5.0(postcss@8.4.21)(typescript@5.4.5) typebot-js: specifier: workspace:* version: link:../typebot-js typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/deprecated/typebot-js: devDependencies: @@ -965,13 +965,13 @@ importers: version: 2.8.3 ts-jest: specifier: 29.0.5 - version: 29.0.5(@babel/core@7.22.9)(esbuild@0.15.18)(jest@29.4.1)(typescript@5.3.2) + version: 29.0.5(@babel/core@7.22.9)(esbuild@0.15.18)(jest@29.4.1)(typescript@5.4.5) tsup: specifier: 6.5.0 - version: 6.5.0(typescript@5.3.2) + version: 6.5.0(typescript@5.4.5) typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/emails: devDependencies: @@ -1056,7 +1056,7 @@ importers: version: 0.4.3(rollup@3.26.2) '@rollup/plugin-typescript': specifier: 11.1.2 - version: 11.1.2(rollup@3.26.2)(tslib@2.6.0)(typescript@5.3.2) + version: 11.1.2(rollup@3.26.2)(tslib@2.6.0)(typescript@5.4.5) '@typebot.io/bot-engine': specifier: workspace:* version: link:../../bot-engine @@ -1095,7 +1095,7 @@ importers: version: link:../../eslint-config-custom eslint-plugin-solid: specifier: 0.12.1 - version: 0.12.1(eslint@8.44.0)(typescript@5.3.2) + version: 0.12.1(eslint@8.44.0)(typescript@5.4.5) postcss: specifier: 8.4.26 version: 8.4.26 @@ -1110,13 +1110,13 @@ importers: version: 4.0.2(postcss@8.4.26) rollup-plugin-typescript-paths: specifier: 1.4.0 - version: 1.4.0(typescript@5.3.2) + version: 1.4.0(typescript@5.4.5) tailwindcss: specifier: 3.3.3 version: 3.3.3 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/embeds/nextjs: dependencies: @@ -1141,7 +1141,7 @@ importers: version: 0.4.3(rollup@3.26.2) '@rollup/plugin-typescript': specifier: 11.1.2 - version: 11.1.2(rollup@3.26.2)(tslib@2.6.0)(typescript@5.3.2) + version: 11.1.2(rollup@3.26.2)(tslib@2.6.0)(typescript@5.4.5) '@typebot.io/js': specifier: workspace:* version: link:../js @@ -1180,7 +1180,7 @@ importers: version: 3.26.2 rollup-plugin-typescript-paths: specifier: 1.4.0 - version: 1.4.0(typescript@5.3.2) + version: 1.4.0(typescript@5.4.5) tslib: specifier: 2.6.0 version: 2.6.0 @@ -1188,14 +1188,14 @@ importers: specifier: 3.12.7 version: 3.12.7 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/embeds/react: dependencies: '@ladle/react': specifier: 2.5.1 - version: 2.5.1(@types/node@20.4.2)(react-dom@18.2.0)(react@18.2.0)(typescript@5.3.2) + version: 2.5.1(@types/node@20.4.2)(react-dom@18.2.0)(react@18.2.0)(typescript@5.4.5) devDependencies: '@babel/preset-react': specifier: 7.22.5 @@ -1214,7 +1214,7 @@ importers: version: 0.4.3(rollup@3.26.2) '@rollup/plugin-typescript': specifier: 11.1.2 - version: 11.1.2(rollup@3.26.2)(tslib@2.6.0)(typescript@5.3.2) + version: 11.1.2(rollup@3.26.2)(tslib@2.6.0)(typescript@5.4.5) '@typebot.io/js': specifier: workspace:* version: link:../js @@ -1250,7 +1250,7 @@ importers: version: 3.26.2 rollup-plugin-typescript-paths: specifier: 1.4.0 - version: 1.4.0(typescript@5.3.2) + version: 1.4.0(typescript@5.4.5) tslib: specifier: 2.6.0 version: 2.6.0 @@ -1258,8 +1258,8 @@ importers: specifier: 3.12.7 version: 3.12.7 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/embeds/wordpress: {} @@ -1289,7 +1289,7 @@ importers: version: 8.44.0 eslint-config-next: specifier: 13.4.9 - version: 13.4.9(eslint@8.44.0)(typescript@5.3.2) + version: 13.4.9(eslint@8.44.0)(typescript@5.4.5) eslint-config-prettier: specifier: 8.8.0 version: 8.8.0(eslint@8.44.0) @@ -1299,19 +1299,19 @@ importers: devDependencies: '@typescript-eslint/eslint-plugin': specifier: 6.0.0 - version: 6.0.0(@typescript-eslint/parser@6.0.0)(eslint@8.44.0)(typescript@5.3.2) + version: 6.0.0(@typescript-eslint/parser@6.0.0)(eslint@8.44.0)(typescript@5.4.5) '@typescript-eslint/parser': specifier: 6.0.0 - version: 6.0.0(eslint@8.44.0)(typescript@5.3.2) + version: 6.0.0(eslint@8.44.0)(typescript@5.4.5) packages/forge/blocks/anthropic: dependencies: '@anthropic-ai/sdk': - specifier: 0.18.0 - version: 0.18.0 + specifier: 0.20.6 + version: 0.20.6 ai: - specifier: 3.0.12 - version: 3.0.12(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4) + specifier: 3.0.31 + version: 3.0.31(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4) devDependencies: '@typebot.io/forge': specifier: workspace:* @@ -1326,8 +1326,8 @@ importers: specifier: 18.2.15 version: 18.2.15 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/forge/blocks/calCom: devDependencies: @@ -1344,8 +1344,8 @@ importers: specifier: 18.2.15 version: 18.2.15 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/forge/blocks/chatNode: devDependencies: @@ -1365,8 +1365,8 @@ importers: specifier: 1.2.3 version: 1.2.3 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/forge/blocks/difyAi: devDependencies: @@ -1386,8 +1386,8 @@ importers: specifier: 1.2.3 version: 1.2.3 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/forge/blocks/elevenlabs: dependencies: @@ -1408,14 +1408,14 @@ importers: specifier: 18.2.15 version: 18.2.15 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/forge/blocks/mistral: dependencies: ai: - specifier: 3.0.12 - version: 3.0.12(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4) + specifier: 3.0.31 + version: 3.0.31(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4) devDependencies: '@typebot.io/forge': specifier: workspace:* @@ -1433,8 +1433,8 @@ importers: specifier: 18.2.15 version: 18.2.15 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/forge/blocks/openRouter: devDependencies: @@ -1457,17 +1457,17 @@ importers: specifier: 1.2.3 version: 1.2.3 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/forge/blocks/openai: dependencies: ai: - specifier: 3.0.12 - version: 3.0.12(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4) + specifier: 3.0.31 + version: 3.0.31(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4) openai: - specifier: 4.28.4 - version: 4.28.4 + specifier: 4.38.3 + version: 4.38.3 devDependencies: '@typebot.io/forge': specifier: workspace:* @@ -1485,8 +1485,8 @@ importers: specifier: 18.2.15 version: 18.2.15 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/forge/blocks/qrcode: dependencies: @@ -1510,8 +1510,8 @@ importers: specifier: 18.2.15 version: 18.2.15 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/forge/blocks/togetherAi: devDependencies: @@ -1534,8 +1534,8 @@ importers: specifier: 18.2.15 version: 18.2.15 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/forge/blocks/zemanticAi: devDependencies: @@ -1555,8 +1555,8 @@ importers: specifier: 1.2.3 version: 1.2.3 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/forge/cli: devDependencies: @@ -1731,8 +1731,8 @@ importers: specifier: 2.6.0 version: 2.6.0 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/migrations: dependencies: @@ -1794,8 +1794,8 @@ importers: specifier: 3.12.7 version: 3.12.7 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/radar: dependencies: @@ -1816,8 +1816,8 @@ importers: specifier: workspace:* version: link:../tsconfig typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/results: dependencies: @@ -1857,8 +1857,8 @@ importers: specifier: workspace:* version: link:../tsconfig typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 packages/scripts: dependencies: @@ -1924,8 +1924,8 @@ importers: specifier: 3.12.7 version: 3.12.7 typescript: - specifier: 5.3.2 - version: 5.3.2 + specifier: 5.4.5 + version: 5.4.5 zod: specifier: 3.22.4 version: 3.22.4 @@ -1988,6 +1988,29 @@ packages: resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} engines: {node: '>=0.10.0'} + /@ai-sdk/provider-utils@0.0.3(zod@3.22.4): + resolution: {integrity: sha512-13+4v62ylduGvwz8966SdnT1aoQRO4QkWzZJyVswdgmYeX2vrXuU4bssK578+FXIXc1jwi2hLZO8lqgLPT/xDA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.0.0 + peerDependenciesMeta: + zod: + optional: true + dependencies: + '@ai-sdk/provider': 0.0.2 + eventsource-parser: 1.1.2 + nanoid: 3.3.6 + secure-json-parse: 2.7.0 + zod: 3.22.4 + dev: false + + /@ai-sdk/provider@0.0.2: + resolution: {integrity: sha512-LDRx7TFWjuuW1V8bGCMvOk4ap5gNGeSxa6w65Y+pHskiLRk/nn+Z2xzMy1JjCTksUblu0i/plai4bOLgqkxJHA==} + engines: {node: '>=18'} + dependencies: + json-schema: 0.4.0 + dev: false + /@alloc/quick-lru@5.2.0: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} @@ -1999,14 +2022,13 @@ packages: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - /@anthropic-ai/sdk@0.18.0: - resolution: {integrity: sha512-3XsWEn/4nPGRd4AdSguugbSDFy6Z2AWTNOeI3iK+aV22+w23+vY9CEb3Hiy0kvKIQuxSmZz/+5WKC8nPWy8gVg==} + /@anthropic-ai/sdk@0.20.6: + resolution: {integrity: sha512-vpVWAol+Ih1UkZGUj8DYPuqWDGxBp6M/JYz4nvq2HBT0zKdvi24Z9oznA7tr+HDed78JZrw+nbxs2I8JbTAIiQ==} dependencies: '@types/node': 18.11.18 '@types/node-fetch': 2.6.11 abort-controller: 3.0.0 agentkeepalive: 4.5.0 - digest-fetch: 1.3.0 form-data-encoder: 1.7.2 formdata-node: 4.4.1 node-fetch: 2.7.0 @@ -7147,7 +7169,7 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@ladle/react@2.5.1(@types/node@20.4.2)(react-dom@18.2.0)(react@18.2.0)(typescript@5.3.2): + /@ladle/react@2.5.1(@types/node@20.4.2)(react-dom@18.2.0)(react@18.2.0)(typescript@5.4.5): resolution: {integrity: sha512-xTSs5dUIK+zQzHNo6i3SDuA9lu0k8nUJ7/RNeNJ7oTkX05FfBSxCUeIKeUAjaVNm/axvylVhdGDm+yLBIxq8EA==} engines: {node: '>=16.0.0'} hasBin: true @@ -7191,7 +7213,7 @@ packages: react-frame-component: 5.2.6(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0) react-inspector: 6.0.2(react@18.2.0) vite: 4.5.2(@types/node@20.4.2) - vite-tsconfig-paths: 4.3.1(typescript@5.3.2)(vite@4.5.2) + vite-tsconfig-paths: 4.3.1(typescript@5.4.5)(vite@4.5.2) transitivePeerDependencies: - '@types/node' - less @@ -7543,7 +7565,7 @@ packages: lodash: 4.17.21 openapi-types: 12.1.3 zod: 3.22.4 - zod-to-json-schema: 3.22.4(zod@3.22.4) + zod-to-json-schema: 3.22.5(zod@3.22.4) dev: true /@next/env@14.0.5-canary.46: @@ -8893,7 +8915,7 @@ packages: terser: 5.29.1 dev: true - /@rollup/plugin-typescript@11.1.2(rollup@3.26.2)(tslib@2.6.0)(typescript@5.3.2): + /@rollup/plugin-typescript@11.1.2(rollup@3.26.2)(tslib@2.6.0)(typescript@5.4.5): resolution: {integrity: sha512-0ghSOCMcA7fl1JM+0gYRf+Q/HWyg+zg7/gDSc+fRLmlJWcW5K1I+CLRzaRhXf4Y3DRyPnnDo4M2ktw+a6JcDEg==} engines: {node: '>=14.0.0'} peerDependencies: @@ -8910,7 +8932,7 @@ packages: resolve: 1.22.8 rollup: 3.26.2 tslib: 2.6.0 - typescript: 5.3.2 + typescript: 5.4.5 dev: true /@rollup/pluginutils@5.1.0(rollup@2.78.0): @@ -9973,7 +9995,7 @@ packages: '@types/yargs-parser': 21.0.3 dev: true - /@typescript-eslint/eslint-plugin@6.0.0(@typescript-eslint/parser@6.0.0)(eslint@8.44.0)(typescript@5.3.2): + /@typescript-eslint/eslint-plugin@6.0.0(@typescript-eslint/parser@6.0.0)(eslint@8.44.0)(typescript@5.4.5): resolution: {integrity: sha512-xuv6ghKGoiq856Bww/yVYnXGsKa588kY3M0XK7uUW/3fJNNULKRfZfSBkMTSpqGG/8ZCXCadfh8G/z/B4aqS/A==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -9985,10 +10007,10 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 6.0.0(eslint@8.44.0)(typescript@5.3.2) + '@typescript-eslint/parser': 6.0.0(eslint@8.44.0)(typescript@5.4.5) '@typescript-eslint/scope-manager': 6.0.0 - '@typescript-eslint/type-utils': 6.0.0(eslint@8.44.0)(typescript@5.3.2) - '@typescript-eslint/utils': 6.0.0(eslint@8.44.0)(typescript@5.3.2) + '@typescript-eslint/type-utils': 6.0.0(eslint@8.44.0)(typescript@5.4.5) + '@typescript-eslint/utils': 6.0.0(eslint@8.44.0)(typescript@5.4.5) '@typescript-eslint/visitor-keys': 6.0.0 debug: 4.3.4 eslint: 8.44.0 @@ -9998,13 +10020,13 @@ packages: natural-compare: 1.4.0 natural-compare-lite: 1.4.0 semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.3.2) - typescript: 5.3.2 + ts-api-utils: 1.3.0(typescript@5.4.5) + typescript: 5.4.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser@5.62.0(eslint@8.44.0)(typescript@5.3.2): + /@typescript-eslint/parser@5.62.0(eslint@8.44.0)(typescript@5.4.5): resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -10016,15 +10038,15 @@ packages: dependencies: '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.3.2) + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5) debug: 4.3.4 eslint: 8.44.0 - typescript: 5.3.2 + typescript: 5.4.5 transitivePeerDependencies: - supports-color dev: false - /@typescript-eslint/parser@6.0.0(eslint@8.44.0)(typescript@5.3.2): + /@typescript-eslint/parser@6.0.0(eslint@8.44.0)(typescript@5.4.5): resolution: {integrity: sha512-TNaufYSPrr1U8n+3xN+Yp9g31vQDJqhXzzPSHfQDLcaO4tU+mCfODPxCwf4H530zo7aUBE3QIdxCXamEnG04Tg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -10036,11 +10058,11 @@ packages: dependencies: '@typescript-eslint/scope-manager': 6.0.0 '@typescript-eslint/types': 6.0.0 - '@typescript-eslint/typescript-estree': 6.0.0(typescript@5.3.2) + '@typescript-eslint/typescript-estree': 6.0.0(typescript@5.4.5) '@typescript-eslint/visitor-keys': 6.0.0 debug: 4.3.4 eslint: 8.44.0 - typescript: 5.3.2 + typescript: 5.4.5 transitivePeerDependencies: - supports-color @@ -10058,7 +10080,7 @@ packages: '@typescript-eslint/types': 6.0.0 '@typescript-eslint/visitor-keys': 6.0.0 - /@typescript-eslint/type-utils@6.0.0(eslint@8.44.0)(typescript@5.3.2): + /@typescript-eslint/type-utils@6.0.0(eslint@8.44.0)(typescript@5.4.5): resolution: {integrity: sha512-ah6LJvLgkoZ/pyJ9GAdFkzeuMZ8goV6BH7eC9FPmojrnX9yNCIsfjB+zYcnex28YO3RFvBkV6rMV6WpIqkPvoQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -10068,12 +10090,12 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.0.0(typescript@5.3.2) - '@typescript-eslint/utils': 6.0.0(eslint@8.44.0)(typescript@5.3.2) + '@typescript-eslint/typescript-estree': 6.0.0(typescript@5.4.5) + '@typescript-eslint/utils': 6.0.0(eslint@8.44.0)(typescript@5.4.5) debug: 4.3.4 eslint: 8.44.0 - ts-api-utils: 1.3.0(typescript@5.3.2) - typescript: 5.3.2 + ts-api-utils: 1.3.0(typescript@5.4.5) + typescript: 5.4.5 transitivePeerDependencies: - supports-color dev: true @@ -10086,7 +10108,7 @@ packages: resolution: {integrity: sha512-Zk9KDggyZM6tj0AJWYYKgF0yQyrcnievdhG0g5FqyU3Y2DRxJn4yWY21sJC0QKBckbsdKKjYDV2yVrrEvuTgxg==} engines: {node: ^16.0.0 || >=18.0.0} - /@typescript-eslint/typescript-estree@5.62.0(typescript@5.3.2): + /@typescript-eslint/typescript-estree@5.62.0(typescript@5.4.5): resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -10101,12 +10123,12 @@ packages: globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.0 - tsutils: 3.21.0(typescript@5.3.2) - typescript: 5.3.2 + tsutils: 3.21.0(typescript@5.4.5) + typescript: 5.4.5 transitivePeerDependencies: - supports-color - /@typescript-eslint/typescript-estree@6.0.0(typescript@5.3.2): + /@typescript-eslint/typescript-estree@6.0.0(typescript@5.4.5): resolution: {integrity: sha512-2zq4O7P6YCQADfmJ5OTDQTP3ktajnXIRrYAtHM9ofto/CJZV3QfJ89GEaM2BNGeSr1KgmBuLhEkz5FBkS2RQhQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -10121,12 +10143,12 @@ packages: globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.3.2) - typescript: 5.3.2 + ts-api-utils: 1.3.0(typescript@5.4.5) + typescript: 5.4.5 transitivePeerDependencies: - supports-color - /@typescript-eslint/utils@5.62.0(eslint@8.44.0)(typescript@5.3.2): + /@typescript-eslint/utils@5.62.0(eslint@8.44.0)(typescript@5.4.5): resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -10137,7 +10159,7 @@ packages: '@types/semver': 7.5.8 '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.3.2) + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5) eslint: 8.44.0 eslint-scope: 5.1.1 semver: 7.6.0 @@ -10146,7 +10168,7 @@ packages: - typescript dev: true - /@typescript-eslint/utils@6.0.0(eslint@8.44.0)(typescript@5.3.2): + /@typescript-eslint/utils@6.0.0(eslint@8.44.0)(typescript@5.4.5): resolution: {integrity: sha512-SOr6l4NB6HE4H/ktz0JVVWNXqCJTOo/mHnvIte1ZhBQ0Cvd04x5uKZa3zT6tiodL06zf5xxdK8COiDvPnQ27JQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -10157,7 +10179,7 @@ packages: '@types/semver': 7.5.8 '@typescript-eslint/scope-manager': 6.0.0 '@typescript-eslint/types': 6.0.0 - '@typescript-eslint/typescript-estree': 6.0.0(typescript@5.3.2) + '@typescript-eslint/typescript-estree': 6.0.0(typescript@5.4.5) eslint: 8.44.0 eslint-scope: 5.1.1 semver: 7.6.0 @@ -10857,7 +10879,7 @@ packages: dependencies: '@vue/compiler-ssr': 3.4.21 '@vue/shared': 3.4.21 - vue: 3.4.21(typescript@5.3.2) + vue: 3.4.21(typescript@5.4.5) dev: false /@vue/shared@3.4.21: @@ -11098,9 +11120,9 @@ packages: indent-string: 5.0.0 dev: true - /ai@3.0.12(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4): - resolution: {integrity: sha512-cP/Moag7PcDOE3kA7WU00YS+mQiuPpAxY+uf57lkWwnqSB1K3/RzwnRF+LD1FqgJfCubI4WEbajMPbnnCr8lAg==} - engines: {node: '>=14.6'} + /ai@3.0.31(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4): + resolution: {integrity: sha512-SmwVgBcTLchKTcQjFYRskCkw9H9p/PivUxAQzqIT+aX97kfBr3uBw3nFOH+RKseCsVEMt3w27K2h9n2u0bskZA==} + engines: {node: '>=18'} peerDependencies: react: ^18.2.0 solid-js: ^1.7.7 @@ -11119,10 +11141,14 @@ packages: zod: optional: true dependencies: - eventsource-parser: 1.0.0 + '@ai-sdk/provider': 0.0.2 + '@ai-sdk/provider-utils': 0.0.3(zod@3.22.4) + eventsource-parser: 1.1.2 + json-schema: 0.4.0 jsondiffpatch: 0.6.0 nanoid: 3.3.6 react: 18.2.0 + secure-json-parse: 2.7.0 solid-js: 1.7.8 solid-swr-store: 0.10.7(solid-js@1.7.8)(swr-store@0.10.6) sswr: 2.0.0(svelte@4.2.12) @@ -11130,9 +11156,9 @@ packages: swr: 2.2.0(react@18.2.0) swr-store: 0.10.6 swrv: 1.0.4(vue@3.4.21) - vue: 3.4.21(typescript@5.3.2) + vue: 3.4.21(typescript@5.4.5) zod: 3.22.4 - zod-to-json-schema: 3.22.4(zod@3.22.4) + zod-to-json-schema: 3.22.5(zod@3.22.4) dev: false /ajv-draft-04@1.0.0(ajv@8.12.0): @@ -13844,7 +13870,7 @@ packages: source-map: 0.6.1 dev: true - /eslint-config-next@13.4.9(eslint@8.44.0)(typescript@5.3.2): + /eslint-config-next@13.4.9(eslint@8.44.0)(typescript@5.4.5): resolution: {integrity: sha512-0fLtKRR268NArpqeXXwnLgMXPvF64YESQvptVg+RMLCaijKm3FICN9Y7Jc1p2o+yrWwE4DufJXDM/Vo53D1L7g==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 @@ -13855,7 +13881,7 @@ packages: dependencies: '@next/eslint-plugin-next': 13.4.9 '@rushstack/eslint-patch': 1.7.2 - '@typescript-eslint/parser': 5.62.0(eslint@8.44.0)(typescript@5.3.2) + '@typescript-eslint/parser': 5.62.0(eslint@8.44.0)(typescript@5.4.5) eslint: 8.44.0 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.44.0) @@ -13863,7 +13889,7 @@ packages: eslint-plugin-jsx-a11y: 6.8.0(eslint@8.44.0) eslint-plugin-react: 7.32.2(eslint@8.44.0) eslint-plugin-react-hooks: 5.0.0-canary-7118f5dd7-20230705(eslint@8.44.0) - typescript: 5.3.2 + typescript: 5.4.5 transitivePeerDependencies: - eslint-import-resolver-webpack - supports-color @@ -13950,7 +13976,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.62.0(eslint@8.44.0)(typescript@5.3.2) + '@typescript-eslint/parser': 5.62.0(eslint@8.44.0)(typescript@5.4.5) debug: 3.2.7 eslint: 8.44.0 eslint-import-resolver-node: 0.3.9 @@ -13980,7 +14006,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 6.0.0(eslint@8.44.0)(typescript@5.3.2) + '@typescript-eslint/parser': 6.0.0(eslint@8.44.0)(typescript@5.4.5) debug: 3.2.7 eslint: 8.44.0 eslint-import-resolver-node: 0.3.9 @@ -13998,7 +14024,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 6.0.0(eslint@8.44.0)(typescript@5.3.2) + '@typescript-eslint/parser': 6.0.0(eslint@8.44.0)(typescript@5.4.5) array-includes: 3.1.7 array.prototype.findlastindex: 1.2.4 array.prototype.flat: 1.3.2 @@ -14081,13 +14107,13 @@ packages: string.prototype.matchall: 4.0.10 dev: false - /eslint-plugin-solid@0.12.1(eslint@8.44.0)(typescript@5.3.2): + /eslint-plugin-solid@0.12.1(eslint@8.44.0)(typescript@5.4.5): resolution: {integrity: sha512-fM0sEg9PcS1mcNbWklwc+W/lOv1/XyEwXf53HmFFy4GOA8E3u41h8JW+hc+Vv1m3kh01umKoTalOTET08zKdAQ==} engines: {node: '>=12.0.0'} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - '@typescript-eslint/utils': 5.62.0(eslint@8.44.0)(typescript@5.3.2) + '@typescript-eslint/utils': 5.62.0(eslint@8.44.0)(typescript@5.4.5) eslint: 8.44.0 is-html: 2.0.0 jsx-ast-utils: 3.3.5 @@ -14355,8 +14381,8 @@ packages: engines: {node: '>=0.8.x'} dev: false - /eventsource-parser@1.0.0: - resolution: {integrity: sha512-9jgfSCa3dmEme2ES3mPByGXfgZ87VbP97tng1G2nWwWx6bV2nYxm2AWCrbQjXToSe+yYlqaZNtxffR9IeQr95g==} + /eventsource-parser@1.1.2: + resolution: {integrity: sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==} engines: {node: '>=14.18'} dev: false @@ -16676,6 +16702,10 @@ packages: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} dev: true + /json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + dev: false + /json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -18918,6 +18948,22 @@ packages: - encoding dev: false + /openai@4.38.3: + resolution: {integrity: sha512-mIL9WtrFNOanpx98mJ+X/wkoepcxdqqu0noWFoNQHl/yODQ47YM7NEYda7qp8JfjqpLFVxY9mQhshoS/Fqac0A==} + hasBin: true + dependencies: + '@types/node': 18.11.18 + '@types/node-fetch': 2.6.11 + abort-controller: 3.0.0 + agentkeepalive: 4.5.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + web-streams-polyfill: 3.3.3 + transitivePeerDependencies: + - encoding + dev: false + /openapi-types@12.1.3: resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} dev: true @@ -20758,12 +20804,12 @@ packages: - ts-node dev: true - /rollup-plugin-typescript-paths@1.4.0(typescript@5.3.2): + /rollup-plugin-typescript-paths@1.4.0(typescript@5.4.5): resolution: {integrity: sha512-6EgeLRjTVmymftEyCuYu91XzY5XMB5lR0YrJkeT0D7OG2RGSdbNL+C/hfPIdc/sjMa9Sl5NLsxIr6C/+/5EUpA==} peerDependencies: typescript: '>=3.4' dependencies: - typescript: 5.3.2 + typescript: 5.4.5 dev: true /rollup-pluginutils@2.8.2: @@ -20930,6 +20976,10 @@ packages: resolution: {integrity: sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==} dev: true + /secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + dev: false + /selderee@0.11.0: resolution: {integrity: sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==} dependencies: @@ -21788,7 +21838,7 @@ packages: peerDependencies: vue: '>=3.2.26 < 4' dependencies: - vue: 3.4.21(typescript@5.3.2) + vue: 3.4.21(typescript@5.4.5) dev: false /symbol-observable@1.0.1: @@ -22128,13 +22178,13 @@ packages: /trough@2.2.0: resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} - /ts-api-utils@1.3.0(typescript@5.3.2): + /ts-api-utils@1.3.0(typescript@5.4.5): resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} peerDependencies: typescript: '>=4.2.0' dependencies: - typescript: 5.3.2 + typescript: 5.4.5 /ts-easing@0.2.0: resolution: {integrity: sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==} @@ -22143,7 +22193,7 @@ packages: /ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - /ts-jest@29.0.5(@babel/core@7.22.9)(esbuild@0.15.18)(jest@29.4.1)(typescript@5.3.2): + /ts-jest@29.0.5(@babel/core@7.22.9)(esbuild@0.15.18)(jest@29.4.1)(typescript@5.4.5): resolution: {integrity: sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -22174,11 +22224,11 @@ packages: lodash.memoize: 4.1.2 make-error: 1.3.6 semver: 7.6.0 - typescript: 5.3.2 + typescript: 5.4.5 yargs-parser: 21.1.1 dev: true - /tsconfck@3.0.3(typescript@5.3.2): + /tsconfck@3.0.3(typescript@5.4.5): resolution: {integrity: sha512-4t0noZX9t6GcPTfBAbIbbIU4pfpCwh0ueq3S4O/5qXI1VwK1outmxhe9dOiEWqMz3MW2LKgDTpqWV+37IWuVbA==} engines: {node: ^18 || >=20} hasBin: true @@ -22188,7 +22238,7 @@ packages: typescript: optional: true dependencies: - typescript: 5.3.2 + typescript: 5.4.5 dev: false /tsconfig-paths@3.15.0: @@ -22210,7 +22260,7 @@ packages: /tslib@2.6.0: resolution: {integrity: sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==} - /tsup@6.5.0(postcss@8.4.21)(typescript@5.3.2): + /tsup@6.5.0(postcss@8.4.21)(typescript@5.4.5): resolution: {integrity: sha512-36u82r7rYqRHFkD15R20Cd4ercPkbYmuvRkz3Q1LCm5BsiFNUgpo36zbjVhCOgvjyxNBWNKHsaD5Rl8SykfzNA==} engines: {node: '>=14'} hasBin: true @@ -22241,13 +22291,13 @@ packages: source-map: 0.8.0-beta.0 sucrase: 3.35.0 tree-kill: 1.2.2 - typescript: 5.3.2 + typescript: 5.4.5 transitivePeerDependencies: - supports-color - ts-node dev: true - /tsup@6.5.0(typescript@5.3.2): + /tsup@6.5.0(typescript@5.4.5): resolution: {integrity: sha512-36u82r7rYqRHFkD15R20Cd4ercPkbYmuvRkz3Q1LCm5BsiFNUgpo36zbjVhCOgvjyxNBWNKHsaD5Rl8SykfzNA==} engines: {node: '>=14'} hasBin: true @@ -22277,20 +22327,20 @@ packages: source-map: 0.8.0-beta.0 sucrase: 3.35.0 tree-kill: 1.2.2 - typescript: 5.3.2 + typescript: 5.4.5 transitivePeerDependencies: - supports-color - ts-node dev: true - /tsutils@3.21.0(typescript@5.3.2): + /tsutils@3.21.0(typescript@5.4.5): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} peerDependencies: typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' dependencies: tslib: 1.14.1 - typescript: 5.3.2 + typescript: 5.4.5 /tsx@3.12.7: resolution: {integrity: sha512-C2Ip+jPmqKd1GWVQDvz/Eyc6QJbGfE7NrR3fx5BpEHMZsEHoIxHL1j+lKdGobr8ovEyqeNkPLSKp6SCSOt7gmw==} @@ -22470,8 +22520,8 @@ packages: hasBin: true dev: false - /typescript@5.3.2: - resolution: {integrity: sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==} + /typescript@5.4.5: + resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} engines: {node: '>=14.17'} hasBin: true @@ -22914,7 +22964,7 @@ packages: vfile-message: 4.0.2 dev: false - /vite-tsconfig-paths@4.3.1(typescript@5.3.2)(vite@4.5.2): + /vite-tsconfig-paths@4.3.1(typescript@5.4.5)(vite@4.5.2): resolution: {integrity: sha512-cfgJwcGOsIxXOLU/nELPny2/LUD/lcf1IbfyeKTv2bsupVbTH/xpFtdQlBmIP1GEK2CjjLxYhFfB+QODFAx5aw==} peerDependencies: vite: '*' @@ -22924,7 +22974,7 @@ packages: dependencies: debug: 4.3.4 globrex: 0.1.2 - tsconfck: 3.0.3(typescript@5.3.2) + tsconfck: 3.0.3(typescript@5.4.5) vite: 4.5.2(@types/node@20.4.2) transitivePeerDependencies: - supports-color @@ -22975,7 +23025,7 @@ packages: resolution: {integrity: sha512-Cl65diFGxz7gpwbav10HqiY/eVYTO1sjQpmRmV991Bj7wAoOAjGQ97PpQcXorDE2Uc4hnGWLY17xme+5t6MlSg==} dev: true - /vue@3.4.21(typescript@5.3.2): + /vue@3.4.21(typescript@5.4.5): resolution: {integrity: sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==} peerDependencies: typescript: '*' @@ -22988,7 +23038,7 @@ packages: '@vue/runtime-dom': 3.4.21 '@vue/server-renderer': 3.4.21(vue@3.4.21) '@vue/shared': 3.4.21 - typescript: 5.3.2 + typescript: 5.4.5 dev: false /w3c-keyname@2.2.8: @@ -23423,8 +23473,8 @@ packages: zod: 3.22.4 dev: false - /zod-to-json-schema@3.22.4(zod@3.22.4): - resolution: {integrity: sha512-2Ed5dJ+n/O3cU383xSY28cuVi0BCQhF8nYqWU5paEpl7fVdqdAmiLdqLyfblbNdfOFwFfi/mqU4O1pwc60iBhQ==} + /zod-to-json-schema@3.22.5(zod@3.22.4): + resolution: {integrity: sha512-+akaPo6a0zpVCCseDed504KBJUQpEW5QZw7RMneNmKw+fGaML1Z9tUNLnHHAC8x6dzVRO1eB2oEMyZRnuBZg7Q==} peerDependencies: zod: ^3.22.4 dependencies: