2023-12-22 09:13:53 +01:00
import { z } from '../../zod'
2022-11-29 10:02:40 +01:00
import {
2023-12-22 09:13:53 +01:00
buttonsInputSchemas ,
dateInputSchema ,
emailInputSchema ,
fileInputBlockSchemas ,
numberInputSchema ,
2022-12-22 17:02:34 +01:00
paymentInputRuntimeOptionsSchema ,
2023-12-22 09:13:53 +01:00
paymentInputSchema ,
phoneNumberInputBlockSchema ,
pictureChoiceBlockSchemas ,
ratingInputBlockSchema ,
textInputSchema ,
urlInputSchema ,
2023-08-24 07:48:30 +02:00
} from '../blocks'
import { logSchema } from '../result'
2023-12-22 09:13:53 +01:00
import { settingsSchema , themeSchema } from '../typebot'
2023-01-25 11:27:47 +01:00
import {
imageBubbleContentSchema ,
videoBubbleContentSchema ,
audioBubbleContentSchema ,
embedBubbleContentSchema ,
2023-08-24 07:48:30 +02:00
} from '../blocks/bubbles'
import { sessionStateSchema } from './sessionState'
import { dynamicThemeSchema } from './shared'
2023-08-24 09:11:10 +02:00
import { preprocessTypebot } from '../typebot/helpers/preprocessTypebot'
2023-11-08 15:34:16 +01:00
import { typebotV5Schema , typebotV6Schema } from '../typebot/typebot'
import { BubbleBlockType } from '../blocks/bubbles/constants'
2023-12-22 09:13:53 +01:00
import { clientSideActionSchema } from './clientSideAction'
2024-04-18 09:38:22 +02:00
import { ChatSession as ChatSessionFromPrisma } from '@typebot.io/prisma'
2022-11-29 10:02:40 +01:00
2023-03-07 14:41:57 +01:00
const chatSessionSchema = z . object ( {
id : z.string ( ) ,
createdAt : z.date ( ) ,
updatedAt : z.date ( ) ,
state : sessionStateSchema ,
2024-04-18 09:38:22 +02:00
isReplying : z
. boolean ( )
. nullable ( )
. describe (
'Used in WhatsApp runtime to avoid concurrent replies from the bot'
) ,
} ) satisfies z . ZodType < ChatSessionFromPrisma , z.ZodTypeDef , unknown >
2023-11-13 15:27:36 +01:00
export type ChatSession = z . infer < typeof chatSessionSchema >
2022-11-29 10:02:40 +01:00
2023-12-22 09:13:53 +01:00
const textMessageSchema = z
. object ( {
type : z . literal ( BubbleBlockType . TEXT ) ,
2024-05-23 16:30:56 +02:00
content : z.discriminatedUnion ( 'type' , [
z . object ( {
type : z . literal ( 'richText' ) ,
richText : z.any ( ) ,
} ) ,
z . object ( {
type : z . literal ( 'markdown' ) ,
markdown : z.string ( ) ,
} ) ,
] ) ,
2023-12-22 09:13:53 +01:00
} )
. openapi ( {
title : 'Text' ,
ref : 'textMessage' ,
} )
2022-12-22 17:02:34 +01:00
2023-12-22 09:13:53 +01:00
const imageMessageSchema = z
. object ( {
type : z . enum ( [ BubbleBlockType . IMAGE ] ) ,
content : imageBubbleContentSchema ,
} )
. openapi ( {
title : 'Image' ,
ref : 'imageMessage' ,
} )
2022-11-29 10:02:40 +01:00
2023-12-22 09:13:53 +01:00
const videoMessageSchema = z
. object ( {
type : z . enum ( [ BubbleBlockType . VIDEO ] ) ,
content : videoBubbleContentSchema ,
} )
. openapi ( {
title : 'Video' ,
ref : 'videoMessage' ,
} )
2022-12-22 17:02:34 +01:00
2023-12-22 09:13:53 +01:00
const audioMessageSchema = z
. object ( {
type : z . enum ( [ BubbleBlockType . AUDIO ] ) ,
content : audioBubbleContentSchema ,
} )
. openapi ( {
title : 'Audio' ,
ref : 'audioMessage' ,
} )
2022-12-22 17:02:34 +01:00
2023-12-22 09:13:53 +01:00
const embedMessageSchema = z
. object ( {
type : z . enum ( [ BubbleBlockType . EMBED ] ) ,
content : embedBubbleContentSchema
. omit ( {
height : true ,
} )
. merge ( z . object ( { height : z.number ( ) . optional ( ) } ) ) ,
} )
. openapi ( {
title : 'Embed' ,
ref : 'embedMessage' ,
} )
2022-12-22 17:02:34 +01:00
2023-12-13 10:22:02 +01:00
const displayEmbedBubbleSchema = z . object ( {
2024-04-18 13:46:49 +02:00
url : z.string ( ) . optional ( ) ,
2023-12-13 10:22:02 +01:00
waitForEventFunction : z
. object ( {
args : z.record ( z . string ( ) , z . unknown ( ) ) ,
content : z.string ( ) ,
} )
. optional ( ) ,
initFunction : z.object ( {
args : z.record ( z . string ( ) , z . unknown ( ) ) ,
content : z.string ( ) ,
} ) ,
} )
2023-12-22 09:13:53 +01:00
const customEmbedSchema = z
. object ( {
type : z . literal ( 'custom-embed' ) ,
content : displayEmbedBubbleSchema ,
} )
. openapi ( {
title : 'Custom embed' ,
ref : 'customEmbedMessage' ,
} )
2023-12-13 10:22:02 +01:00
export type CustomEmbedBubble = z . infer < typeof customEmbedSchema >
2023-11-13 15:27:36 +01:00
export const chatMessageSchema = z
2023-01-27 10:54:59 +01:00
. object ( { id : z.string ( ) } )
. and (
2023-03-14 16:42:12 +01:00
z . discriminatedUnion ( 'type' , [
textMessageSchema ,
imageMessageSchema ,
videoMessageSchema ,
audioMessageSchema ,
embedMessageSchema ,
2023-12-13 10:22:02 +01:00
customEmbedSchema ,
2023-03-14 16:42:12 +01:00
] )
2023-01-27 10:54:59 +01:00
)
2023-11-13 15:27:36 +01:00
export type ChatMessage = z . infer < typeof chatMessageSchema >
2022-11-29 10:02:40 +01:00
2023-11-08 15:34:16 +01:00
const startTypebotPick = {
version : true ,
id : true ,
groups : true ,
events : true ,
edges : true ,
variables : true ,
settings : true ,
theme : true ,
} as const
2023-08-24 09:11:10 +02:00
export const startTypebotSchema = z . preprocess (
preprocessTypebot ,
2023-11-08 15:34:16 +01:00
z . discriminatedUnion ( 'version' , [
2023-12-22 09:13:53 +01:00
typebotV5Schema . _def . schema . pick ( startTypebotPick ) . openapi ( {
title : 'Typebot V5' ,
ref : 'typebotV5' ,
} ) ,
typebotV6Schema . pick ( startTypebotPick ) . openapi ( {
title : 'Typebot V6' ,
ref : 'typebotV6' ,
} ) ,
2023-11-08 15:34:16 +01:00
] )
2023-08-24 09:11:10 +02:00
)
2023-11-13 15:27:36 +01:00
export type StartTypebot = z . infer < typeof startTypebotSchema >
2023-01-16 12:13:21 +01:00
2023-11-13 15:27:36 +01:00
export const chatLogSchema = logSchema
2023-06-16 19:26:29 +02:00
. pick ( {
status : true ,
description : true ,
} )
. merge ( z . object ( { details : z.unknown ( ) . optional ( ) } ) )
2023-11-13 15:27:36 +01:00
export type ChatLog = z . infer < typeof chatLogSchema >
2023-06-16 19:26:29 +02:00
2023-11-13 15:27:36 +01:00
export const startChatInputSchema = z . object ( {
2023-12-22 09:13:53 +01:00
publicId : z
. string ( )
. describe (
"[Where to find my bot's public ID?](../how-to#how-to-find-my-publicid)"
) ,
message : z
. string ( )
. optional ( )
. describe (
"Only provide it if your flow starts with an input block and you'd like to directly provide an answer to it."
) ,
isStreamEnabled : z
. boolean ( )
. optional ( )
. default ( false )
. describe (
'If enabled, you will be required to stream OpenAI completions on a client and send the generated response back to the API.'
) ,
2023-11-13 15:27:36 +01:00
resultId : z
2022-12-22 17:02:34 +01:00
. string ( )
. optional ( )
2023-11-13 15:27:36 +01:00
. describe ( "Provide it if you'd like to overwrite an existing result." ) ,
isOnlyRegistering : z
. boolean ( )
. optional ( )
2023-12-22 09:13:53 +01:00
. default ( false )
2022-12-22 17:02:34 +01:00
. describe (
2023-11-13 15:27:36 +01:00
'If set to `true`, it will only register the session and not start the bot. This is used for 3rd party chat platforms as it can require a session to be registered before sending the first message.'
2022-12-22 17:02:34 +01:00
) ,
2023-11-13 15:27:36 +01:00
prefilledVariables : z
. record ( z . unknown ( ) )
2022-12-22 17:02:34 +01:00
. optional ( )
. describe (
2023-12-22 09:13:53 +01:00
'[More info about prefilled variables.](../../editor/variables#prefilled-variables)'
)
. openapi ( {
example : {
'First name' : 'John' ,
Email : 'john@gmail.com' ,
} ,
} ) ,
2024-05-23 16:30:56 +02:00
textBubbleContentFormat : z.enum ( [ 'richText' , 'markdown' ] ) . default ( 'richText' ) ,
2023-11-13 15:27:36 +01:00
} )
export type StartChatInput = z . infer < typeof startChatInputSchema >
export const startFromSchema = z . discriminatedUnion ( 'type' , [
z . object ( {
type : z . literal ( 'group' ) ,
groupId : z.string ( ) ,
} ) ,
z . object ( {
type : z . literal ( 'event' ) ,
eventId : z.string ( ) ,
} ) ,
] )
export type StartFrom = z . infer < typeof startFromSchema >
export const startPreviewChatInputSchema = z . object ( {
2023-12-22 09:13:53 +01:00
typebotId : z
. string ( )
. describe (
"[Where to find my bot's ID?](../how-to#how-to-find-my-typebotid)"
) ,
2024-03-21 10:23:23 +01:00
isStreamEnabled : z.boolean ( ) . optional ( ) . default ( false ) ,
2023-11-13 15:27:36 +01:00
message : z.string ( ) . optional ( ) ,
isOnlyRegistering : z
. boolean ( )
. optional ( )
. describe (
'If set to `true`, it will only register the session and not start the bot. This is used for 3rd party chat platforms as it can require a session to be registered before sending the first message.'
2024-03-21 10:23:23 +01:00
)
. default ( false ) ,
2023-11-13 15:27:36 +01:00
typebot : startTypebotSchema
2023-06-16 19:26:29 +02:00
. optional ( )
2023-11-13 15:27:36 +01:00
. describe (
'If set, it will override the typebot that is used to start the chat.'
) ,
startFrom : startFromSchema.optional ( ) ,
2024-02-28 14:49:04 +01:00
prefilledVariables : z
. record ( z . unknown ( ) )
. optional ( )
. describe (
'[More info about prefilled variables.](../../editor/variables#prefilled-variables)'
)
. openapi ( {
example : {
'First name' : 'John' ,
Email : 'john@gmail.com' ,
} ,
} ) ,
2024-05-15 14:24:55 +02:00
sessionId : z
. string ( )
. optional ( )
. describe (
'If provided, will be used as the session ID and will overwrite any existing session with the same ID.'
) ,
2024-05-23 16:30:56 +02:00
textBubbleContentFormat : z.enum ( [ 'richText' , 'markdown' ] ) . default ( 'richText' ) ,
2022-12-22 17:02:34 +01:00
} )
2023-11-13 15:27:36 +01:00
export type StartPreviewChatInput = z . infer < typeof startPreviewChatInputSchema >
2022-12-22 17:02:34 +01:00
2023-11-13 15:27:36 +01:00
export const runtimeOptionsSchema = paymentInputRuntimeOptionsSchema . optional ( )
export type RuntimeOptions = z . infer < typeof runtimeOptionsSchema >
2022-12-22 17:02:34 +01:00
2023-11-08 15:34:16 +01:00
const typebotInChatReplyPick = {
version : true ,
id : true ,
groups : true ,
edges : true ,
variables : true ,
settings : true ,
theme : true ,
} as const
export const typebotInChatReply = z . preprocess (
preprocessTypebot ,
z . discriminatedUnion ( 'version' , [
typebotV5Schema . _def . schema . pick ( typebotInChatReplyPick ) ,
typebotV6Schema . pick ( typebotInChatReplyPick ) ,
] )
)
2023-11-13 15:27:36 +01:00
const chatResponseBaseSchema = z . object ( {
lastMessageNewFormat : z
. string ( )
. optional ( )
. describe (
2023-12-22 09:13:53 +01:00
'The sent message is validated and formatted on the backend. For example, if for a date input you replied something like `tomorrow`, the backend will convert it to a date string. This field returns the formatted message.'
2023-11-13 15:27:36 +01:00
) ,
2022-12-22 17:02:34 +01:00
messages : z.array ( chatMessageSchema ) ,
2023-05-04 09:20:30 -04:00
input : z
2023-11-08 15:34:16 +01:00
. union ( [
2023-12-22 09:13:53 +01:00
z . discriminatedUnion ( 'type' , [
textInputSchema ,
buttonsInputSchemas . v6 ,
emailInputSchema ,
numberInputSchema ,
urlInputSchema ,
phoneNumberInputBlockSchema ,
dateInputSchema ,
paymentInputSchema ,
ratingInputBlockSchema ,
fileInputBlockSchemas . v6 ,
pictureChoiceBlockSchemas . v6 ,
] ) ,
z . discriminatedUnion ( 'type' , [
buttonsInputSchemas . v5 ,
fileInputBlockSchemas . v5 ,
pictureChoiceBlockSchemas . v5 ,
] ) ,
2023-11-08 15:34:16 +01:00
] )
2023-12-22 10:24:33 +01:00
. and (
z . object ( {
prefilledValue : z.string ( ) . optional ( ) ,
runtimeOptions : runtimeOptionsSchema.optional ( ) ,
} )
)
2022-12-22 17:02:34 +01:00
. optional ( ) ,
2023-12-22 09:13:53 +01:00
clientSideActions : z
. array ( clientSideActionSchema )
. optional ( )
. describe ( 'Actions to execute on the client side' ) ,
logs : z
. array ( chatLogSchema )
. optional ( )
. describe ( 'Logs that were saved during the last execution' ) ,
dynamicTheme : dynamicThemeSchema
. optional ( )
. describe (
'If the typebot contains dynamic avatars, dynamicTheme returns the new avatar URLs whenever their variables are updated.'
) ,
2024-02-23 08:31:14 +01:00
progress : z
. number ( )
. optional ( )
. describe (
'If progress bar is enabled, this field will return a number between 0 and 100 indicating the current progress based on the longest remaining path of the flow.'
) ,
2023-11-13 15:27:36 +01:00
} )
2023-12-22 09:13:53 +01:00
export const startChatResponseSchema = z
. object ( {
sessionId : z
. string ( )
. describe ( 'To save and use for /continueChat requests.' ) ,
2023-12-23 10:13:27 +01:00
resultId : z.string ( ) . optional ( ) ,
2023-12-22 09:13:53 +01:00
typebot : z.object ( {
id : z.string ( ) ,
theme : themeSchema ,
settings : settingsSchema ,
} ) ,
} )
. merge ( chatResponseBaseSchema )
2023-11-13 15:27:36 +01:00
export type StartChatResponse = z . infer < typeof startChatResponseSchema >
2022-11-29 10:02:40 +01:00
2023-11-13 15:27:36 +01:00
export const startPreviewChatResponseSchema = startChatResponseSchema . omit ( {
resultId : true ,
} )
2023-08-24 07:48:30 +02:00
2023-11-13 15:27:36 +01:00
export const continueChatResponseSchema = chatResponseBaseSchema
export type ContinueChatResponse = z . infer < typeof continueChatResponseSchema >