@ -116,6 +116,7 @@ export const startWhatsAppPreview = authenticatedProcedure
|
|||||||
startFrom,
|
startFrom,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
isStreamEnabled: false,
|
isStreamEnabled: false,
|
||||||
|
textBubbleContentFormat: 'richText',
|
||||||
},
|
},
|
||||||
initialSessionState: {
|
initialSessionState: {
|
||||||
whatsApp: (existingSession?.state as SessionState | undefined)
|
whatsApp: (existingSession?.state as SessionState | undefined)
|
||||||
|
@ -19,15 +19,24 @@ export const continueChat = publicProcedure
|
|||||||
.describe(
|
.describe(
|
||||||
'The session ID you got from the [startChat](./start-chat) response.'
|
'The session ID you got from the [startChat](./start-chat) response.'
|
||||||
),
|
),
|
||||||
|
textBubbleContentFormat: z
|
||||||
|
.enum(['richText', 'markdown'])
|
||||||
|
.default('richText'),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.output(continueChatResponseSchema)
|
.output(continueChatResponseSchema)
|
||||||
.mutation(async ({ input: { sessionId, message }, ctx: { origin, res } }) => {
|
.mutation(
|
||||||
const { corsOrigin, ...response } = await continueChatFn({
|
async ({
|
||||||
origin,
|
input: { sessionId, message, textBubbleContentFormat },
|
||||||
sessionId,
|
ctx: { origin, res },
|
||||||
message,
|
}) => {
|
||||||
})
|
const { corsOrigin, ...response } = await continueChatFn({
|
||||||
if (corsOrigin) res.setHeader('Access-Control-Allow-Origin', corsOrigin)
|
origin,
|
||||||
return response
|
sessionId,
|
||||||
})
|
message,
|
||||||
|
textBubbleContentFormat,
|
||||||
|
})
|
||||||
|
if (corsOrigin) res.setHeader('Access-Control-Allow-Origin', corsOrigin)
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ -92,6 +92,7 @@ export const sendMessageV1 = publicProcedure
|
|||||||
: startParams.typebot,
|
: startParams.typebot,
|
||||||
message,
|
message,
|
||||||
userId: user?.id,
|
userId: user?.id,
|
||||||
|
textBubbleContentFormat: 'richText',
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
type: 'live',
|
type: 'live',
|
||||||
@ -101,6 +102,7 @@ export const sendMessageV1 = publicProcedure
|
|||||||
prefilledVariables: startParams.prefilledVariables,
|
prefilledVariables: startParams.prefilledVariables,
|
||||||
resultId: startParams.resultId,
|
resultId: startParams.resultId,
|
||||||
message,
|
message,
|
||||||
|
textBubbleContentFormat: 'richText',
|
||||||
},
|
},
|
||||||
message,
|
message,
|
||||||
})
|
})
|
||||||
@ -179,7 +181,11 @@ export const sendMessageV1 = publicProcedure
|
|||||||
lastMessageNewFormat,
|
lastMessageNewFormat,
|
||||||
visitedEdges,
|
visitedEdges,
|
||||||
setVariableHistory,
|
setVariableHistory,
|
||||||
} = await continueBotFlow(message, { version: 1, state: session.state })
|
} = await continueBotFlow(message, {
|
||||||
|
version: 1,
|
||||||
|
state: session.state,
|
||||||
|
textBubbleContentFormat: 'richText',
|
||||||
|
})
|
||||||
|
|
||||||
const allLogs = clientLogs ? [...(logs ?? []), ...clientLogs] : logs
|
const allLogs = clientLogs ? [...(logs ?? []), ...clientLogs] : logs
|
||||||
|
|
||||||
|
@ -92,6 +92,7 @@ export const sendMessageV2 = publicProcedure
|
|||||||
: startParams.typebot,
|
: startParams.typebot,
|
||||||
message,
|
message,
|
||||||
userId: user?.id,
|
userId: user?.id,
|
||||||
|
textBubbleContentFormat: 'richText',
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
type: 'live',
|
type: 'live',
|
||||||
@ -101,6 +102,7 @@ export const sendMessageV2 = publicProcedure
|
|||||||
prefilledVariables: startParams.prefilledVariables,
|
prefilledVariables: startParams.prefilledVariables,
|
||||||
resultId: startParams.resultId,
|
resultId: startParams.resultId,
|
||||||
message,
|
message,
|
||||||
|
textBubbleContentFormat: 'richText',
|
||||||
},
|
},
|
||||||
message,
|
message,
|
||||||
})
|
})
|
||||||
@ -178,7 +180,11 @@ export const sendMessageV2 = publicProcedure
|
|||||||
lastMessageNewFormat,
|
lastMessageNewFormat,
|
||||||
visitedEdges,
|
visitedEdges,
|
||||||
setVariableHistory,
|
setVariableHistory,
|
||||||
} = await continueBotFlow(message, { version: 2, state: session.state })
|
} = await continueBotFlow(message, {
|
||||||
|
version: 2,
|
||||||
|
state: session.state,
|
||||||
|
textBubbleContentFormat: 'richText',
|
||||||
|
})
|
||||||
|
|
||||||
const allLogs = clientLogs ? [...(logs ?? []), ...clientLogs] : logs
|
const allLogs = clientLogs ? [...(logs ?? []), ...clientLogs] : logs
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ export const startChatPreview = publicProcedure
|
|||||||
typebot: startTypebot,
|
typebot: startTypebot,
|
||||||
prefilledVariables,
|
prefilledVariables,
|
||||||
sessionId,
|
sessionId,
|
||||||
|
textBubbleContentFormat,
|
||||||
},
|
},
|
||||||
ctx: { user },
|
ctx: { user },
|
||||||
}) =>
|
}) =>
|
||||||
@ -41,5 +42,6 @@ export const startChatPreview = publicProcedure
|
|||||||
userId: user?.id,
|
userId: user?.id,
|
||||||
prefilledVariables,
|
prefilledVariables,
|
||||||
sessionId,
|
sessionId,
|
||||||
|
textBubbleContentFormat,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
@ -48,6 +48,7 @@ test('API chat execution should work on preview bot', async ({ request }) => {
|
|||||||
data: {
|
data: {
|
||||||
isOnlyRegistering: false,
|
isOnlyRegistering: false,
|
||||||
isStreamEnabled: false,
|
isStreamEnabled: false,
|
||||||
|
textBubbleContentFormat: 'richText',
|
||||||
} satisfies Omit<StartPreviewChatInput, 'typebotId'>,
|
} satisfies Omit<StartPreviewChatInput, 'typebotId'>,
|
||||||
})
|
})
|
||||||
).json()
|
).json()
|
||||||
@ -120,6 +121,7 @@ test('API chat execution should work on published bot', async ({ request }) => {
|
|||||||
data: {
|
data: {
|
||||||
isOnlyRegistering: false,
|
isOnlyRegistering: false,
|
||||||
isStreamEnabled: false,
|
isStreamEnabled: false,
|
||||||
|
textBubbleContentFormat: 'richText',
|
||||||
} satisfies Omit<StartChatInput, 'publicId'>,
|
} satisfies Omit<StartChatInput, 'publicId'>,
|
||||||
})
|
})
|
||||||
).json()
|
).json()
|
||||||
@ -302,6 +304,7 @@ test('API chat execution should work on published bot', async ({ request }) => {
|
|||||||
message: 'Hey',
|
message: 'Hey',
|
||||||
isStreamEnabled: false,
|
isStreamEnabled: false,
|
||||||
isOnlyRegistering: false,
|
isOnlyRegistering: false,
|
||||||
|
textBubbleContentFormat: 'richText',
|
||||||
} satisfies Omit<StartChatInput, 'publicId'>,
|
} satisfies Omit<StartChatInput, 'publicId'>,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -317,4 +320,19 @@ test('API chat execution should work on published bot', async ({ request }) => {
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
await test.step('Markdown text bubble format should work', async () => {
|
||||||
|
const { messages } = await (
|
||||||
|
await request.post(`/api/v1/typebots/${typebotId}/preview/startChat`, {
|
||||||
|
data: {
|
||||||
|
isOnlyRegistering: false,
|
||||||
|
isStreamEnabled: false,
|
||||||
|
textBubbleContentFormat: 'markdown',
|
||||||
|
} satisfies Omit<StartPreviewChatInput, 'typebotId'>,
|
||||||
|
})
|
||||||
|
).json()
|
||||||
|
expect(messages[0].content.markdown).toStrictEqual('Hi there! 👋')
|
||||||
|
expect(messages[1].content.markdown).toStrictEqual(
|
||||||
|
'Welcome. What's your name?'
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -11,8 +11,14 @@ type Props = {
|
|||||||
origin: string | undefined
|
origin: string | undefined
|
||||||
message?: string
|
message?: string
|
||||||
sessionId: string
|
sessionId: string
|
||||||
|
textBubbleContentFormat: 'richText' | 'markdown'
|
||||||
}
|
}
|
||||||
export const continueChat = async ({ origin, sessionId, message }: Props) => {
|
export const continueChat = async ({
|
||||||
|
origin,
|
||||||
|
sessionId,
|
||||||
|
message,
|
||||||
|
textBubbleContentFormat,
|
||||||
|
}: Props) => {
|
||||||
const session = await getSession(sessionId)
|
const session = await getSession(sessionId)
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
@ -57,6 +63,7 @@ export const continueChat = async ({ origin, sessionId, message }: Props) => {
|
|||||||
version: 2,
|
version: 2,
|
||||||
state: session.state,
|
state: session.state,
|
||||||
startTime: Date.now(),
|
startTime: Date.now(),
|
||||||
|
textBubbleContentFormat,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (newSessionState)
|
if (newSessionState)
|
||||||
|
@ -12,6 +12,7 @@ type Props = {
|
|||||||
isStreamEnabled: boolean
|
isStreamEnabled: boolean
|
||||||
prefilledVariables?: Record<string, unknown>
|
prefilledVariables?: Record<string, unknown>
|
||||||
resultId?: string
|
resultId?: string
|
||||||
|
textBubbleContentFormat: 'richText' | 'markdown'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const startChat = async ({
|
export const startChat = async ({
|
||||||
@ -22,6 +23,7 @@ export const startChat = async ({
|
|||||||
isStreamEnabled,
|
isStreamEnabled,
|
||||||
prefilledVariables,
|
prefilledVariables,
|
||||||
resultId: startResultId,
|
resultId: startResultId,
|
||||||
|
textBubbleContentFormat,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const {
|
const {
|
||||||
typebot,
|
typebot,
|
||||||
@ -43,6 +45,7 @@ export const startChat = async ({
|
|||||||
publicId,
|
publicId,
|
||||||
prefilledVariables,
|
prefilledVariables,
|
||||||
resultId: startResultId,
|
resultId: startResultId,
|
||||||
|
textBubbleContentFormat,
|
||||||
},
|
},
|
||||||
message,
|
message,
|
||||||
})
|
})
|
||||||
|
@ -14,6 +14,7 @@ type Props = {
|
|||||||
userId?: string
|
userId?: string
|
||||||
prefilledVariables?: Record<string, unknown>
|
prefilledVariables?: Record<string, unknown>
|
||||||
sessionId?: string
|
sessionId?: string
|
||||||
|
textBubbleContentFormat: 'richText' | 'markdown'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const startChatPreview = async ({
|
export const startChatPreview = async ({
|
||||||
@ -26,6 +27,7 @@ export const startChatPreview = async ({
|
|||||||
userId,
|
userId,
|
||||||
prefilledVariables,
|
prefilledVariables,
|
||||||
sessionId,
|
sessionId,
|
||||||
|
textBubbleContentFormat,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const {
|
const {
|
||||||
typebot,
|
typebot,
|
||||||
@ -49,6 +51,7 @@ export const startChatPreview = async ({
|
|||||||
userId,
|
userId,
|
||||||
prefilledVariables,
|
prefilledVariables,
|
||||||
sessionId,
|
sessionId,
|
||||||
|
textBubbleContentFormat,
|
||||||
},
|
},
|
||||||
message,
|
message,
|
||||||
})
|
})
|
||||||
|
@ -50,10 +50,11 @@ type Params = {
|
|||||||
version: 1 | 2
|
version: 1 | 2
|
||||||
state: SessionState
|
state: SessionState
|
||||||
startTime?: number
|
startTime?: number
|
||||||
|
textBubbleContentFormat: 'richText' | 'markdown'
|
||||||
}
|
}
|
||||||
export const continueBotFlow = async (
|
export const continueBotFlow = async (
|
||||||
reply: Reply,
|
reply: Reply,
|
||||||
{ state, version, startTime }: Params
|
{ state, version, startTime, textBubbleContentFormat }: Params
|
||||||
): Promise<
|
): Promise<
|
||||||
ContinueChatResponse & {
|
ContinueChatResponse & {
|
||||||
newSessionState: SessionState
|
newSessionState: SessionState
|
||||||
@ -66,7 +67,8 @@ export const continueBotFlow = async (
|
|||||||
const visitedEdges: VisitedEdge[] = []
|
const visitedEdges: VisitedEdge[] = []
|
||||||
const setVariableHistory: SetVariableHistoryItem[] = []
|
const setVariableHistory: SetVariableHistoryItem[] = []
|
||||||
|
|
||||||
if (!newSessionState.currentBlockId) return startBotFlow({ state, version })
|
if (!newSessionState.currentBlockId)
|
||||||
|
return startBotFlow({ state, version, textBubbleContentFormat })
|
||||||
|
|
||||||
const { block, group, blockIndex } = getBlockById(
|
const { block, group, blockIndex } = getBlockById(
|
||||||
newSessionState.currentBlockId,
|
newSessionState.currentBlockId,
|
||||||
@ -167,7 +169,10 @@ export const continueBotFlow = async (
|
|||||||
|
|
||||||
if (parsedReplyResult.status === 'fail')
|
if (parsedReplyResult.status === 'fail')
|
||||||
return {
|
return {
|
||||||
...(await parseRetryMessage(newSessionState)(block)),
|
...(await parseRetryMessage(newSessionState)(
|
||||||
|
block,
|
||||||
|
textBubbleContentFormat
|
||||||
|
)),
|
||||||
newSessionState,
|
newSessionState,
|
||||||
visitedEdges: [],
|
visitedEdges: [],
|
||||||
setVariableHistory: [],
|
setVariableHistory: [],
|
||||||
@ -197,6 +202,7 @@ export const continueBotFlow = async (
|
|||||||
setVariableHistory,
|
setVariableHistory,
|
||||||
firstBubbleWasStreamed,
|
firstBubbleWasStreamed,
|
||||||
startTime,
|
startTime,
|
||||||
|
textBubbleContentFormat,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
@ -243,6 +249,7 @@ export const continueBotFlow = async (
|
|||||||
visitedEdges,
|
visitedEdges,
|
||||||
setVariableHistory,
|
setVariableHistory,
|
||||||
startTime,
|
startTime,
|
||||||
|
textBubbleContentFormat,
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -287,7 +294,8 @@ const saveVariableValueIfAny =
|
|||||||
const parseRetryMessage =
|
const parseRetryMessage =
|
||||||
(state: SessionState) =>
|
(state: SessionState) =>
|
||||||
async (
|
async (
|
||||||
block: InputBlock
|
block: InputBlock,
|
||||||
|
textBubbleContentFormat: 'richText' | 'markdown'
|
||||||
): Promise<Pick<ContinueChatResponse, 'messages' | 'input'>> => {
|
): Promise<Pick<ContinueChatResponse, 'messages' | 'input'>> => {
|
||||||
const retryMessage =
|
const retryMessage =
|
||||||
block.options &&
|
block.options &&
|
||||||
@ -302,9 +310,16 @@ const parseRetryMessage =
|
|||||||
{
|
{
|
||||||
id: block.id,
|
id: block.id,
|
||||||
type: BubbleBlockType.TEXT,
|
type: BubbleBlockType.TEXT,
|
||||||
content: {
|
content:
|
||||||
richText: [{ type: 'p', children: [{ text: retryMessage }] }],
|
textBubbleContentFormat === 'richText'
|
||||||
},
|
? {
|
||||||
|
type: 'richText',
|
||||||
|
richText: [{ type: 'p', children: [{ text: retryMessage }] }],
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
type: 'markdown',
|
||||||
|
markdown: retryMessage,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
input: await parseInput(state)(block),
|
input: await parseInput(state)(block),
|
||||||
|
@ -42,6 +42,7 @@ type ContextProps = {
|
|||||||
visitedEdges: VisitedEdge[]
|
visitedEdges: VisitedEdge[]
|
||||||
setVariableHistory: SetVariableHistoryItem[]
|
setVariableHistory: SetVariableHistoryItem[]
|
||||||
startTime?: number
|
startTime?: number
|
||||||
|
textBubbleContentFormat: 'richText' | 'markdown'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const executeGroup = async (
|
export const executeGroup = async (
|
||||||
@ -55,6 +56,7 @@ export const executeGroup = async (
|
|||||||
currentLastBubbleId,
|
currentLastBubbleId,
|
||||||
firstBubbleWasStreamed,
|
firstBubbleWasStreamed,
|
||||||
startTime,
|
startTime,
|
||||||
|
textBubbleContentFormat,
|
||||||
}: ContextProps
|
}: ContextProps
|
||||||
): Promise<
|
): Promise<
|
||||||
ContinueChatResponse & {
|
ContinueChatResponse & {
|
||||||
@ -98,6 +100,7 @@ export const executeGroup = async (
|
|||||||
version,
|
version,
|
||||||
variables: newSessionState.typebotsQueue[0].typebot.variables,
|
variables: newSessionState.typebotsQueue[0].typebot.variables,
|
||||||
typebotVersion: newSessionState.typebotsQueue[0].typebot.version,
|
typebotVersion: newSessionState.typebotsQueue[0].typebot.version,
|
||||||
|
textBubbleContentFormat,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
lastBubbleBlockId = block.id
|
lastBubbleBlockId = block.id
|
||||||
@ -250,6 +253,7 @@ export const executeGroup = async (
|
|||||||
},
|
},
|
||||||
currentLastBubbleId: lastBubbleBlockId,
|
currentLastBubbleId: lastBubbleBlockId,
|
||||||
startTime: newStartTime,
|
startTime: newStartTime,
|
||||||
|
textBubbleContentFormat,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,15 +11,17 @@ import {
|
|||||||
getVariablesToParseInfoInText,
|
getVariablesToParseInfoInText,
|
||||||
parseVariables,
|
parseVariables,
|
||||||
} from '@typebot.io/variables/parseVariables'
|
} from '@typebot.io/variables/parseVariables'
|
||||||
import { TDescendant } from '@udecode/plate-common'
|
import { TDescendant, TElement } from '@udecode/plate-common'
|
||||||
import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants'
|
import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants'
|
||||||
import { defaultVideoBubbleContent } from '@typebot.io/schemas/features/blocks/bubbles/video/constants'
|
import { defaultVideoBubbleContent } from '@typebot.io/schemas/features/blocks/bubbles/video/constants'
|
||||||
import { convertMarkdownToRichText } from '@typebot.io/lib/markdown/convertMarkdownToRichText'
|
import { convertMarkdownToRichText } from '@typebot.io/lib/markdown/convertMarkdownToRichText'
|
||||||
|
import { convertRichTextToMarkdown } from '@typebot.io/lib/markdown/convertRichTextToMarkdown'
|
||||||
|
|
||||||
type Params = {
|
type Params = {
|
||||||
version: 1 | 2
|
version: 1 | 2
|
||||||
typebotVersion: Typebot['version']
|
typebotVersion: Typebot['version']
|
||||||
variables: Variable[]
|
variables: Variable[]
|
||||||
|
textBubbleContentFormat: 'richText' | 'markdown'
|
||||||
}
|
}
|
||||||
|
|
||||||
export type BubbleBlockWithDefinedContent = BubbleBlock & {
|
export type BubbleBlockWithDefinedContent = BubbleBlock & {
|
||||||
@ -28,7 +30,7 @@ export type BubbleBlockWithDefinedContent = BubbleBlock & {
|
|||||||
|
|
||||||
export const parseBubbleBlock = (
|
export const parseBubbleBlock = (
|
||||||
block: BubbleBlockWithDefinedContent,
|
block: BubbleBlockWithDefinedContent,
|
||||||
{ version, variables, typebotVersion }: Params
|
{ version, variables, typebotVersion, textBubbleContentFormat }: Params
|
||||||
): ContinueChatResponse['messages'][0] => {
|
): ContinueChatResponse['messages'][0] => {
|
||||||
switch (block.type) {
|
switch (block.type) {
|
||||||
case BubbleBlockType.TEXT: {
|
case BubbleBlockType.TEXT: {
|
||||||
@ -36,21 +38,29 @@ export const parseBubbleBlock = (
|
|||||||
return {
|
return {
|
||||||
...block,
|
...block,
|
||||||
content: {
|
content: {
|
||||||
...block.content,
|
type: 'richText',
|
||||||
richText: (block.content?.richText ?? []).map(
|
richText: (block.content?.richText ?? []).map(
|
||||||
deepParseVariables(variables)
|
deepParseVariables(variables)
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const richText = parseVariablesInRichText(block.content?.richText ?? [], {
|
||||||
|
variables,
|
||||||
|
takeLatestIfList: typebotVersion !== '6',
|
||||||
|
}).parsedElements
|
||||||
return {
|
return {
|
||||||
...block,
|
...block,
|
||||||
content: {
|
content:
|
||||||
...block.content,
|
textBubbleContentFormat === 'richText'
|
||||||
richText: parseVariablesInRichText(block.content?.richText ?? [], {
|
? {
|
||||||
variables,
|
type: 'richText',
|
||||||
takeLatestIfList: typebotVersion !== '6',
|
richText,
|
||||||
}).parsedElements,
|
}
|
||||||
},
|
: {
|
||||||
|
type: 'markdown',
|
||||||
|
markdown: convertRichTextToMarkdown(richText as TElement[]),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ type Props = {
|
|||||||
state: SessionState
|
state: SessionState
|
||||||
startFrom?: StartFrom
|
startFrom?: StartFrom
|
||||||
startTime?: number
|
startTime?: number
|
||||||
|
textBubbleContentFormat: 'richText' | 'markdown'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const startBotFlow = async ({
|
export const startBotFlow = async ({
|
||||||
@ -22,6 +23,7 @@ export const startBotFlow = async ({
|
|||||||
state,
|
state,
|
||||||
startFrom,
|
startFrom,
|
||||||
startTime,
|
startTime,
|
||||||
|
textBubbleContentFormat,
|
||||||
}: Props): Promise<
|
}: Props): Promise<
|
||||||
ContinueChatResponse & {
|
ContinueChatResponse & {
|
||||||
newSessionState: SessionState
|
newSessionState: SessionState
|
||||||
@ -47,6 +49,7 @@ export const startBotFlow = async ({
|
|||||||
visitedEdges,
|
visitedEdges,
|
||||||
setVariableHistory,
|
setVariableHistory,
|
||||||
startTime,
|
startTime,
|
||||||
|
textBubbleContentFormat,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const firstEdgeId = getFirstEdgeId({
|
const firstEdgeId = getFirstEdgeId({
|
||||||
@ -74,5 +77,6 @@ export const startBotFlow = async ({
|
|||||||
visitedEdges,
|
visitedEdges,
|
||||||
setVariableHistory,
|
setVariableHistory,
|
||||||
startTime,
|
startTime,
|
||||||
|
textBubbleContentFormat,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -184,6 +184,7 @@ export const startSession = async ({
|
|||||||
startFrom:
|
startFrom:
|
||||||
startParams.type === 'preview' ? startParams.startFrom : undefined,
|
startParams.type === 'preview' ? startParams.startFrom : undefined,
|
||||||
startTime: Date.now(),
|
startTime: Date.now(),
|
||||||
|
textBubbleContentFormat: startParams.textBubbleContentFormat,
|
||||||
})
|
})
|
||||||
|
|
||||||
// If params has message and first block is an input block, we can directly continue the bot flow
|
// If params has message and first block is an input block, we can directly continue the bot flow
|
||||||
@ -218,6 +219,7 @@ export const startSession = async ({
|
|||||||
...newSessionState,
|
...newSessionState,
|
||||||
currentBlockId: firstBlock.id,
|
currentBlockId: firstBlock.id,
|
||||||
},
|
},
|
||||||
|
textBubbleContentFormat: startParams.textBubbleContentFormat,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,8 @@ export const convertInputToWhatsAppMessages = (
|
|||||||
lastMessage: ContinueChatResponse['messages'][number] | undefined
|
lastMessage: ContinueChatResponse['messages'][number] | undefined
|
||||||
): WhatsAppSendingMessage[] => {
|
): WhatsAppSendingMessage[] => {
|
||||||
const lastMessageText =
|
const lastMessageText =
|
||||||
lastMessage?.type === BubbleBlockType.TEXT
|
lastMessage?.type === BubbleBlockType.TEXT &&
|
||||||
|
lastMessage.content.type === 'richText'
|
||||||
? convertRichTextToMarkdown(lastMessage.content.richText ?? [], {
|
? convertRichTextToMarkdown(lastMessage.content.richText ?? [], {
|
||||||
flavour: 'whatsapp',
|
flavour: 'whatsapp',
|
||||||
})
|
})
|
||||||
|
@ -17,6 +17,8 @@ export const convertMessageToWhatsAppMessage = (
|
|||||||
): WhatsAppSendingMessage | null => {
|
): WhatsAppSendingMessage | null => {
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case BubbleBlockType.TEXT: {
|
case BubbleBlockType.TEXT: {
|
||||||
|
if (message.content.type === 'markdown')
|
||||||
|
throw new Error('Expect rich text message')
|
||||||
if (!message.content.richText || message.content.richText.length === 0)
|
if (!message.content.richText || message.content.richText.length === 0)
|
||||||
return null
|
return null
|
||||||
return {
|
return {
|
||||||
|
@ -93,6 +93,7 @@ export const resumeWhatsAppFlow = async ({
|
|||||||
? await continueBotFlow(reply, {
|
? await continueBotFlow(reply, {
|
||||||
version: 2,
|
version: 2,
|
||||||
state: { ...session.state, whatsApp: { contact } },
|
state: { ...session.state, whatsApp: { contact } },
|
||||||
|
textBubbleContentFormat: 'richText',
|
||||||
})
|
})
|
||||||
: workspaceId
|
: workspaceId
|
||||||
? await startWhatsAppSession({
|
? await startWhatsAppSession({
|
||||||
|
@ -58,7 +58,11 @@ export const sendChatReplyToWhatsApp = async ({
|
|||||||
const result = await executeClientSideAction({ to, credentials })(action)
|
const result = await executeClientSideAction({ to, credentials })(action)
|
||||||
if (!result) continue
|
if (!result) continue
|
||||||
const { input, newSessionState, messages, clientSideActions } =
|
const { input, newSessionState, messages, clientSideActions } =
|
||||||
await continueBotFlow(result.replyToSend, { version: 2, state })
|
await continueBotFlow(result.replyToSend, {
|
||||||
|
version: 2,
|
||||||
|
state,
|
||||||
|
textBubbleContentFormat: 'richText',
|
||||||
|
})
|
||||||
|
|
||||||
return sendChatReplyToWhatsApp({
|
return sendChatReplyToWhatsApp({
|
||||||
to,
|
to,
|
||||||
@ -124,7 +128,11 @@ export const sendChatReplyToWhatsApp = async ({
|
|||||||
)
|
)
|
||||||
if (!result) continue
|
if (!result) continue
|
||||||
const { input, newSessionState, messages, clientSideActions } =
|
const { input, newSessionState, messages, clientSideActions } =
|
||||||
await continueBotFlow(result.replyToSend, { version: 2, state })
|
await continueBotFlow(result.replyToSend, {
|
||||||
|
version: 2,
|
||||||
|
state,
|
||||||
|
textBubbleContentFormat: 'richText',
|
||||||
|
})
|
||||||
|
|
||||||
return sendChatReplyToWhatsApp({
|
return sendChatReplyToWhatsApp({
|
||||||
to,
|
to,
|
||||||
|
@ -96,6 +96,7 @@ export const startWhatsAppSession = async ({
|
|||||||
publicId: publicTypebot.typebot.publicId as string,
|
publicId: publicTypebot.typebot.publicId as string,
|
||||||
isOnlyRegistering: false,
|
isOnlyRegistering: false,
|
||||||
isStreamEnabled: false,
|
isStreamEnabled: false,
|
||||||
|
textBubbleContentFormat: 'richText',
|
||||||
},
|
},
|
||||||
initialSessionState: {
|
initialSessionState: {
|
||||||
whatsApp: {
|
whatsApp: {
|
||||||
|
@ -88,7 +88,7 @@ export async function startChatQuery({
|
|||||||
sessionId,
|
sessionId,
|
||||||
} satisfies Omit<
|
} satisfies Omit<
|
||||||
StartPreviewChatInput,
|
StartPreviewChatInput,
|
||||||
'typebotId' | 'isOnlyRegistering'
|
'typebotId' | 'isOnlyRegistering' | 'textBubbleContentFormat'
|
||||||
>,
|
>,
|
||||||
timeout: false,
|
timeout: false,
|
||||||
}
|
}
|
||||||
@ -113,7 +113,10 @@ export async function startChatQuery({
|
|||||||
prefilledVariables,
|
prefilledVariables,
|
||||||
resultId,
|
resultId,
|
||||||
isOnlyRegistering: false,
|
isOnlyRegistering: false,
|
||||||
} satisfies Omit<StartChatInput, 'publicId'>,
|
} satisfies Omit<
|
||||||
|
StartChatInput,
|
||||||
|
'publicId' | 'textBubbleContentFormat'
|
||||||
|
>,
|
||||||
timeout: false,
|
timeout: false,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -147,6 +147,7 @@ const executeGroup = ({
|
|||||||
version: 2,
|
version: 2,
|
||||||
variables: typebotsQueue[0].typebot.variables,
|
variables: typebotsQueue[0].typebot.variables,
|
||||||
typebotVersion: typebotsQueue[0].typebot.version,
|
typebotVersion: typebotsQueue[0].typebot.version,
|
||||||
|
textBubbleContentFormat: 'markdown',
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
const newMessage =
|
const newMessage =
|
||||||
@ -321,11 +322,11 @@ const convertChatMessageToTranscriptMessage = (
|
|||||||
): TranscriptMessage | null => {
|
): TranscriptMessage | null => {
|
||||||
switch (chatMessage.type) {
|
switch (chatMessage.type) {
|
||||||
case BubbleBlockType.TEXT: {
|
case BubbleBlockType.TEXT: {
|
||||||
if (!chatMessage.content.richText) return null
|
if (chatMessage.content.type === 'richText') return null
|
||||||
return {
|
return {
|
||||||
role: 'bot',
|
role: 'bot',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
text: convertRichTextToMarkdown(chatMessage.content.richText),
|
text: chatMessage.content.markdown,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case BubbleBlockType.IMAGE: {
|
case BubbleBlockType.IMAGE: {
|
||||||
|
@ -47,7 +47,16 @@ export type ChatSession = z.infer<typeof chatSessionSchema>
|
|||||||
const textMessageSchema = z
|
const textMessageSchema = z
|
||||||
.object({
|
.object({
|
||||||
type: z.literal(BubbleBlockType.TEXT),
|
type: z.literal(BubbleBlockType.TEXT),
|
||||||
content: textBubbleContentSchema,
|
content: z.discriminatedUnion('type', [
|
||||||
|
z.object({
|
||||||
|
type: z.literal('richText'),
|
||||||
|
richText: z.any(),
|
||||||
|
}),
|
||||||
|
z.object({
|
||||||
|
type: z.literal('markdown'),
|
||||||
|
markdown: z.string(),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
})
|
})
|
||||||
.openapi({
|
.openapi({
|
||||||
title: 'Text',
|
title: 'Text',
|
||||||
@ -211,6 +220,7 @@ export const startChatInputSchema = z.object({
|
|||||||
Email: 'john@gmail.com',
|
Email: 'john@gmail.com',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
textBubbleContentFormat: z.enum(['richText', 'markdown']).default('richText'),
|
||||||
})
|
})
|
||||||
export type StartChatInput = z.infer<typeof startChatInputSchema>
|
export type StartChatInput = z.infer<typeof startChatInputSchema>
|
||||||
|
|
||||||
@ -265,6 +275,7 @@ export const startPreviewChatInputSchema = z.object({
|
|||||||
.describe(
|
.describe(
|
||||||
'If provided, will be used as the session ID and will overwrite any existing session with the same ID.'
|
'If provided, will be used as the session ID and will overwrite any existing session with the same ID.'
|
||||||
),
|
),
|
||||||
|
textBubbleContentFormat: z.enum(['richText', 'markdown']).default('richText'),
|
||||||
})
|
})
|
||||||
export type StartPreviewChatInput = z.infer<typeof startPreviewChatInputSchema>
|
export type StartPreviewChatInput = z.infer<typeof startPreviewChatInputSchema>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user