⚡ Improve new bot engine client side actions
We make sure to save client side actions in an array that will be executed sequentially
This commit is contained in:
@ -108,17 +108,18 @@ const deleteOutgoingEdgeIdProps = (
|
|||||||
const block = typebot.groups[fromGroupIndex].blocks[fromBlockIndex] as
|
const block = typebot.groups[fromGroupIndex].blocks[fromBlockIndex] as
|
||||||
| Block
|
| Block
|
||||||
| undefined
|
| undefined
|
||||||
|
if (!block) return
|
||||||
const fromItemIndex =
|
const fromItemIndex =
|
||||||
edge.from.itemId && block && blockHasItems(block)
|
edge.from.itemId && blockHasItems(block)
|
||||||
? block.items.findIndex(byId(edge.from.itemId))
|
? block.items.findIndex(byId(edge.from.itemId))
|
||||||
: -1
|
: -1
|
||||||
if (fromBlockIndex !== -1)
|
if (fromItemIndex !== -1) {
|
||||||
typebot.groups[fromGroupIndex].blocks[fromBlockIndex].outgoingEdgeId =
|
;(
|
||||||
undefined
|
|
||||||
if (fromItemIndex !== -1)
|
|
||||||
(
|
|
||||||
typebot.groups[fromGroupIndex].blocks[fromBlockIndex] as BlockWithItems
|
typebot.groups[fromGroupIndex].blocks[fromBlockIndex] as BlockWithItems
|
||||||
).items[fromItemIndex].outgoingEdgeId = undefined
|
).items[fromItemIndex].outgoingEdgeId = undefined
|
||||||
|
} else if (fromBlockIndex !== -1)
|
||||||
|
typebot.groups[fromGroupIndex].blocks[fromBlockIndex].outgoingEdgeId =
|
||||||
|
undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export const cleanUpEdgeDraft = (
|
export const cleanUpEdgeDraft = (
|
||||||
|
@ -56,21 +56,23 @@ export const executeChatwootBlock = (
|
|||||||
const chatwootCode = parseChatwootOpenCode(block.options)
|
const chatwootCode = parseChatwootOpenCode(block.options)
|
||||||
return {
|
return {
|
||||||
outgoingEdgeId: block.outgoingEdgeId,
|
outgoingEdgeId: block.outgoingEdgeId,
|
||||||
integrations: {
|
clientSideActions: [
|
||||||
chatwoot: {
|
{
|
||||||
codeToExecute: {
|
chatwoot: {
|
||||||
content: parseVariables(variables, { fieldToParse: 'id' })(
|
codeToExecute: {
|
||||||
chatwootCode
|
content: parseVariables(variables, { fieldToParse: 'id' })(
|
||||||
),
|
chatwootCode
|
||||||
args: extractVariablesFromText(variables)(chatwootCode).map(
|
),
|
||||||
(variable) => ({
|
args: extractVariablesFromText(variables)(chatwootCode).map(
|
||||||
id: variable.id,
|
(variable) => ({
|
||||||
value: parseCorrectValueType(variable.value),
|
id: variable.id,
|
||||||
})
|
value: parseCorrectValueType(variable.value),
|
||||||
),
|
})
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
],
|
||||||
logs: isPreview
|
logs: isPreview
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,9 @@ export const executeGoogleAnalyticsBlock = (
|
|||||||
block: GoogleAnalyticsBlock
|
block: GoogleAnalyticsBlock
|
||||||
): ExecuteIntegrationResponse => ({
|
): ExecuteIntegrationResponse => ({
|
||||||
outgoingEdgeId: block.outgoingEdgeId,
|
outgoingEdgeId: block.outgoingEdgeId,
|
||||||
integrations: {
|
clientSideActions: [
|
||||||
googleAnalytics: deepParseVariable(variables)(block.options),
|
{
|
||||||
},
|
googleAnalytics: deepParseVariable(variables)(block.options),
|
||||||
|
},
|
||||||
|
],
|
||||||
})
|
})
|
||||||
|
@ -10,7 +10,6 @@ export const insertRow = async (
|
|||||||
options,
|
options,
|
||||||
}: { outgoingEdgeId?: string; options: GoogleSheetsInsertRowOptions }
|
}: { outgoingEdgeId?: string; options: GoogleSheetsInsertRowOptions }
|
||||||
): Promise<ExecuteIntegrationResponse> => {
|
): Promise<ExecuteIntegrationResponse> => {
|
||||||
console.log('insertRow', options)
|
|
||||||
if (!options.cellsToInsert || !options.sheetId) return { outgoingEdgeId }
|
if (!options.cellsToInsert || !options.sheetId) return { outgoingEdgeId }
|
||||||
|
|
||||||
let log: ReplyLog | undefined
|
let log: ReplyLog | undefined
|
||||||
|
@ -24,11 +24,13 @@ export const executeCode = (
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
outgoingEdgeId: block.outgoingEdgeId,
|
outgoingEdgeId: block.outgoingEdgeId,
|
||||||
logic: {
|
clientSideActions: [
|
||||||
codeToExecute: {
|
{
|
||||||
content,
|
codeToExecute: {
|
||||||
args,
|
content,
|
||||||
|
args,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,11 @@ export const executeRedirect = (
|
|||||||
if (!block.options?.url) return { outgoingEdgeId: block.outgoingEdgeId }
|
if (!block.options?.url) return { outgoingEdgeId: block.outgoingEdgeId }
|
||||||
const formattedUrl = sanitizeUrl(parseVariables(variables)(block.options.url))
|
const formattedUrl = sanitizeUrl(parseVariables(variables)(block.options.url))
|
||||||
return {
|
return {
|
||||||
logic: {
|
clientSideActions: [
|
||||||
redirect: { url: formattedUrl, isNewTab: block.options.isNewTab },
|
{
|
||||||
},
|
redirect: { url: formattedUrl, isNewTab: block.options.isNewTab },
|
||||||
|
},
|
||||||
|
],
|
||||||
outgoingEdgeId: block.outgoingEdgeId,
|
outgoingEdgeId: block.outgoingEdgeId,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@ export const sendMessageProcedure = publicProcedure
|
|||||||
resultId,
|
resultId,
|
||||||
dynamicTheme,
|
dynamicTheme,
|
||||||
logs,
|
logs,
|
||||||
|
clientSideActions,
|
||||||
} = await startSession(startParams)
|
} = await startSession(startParams)
|
||||||
return {
|
return {
|
||||||
sessionId,
|
sessionId,
|
||||||
@ -63,9 +64,10 @@ export const sendMessageProcedure = publicProcedure
|
|||||||
resultId,
|
resultId,
|
||||||
dynamicTheme,
|
dynamicTheme,
|
||||||
logs,
|
logs,
|
||||||
|
clientSideActions,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const { messages, input, logic, newSessionState, integrations, logs } =
|
const { messages, input, clientSideActions, newSessionState, logs } =
|
||||||
await continueBotFlow(session.state)(message)
|
await continueBotFlow(session.state)(message)
|
||||||
|
|
||||||
await prisma.chatSession.updateMany({
|
await prisma.chatSession.updateMany({
|
||||||
@ -78,8 +80,7 @@ export const sendMessageProcedure = publicProcedure
|
|||||||
return {
|
return {
|
||||||
messages,
|
messages,
|
||||||
input,
|
input,
|
||||||
logic,
|
clientSideActions,
|
||||||
integrations,
|
|
||||||
dynamicTheme: parseDynamicThemeReply(newSessionState),
|
dynamicTheme: parseDynamicThemeReply(newSessionState),
|
||||||
logs,
|
logs,
|
||||||
}
|
}
|
||||||
@ -133,7 +134,7 @@ const startSession = async (startParams?: StartParams) => {
|
|||||||
const {
|
const {
|
||||||
messages,
|
messages,
|
||||||
input,
|
input,
|
||||||
logic,
|
clientSideActions,
|
||||||
newSessionState: newInitialState,
|
newSessionState: newInitialState,
|
||||||
logs,
|
logs,
|
||||||
} = await startBotFlow(initialState, startParams.startGroupId)
|
} = await startBotFlow(initialState, startParams.startGroupId)
|
||||||
@ -141,7 +142,7 @@ const startSession = async (startParams?: StartParams) => {
|
|||||||
if (!input)
|
if (!input)
|
||||||
return {
|
return {
|
||||||
messages,
|
messages,
|
||||||
logic,
|
clientSideActions,
|
||||||
typebot: {
|
typebot: {
|
||||||
id: typebot.id,
|
id: typebot.id,
|
||||||
settings: deepParseVariable(newInitialState.typebot.variables)(
|
settings: deepParseVariable(newInitialState.typebot.variables)(
|
||||||
@ -183,7 +184,7 @@ const startSession = async (startParams?: StartParams) => {
|
|||||||
},
|
},
|
||||||
messages,
|
messages,
|
||||||
input,
|
input,
|
||||||
logic,
|
clientSideActions,
|
||||||
dynamicTheme: parseDynamicThemeReply(newInitialState),
|
dynamicTheme: parseDynamicThemeReply(newInitialState),
|
||||||
logs,
|
logs,
|
||||||
} satisfies ChatReply
|
} satisfies ChatReply
|
||||||
|
@ -25,8 +25,8 @@ export const executeGroup =
|
|||||||
group: Group
|
group: Group
|
||||||
): Promise<ChatReply & { newSessionState: SessionState }> => {
|
): Promise<ChatReply & { newSessionState: SessionState }> => {
|
||||||
const messages: ChatReply['messages'] = currentReply?.messages ?? []
|
const messages: ChatReply['messages'] = currentReply?.messages ?? []
|
||||||
let logic: ChatReply['logic'] = currentReply?.logic
|
let clientSideActions: ChatReply['clientSideActions'] =
|
||||||
let integrations: ChatReply['integrations'] = currentReply?.integrations
|
currentReply?.clientSideActions
|
||||||
let logs: ChatReply['logs'] = currentReply?.logs
|
let logs: ChatReply['logs'] = currentReply?.logs
|
||||||
let nextEdgeId = null
|
let nextEdgeId = null
|
||||||
|
|
||||||
@ -59,8 +59,7 @@ export const executeGroup =
|
|||||||
blockId: block.id,
|
blockId: block.id,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
logic,
|
clientSideActions,
|
||||||
integrations,
|
|
||||||
logs,
|
logs,
|
||||||
}
|
}
|
||||||
const executionResponse = isLogicBlock(block)
|
const executionResponse = isLogicBlock(block)
|
||||||
@ -70,10 +69,14 @@ export const executeGroup =
|
|||||||
: null
|
: null
|
||||||
|
|
||||||
if (!executionResponse) continue
|
if (!executionResponse) continue
|
||||||
if ('logic' in executionResponse && executionResponse.logic)
|
if (
|
||||||
logic = { ...logic, ...executionResponse.logic }
|
'clientSideActions' in executionResponse &&
|
||||||
if ('integrations' in executionResponse && executionResponse.integrations)
|
executionResponse.clientSideActions
|
||||||
integrations = { ...integrations, ...executionResponse.integrations }
|
)
|
||||||
|
clientSideActions = [
|
||||||
|
...(clientSideActions ?? []),
|
||||||
|
...executionResponse.clientSideActions,
|
||||||
|
]
|
||||||
if (executionResponse.logs)
|
if (executionResponse.logs)
|
||||||
logs = [...(logs ?? []), ...executionResponse.logs]
|
logs = [...(logs ?? []), ...executionResponse.logs]
|
||||||
if (executionResponse.newSessionState)
|
if (executionResponse.newSessionState)
|
||||||
@ -85,20 +88,19 @@ export const executeGroup =
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!nextEdgeId)
|
if (!nextEdgeId)
|
||||||
return { messages, newSessionState, logic, integrations, logs }
|
return { messages, newSessionState, clientSideActions, logs }
|
||||||
|
|
||||||
const nextGroup = getNextGroup(newSessionState)(nextEdgeId)
|
const nextGroup = getNextGroup(newSessionState)(nextEdgeId)
|
||||||
|
|
||||||
if (nextGroup?.updatedContext) newSessionState = nextGroup.updatedContext
|
if (nextGroup?.updatedContext) newSessionState = nextGroup.updatedContext
|
||||||
|
|
||||||
if (!nextGroup) {
|
if (!nextGroup) {
|
||||||
return { messages, newSessionState, logic, integrations, logs }
|
return { messages, newSessionState, clientSideActions, logs }
|
||||||
}
|
}
|
||||||
|
|
||||||
return executeGroup(newSessionState, {
|
return executeGroup(newSessionState, {
|
||||||
messages,
|
messages,
|
||||||
logic,
|
clientSideActions,
|
||||||
integrations,
|
|
||||||
logs,
|
logs,
|
||||||
})(nextGroup.group)
|
})(nextGroup.group)
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,9 @@ export type EdgeId = string
|
|||||||
export type ExecuteLogicResponse = {
|
export type ExecuteLogicResponse = {
|
||||||
outgoingEdgeId: EdgeId | undefined
|
outgoingEdgeId: EdgeId | undefined
|
||||||
newSessionState?: SessionState
|
newSessionState?: SessionState
|
||||||
} & Pick<ChatReply, 'logic' | 'logs'>
|
} & Pick<ChatReply, 'clientSideActions' | 'logs'>
|
||||||
|
|
||||||
export type ExecuteIntegrationResponse = {
|
export type ExecuteIntegrationResponse = {
|
||||||
outgoingEdgeId: EdgeId | undefined
|
outgoingEdgeId: EdgeId | undefined
|
||||||
newSessionState?: SessionState
|
newSessionState?: SessionState
|
||||||
} & Pick<ChatReply, 'integrations' | 'logs'>
|
} & Pick<ChatReply, 'clientSideActions' | 'logs'>
|
||||||
|
@ -12,14 +12,17 @@ type Props = Pick<ChatReply, 'messages' | 'input'> & {
|
|||||||
context: BotContext
|
context: BotContext
|
||||||
onScrollToBottom: () => void
|
onScrollToBottom: () => void
|
||||||
onSubmit: (input: string) => void
|
onSubmit: (input: string) => void
|
||||||
onEnd?: () => void
|
|
||||||
onSkip: () => void
|
onSkip: () => void
|
||||||
|
onAllBubblesDisplayed: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ChatChunk = (props: Props) => {
|
export const ChatChunk = (props: Props) => {
|
||||||
const [displayedMessageIndex, setDisplayedMessageIndex] = createSignal(0)
|
const [displayedMessageIndex, setDisplayedMessageIndex] = createSignal(0)
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
|
if (props.messages.length === 0) {
|
||||||
|
props.onAllBubblesDisplayed()
|
||||||
|
}
|
||||||
props.onScrollToBottom()
|
props.onScrollToBottom()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -30,8 +33,9 @@ export const ChatChunk = (props: Props) => {
|
|||||||
: displayedMessageIndex() + 1
|
: displayedMessageIndex() + 1
|
||||||
)
|
)
|
||||||
props.onScrollToBottom()
|
props.onScrollToBottom()
|
||||||
if (!props.input && displayedMessageIndex() === props.messages.length)
|
if (displayedMessageIndex() === props.messages.length) {
|
||||||
return props.onEnd?.()
|
props.onAllBubblesDisplayed()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -3,8 +3,8 @@ import { createEffect, createSignal, For } from 'solid-js'
|
|||||||
import { sendMessageQuery } from '@/queries/sendMessageQuery'
|
import { sendMessageQuery } from '@/queries/sendMessageQuery'
|
||||||
import { ChatChunk } from './ChatChunk'
|
import { ChatChunk } from './ChatChunk'
|
||||||
import { BotContext, InitialChatReply } from '@/types'
|
import { BotContext, InitialChatReply } from '@/types'
|
||||||
import { executeIntegrations } from '@/utils/executeIntegrations'
|
import { isNotDefined } from 'utils'
|
||||||
import { executeLogic } from '@/utils/executeLogic'
|
import { executeClientSideAction } from '@/utils/executeClientSideActions'
|
||||||
|
|
||||||
const parseDynamicTheme = (
|
const parseDynamicTheme = (
|
||||||
initialTheme: Theme,
|
initialTheme: Theme,
|
||||||
@ -42,10 +42,13 @@ type Props = {
|
|||||||
export const ConversationContainer = (props: Props) => {
|
export const ConversationContainer = (props: Props) => {
|
||||||
let chatContainer: HTMLDivElement | undefined
|
let chatContainer: HTMLDivElement | undefined
|
||||||
let bottomSpacer: HTMLDivElement | undefined
|
let bottomSpacer: HTMLDivElement | undefined
|
||||||
const [chatChunks, setChatChunks] = createSignal<ChatReply[]>([
|
const [chatChunks, setChatChunks] = createSignal<
|
||||||
|
Pick<ChatReply, 'messages' | 'input' | 'clientSideActions'>[]
|
||||||
|
>([
|
||||||
{
|
{
|
||||||
input: props.initialChatReply.input,
|
input: props.initialChatReply.input,
|
||||||
messages: props.initialChatReply.messages,
|
messages: props.initialChatReply.messages,
|
||||||
|
clientSideActions: props.initialChatReply.clientSideActions,
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
const [dynamicTheme, setDynamicTheme] = createSignal<
|
const [dynamicTheme, setDynamicTheme] = createSignal<
|
||||||
@ -77,17 +80,12 @@ export const ConversationContainer = (props: Props) => {
|
|||||||
groupId: data.input.groupId,
|
groupId: data.input.groupId,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (data.integrations) {
|
|
||||||
executeIntegrations(data.integrations)
|
|
||||||
}
|
|
||||||
if (data.logic) {
|
|
||||||
await executeLogic(data.logic)
|
|
||||||
}
|
|
||||||
setChatChunks((displayedChunks) => [
|
setChatChunks((displayedChunks) => [
|
||||||
...displayedChunks,
|
...displayedChunks,
|
||||||
{
|
{
|
||||||
input: data.input,
|
input: data.input,
|
||||||
messages: data.messages,
|
messages: data.messages,
|
||||||
|
clientSideActions: data.clientSideActions,
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
@ -99,6 +97,19 @@ export const ConversationContainer = (props: Props) => {
|
|||||||
}, 50)
|
}, 50)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleAllBubblesDisplayed = async () => {
|
||||||
|
const lastChunk = chatChunks().at(-1)
|
||||||
|
if (!lastChunk) return
|
||||||
|
if (lastChunk.clientSideActions) {
|
||||||
|
for (const action of lastChunk.clientSideActions) {
|
||||||
|
await executeClientSideAction(action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isNotDefined(lastChunk.input)) {
|
||||||
|
props.onEnd?.()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={chatContainer}
|
ref={chatContainer}
|
||||||
@ -112,12 +123,12 @@ export const ConversationContainer = (props: Props) => {
|
|||||||
input={chatChunk.input}
|
input={chatChunk.input}
|
||||||
theme={theme()}
|
theme={theme()}
|
||||||
settings={props.initialChatReply.typebot.settings}
|
settings={props.initialChatReply.typebot.settings}
|
||||||
|
onAllBubblesDisplayed={handleAllBubblesDisplayed}
|
||||||
onSubmit={sendMessage}
|
onSubmit={sendMessage}
|
||||||
onScrollToBottom={autoScrollToBottom}
|
onScrollToBottom={autoScrollToBottom}
|
||||||
onSkip={() => {
|
onSkip={() => {
|
||||||
// TODO: implement skip
|
// TODO: implement skip
|
||||||
}}
|
}}
|
||||||
onEnd={props.onEnd}
|
|
||||||
context={props.context}
|
context={props.context}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
22
packages/js/src/utils/executeClientSideActions.ts
Normal file
22
packages/js/src/utils/executeClientSideActions.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { executeChatwoot } from '@/features/blocks/integrations/chatwoot'
|
||||||
|
import { executeGoogleAnalyticsBlock } from '@/features/blocks/integrations/googleAnalytics/utils/executeGoogleAnalytics'
|
||||||
|
import { executeCode } from '@/features/blocks/logic/code'
|
||||||
|
import { executeRedirect } from '@/features/blocks/logic/redirect'
|
||||||
|
import type { ChatReply } from 'models'
|
||||||
|
|
||||||
|
export const executeClientSideAction = async (
|
||||||
|
clientSideAction: NonNullable<ChatReply['clientSideActions']>[0]
|
||||||
|
) => {
|
||||||
|
if ('chatwoot' in clientSideAction) {
|
||||||
|
executeChatwoot(clientSideAction.chatwoot)
|
||||||
|
}
|
||||||
|
if ('googleAnalytics' in clientSideAction) {
|
||||||
|
executeGoogleAnalyticsBlock(clientSideAction.googleAnalytics)
|
||||||
|
}
|
||||||
|
if ('codeToExecute' in clientSideAction) {
|
||||||
|
await executeCode(clientSideAction.codeToExecute)
|
||||||
|
}
|
||||||
|
if ('redirect' in clientSideAction) {
|
||||||
|
executeRedirect(clientSideAction.redirect)
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +0,0 @@
|
|||||||
import { executeChatwoot } from '@/features/blocks/integrations/chatwoot'
|
|
||||||
import { executeGoogleAnalyticsBlock } from '@/features/blocks/integrations/googleAnalytics/utils/executeGoogleAnalytics'
|
|
||||||
import type { ChatReply } from 'models'
|
|
||||||
|
|
||||||
export const executeIntegrations = async (
|
|
||||||
integrations: ChatReply['integrations']
|
|
||||||
) => {
|
|
||||||
if (integrations?.chatwoot?.codeToExecute) {
|
|
||||||
executeChatwoot(integrations.chatwoot)
|
|
||||||
}
|
|
||||||
if (integrations?.googleAnalytics) {
|
|
||||||
executeGoogleAnalyticsBlock(integrations.googleAnalytics)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
import { executeCode } from '@/features/blocks/logic/code'
|
|
||||||
import { executeRedirect } from '@/features/blocks/logic/redirect'
|
|
||||||
import type { ChatReply } from 'models'
|
|
||||||
|
|
||||||
export const executeLogic = async (logic: ChatReply['logic']) => {
|
|
||||||
if (logic?.codeToExecute) {
|
|
||||||
await executeCode(logic.codeToExecute)
|
|
||||||
}
|
|
||||||
if (logic?.redirect) {
|
|
||||||
executeRedirect(logic.redirect)
|
|
||||||
}
|
|
||||||
}
|
|
@ -165,6 +165,26 @@ const replyLogSchema = logSchema
|
|||||||
})
|
})
|
||||||
.and(z.object({ details: z.unknown().optional() }))
|
.and(z.object({ details: z.unknown().optional() }))
|
||||||
|
|
||||||
|
const clientSideActionSchema = z
|
||||||
|
.object({
|
||||||
|
codeToExecute: codeToExecuteSchema,
|
||||||
|
})
|
||||||
|
.or(
|
||||||
|
z.object({
|
||||||
|
redirect: redirectOptionsSchema,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.or(
|
||||||
|
z.object({
|
||||||
|
chatwoot: z.object({ codeToExecute: codeToExecuteSchema }),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.or(
|
||||||
|
z.object({
|
||||||
|
googleAnalytics: googleAnalyticsOptionsSchema,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
export const chatReplySchema = z.object({
|
export const chatReplySchema = z.object({
|
||||||
messages: z.array(chatMessageSchema),
|
messages: z.array(chatMessageSchema),
|
||||||
input: inputBlockSchema
|
input: inputBlockSchema
|
||||||
@ -175,22 +195,7 @@ export const chatReplySchema = z.object({
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
.optional(),
|
.optional(),
|
||||||
logic: z
|
clientSideActions: z.array(clientSideActionSchema).optional(),
|
||||||
.object({
|
|
||||||
redirect: redirectOptionsSchema.optional(),
|
|
||||||
codeToExecute: codeToExecuteSchema.optional(),
|
|
||||||
})
|
|
||||||
.optional(),
|
|
||||||
integrations: z
|
|
||||||
.object({
|
|
||||||
chatwoot: z
|
|
||||||
.object({
|
|
||||||
codeToExecute: codeToExecuteSchema,
|
|
||||||
})
|
|
||||||
.optional(),
|
|
||||||
googleAnalytics: googleAnalyticsOptionsSchema.optional(),
|
|
||||||
})
|
|
||||||
.optional(),
|
|
||||||
sessionId: z.string().optional(),
|
sessionId: z.string().optional(),
|
||||||
typebot: typebotSchema
|
typebot: typebotSchema
|
||||||
.pick({ id: true, theme: true, settings: true })
|
.pick({ id: true, theme: true, settings: true })
|
||||||
|
Reference in New Issue
Block a user