2
0
Files
bot/packages/bot-engine/apiHandlers/getMessageStream.ts
2024-04-24 16:11:06 +02:00

150 lines
4.6 KiB
TypeScript

import { IntegrationBlockType } from '@typebot.io/schemas/features/blocks/integrations/constants'
import { ChatCompletionOpenAIOptions } from '@typebot.io/schemas/features/blocks/integrations/openai'
import { OpenAI } from 'openai'
import { decryptV2 } from '@typebot.io/lib/api/encryption/decryptV2'
import { forgedBlocks } from '@typebot.io/forge-repository/definitions'
import { VariableStore } from '@typebot.io/forge'
import {
ParseVariablesOptions,
parseVariables,
} from '@typebot.io/variables/parseVariables'
import { getOpenAIChatCompletionStream } from './legacy/getOpenAIChatCompletionStream'
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
messages: OpenAI.Chat.ChatCompletionMessage[] | undefined
}
export const getMessageStream = async ({ sessionId, messages }: Props) => {
const session = await getSession(sessionId)
if (!session?.state || !session.state.currentBlockId)
return { status: 404, message: 'Could not find session' }
const { group, block } = getBlockById(
session.state.currentBlockId,
session.state.typebotsQueue[0].typebot.groups
)
if (!block || !group)
return {
status: 404,
message: 'Could not find block or group',
}
if (!('options' in block))
return {
status: 400,
message: 'This block does not have options',
}
if (block.type === IntegrationBlockType.OPEN_AI && messages) {
try {
const stream = await getOpenAIChatCompletionStream(
session.state,
block.options as ChatCompletionOpenAIOptions,
messages
)
if (!stream)
return {
status: 500,
message: 'Could not create stream',
}
return { stream }
} catch (error) {
if (error instanceof OpenAI.APIError) {
const { message } = error
return {
status: 500,
message,
}
} else {
throw error
}
}
}
if (!isForgedBlockType(block.type))
return {
status: 400,
message: 'This block does not have a stream function',
}
const blockDef = forgedBlocks[block.type]
const action = blockDef?.actions.find((a) => a.name === block.options?.action)
if (!action || !action.run?.stream)
return {
status: 400,
message: 'This block does not have a stream function',
}
try {
if (!block.options.credentialsId)
return { status: 404, message: 'Could not find credentials' }
const credentials = await getCredentials(block.options.credentialsId)
if (!credentials)
return { status: 404, message: 'Could not find credentials' }
const decryptedCredentials = await decryptV2(
credentials.data,
credentials.iv
)
const variables: VariableStore = {
list: () => session.state.typebotsQueue[0].typebot.variables,
get: (id: string) => {
const variable = session.state.typebotsQueue[0].typebot.variables.find(
(variable) => variable.id === id
)
return variable?.value
},
parse: (text: string, params?: ParseVariablesOptions) =>
parseVariables(
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: deepParseVariables(
session.state.typebotsQueue[0].typebot.variables
)(block.options),
variables,
})
if (!stream) return { status: 500, message: 'Could not create stream' }
return { stream }
} catch (error) {
if (error instanceof OpenAI.APIError) {
const { message } = error
return {
status: 500,
message,
}
}
return {
status: 500,
message: 'Could not create stream',
}
}
}