@@ -1,7 +1,15 @@
|
|||||||
import { Stack } from '@chakra-ui/react'
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionButton,
|
||||||
|
AccordionIcon,
|
||||||
|
AccordionItem,
|
||||||
|
AccordionPanel,
|
||||||
|
Stack,
|
||||||
|
} from '@chakra-ui/react'
|
||||||
import { WaitOptions } from '@typebot.io/schemas'
|
import { WaitOptions } from '@typebot.io/schemas'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { TextInput } from '@/components/inputs'
|
import { TextInput } from '@/components/inputs'
|
||||||
|
import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
options: WaitOptions
|
options: WaitOptions
|
||||||
@@ -13,6 +21,10 @@ export const WaitSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
onOptionsChange({ ...options, secondsToWaitFor })
|
onOptionsChange({ ...options, secondsToWaitFor })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateShouldPause = (shouldPause: boolean) => {
|
||||||
|
onOptionsChange({ ...options, shouldPause })
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<TextInput
|
<TextInput
|
||||||
@@ -21,6 +33,22 @@ export const WaitSettings = ({ options, onOptionsChange }: Props) => {
|
|||||||
onChange={handleSecondsChange}
|
onChange={handleSecondsChange}
|
||||||
placeholder="0"
|
placeholder="0"
|
||||||
/>
|
/>
|
||||||
|
<Accordion allowToggle>
|
||||||
|
<AccordionItem>
|
||||||
|
<AccordionButton justifyContent="space-between">
|
||||||
|
Advanced
|
||||||
|
<AccordionIcon />
|
||||||
|
</AccordionButton>
|
||||||
|
<AccordionPanel py="4">
|
||||||
|
<SwitchWithLabel
|
||||||
|
label="Pause the flow"
|
||||||
|
moreInfoContent="When enabled, the flow is paused until the client sends another message. This is automatic on the web bot."
|
||||||
|
initialValue={options.shouldPause ?? false}
|
||||||
|
onCheckChange={updateShouldPause}
|
||||||
|
/>
|
||||||
|
</AccordionPanel>
|
||||||
|
</AccordionItem>
|
||||||
|
</Accordion>
|
||||||
</Stack>
|
</Stack>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,3 +7,9 @@ This can be useful if you want the bot to emphasize on what's been said or to wa
|
|||||||
:::caution
|
:::caution
|
||||||
This should be used wisely. If you want the bot to write slower or faster in a more general sense, you need to check the [Typing emulation settings](/editor/settings#typing-emulation)
|
This should be used wisely. If you want the bot to write slower or faster in a more general sense, you need to check the [Typing emulation settings](/editor/settings#typing-emulation)
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
## Pause the flow
|
||||||
|
|
||||||
|
You can enable the "Pause the flow" option if you ever need to mark a pause in the flow.
|
||||||
|
|
||||||
|
Under the hood, typebot always compute all the blocks between each input blocks. But sometimes you may want to display some messages before a long-running action like a slow webhook request.
|
||||||
|
|||||||
@@ -2088,6 +2088,9 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"secondsToWaitFor": {
|
"secondsToWaitFor": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"shouldPause": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
@@ -6381,6 +6384,9 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"secondsToWaitFor": {
|
"secondsToWaitFor": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"shouldPause": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
@@ -10309,6 +10315,9 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"secondsToWaitFor": {
|
"secondsToWaitFor": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"shouldPause": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
@@ -14377,6 +14386,9 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"secondsToWaitFor": {
|
"secondsToWaitFor": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"shouldPause": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
@@ -18325,6 +18337,9 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"secondsToWaitFor": {
|
"secondsToWaitFor": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"shouldPause": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
@@ -22328,6 +22343,9 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"secondsToWaitFor": {
|
"secondsToWaitFor": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"shouldPause": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
@@ -26394,6 +26412,9 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"secondsToWaitFor": {
|
"secondsToWaitFor": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"shouldPause": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
|||||||
@@ -1671,6 +1671,9 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"secondsToWaitFor": {
|
"secondsToWaitFor": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"shouldPause": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
@@ -5204,6 +5207,9 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"lastBubbleBlockId": {
|
"lastBubbleBlockId": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"expectsDedicatedReply": {
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ export const createChatCompletionOpenAI = async (
|
|||||||
assistantMessageVariableName
|
assistantMessageVariableName
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
expectsDedicatedReply: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
outgoingEdgeId,
|
outgoingEdgeId,
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ export const executeWebhookBlock = async (
|
|||||||
clientSideActions: [
|
clientSideActions: [
|
||||||
{
|
{
|
||||||
webhookToExecute: parsedWebhook,
|
webhookToExecute: parsedWebhook,
|
||||||
|
expectsDedicatedReply: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ export const executeSetVariable = (
|
|||||||
setVariable: {
|
setVariable: {
|
||||||
scriptToExecute,
|
scriptToExecute,
|
||||||
},
|
},
|
||||||
|
expectsDedicatedReply: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export const executeWait = (
|
|||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
wait: { secondsToWaitFor: parsedSecondsToWaitFor },
|
wait: { secondsToWaitFor: parsedSecondsToWaitFor },
|
||||||
|
expectsDedicatedReply: block.options.shouldPause,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
: undefined,
|
: undefined,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { TRPCError } from '@trpc/server'
|
|
||||||
import {
|
import {
|
||||||
AnswerInSessionState,
|
AnswerInSessionState,
|
||||||
|
Block,
|
||||||
BubbleBlockType,
|
BubbleBlockType,
|
||||||
ChatReply,
|
ChatReply,
|
||||||
InputBlock,
|
InputBlock,
|
||||||
@@ -8,8 +8,6 @@ import {
|
|||||||
IntegrationBlockType,
|
IntegrationBlockType,
|
||||||
LogicBlockType,
|
LogicBlockType,
|
||||||
SessionState,
|
SessionState,
|
||||||
SetVariableBlock,
|
|
||||||
WebhookBlock,
|
|
||||||
defaultPaymentInputOptions,
|
defaultPaymentInputOptions,
|
||||||
invalidEmailDefaultRetryMessage,
|
invalidEmailDefaultRetryMessage,
|
||||||
} from '@typebot.io/schemas'
|
} from '@typebot.io/schemas'
|
||||||
@@ -21,7 +19,6 @@ import { formatPhoneNumber } from '@/features/blocks/inputs/phone/formatPhoneNum
|
|||||||
import { validateUrl } from '@/features/blocks/inputs/url/validateUrl'
|
import { validateUrl } from '@/features/blocks/inputs/url/validateUrl'
|
||||||
import { updateVariables } from '@/features/variables/updateVariables'
|
import { updateVariables } from '@/features/variables/updateVariables'
|
||||||
import { parseVariables } from '@/features/variables/parseVariables'
|
import { parseVariables } from '@/features/variables/parseVariables'
|
||||||
import { OpenAIBlock } from '@typebot.io/schemas/features/blocks/integrations/openai'
|
|
||||||
import { resumeChatCompletion } from '@/features/blocks/integrations/openai/resumeChatCompletion'
|
import { resumeChatCompletion } from '@/features/blocks/integrations/openai/resumeChatCompletion'
|
||||||
import { resumeWebhookExecution } from '@/features/blocks/integrations/webhook/resumeWebhookExecution'
|
import { resumeWebhookExecution } from '@/features/blocks/integrations/webhook/resumeWebhookExecution'
|
||||||
import { upsertAnswer } from '../queries/upsertAnswer'
|
import { upsertAnswer } from '../queries/upsertAnswer'
|
||||||
@@ -80,11 +77,7 @@ export const continueBotFlow =
|
|||||||
})(reply)
|
})(reply)
|
||||||
newSessionState = result.newSessionState
|
newSessionState = result.newSessionState
|
||||||
}
|
}
|
||||||
} else if (!isInputBlock(block))
|
}
|
||||||
throw new TRPCError({
|
|
||||||
code: 'INTERNAL_SERVER_ERROR',
|
|
||||||
message: 'Current block is not an input block',
|
|
||||||
})
|
|
||||||
|
|
||||||
let formattedReply: string | undefined
|
let formattedReply: string | undefined
|
||||||
|
|
||||||
@@ -276,10 +269,7 @@ const setNewAnswerInState =
|
|||||||
|
|
||||||
const getOutgoingEdgeId =
|
const getOutgoingEdgeId =
|
||||||
(state: Pick<SessionState, 'typebotsQueue'>) =>
|
(state: Pick<SessionState, 'typebotsQueue'>) =>
|
||||||
(
|
(block: Block, reply: string | undefined) => {
|
||||||
block: InputBlock | SetVariableBlock | OpenAIBlock | WebhookBlock,
|
|
||||||
reply: string | undefined
|
|
||||||
) => {
|
|
||||||
const variables = state.typebotsQueue[0].typebot.variables
|
const variables = state.typebotsQueue[0].typebot.variables
|
||||||
if (
|
if (
|
||||||
block.type === InputBlockType.CHOICE &&
|
block.type === InputBlockType.CHOICE &&
|
||||||
|
|||||||
@@ -94,10 +94,7 @@ export const executeGroup =
|
|||||||
]
|
]
|
||||||
if (
|
if (
|
||||||
executionResponse.clientSideActions?.find(
|
executionResponse.clientSideActions?.find(
|
||||||
(action) =>
|
(action) => action.expectsDedicatedReply
|
||||||
'setVariable' in action ||
|
|
||||||
'streamOpenAiChatCompletion' in action ||
|
|
||||||
'webhookToExecute' in action
|
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -22,10 +22,7 @@ export const saveStateToDatabase = async ({
|
|||||||
clientSideActions,
|
clientSideActions,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const containsSetVariableClientSideAction = clientSideActions?.some(
|
const containsSetVariableClientSideAction = clientSideActions?.some(
|
||||||
(action) =>
|
(action) => action.expectsDedicatedReply
|
||||||
'setVariable' in action ||
|
|
||||||
'webhookToExecute' in action ||
|
|
||||||
'streamOpenAiChatCompletion' in action
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const isCompleted = Boolean(!input && !containsSetVariableClientSideAction)
|
const isCompleted = Boolean(!input && !containsSetVariableClientSideAction)
|
||||||
|
|||||||
@@ -165,10 +165,7 @@ export const startSession = async ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const clientSideActionsNeedSessionId = clientSideActions?.some(
|
const clientSideActionsNeedSessionId = clientSideActions?.some(
|
||||||
(action) =>
|
(action) => action.expectsDedicatedReply
|
||||||
'setVariable' in action ||
|
|
||||||
'streamOpenAiChatCompletion' in action ||
|
|
||||||
'webhookToExecute' in action
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!input && !clientSideActionsNeedSessionId)
|
if (!input && !clientSideActionsNeedSessionId)
|
||||||
|
|||||||
@@ -39,7 +39,10 @@ export const executeClientSideAction = async ({
|
|||||||
return executeRedirect(clientSideAction.redirect)
|
return executeRedirect(clientSideAction.redirect)
|
||||||
}
|
}
|
||||||
if ('wait' in clientSideAction) {
|
if ('wait' in clientSideAction) {
|
||||||
return executeWait(clientSideAction.wait)
|
await executeWait(clientSideAction.wait)
|
||||||
|
return clientSideAction.expectsDedicatedReply
|
||||||
|
? { replyToSend: undefined }
|
||||||
|
: undefined
|
||||||
}
|
}
|
||||||
if ('setVariable' in clientSideAction) {
|
if ('setVariable' in clientSideAction) {
|
||||||
return executeSetVariable(clientSideAction.setVariable.scriptToExecute)
|
return executeSetVariable(clientSideAction.setVariable.scriptToExecute)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { LogicBlockType } from './enums'
|
|||||||
|
|
||||||
export const waitOptionsSchema = z.object({
|
export const waitOptionsSchema = z.object({
|
||||||
secondsToWaitFor: z.string().optional(),
|
secondsToWaitFor: z.string().optional(),
|
||||||
|
shouldPause: z.boolean().optional(),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const waitBlockSchema = blockBaseSchema.merge(
|
export const waitBlockSchema = blockBaseSchema.merge(
|
||||||
|
|||||||
@@ -177,6 +177,7 @@ const startPropsToInjectSchema = z.object({
|
|||||||
const clientSideActionSchema = z
|
const clientSideActionSchema = z
|
||||||
.object({
|
.object({
|
||||||
lastBubbleBlockId: z.string().optional(),
|
lastBubbleBlockId: z.string().optional(),
|
||||||
|
expectsDedicatedReply: z.boolean().optional(),
|
||||||
})
|
})
|
||||||
.and(
|
.and(
|
||||||
z
|
z
|
||||||
|
|||||||
1156
pnpm-lock.yaml
generated
1156
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user