1
.eslintignore
Normal file
1
.eslintignore
Normal file
@ -0,0 +1 @@
|
|||||||
|
node_modules
|
@ -21,7 +21,7 @@ const injectViewerUrlIfVercelPreview = (val) => {
|
|||||||
process.env.VERCEL_BUILDER_PROJECT_NAME,
|
process.env.VERCEL_BUILDER_PROJECT_NAME,
|
||||||
process.env.NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME
|
process.env.NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME
|
||||||
)
|
)
|
||||||
if (process.env.NEXT_PUBLIC_CHAT_API_URL.includes('{{pr_id}}'))
|
if (process.env.NEXT_PUBLIC_CHAT_API_URL?.includes('{{pr_id}}'))
|
||||||
process.env.NEXT_PUBLIC_CHAT_API_URL =
|
process.env.NEXT_PUBLIC_CHAT_API_URL =
|
||||||
process.env.NEXT_PUBLIC_CHAT_API_URL.replace(
|
process.env.NEXT_PUBLIC_CHAT_API_URL.replace(
|
||||||
'{{pr_id}}',
|
'{{pr_id}}',
|
||||||
@ -56,12 +56,14 @@ const nextConfig = {
|
|||||||
if (nextRuntime === 'edge') {
|
if (nextRuntime === 'edge') {
|
||||||
config.resolve.alias['minio'] = false
|
config.resolve.alias['minio'] = false
|
||||||
config.resolve.alias['got'] = false
|
config.resolve.alias['got'] = false
|
||||||
|
config.resolve.alias['qrcode'] = false
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
// These packages are imports from the integrations definition files that can be ignored for the client.
|
// These packages are imports from the integrations definition files that can be ignored for the client.
|
||||||
config.resolve.alias['minio'] = false
|
config.resolve.alias['minio'] = false
|
||||||
config.resolve.alias['got'] = false
|
config.resolve.alias['got'] = false
|
||||||
config.resolve.alias['openai'] = false
|
config.resolve.alias['openai'] = false
|
||||||
|
config.resolve.alias['qrcode'] = false
|
||||||
return config
|
return config
|
||||||
},
|
},
|
||||||
headers: async () => {
|
headers: async () => {
|
||||||
|
@ -67,7 +67,7 @@
|
|||||||
"framer-motion": "10.3.0",
|
"framer-motion": "10.3.0",
|
||||||
"google-auth-library": "8.9.0",
|
"google-auth-library": "8.9.0",
|
||||||
"google-spreadsheet": "4.1.1",
|
"google-spreadsheet": "4.1.1",
|
||||||
"got": "12.6.0",
|
"ky": "1.2.3",
|
||||||
"immer": "10.0.2",
|
"immer": "10.0.2",
|
||||||
"jsonwebtoken": "9.0.1",
|
"jsonwebtoken": "9.0.1",
|
||||||
"libphonenumber-js": "1.10.37",
|
"libphonenumber-js": "1.10.37",
|
||||||
|
@ -32,7 +32,6 @@ export const getResultExample = authenticatedProcedure
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
.query(async ({ input: { typebotId, blockId }, ctx: { user } }) => {
|
.query(async ({ input: { typebotId, blockId }, ctx: { user } }) => {
|
||||||
console.log('user', user)
|
|
||||||
const typebot = (await prisma.typebot.findFirst({
|
const typebot = (await prisma.typebot.findFirst({
|
||||||
where: canReadTypebots(typebotId, user),
|
where: canReadTypebots(typebotId, user),
|
||||||
select: {
|
select: {
|
||||||
|
@ -17,7 +17,7 @@ export const convertVariablesForTestToVariables = (
|
|||||||
) as Variable
|
) as Variable
|
||||||
return { ...variable, value: parseVariableValue(variableForTest.value) }
|
return { ...variable, value: parseVariableValue(variableForTest.value) }
|
||||||
}, {}),
|
}, {}),
|
||||||
]
|
].filter((v) => v.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const parseVariableValue = (value: string | undefined): string | string[] => {
|
const parseVariableValue = (value: string | undefined): string | string[] => {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Variable, HttpResponse } from '@typebot.io/schemas'
|
import { Variable, HttpResponse } from '@typebot.io/schemas'
|
||||||
import { sendRequest } from '@typebot.io/lib'
|
import { sendRequest } from '@typebot.io/lib'
|
||||||
import { env } from '@typebot.io/env'
|
|
||||||
|
|
||||||
export const executeWebhook = (
|
export const executeWebhook = (
|
||||||
typebotId: string,
|
typebotId: string,
|
||||||
@ -8,7 +7,7 @@ export const executeWebhook = (
|
|||||||
{ blockId }: { blockId: string }
|
{ blockId }: { blockId: string }
|
||||||
) =>
|
) =>
|
||||||
sendRequest<HttpResponse>({
|
sendRequest<HttpResponse>({
|
||||||
url: `${env.NEXT_PUBLIC_VIEWER_URL[0]}/api/typebots/${typebotId}/blocks/${blockId}/executeWebhook`,
|
url: `/api/typebots/${typebotId}/blocks/${blockId}/testWebhook`,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: {
|
body: {
|
||||||
variables,
|
variables,
|
||||||
|
@ -5,7 +5,7 @@ import { z } from 'zod'
|
|||||||
import { isReadWorkspaceFobidden } from '@/features/workspace/helpers/isReadWorkspaceFobidden'
|
import { isReadWorkspaceFobidden } from '@/features/workspace/helpers/isReadWorkspaceFobidden'
|
||||||
import { decrypt } from '@typebot.io/lib/api/encryption/decrypt'
|
import { decrypt } from '@typebot.io/lib/api/encryption/decrypt'
|
||||||
import { ZemanticAiCredentials } from '@typebot.io/schemas/features/blocks/integrations/zemanticAi'
|
import { ZemanticAiCredentials } from '@typebot.io/schemas/features/blocks/integrations/zemanticAi'
|
||||||
import got from 'got'
|
import ky from 'ky'
|
||||||
|
|
||||||
export const listProjects = authenticatedProcedure
|
export const listProjects = authenticatedProcedure
|
||||||
.input(
|
.input(
|
||||||
@ -58,7 +58,7 @@ export const listProjects = authenticatedProcedure
|
|||||||
const url = 'https://api.zemantic.ai/v1/projects'
|
const url = 'https://api.zemantic.ai/v1/projects'
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await got
|
const response = await ky
|
||||||
.get(url, {
|
.get(url, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${data.apiKey}`,
|
Authorization: `Bearer ${data.apiKey}`,
|
||||||
|
@ -3,7 +3,7 @@ import { authenticatedProcedure } from '@/helpers/server/trpc'
|
|||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { customDomainSchema } from '@typebot.io/schemas/features/customDomains'
|
import { customDomainSchema } from '@typebot.io/schemas/features/customDomains'
|
||||||
import got, { HTTPError } from 'got'
|
import ky, { HTTPError } from 'ky'
|
||||||
import { env } from '@typebot.io/env'
|
import { env } from '@typebot.io/env'
|
||||||
import { isWriteWorkspaceForbidden } from '@/features/workspace/helpers/isWriteWorkspaceForbidden'
|
import { isWriteWorkspaceForbidden } from '@/features/workspace/helpers/isWriteWorkspaceForbidden'
|
||||||
import { trackEvents } from '@typebot.io/telemetry/trackEvents'
|
import { trackEvents } from '@typebot.io/telemetry/trackEvents'
|
||||||
@ -61,12 +61,12 @@ export const createCustomDomain = authenticatedProcedure
|
|||||||
try {
|
try {
|
||||||
await createDomainOnVercel(name)
|
await createDomainOnVercel(name)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err)
|
if (err instanceof HTTPError && err.response.status !== 409) {
|
||||||
if (err instanceof HTTPError && err.response.statusCode !== 409)
|
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: 'INTERNAL_SERVER_ERROR',
|
code: 'INTERNAL_SERVER_ERROR',
|
||||||
message: 'Failed to create custom domain on Vercel',
|
message: 'Failed to create custom domain on Vercel',
|
||||||
})
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const customDomain = await prisma.customDomain.create({
|
const customDomain = await prisma.customDomain.create({
|
||||||
@ -91,8 +91,12 @@ export const createCustomDomain = authenticatedProcedure
|
|||||||
})
|
})
|
||||||
|
|
||||||
const createDomainOnVercel = (name: string) =>
|
const createDomainOnVercel = (name: string) =>
|
||||||
got.post({
|
ky.post(
|
||||||
url: `https://api.vercel.com/v10/projects/${env.NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME}/domains?teamId=${env.VERCEL_TEAM_ID}`,
|
`https://api.vercel.com/v10/projects/${env.NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME}/domains?teamId=${env.VERCEL_TEAM_ID}`,
|
||||||
headers: { Authorization: `Bearer ${env.VERCEL_TOKEN}` },
|
{
|
||||||
json: { name },
|
headers: {
|
||||||
})
|
authorization: `Bearer ${env.VERCEL_TOKEN}`,
|
||||||
|
},
|
||||||
|
json: { name },
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ -2,7 +2,7 @@ import prisma from '@typebot.io/lib/prisma'
|
|||||||
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import got from 'got'
|
import ky from 'ky'
|
||||||
import { env } from '@typebot.io/env'
|
import { env } from '@typebot.io/env'
|
||||||
import { isWriteWorkspaceForbidden } from '@/features/workspace/helpers/isWriteWorkspaceForbidden'
|
import { isWriteWorkspaceForbidden } from '@/features/workspace/helpers/isWriteWorkspaceForbidden'
|
||||||
|
|
||||||
@ -63,7 +63,9 @@ export const deleteCustomDomain = authenticatedProcedure
|
|||||||
})
|
})
|
||||||
|
|
||||||
const deleteDomainOnVercel = (name: string) =>
|
const deleteDomainOnVercel = (name: string) =>
|
||||||
got.delete({
|
ky.delete(
|
||||||
url: `https://api.vercel.com/v9/projects/${env.NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME}/domains/${name}?teamId=${env.VERCEL_TEAM_ID}`,
|
`https://api.vercel.com/v9/projects/${env.NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME}/domains/${name}?teamId=${env.VERCEL_TEAM_ID}`,
|
||||||
headers: { Authorization: `Bearer ${env.VERCEL_TOKEN}` },
|
{
|
||||||
})
|
headers: { Authorization: `Bearer ${env.VERCEL_TOKEN}` },
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ -377,6 +377,7 @@ const SystemUserToken = ({
|
|||||||
<ListItem>Copy and paste the generated token:</ListItem>
|
<ListItem>Copy and paste the generated token:</ListItem>
|
||||||
<TextInput
|
<TextInput
|
||||||
isRequired
|
isRequired
|
||||||
|
type="password"
|
||||||
label="System User Token"
|
label="System User Token"
|
||||||
defaultValue={initialToken}
|
defaultValue={initialToken}
|
||||||
onChange={(val) => setToken(val.trim())}
|
onChange={(val) => setToken(val.trim())}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import got from 'got'
|
import ky from 'ky'
|
||||||
import prisma from '@typebot.io/lib/prisma'
|
import prisma from '@typebot.io/lib/prisma'
|
||||||
import { decrypt } from '@typebot.io/lib/api/encryption/decrypt'
|
import { decrypt } from '@typebot.io/lib/api/encryption/decrypt'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
@ -22,16 +22,13 @@ export const getPhoneNumber = authenticatedProcedure
|
|||||||
code: 'NOT_FOUND',
|
code: 'NOT_FOUND',
|
||||||
message: 'Credentials not found',
|
message: 'Credentials not found',
|
||||||
})
|
})
|
||||||
const { display_phone_number } = (await got(
|
const { display_phone_number } = await ky
|
||||||
`${env.WHATSAPP_CLOUD_API_URL}/v17.0/${credentials.phoneNumberId}`,
|
.get(`${env.WHATSAPP_CLOUD_API_URL}/v17.0/${credentials.phoneNumberId}`, {
|
||||||
{
|
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${credentials.systemUserAccessToken}`,
|
Authorization: `Bearer ${credentials.systemUserAccessToken}`,
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
).json()) as {
|
.json<{ display_phone_number: string }>()
|
||||||
display_phone_number: string
|
|
||||||
}
|
|
||||||
|
|
||||||
const formattedPhoneNumber = `${
|
const formattedPhoneNumber = `${
|
||||||
display_phone_number.startsWith('+') ? '' : '+'
|
display_phone_number.startsWith('+') ? '' : '+'
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import got from 'got'
|
import ky from 'ky'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { WhatsAppCredentials } from '@typebot.io/schemas/features/whatsapp'
|
import { WhatsAppCredentials } from '@typebot.io/schemas/features/whatsapp'
|
||||||
import prisma from '@typebot.io/lib/prisma'
|
import prisma from '@typebot.io/lib/prisma'
|
||||||
@ -28,21 +28,23 @@ export const getSystemTokenInfo = authenticatedProcedure
|
|||||||
})
|
})
|
||||||
const {
|
const {
|
||||||
data: { expires_at, scopes, app_id, application },
|
data: { expires_at, scopes, app_id, application },
|
||||||
} = (await got(
|
} = await ky
|
||||||
`${env.WHATSAPP_CLOUD_API_URL}/v17.0/debug_token?input_token=${credentials.systemUserAccessToken}`,
|
.get(
|
||||||
{
|
`${env.WHATSAPP_CLOUD_API_URL}/v17.0/debug_token?input_token=${credentials.systemUserAccessToken}`,
|
||||||
headers: {
|
{
|
||||||
Authorization: `Bearer ${credentials.systemUserAccessToken}`,
|
headers: {
|
||||||
},
|
Authorization: `Bearer ${credentials.systemUserAccessToken}`,
|
||||||
}
|
},
|
||||||
).json()) as {
|
}
|
||||||
data: {
|
)
|
||||||
app_id: string
|
.json<{
|
||||||
application: string
|
data: {
|
||||||
expires_at: number
|
app_id: string
|
||||||
scopes: string[]
|
application: string
|
||||||
}
|
expires_at: number
|
||||||
}
|
scopes: string[]
|
||||||
|
}
|
||||||
|
}>()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
appId: app_id,
|
appId: app_id,
|
||||||
|
@ -3,7 +3,7 @@ import { z } from 'zod'
|
|||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { startSession } from '@typebot.io/bot-engine/startSession'
|
import { startSession } from '@typebot.io/bot-engine/startSession'
|
||||||
import { env } from '@typebot.io/env'
|
import { env } from '@typebot.io/env'
|
||||||
import { HTTPError } from 'got'
|
import { HTTPError } from 'ky'
|
||||||
import prisma from '@typebot.io/lib/prisma'
|
import prisma from '@typebot.io/lib/prisma'
|
||||||
import { saveStateToDatabase } from '@typebot.io/bot-engine/saveStateToDatabase'
|
import { saveStateToDatabase } from '@typebot.io/bot-engine/saveStateToDatabase'
|
||||||
import { restartSession } from '@typebot.io/bot-engine/queries/restartSession'
|
import { restartSession } from '@typebot.io/bot-engine/queries/restartSession'
|
||||||
@ -169,7 +169,7 @@ export const startWhatsAppPreview = authenticatedProcedure
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof HTTPError) console.log(err.response.body)
|
if (err instanceof HTTPError) console.log(await err.response.text())
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: 'INTERNAL_SERVER_ERROR',
|
code: 'INTERNAL_SERVER_ERROR',
|
||||||
message: 'Request to Meta to send preview message failed',
|
message: 'Request to Meta to send preview message failed',
|
||||||
|
@ -16,7 +16,7 @@ import { getNewUserInvitations } from '@/features/auth/helpers/getNewUserInvitat
|
|||||||
import { sendVerificationRequest } from '@/features/auth/helpers/sendVerificationRequest'
|
import { sendVerificationRequest } from '@/features/auth/helpers/sendVerificationRequest'
|
||||||
import { Ratelimit } from '@upstash/ratelimit'
|
import { Ratelimit } from '@upstash/ratelimit'
|
||||||
import { Redis } from '@upstash/redis/nodejs'
|
import { Redis } from '@upstash/redis/nodejs'
|
||||||
import got from 'got'
|
import ky from 'ky'
|
||||||
import { env } from '@typebot.io/env'
|
import { env } from '@typebot.io/env'
|
||||||
import * as Sentry from '@sentry/nextjs'
|
import * as Sentry from '@sentry/nextjs'
|
||||||
import { getIp } from '@typebot.io/lib/getIp'
|
import { getIp } from '@typebot.io/lib/getIp'
|
||||||
@ -164,10 +164,12 @@ export const getAuthOptions = ({
|
|||||||
if (!account) return false
|
if (!account) return false
|
||||||
const isNewUser = !('createdAt' in user && isDefined(user.createdAt))
|
const isNewUser = !('createdAt' in user && isDefined(user.createdAt))
|
||||||
if (isNewUser && user.email) {
|
if (isNewUser && user.email) {
|
||||||
const { body } = await got.get(
|
const data = await ky
|
||||||
'https://raw.githubusercontent.com/disposable-email-domains/disposable-email-domains/master/disposable_email_blocklist.conf'
|
.get(
|
||||||
)
|
'https://raw.githubusercontent.com/disposable-email-domains/disposable-email-domains/master/disposable_email_blocklist.conf'
|
||||||
const disposableEmailDomains = body.split('\n')
|
)
|
||||||
|
.text()
|
||||||
|
const disposableEmailDomains = data.split('\n')
|
||||||
if (disposableEmailDomains.includes(user.email.split('@')[1]))
|
if (disposableEmailDomains.includes(user.email.split('@')[1]))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
methodNotAllowed,
|
methodNotAllowed,
|
||||||
notAuthenticated,
|
notAuthenticated,
|
||||||
} from '@typebot.io/lib/api'
|
} from '@typebot.io/lib/api'
|
||||||
import { got } from 'got'
|
import ky from 'ky'
|
||||||
import { getAuthenticatedUser } from '@/features/auth/helpers/getAuthenticatedUser'
|
import { getAuthenticatedUser } from '@/features/auth/helpers/getAuthenticatedUser'
|
||||||
import { env } from '@typebot.io/env'
|
import { env } from '@typebot.io/env'
|
||||||
|
|
||||||
@ -31,9 +31,11 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const deleteDomainOnVercel = (name: string) =>
|
const deleteDomainOnVercel = (name: string) =>
|
||||||
got.delete({
|
ky.delete(
|
||||||
url: `https://api.vercel.com/v8/projects/${env.NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME}/domains/${name}?teamId=${env.VERCEL_TEAM_ID}`,
|
`https://api.vercel.com/v8/projects/${env.NEXT_PUBLIC_VERCEL_VIEWER_PROJECT_NAME}/domains/${name}?teamId=${env.VERCEL_TEAM_ID}`,
|
||||||
headers: { Authorization: `Bearer ${env.VERCEL_TOKEN}` },
|
{
|
||||||
})
|
headers: { Authorization: `Bearer ${env.VERCEL_TOKEN}` },
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
export default handler
|
export default handler
|
||||||
|
@ -0,0 +1,114 @@
|
|||||||
|
import {
|
||||||
|
Typebot,
|
||||||
|
Variable,
|
||||||
|
HttpRequest,
|
||||||
|
Block,
|
||||||
|
AnswerInSessionState,
|
||||||
|
} from '@typebot.io/schemas'
|
||||||
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
|
import { byId } from '@typebot.io/lib'
|
||||||
|
import { isWebhookBlock } from '@typebot.io/schemas/helpers'
|
||||||
|
import { methodNotAllowed, notFound } from '@typebot.io/lib/api'
|
||||||
|
import prisma from '@typebot.io/lib/prisma'
|
||||||
|
import { getBlockById } from '@typebot.io/schemas/helpers'
|
||||||
|
import {
|
||||||
|
executeWebhook,
|
||||||
|
parseWebhookAttributes,
|
||||||
|
} from '@typebot.io/bot-engine/blocks/integrations/webhook/executeWebhookBlock'
|
||||||
|
import { fetchLinkedChildTypebots } from '@typebot.io/bot-engine/blocks/logic/typebotLink/fetchLinkedChildTypebots'
|
||||||
|
import { parseSampleResult } from '@typebot.io/bot-engine/blocks/integrations/webhook/parseSampleResult'
|
||||||
|
import { saveLog } from '@typebot.io/bot-engine/logs/saveLog'
|
||||||
|
import { getAuthenticatedUser } from '@/features/auth/helpers/getAuthenticatedUser'
|
||||||
|
|
||||||
|
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
|
if (req.method === 'POST') {
|
||||||
|
const user = await getAuthenticatedUser(req, res)
|
||||||
|
const typebotId = req.query.typebotId as string
|
||||||
|
const blockId = req.query.blockId as string
|
||||||
|
const resultId = req.query.resultId as string | undefined
|
||||||
|
const { variables } = (
|
||||||
|
typeof req.body === 'string' ? JSON.parse(req.body) : req.body
|
||||||
|
) as {
|
||||||
|
variables: Variable[]
|
||||||
|
}
|
||||||
|
const typebot = (await prisma.typebot.findUnique({
|
||||||
|
where: { id: typebotId },
|
||||||
|
include: { webhooks: true },
|
||||||
|
})) as unknown as (Typebot & { webhooks: HttpRequest[] }) | null
|
||||||
|
if (!typebot) return notFound(res)
|
||||||
|
const block = typebot.groups
|
||||||
|
.flatMap<Block>((g) => g.blocks)
|
||||||
|
.find(byId(blockId))
|
||||||
|
if (!block || !isWebhookBlock(block))
|
||||||
|
return notFound(res, 'Webhook block not found')
|
||||||
|
const webhookId = 'webhookId' in block ? block.webhookId : undefined
|
||||||
|
const webhook =
|
||||||
|
block.options?.webhook ??
|
||||||
|
typebot.webhooks.find((w) => {
|
||||||
|
if ('id' in w) return w.id === webhookId
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
if (!webhook)
|
||||||
|
return res
|
||||||
|
.status(404)
|
||||||
|
.send({ statusCode: 404, data: { message: `Couldn't find webhook` } })
|
||||||
|
const { group } = getBlockById(blockId, typebot.groups)
|
||||||
|
const linkedTypebots = await fetchLinkedChildTypebots({
|
||||||
|
isPreview: !('typebotId' in typebot),
|
||||||
|
typebots: [typebot],
|
||||||
|
userId: user?.id,
|
||||||
|
})([])
|
||||||
|
|
||||||
|
const answers = arrayify(
|
||||||
|
await parseSampleResult(typebot, linkedTypebots)(group.id, variables)
|
||||||
|
)
|
||||||
|
|
||||||
|
const parsedWebhook = await parseWebhookAttributes({
|
||||||
|
webhook,
|
||||||
|
isCustomBody: block.options?.isCustomBody,
|
||||||
|
typebot: {
|
||||||
|
...typebot,
|
||||||
|
variables: typebot.variables.map((v) => {
|
||||||
|
const matchingVariable = variables.find(byId(v.id))
|
||||||
|
if (!matchingVariable) return v
|
||||||
|
return { ...v, value: matchingVariable.value }
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
answers,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!parsedWebhook)
|
||||||
|
return res.status(500).send({
|
||||||
|
statusCode: 500,
|
||||||
|
data: { message: `Couldn't parse webhook attributes` },
|
||||||
|
})
|
||||||
|
|
||||||
|
const { response, logs } = await executeWebhook(parsedWebhook, {
|
||||||
|
timeout: block.options?.timeout,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (resultId)
|
||||||
|
await Promise.all(
|
||||||
|
logs?.map((log) =>
|
||||||
|
saveLog({
|
||||||
|
message: log.description,
|
||||||
|
details: log.details,
|
||||||
|
status: log.status as 'error' | 'success' | 'info',
|
||||||
|
resultId,
|
||||||
|
})
|
||||||
|
) ?? []
|
||||||
|
)
|
||||||
|
|
||||||
|
return res.status(200).send(response)
|
||||||
|
}
|
||||||
|
return methodNotAllowed(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
const arrayify = (
|
||||||
|
obj: Record<string, string | boolean | undefined>
|
||||||
|
): AnswerInSessionState[] =>
|
||||||
|
Object.entries(obj)
|
||||||
|
.map(([key, value]) => ({ key, value: value?.toString() }))
|
||||||
|
.filter((a) => a.value) as AnswerInSessionState[]
|
||||||
|
|
||||||
|
export default handler
|
@ -9,7 +9,7 @@ Here is the `sendMessage` action of the Telegram block:
|
|||||||
```ts
|
```ts
|
||||||
import { createAction, option } from '@typebot.io/forge'
|
import { createAction, option } from '@typebot.io/forge'
|
||||||
import { auth } from '../auth'
|
import { auth } from '../auth'
|
||||||
import { got } from 'got'
|
import ky from 'ky'
|
||||||
|
|
||||||
export const sendMessage = createAction({
|
export const sendMessage = createAction({
|
||||||
auth,
|
auth,
|
||||||
@ -27,14 +27,14 @@ export const sendMessage = createAction({
|
|||||||
run: {
|
run: {
|
||||||
server: async ({ credentials: { token }, options: { chatId, text } }) => {
|
server: async ({ credentials: { token }, options: { chatId, text } }) => {
|
||||||
try {
|
try {
|
||||||
await got.post(`https://api.telegram.org/bot${token}/sendMessage`, {
|
await ky.post(`https://api.telegram.org/bot${token}/sendMessage`, {
|
||||||
json: {
|
json: {
|
||||||
chat_id: chatId,
|
chat_id: chatId,
|
||||||
text,
|
text,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('ERROR', error.response.body)
|
console.log('ERROR', await error.response.text())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -13,8 +13,6 @@ An action can do one of the following things:
|
|||||||
|
|
||||||
The most common action is to execute a function on the server. This is done by simply declaring that function in the action block.
|
The most common action is to execute a function on the server. This is done by simply declaring that function in the action block.
|
||||||
|
|
||||||
If you need to use an external package that is not compatible with web browser environment, you will have to dynamically import it in the server function. You can find an example of this in the [Anthropic's Create Chat Message action](https://github.com/baptisteArno/typebot.io/blob/main/packages/forge/blocks/anthropic/actions/createChatMessage.tsx)
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
|
@ -17,7 +17,7 @@ const injectViewerUrlIfVercelPreview = (val) => {
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
process.env.NEXT_PUBLIC_VIEWER_URL = `https://${process.env.VERCEL_BRANCH_URL}`
|
process.env.NEXT_PUBLIC_VIEWER_URL = `https://${process.env.VERCEL_BRANCH_URL}`
|
||||||
if (process.env.NEXT_PUBLIC_CHAT_API_URL.includes('{{pr_id}}'))
|
if (process.env.NEXT_PUBLIC_CHAT_API_URL?.includes('{{pr_id}}'))
|
||||||
process.env.NEXT_PUBLIC_CHAT_API_URL =
|
process.env.NEXT_PUBLIC_CHAT_API_URL =
|
||||||
process.env.NEXT_PUBLIC_CHAT_API_URL.replace(
|
process.env.NEXT_PUBLIC_CHAT_API_URL.replace(
|
||||||
'{{pr_id}}',
|
'{{pr_id}}',
|
||||||
@ -56,12 +56,14 @@ const nextConfig = {
|
|||||||
if (nextRuntime === 'edge') {
|
if (nextRuntime === 'edge') {
|
||||||
config.resolve.alias['minio'] = false
|
config.resolve.alias['minio'] = false
|
||||||
config.resolve.alias['got'] = false
|
config.resolve.alias['got'] = false
|
||||||
|
config.resolve.alias['qrcode'] = false
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
// These packages are imports from the integrations definition files that can be ignored for the client.
|
// These packages are imports from the integrations definition files that can be ignored for the client.
|
||||||
config.resolve.alias['minio'] = false
|
config.resolve.alias['minio'] = false
|
||||||
config.resolve.alias['got'] = false
|
config.resolve.alias['got'] = false
|
||||||
config.resolve.alias['openai'] = false
|
config.resolve.alias['openai'] = false
|
||||||
|
config.resolve.alias['qrcode'] = false
|
||||||
return config
|
return config
|
||||||
},
|
},
|
||||||
async redirects() {
|
async redirects() {
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
"cors": "2.8.5",
|
"cors": "2.8.5",
|
||||||
"google-spreadsheet": "4.1.1",
|
"google-spreadsheet": "4.1.1",
|
||||||
"got": "12.6.0",
|
"got": "12.6.0",
|
||||||
|
"ky": "1.2.3",
|
||||||
"next": "14.1.0",
|
"next": "14.1.0",
|
||||||
"nextjs-cors": "2.1.2",
|
"nextjs-cors": "2.1.2",
|
||||||
"nodemailer": "6.9.8",
|
"nodemailer": "6.9.8",
|
||||||
|
@ -1,45 +1,35 @@
|
|||||||
import {
|
import {
|
||||||
PublicTypebot,
|
|
||||||
ResultValues,
|
ResultValues,
|
||||||
Typebot,
|
Typebot,
|
||||||
Variable,
|
Variable,
|
||||||
HttpRequest,
|
HttpRequest,
|
||||||
HttpResponse,
|
|
||||||
Block,
|
Block,
|
||||||
|
PublicTypebot,
|
||||||
|
AnswerInSessionState,
|
||||||
} from '@typebot.io/schemas'
|
} from '@typebot.io/schemas'
|
||||||
import { NextApiRequest, NextApiResponse } from 'next'
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
import got, { Method, Headers, HTTPError } from 'got'
|
import { byId } from '@typebot.io/lib'
|
||||||
import { byId, isEmpty, isNotDefined, omit } from '@typebot.io/lib'
|
|
||||||
import { isWebhookBlock } from '@typebot.io/schemas/helpers'
|
import { isWebhookBlock } from '@typebot.io/schemas/helpers'
|
||||||
import { parseAnswers } from '@typebot.io/results/parseAnswers'
|
|
||||||
import { initMiddleware, methodNotAllowed, notFound } from '@typebot.io/lib/api'
|
import { initMiddleware, methodNotAllowed, notFound } from '@typebot.io/lib/api'
|
||||||
import { stringify } from 'qs'
|
|
||||||
import Cors from 'cors'
|
import Cors from 'cors'
|
||||||
import prisma from '@typebot.io/lib/prisma'
|
import prisma from '@typebot.io/lib/prisma'
|
||||||
import { fetchLinkedTypebots } from '@typebot.io/bot-engine/blocks/logic/typebotLink/fetchLinkedTypebots'
|
|
||||||
import { getPreviouslyLinkedTypebots } from '@typebot.io/bot-engine/blocks/logic/typebotLink/getPreviouslyLinkedTypebots'
|
|
||||||
import { parseVariables } from '@typebot.io/variables/parseVariables'
|
|
||||||
import { saveErrorLog } from '@typebot.io/bot-engine/logs/saveErrorLog'
|
|
||||||
import { saveSuccessLog } from '@typebot.io/bot-engine/logs/saveSuccessLog'
|
|
||||||
import { parseSampleResult } from '@typebot.io/bot-engine/blocks/integrations/webhook/parseSampleResult'
|
|
||||||
import {
|
|
||||||
HttpMethod,
|
|
||||||
defaultTimeout,
|
|
||||||
defaultWebhookAttributes,
|
|
||||||
maxTimeout,
|
|
||||||
} from '@typebot.io/schemas/features/blocks/integrations/webhook/constants'
|
|
||||||
import { getBlockById } from '@typebot.io/schemas/helpers'
|
import { getBlockById } from '@typebot.io/schemas/helpers'
|
||||||
import {
|
import {
|
||||||
convertKeyValueTableToObject,
|
executeWebhook,
|
||||||
longReqTimeoutWhitelist,
|
parseWebhookAttributes,
|
||||||
} from '@typebot.io/bot-engine/blocks/integrations/webhook/executeWebhookBlock'
|
} from '@typebot.io/bot-engine/blocks/integrations/webhook/executeWebhookBlock'
|
||||||
import { env } from '@typebot.io/env'
|
import { fetchLinkedParentTypebots } from '@typebot.io/bot-engine/blocks/logic/typebotLink/fetchLinkedParentTypebots'
|
||||||
|
import { fetchLinkedChildTypebots } from '@typebot.io/bot-engine/blocks/logic/typebotLink/fetchLinkedChildTypebots'
|
||||||
|
import { parseSampleResult } from '@typebot.io/bot-engine/blocks/integrations/webhook/parseSampleResult'
|
||||||
|
import { saveLog } from '@typebot.io/bot-engine/logs/saveLog'
|
||||||
|
import { authenticateUser } from '@/helpers/authenticateUser'
|
||||||
|
|
||||||
const cors = initMiddleware(Cors())
|
const cors = initMiddleware(Cors())
|
||||||
|
|
||||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
await cors(req, res)
|
await cors(req, res)
|
||||||
if (req.method === 'POST') {
|
if (req.method === 'POST') {
|
||||||
|
const user = await authenticateUser(req)
|
||||||
const typebotId = req.query.typebotId as string
|
const typebotId = req.query.typebotId as string
|
||||||
const blockId = req.query.blockId as string
|
const blockId = req.query.blockId as string
|
||||||
const resultId = req.query.resultId as string | undefined
|
const resultId = req.query.resultId as string | undefined
|
||||||
@ -72,232 +62,81 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||||||
.status(404)
|
.status(404)
|
||||||
.send({ statusCode: 404, data: { message: `Couldn't find webhook` } })
|
.send({ statusCode: 404, data: { message: `Couldn't find webhook` } })
|
||||||
const { group } = getBlockById(blockId, typebot.groups)
|
const { group } = getBlockById(blockId, typebot.groups)
|
||||||
const result = await executeWebhook(typebot)({
|
const linkedTypebotsParents = (await fetchLinkedParentTypebots({
|
||||||
webhook,
|
isPreview: !('typebotId' in typebot),
|
||||||
variables,
|
|
||||||
groupId: group.id,
|
|
||||||
resultValues,
|
|
||||||
resultId,
|
|
||||||
parentTypebotIds,
|
parentTypebotIds,
|
||||||
|
userId: user?.id,
|
||||||
|
})) as (Typebot | PublicTypebot)[]
|
||||||
|
const linkedTypebotsChildren = await fetchLinkedChildTypebots({
|
||||||
|
isPreview: !('typebotId' in typebot),
|
||||||
|
typebots: [typebot],
|
||||||
|
userId: user?.id,
|
||||||
|
})([])
|
||||||
|
|
||||||
|
const linkedTypebots = [...linkedTypebotsParents, ...linkedTypebotsChildren]
|
||||||
|
|
||||||
|
const answers = resultValues
|
||||||
|
? resultValues.answers.map((answer) => ({
|
||||||
|
key:
|
||||||
|
(answer.variableId
|
||||||
|
? typebot.variables.find(
|
||||||
|
(variable) => variable.id === answer.variableId
|
||||||
|
)?.name
|
||||||
|
: typebot.groups.find((group) =>
|
||||||
|
group.blocks.find((block) => block.id === answer.blockId)
|
||||||
|
)?.title) ?? '',
|
||||||
|
value: answer.content,
|
||||||
|
}))
|
||||||
|
: arrayify(
|
||||||
|
await parseSampleResult(typebot, linkedTypebots)(group.id, variables)
|
||||||
|
)
|
||||||
|
|
||||||
|
const parsedWebhook = await parseWebhookAttributes({
|
||||||
|
webhook,
|
||||||
isCustomBody: block.options?.isCustomBody,
|
isCustomBody: block.options?.isCustomBody,
|
||||||
|
typebot: {
|
||||||
|
...typebot,
|
||||||
|
variables: typebot.variables.map((v) => {
|
||||||
|
const matchingVariable = variables.find(byId(v.id))
|
||||||
|
if (!matchingVariable) return v
|
||||||
|
return { ...v, value: matchingVariable.value }
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
answers,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!parsedWebhook)
|
||||||
|
return res.status(500).send({
|
||||||
|
statusCode: 500,
|
||||||
|
data: { message: `Couldn't parse webhook attributes` },
|
||||||
|
})
|
||||||
|
|
||||||
|
const { response, logs } = await executeWebhook(parsedWebhook, {
|
||||||
timeout: block.options?.timeout,
|
timeout: block.options?.timeout,
|
||||||
})
|
})
|
||||||
return res.status(200).send(result)
|
|
||||||
|
if (resultId)
|
||||||
|
await Promise.all(
|
||||||
|
logs?.map((log) =>
|
||||||
|
saveLog({
|
||||||
|
message: log.description,
|
||||||
|
details: log.details,
|
||||||
|
status: log.status as 'error' | 'success' | 'info',
|
||||||
|
resultId,
|
||||||
|
})
|
||||||
|
) ?? []
|
||||||
|
)
|
||||||
|
|
||||||
|
return res.status(200).send(response)
|
||||||
}
|
}
|
||||||
return methodNotAllowed(res)
|
return methodNotAllowed(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkIfBodyIsAVariable = (body: string) => /^{{.+}}$/.test(body)
|
const arrayify = (
|
||||||
|
obj: Record<string, string | boolean | undefined>
|
||||||
export const executeWebhook =
|
): AnswerInSessionState[] =>
|
||||||
(typebot: Typebot) =>
|
Object.entries(obj)
|
||||||
async ({
|
.map(([key, value]) => ({ key, value: value?.toString() }))
|
||||||
webhook,
|
.filter((a) => a.value) as AnswerInSessionState[]
|
||||||
variables,
|
|
||||||
groupId,
|
|
||||||
resultValues,
|
|
||||||
resultId,
|
|
||||||
parentTypebotIds = [],
|
|
||||||
isCustomBody,
|
|
||||||
timeout,
|
|
||||||
}: {
|
|
||||||
webhook: HttpRequest
|
|
||||||
variables: Variable[]
|
|
||||||
groupId: string
|
|
||||||
resultValues?: ResultValues
|
|
||||||
resultId?: string
|
|
||||||
parentTypebotIds: string[]
|
|
||||||
isCustomBody?: boolean
|
|
||||||
timeout?: number
|
|
||||||
}): Promise<HttpResponse> => {
|
|
||||||
if (!webhook.url)
|
|
||||||
return {
|
|
||||||
statusCode: 400,
|
|
||||||
data: { message: `Webhook doesn't have url or method` },
|
|
||||||
}
|
|
||||||
const basicAuth: { username?: string; password?: string } = {}
|
|
||||||
const basicAuthHeaderIdx =
|
|
||||||
webhook.headers?.findIndex(
|
|
||||||
(h) =>
|
|
||||||
h.key?.toLowerCase() === 'authorization' &&
|
|
||||||
h.value?.toLowerCase()?.includes('basic')
|
|
||||||
) ?? -1
|
|
||||||
const isUsernamePasswordBasicAuth =
|
|
||||||
basicAuthHeaderIdx !== -1 &&
|
|
||||||
webhook.headers?.[basicAuthHeaderIdx].value?.includes(':')
|
|
||||||
if (isUsernamePasswordBasicAuth) {
|
|
||||||
const [username, password] =
|
|
||||||
webhook.headers?.[basicAuthHeaderIdx].value?.slice(6).split(':') ?? []
|
|
||||||
basicAuth.username = username
|
|
||||||
basicAuth.password = password
|
|
||||||
webhook.headers?.splice(basicAuthHeaderIdx, 1)
|
|
||||||
}
|
|
||||||
const headers = convertKeyValueTableToObject(webhook.headers, variables) as
|
|
||||||
| Headers
|
|
||||||
| undefined
|
|
||||||
const queryParams = stringify(
|
|
||||||
convertKeyValueTableToObject(webhook.queryParams, variables)
|
|
||||||
)
|
|
||||||
const contentType = headers ? headers['Content-Type'] : undefined
|
|
||||||
const linkedTypebotsParents = (await fetchLinkedTypebots({
|
|
||||||
isPreview: !('typebotId' in typebot),
|
|
||||||
typebotIds: parentTypebotIds,
|
|
||||||
})) as (Typebot | PublicTypebot)[]
|
|
||||||
const linkedTypebotsChildren = await getPreviouslyLinkedTypebots({
|
|
||||||
isPreview: !('typebotId' in typebot),
|
|
||||||
typebots: [typebot],
|
|
||||||
})([])
|
|
||||||
const bodyContent = await getBodyContent(typebot, [
|
|
||||||
...linkedTypebotsParents,
|
|
||||||
...linkedTypebotsChildren,
|
|
||||||
])({
|
|
||||||
body: webhook.body,
|
|
||||||
isCustomBody,
|
|
||||||
resultValues,
|
|
||||||
groupId,
|
|
||||||
variables,
|
|
||||||
})
|
|
||||||
const { data: body, isJson } =
|
|
||||||
bodyContent && webhook.method !== HttpMethod.GET
|
|
||||||
? safeJsonParse(
|
|
||||||
parseVariables(variables, {
|
|
||||||
isInsideJson: !checkIfBodyIsAVariable(bodyContent),
|
|
||||||
})(bodyContent)
|
|
||||||
)
|
|
||||||
: { data: undefined, isJson: false }
|
|
||||||
|
|
||||||
const url = parseVariables(variables)(
|
|
||||||
webhook.url + (queryParams !== '' ? `?${queryParams}` : '')
|
|
||||||
)
|
|
||||||
|
|
||||||
const isLongRequest = longReqTimeoutWhitelist.some((whiteListedUrl) =>
|
|
||||||
url?.includes(whiteListedUrl)
|
|
||||||
)
|
|
||||||
|
|
||||||
const request = {
|
|
||||||
url,
|
|
||||||
method: (webhook.method ?? defaultWebhookAttributes.method) as Method,
|
|
||||||
headers: headers ?? {},
|
|
||||||
...basicAuth,
|
|
||||||
json:
|
|
||||||
!contentType?.includes('x-www-form-urlencoded') && body && isJson
|
|
||||||
? body
|
|
||||||
: undefined,
|
|
||||||
form:
|
|
||||||
contentType?.includes('x-www-form-urlencoded') && body
|
|
||||||
? body
|
|
||||||
: undefined,
|
|
||||||
body: body && !isJson ? body : undefined,
|
|
||||||
timeout: {
|
|
||||||
response: isNotDefined(env.CHAT_API_TIMEOUT)
|
|
||||||
? undefined
|
|
||||||
: timeout && timeout !== defaultTimeout
|
|
||||||
? Math.min(timeout, maxTimeout) * 1000
|
|
||||||
: isLongRequest
|
|
||||||
? maxTimeout * 1000
|
|
||||||
: defaultTimeout * 1000,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const response = await got(request.url, omit(request, 'url'))
|
|
||||||
await saveSuccessLog({
|
|
||||||
resultId,
|
|
||||||
message: 'Webhook successfuly executed.',
|
|
||||||
details: {
|
|
||||||
statusCode: response.statusCode,
|
|
||||||
request,
|
|
||||||
response: safeJsonParse(response.body).data,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return {
|
|
||||||
statusCode: response.statusCode,
|
|
||||||
data: safeJsonParse(response.body).data,
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof HTTPError) {
|
|
||||||
const response = {
|
|
||||||
statusCode: error.response.statusCode,
|
|
||||||
data: safeJsonParse(error.response.body as string).data,
|
|
||||||
}
|
|
||||||
await saveErrorLog({
|
|
||||||
resultId,
|
|
||||||
message: 'Webhook returned an error',
|
|
||||||
details: {
|
|
||||||
request,
|
|
||||||
response,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
const response = {
|
|
||||||
statusCode: 500,
|
|
||||||
data: { message: `Error from Typebot server: ${error}` },
|
|
||||||
}
|
|
||||||
console.error(error)
|
|
||||||
await saveErrorLog({
|
|
||||||
resultId,
|
|
||||||
message: 'Webhook failed to execute',
|
|
||||||
details: {
|
|
||||||
request,
|
|
||||||
response,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const getBodyContent =
|
|
||||||
(
|
|
||||||
typebot: Pick<Typebot | PublicTypebot, 'groups' | 'variables' | 'edges'>,
|
|
||||||
linkedTypebots: (Typebot | PublicTypebot)[]
|
|
||||||
) =>
|
|
||||||
async ({
|
|
||||||
body,
|
|
||||||
resultValues,
|
|
||||||
groupId,
|
|
||||||
variables,
|
|
||||||
isCustomBody,
|
|
||||||
}: {
|
|
||||||
body?: string | null
|
|
||||||
resultValues?: ResultValues
|
|
||||||
groupId: string
|
|
||||||
variables: Variable[]
|
|
||||||
isCustomBody?: boolean
|
|
||||||
}): Promise<string | undefined> => {
|
|
||||||
return body === '{{state}}' || isEmpty(body) || isCustomBody !== true
|
|
||||||
? JSON.stringify(
|
|
||||||
resultValues
|
|
||||||
? parseAnswers({
|
|
||||||
answers: resultValues.answers.map((answer) => ({
|
|
||||||
key:
|
|
||||||
(answer.variableId
|
|
||||||
? typebot.variables.find(
|
|
||||||
(variable) => variable.id === answer.variableId
|
|
||||||
)?.name
|
|
||||||
: typebot.groups.find((group) =>
|
|
||||||
group.blocks.find(
|
|
||||||
(block) => block.id === answer.blockId
|
|
||||||
)
|
|
||||||
)?.title) ?? '',
|
|
||||||
value: answer.content,
|
|
||||||
})),
|
|
||||||
variables: resultValues.variables,
|
|
||||||
})
|
|
||||||
: await parseSampleResult(typebot, linkedTypebots)(
|
|
||||||
groupId,
|
|
||||||
variables
|
|
||||||
)
|
|
||||||
)
|
|
||||||
: body ?? undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const safeJsonParse = (json: string): { data: any; isJson: boolean } => {
|
|
||||||
try {
|
|
||||||
return { data: JSON.parse(json), isJson: true }
|
|
||||||
} catch (err) {
|
|
||||||
return { data: json, isJson: false }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default handler
|
export default handler
|
||||||
|
@ -13,7 +13,6 @@ type Props = {
|
|||||||
sessionId: string
|
sessionId: string
|
||||||
}
|
}
|
||||||
export const continueChat = async ({ origin, sessionId, message }: Props) => {
|
export const continueChat = async ({ origin, sessionId, message }: Props) => {
|
||||||
console.log('test')
|
|
||||||
const session = await getSession(sessionId)
|
const session = await getSession(sessionId)
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { isNotEmpty } from '@typebot.io/lib/utils'
|
import { isNotEmpty } from '@typebot.io/lib/utils'
|
||||||
import { ContinueChatResponse } from '@typebot.io/schemas'
|
import { ContinueChatResponse } from '@typebot.io/schemas'
|
||||||
import { OpenAIBlock } from '@typebot.io/schemas/features/blocks/integrations/openai'
|
import { OpenAIBlock } from '@typebot.io/schemas/features/blocks/integrations/openai'
|
||||||
import { HTTPError } from 'got'
|
import { HTTPError } from 'ky'
|
||||||
import { ClientOptions, OpenAI } from 'openai'
|
import { ClientOptions, OpenAI } from 'openai'
|
||||||
|
|
||||||
type Props = Pick<
|
type Props = Pick<
|
||||||
@ -55,9 +55,9 @@ export const executeChatCompletionOpenAIRequest = async ({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof HTTPError) {
|
if (error instanceof HTTPError) {
|
||||||
if (
|
if (
|
||||||
(error.response.statusCode === 503 ||
|
(error.response.status === 503 ||
|
||||||
error.response.statusCode === 500 ||
|
error.response.status === 500 ||
|
||||||
error.response.statusCode === 403) &&
|
error.response.status === 403) &&
|
||||||
!isRetrying
|
!isRetrying
|
||||||
) {
|
) {
|
||||||
console.log('OpenAI API error - 503, retrying in 3 seconds')
|
console.log('OpenAI API error - 503, retrying in 3 seconds')
|
||||||
@ -73,7 +73,7 @@ export const executeChatCompletionOpenAIRequest = async ({
|
|||||||
isRetrying: true,
|
isRetrying: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (error.response.statusCode === 400) {
|
if (error.response.status === 400) {
|
||||||
const log = {
|
const log = {
|
||||||
status: 'info',
|
status: 'info',
|
||||||
description:
|
description:
|
||||||
@ -93,8 +93,8 @@ export const executeChatCompletionOpenAIRequest = async ({
|
|||||||
}
|
}
|
||||||
logs.push({
|
logs.push({
|
||||||
status: 'error',
|
status: 'error',
|
||||||
description: `OpenAI API error - ${error.response.statusCode}`,
|
description: `OpenAI API error - ${error.response.status}`,
|
||||||
details: error.response.body,
|
details: await error.response.text(),
|
||||||
})
|
})
|
||||||
return { logs }
|
return { logs }
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,11 @@ import {
|
|||||||
ChatLog,
|
ChatLog,
|
||||||
ExecutableHttpRequest,
|
ExecutableHttpRequest,
|
||||||
AnswerInSessionState,
|
AnswerInSessionState,
|
||||||
|
TypebotInSession,
|
||||||
} from '@typebot.io/schemas'
|
} from '@typebot.io/schemas'
|
||||||
import { stringify } from 'qs'
|
import { stringify } from 'qs'
|
||||||
import { isDefined, isEmpty, isNotDefined, omit } from '@typebot.io/lib'
|
import { isDefined, isEmpty, isNotDefined, omit } from '@typebot.io/lib'
|
||||||
import got, { Method, HTTPError, OptionsInit } from 'got'
|
import ky, { HTTPError, Options } from 'ky'
|
||||||
import { resumeWebhookExecution } from './resumeWebhookExecution'
|
import { resumeWebhookExecution } from './resumeWebhookExecution'
|
||||||
import { ExecuteIntegrationResponse } from '../../../types'
|
import { ExecuteIntegrationResponse } from '../../../types'
|
||||||
import { parseVariables } from '@typebot.io/variables/parseVariables'
|
import { parseVariables } from '@typebot.io/variables/parseVariables'
|
||||||
@ -60,9 +61,11 @@ export const executeWebhookBlock = async (
|
|||||||
})) as HttpRequest | null)
|
})) as HttpRequest | null)
|
||||||
: null)
|
: null)
|
||||||
if (!webhook) return { outgoingEdgeId: block.outgoingEdgeId }
|
if (!webhook) return { outgoingEdgeId: block.outgoingEdgeId }
|
||||||
const parsedWebhook = await parseWebhookAttributes(state)({
|
const parsedWebhook = await parseWebhookAttributes({
|
||||||
webhook,
|
webhook,
|
||||||
isCustomBody: block.options?.isCustomBody,
|
isCustomBody: block.options?.isCustomBody,
|
||||||
|
typebot: state.typebotsQueue[0].typebot,
|
||||||
|
answers: state.typebotsQueue[0].answers,
|
||||||
})
|
})
|
||||||
if (!parsedWebhook) {
|
if (!parsedWebhook) {
|
||||||
logs.push({
|
logs.push({
|
||||||
@ -104,69 +107,69 @@ export const executeWebhookBlock = async (
|
|||||||
|
|
||||||
const checkIfBodyIsAVariable = (body: string) => /^{{.+}}$/.test(body)
|
const checkIfBodyIsAVariable = (body: string) => /^{{.+}}$/.test(body)
|
||||||
|
|
||||||
const parseWebhookAttributes =
|
export const parseWebhookAttributes = async ({
|
||||||
(state: SessionState) =>
|
webhook,
|
||||||
async ({
|
isCustomBody,
|
||||||
webhook,
|
typebot,
|
||||||
isCustomBody,
|
answers,
|
||||||
}: {
|
}: {
|
||||||
webhook: HttpRequest
|
webhook: HttpRequest
|
||||||
isCustomBody?: boolean
|
isCustomBody?: boolean
|
||||||
}): Promise<ParsedWebhook | undefined> => {
|
typebot: TypebotInSession
|
||||||
if (!webhook.url) return
|
answers: AnswerInSessionState[]
|
||||||
const { typebot } = state.typebotsQueue[0]
|
}): Promise<ParsedWebhook | undefined> => {
|
||||||
const basicAuth: { username?: string; password?: string } = {}
|
if (!webhook.url) return
|
||||||
const basicAuthHeaderIdx = webhook.headers?.findIndex(
|
const basicAuth: { username?: string; password?: string } = {}
|
||||||
(h) =>
|
const basicAuthHeaderIdx = webhook.headers?.findIndex(
|
||||||
h.key?.toLowerCase() === 'authorization' &&
|
(h) =>
|
||||||
h.value?.toLowerCase()?.includes('basic')
|
h.key?.toLowerCase() === 'authorization' &&
|
||||||
)
|
h.value?.toLowerCase()?.includes('basic')
|
||||||
const isUsernamePasswordBasicAuth =
|
)
|
||||||
basicAuthHeaderIdx !== -1 &&
|
const isUsernamePasswordBasicAuth =
|
||||||
isDefined(basicAuthHeaderIdx) &&
|
basicAuthHeaderIdx !== -1 &&
|
||||||
webhook.headers?.at(basicAuthHeaderIdx)?.value?.includes(':')
|
isDefined(basicAuthHeaderIdx) &&
|
||||||
if (isUsernamePasswordBasicAuth) {
|
webhook.headers?.at(basicAuthHeaderIdx)?.value?.includes(':')
|
||||||
const [username, password] =
|
if (isUsernamePasswordBasicAuth) {
|
||||||
webhook.headers?.at(basicAuthHeaderIdx)?.value?.slice(6).split(':') ??
|
const [username, password] =
|
||||||
[]
|
webhook.headers?.at(basicAuthHeaderIdx)?.value?.slice(6).split(':') ?? []
|
||||||
basicAuth.username = username
|
basicAuth.username = username
|
||||||
basicAuth.password = password
|
basicAuth.password = password
|
||||||
webhook.headers?.splice(basicAuthHeaderIdx, 1)
|
webhook.headers?.splice(basicAuthHeaderIdx, 1)
|
||||||
}
|
|
||||||
const headers = convertKeyValueTableToObject(
|
|
||||||
webhook.headers,
|
|
||||||
typebot.variables
|
|
||||||
) as ExecutableHttpRequest['headers'] | undefined
|
|
||||||
const queryParams = stringify(
|
|
||||||
convertKeyValueTableToObject(webhook.queryParams, typebot.variables)
|
|
||||||
)
|
|
||||||
const bodyContent = await getBodyContent({
|
|
||||||
body: webhook.body,
|
|
||||||
answers: state.typebotsQueue[0].answers,
|
|
||||||
variables: typebot.variables,
|
|
||||||
isCustomBody,
|
|
||||||
})
|
|
||||||
const method = webhook.method ?? defaultWebhookAttributes.method
|
|
||||||
const { data: body, isJson } =
|
|
||||||
bodyContent && method !== HttpMethod.GET
|
|
||||||
? safeJsonParse(
|
|
||||||
parseVariables(typebot.variables, {
|
|
||||||
isInsideJson: !checkIfBodyIsAVariable(bodyContent),
|
|
||||||
})(bodyContent)
|
|
||||||
)
|
|
||||||
: { data: undefined, isJson: false }
|
|
||||||
|
|
||||||
return {
|
|
||||||
url: parseVariables(typebot.variables)(
|
|
||||||
webhook.url + (queryParams !== '' ? `?${queryParams}` : '')
|
|
||||||
),
|
|
||||||
basicAuth,
|
|
||||||
method,
|
|
||||||
headers,
|
|
||||||
body,
|
|
||||||
isJson,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
const headers = convertKeyValueTableToObject(
|
||||||
|
webhook.headers,
|
||||||
|
typebot.variables
|
||||||
|
) as ExecutableHttpRequest['headers'] | undefined
|
||||||
|
const queryParams = stringify(
|
||||||
|
convertKeyValueTableToObject(webhook.queryParams, typebot.variables)
|
||||||
|
)
|
||||||
|
const bodyContent = await getBodyContent({
|
||||||
|
body: webhook.body,
|
||||||
|
answers,
|
||||||
|
variables: typebot.variables,
|
||||||
|
isCustomBody,
|
||||||
|
})
|
||||||
|
const method = webhook.method ?? defaultWebhookAttributes.method
|
||||||
|
const { data: body, isJson } =
|
||||||
|
bodyContent && method !== HttpMethod.GET
|
||||||
|
? safeJsonParse(
|
||||||
|
parseVariables(typebot.variables, {
|
||||||
|
isInsideJson: !checkIfBodyIsAVariable(bodyContent),
|
||||||
|
})(bodyContent)
|
||||||
|
)
|
||||||
|
: { data: undefined, isJson: false }
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: parseVariables(typebot.variables)(
|
||||||
|
webhook.url + (queryParams !== '' ? `?${queryParams}` : '')
|
||||||
|
),
|
||||||
|
basicAuth,
|
||||||
|
method,
|
||||||
|
headers,
|
||||||
|
body,
|
||||||
|
isJson,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const executeWebhook = async (
|
export const executeWebhook = async (
|
||||||
webhook: ParsedWebhook,
|
webhook: ParsedWebhook,
|
||||||
@ -177,7 +180,8 @@ export const executeWebhook = async (
|
|||||||
startTimeShouldBeUpdated?: boolean
|
startTimeShouldBeUpdated?: boolean
|
||||||
}> => {
|
}> => {
|
||||||
const logs: ChatLog[] = []
|
const logs: ChatLog[] = []
|
||||||
const { headers, url, method, basicAuth, body, isJson } = webhook
|
|
||||||
|
const { headers, url, method, basicAuth, isJson } = webhook
|
||||||
const contentType = headers ? headers['Content-Type'] : undefined
|
const contentType = headers ? headers['Content-Type'] : undefined
|
||||||
|
|
||||||
const isLongRequest = params.disableRequestTimeout
|
const isLongRequest = params.disableRequestTimeout
|
||||||
@ -186,59 +190,60 @@ export const executeWebhook = async (
|
|||||||
url?.includes(whiteListedUrl)
|
url?.includes(whiteListedUrl)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const isFormData = contentType?.includes('x-www-form-urlencoded')
|
||||||
|
|
||||||
|
let body = webhook.body
|
||||||
|
|
||||||
|
if (isFormData && isJson) body = parseFormDataBody(body as object)
|
||||||
|
|
||||||
const request = {
|
const request = {
|
||||||
url,
|
url,
|
||||||
method: method as Method,
|
method,
|
||||||
headers: headers ?? {},
|
headers: headers ?? {},
|
||||||
...(basicAuth ?? {}),
|
...(basicAuth ?? {}),
|
||||||
json:
|
json: !isFormData && body && isJson ? body : undefined,
|
||||||
!contentType?.includes('x-www-form-urlencoded') && body && isJson
|
body: (isFormData && body ? body : undefined) as any,
|
||||||
? body
|
timeout: isNotDefined(env.CHAT_API_TIMEOUT)
|
||||||
: undefined,
|
? undefined
|
||||||
form:
|
: params.timeout && params.timeout !== defaultTimeout
|
||||||
contentType?.includes('x-www-form-urlencoded') && body ? body : undefined,
|
? Math.min(params.timeout, maxTimeout) * 1000
|
||||||
body: body && !isJson ? (body as string) : undefined,
|
: isLongRequest
|
||||||
timeout: {
|
? maxTimeout * 1000
|
||||||
response: isNotDefined(env.CHAT_API_TIMEOUT)
|
: defaultTimeout * 1000,
|
||||||
? undefined
|
} satisfies Options & { url: string; body: any }
|
||||||
: params.timeout && params.timeout !== defaultTimeout
|
|
||||||
? Math.min(params.timeout, maxTimeout) * 1000
|
|
||||||
: isLongRequest
|
|
||||||
? maxTimeout * 1000
|
|
||||||
: defaultTimeout * 1000,
|
|
||||||
},
|
|
||||||
} satisfies OptionsInit
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await got(request.url, omit(request, 'url'))
|
const response = await ky(request.url, omit(request, 'url'))
|
||||||
|
const body = await response.text()
|
||||||
logs.push({
|
logs.push({
|
||||||
status: 'success',
|
status: 'success',
|
||||||
description: webhookSuccessDescription,
|
description: webhookSuccessDescription,
|
||||||
details: {
|
details: {
|
||||||
statusCode: response.statusCode,
|
statusCode: response.status,
|
||||||
response: safeJsonParse(response.body).data,
|
response: safeJsonParse(body).data,
|
||||||
request,
|
request,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
response: {
|
response: {
|
||||||
statusCode: response.statusCode,
|
statusCode: response.status,
|
||||||
data: safeJsonParse(response.body).data,
|
data: safeJsonParse(body).data,
|
||||||
},
|
},
|
||||||
logs,
|
logs,
|
||||||
startTimeShouldBeUpdated: true,
|
startTimeShouldBeUpdated: true,
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof HTTPError) {
|
if (error instanceof HTTPError) {
|
||||||
|
const responseBody = await error.response.text()
|
||||||
const response = {
|
const response = {
|
||||||
statusCode: error.response.statusCode,
|
statusCode: error.response.status,
|
||||||
data: safeJsonParse(error.response.body as string).data,
|
data: safeJsonParse(responseBody).data,
|
||||||
}
|
}
|
||||||
logs.push({
|
logs.push({
|
||||||
status: 'error',
|
status: 'error',
|
||||||
description: webhookErrorDescription,
|
description: webhookErrorDescription,
|
||||||
details: {
|
details: {
|
||||||
statusCode: error.response.statusCode,
|
statusCode: error.response.status,
|
||||||
request,
|
request,
|
||||||
response,
|
response,
|
||||||
},
|
},
|
||||||
@ -257,7 +262,7 @@ export const executeWebhook = async (
|
|||||||
}
|
}
|
||||||
logs.push({
|
logs.push({
|
||||||
status: 'error',
|
status: 'error',
|
||||||
description: `Webhook request timed out. (${request.timeout.response}ms)`,
|
description: `Webhook request timed out. (${request.timeout}ms)`,
|
||||||
details: {
|
details: {
|
||||||
response,
|
response,
|
||||||
request,
|
request,
|
||||||
@ -320,10 +325,18 @@ export const convertKeyValueTableToObject = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const safeJsonParse = (json: string): { data: any; isJson: boolean } => {
|
const safeJsonParse = (json: unknown): { data: any; isJson: boolean } => {
|
||||||
try {
|
try {
|
||||||
return { data: JSON.parse(json), isJson: true }
|
return { data: JSON.parse(json as string), isJson: true }
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return { data: json, isJson: false }
|
return { data: json, isJson: false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const parseFormDataBody = (body: object) => {
|
||||||
|
const searchParams = new URLSearchParams()
|
||||||
|
Object.entries(body as object).forEach(([key, value]) => {
|
||||||
|
searchParams.set(key, value)
|
||||||
|
})
|
||||||
|
return searchParams
|
||||||
|
}
|
||||||
|
@ -4,7 +4,7 @@ import {
|
|||||||
ZemanticAiCredentials,
|
ZemanticAiCredentials,
|
||||||
ZemanticAiResponse,
|
ZemanticAiResponse,
|
||||||
} from '@typebot.io/schemas/features/blocks/integrations/zemanticAi'
|
} from '@typebot.io/schemas/features/blocks/integrations/zemanticAi'
|
||||||
import got from 'got'
|
import ky from 'ky'
|
||||||
import { decrypt } from '@typebot.io/lib/api/encryption/decrypt'
|
import { decrypt } from '@typebot.io/lib/api/encryption/decrypt'
|
||||||
import { byId, isDefined, isEmpty } from '@typebot.io/lib'
|
import { byId, isDefined, isEmpty } from '@typebot.io/lib'
|
||||||
import { ExecuteIntegrationResponse } from '../../../types'
|
import { ExecuteIntegrationResponse } from '../../../types'
|
||||||
@ -51,7 +51,7 @@ export const executeZemanticAiBlock = async (
|
|||||||
})
|
})
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res: ZemanticAiResponse = await got
|
const res: ZemanticAiResponse = await ky
|
||||||
.post(URL, {
|
.post(URL, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${apiKey}`,
|
Authorization: `Bearer ${apiKey}`,
|
||||||
|
@ -11,12 +11,12 @@ import { LogicBlockType } from '@typebot.io/schemas/features/blocks/logic/consta
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
typebots: Pick<PublicTypebot, 'groups'>[]
|
typebots: Pick<PublicTypebot, 'groups'>[]
|
||||||
user?: User
|
userId: string | undefined
|
||||||
isPreview?: boolean
|
isPreview?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getPreviouslyLinkedTypebots =
|
export const fetchLinkedChildTypebots =
|
||||||
({ typebots, user, isPreview }: Props) =>
|
({ typebots, userId, isPreview }: Props) =>
|
||||||
async (
|
async (
|
||||||
capturedLinkedBots: (Typebot | PublicTypebot)[]
|
capturedLinkedBots: (Typebot | PublicTypebot)[]
|
||||||
): Promise<(Typebot | PublicTypebot)[]> => {
|
): Promise<(Typebot | PublicTypebot)[]> => {
|
||||||
@ -40,13 +40,13 @@ export const getPreviouslyLinkedTypebots =
|
|||||||
.filter(isDefined)
|
.filter(isDefined)
|
||||||
if (linkedTypebotIds.length === 0) return capturedLinkedBots
|
if (linkedTypebotIds.length === 0) return capturedLinkedBots
|
||||||
const linkedTypebots = (await fetchLinkedTypebots({
|
const linkedTypebots = (await fetchLinkedTypebots({
|
||||||
user,
|
userId,
|
||||||
typebotIds: linkedTypebotIds,
|
typebotIds: linkedTypebotIds,
|
||||||
isPreview,
|
isPreview,
|
||||||
})) as (Typebot | PublicTypebot)[]
|
})) as (Typebot | PublicTypebot)[]
|
||||||
return getPreviouslyLinkedTypebots({
|
return fetchLinkedChildTypebots({
|
||||||
typebots: linkedTypebots,
|
typebots: linkedTypebots,
|
||||||
user,
|
userId,
|
||||||
isPreview,
|
isPreview,
|
||||||
})([...capturedLinkedBots, ...linkedTypebots])
|
})([...capturedLinkedBots, ...linkedTypebots])
|
||||||
}
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
import { fetchLinkedTypebots } from './fetchLinkedTypebots'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
parentTypebotIds: string[]
|
||||||
|
userId: string | undefined
|
||||||
|
isPreview?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchLinkedParentTypebots = ({
|
||||||
|
parentTypebotIds,
|
||||||
|
isPreview,
|
||||||
|
userId,
|
||||||
|
}: Props) =>
|
||||||
|
parentTypebotIds.length > 0
|
||||||
|
? fetchLinkedTypebots({
|
||||||
|
typebotIds: parentTypebotIds,
|
||||||
|
isPreview,
|
||||||
|
userId,
|
||||||
|
})
|
||||||
|
: []
|
@ -1,20 +1,19 @@
|
|||||||
import prisma from '@typebot.io/lib/prisma'
|
import prisma from '@typebot.io/lib/prisma'
|
||||||
import { User } from '@typebot.io/prisma'
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isPreview?: boolean
|
isPreview?: boolean
|
||||||
typebotIds: string[]
|
typebotIds: string[]
|
||||||
user?: User
|
userId: string | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fetchLinkedTypebots = async ({
|
export const fetchLinkedTypebots = async ({
|
||||||
user,
|
userId,
|
||||||
isPreview,
|
isPreview,
|
||||||
typebotIds,
|
typebotIds,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
if (!user || !isPreview)
|
if (!userId || !isPreview)
|
||||||
return prisma.publicTypebot.findMany({
|
return prisma.publicTypebot.findMany({
|
||||||
where: { id: { in: typebotIds } },
|
where: { typebotId: { in: typebotIds } },
|
||||||
})
|
})
|
||||||
const linkedTypebots = await prisma.typebot.findMany({
|
const linkedTypebots = await prisma.typebot.findMany({
|
||||||
where: { id: { in: typebotIds } },
|
where: { id: { in: typebotIds } },
|
||||||
@ -39,7 +38,7 @@ export const fetchLinkedTypebots = async ({
|
|||||||
return linkedTypebots.filter(
|
return linkedTypebots.filter(
|
||||||
(typebot) =>
|
(typebot) =>
|
||||||
typebot.collaborators.some(
|
typebot.collaborators.some(
|
||||||
(collaborator) => collaborator.userId === user.id
|
(collaborator) => collaborator.userId === userId
|
||||||
) || typebot.workspace.members.some((member) => member.userId === user.id)
|
) || typebot.workspace.members.some((member) => member.userId === userId)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,6 @@ export const executeGroup = async (
|
|||||||
logs,
|
logs,
|
||||||
visitedEdges,
|
visitedEdges,
|
||||||
}
|
}
|
||||||
console.log('yes')
|
|
||||||
const executionResponse = (
|
const executionResponse = (
|
||||||
isLogicBlock(block)
|
isLogicBlock(block)
|
||||||
? await executeLogic(newSessionState)(block)
|
? await executeLogic(newSessionState)(block)
|
||||||
|
@ -16,7 +16,6 @@ import { env } from '@typebot.io/env'
|
|||||||
export const executeIntegration =
|
export const executeIntegration =
|
||||||
(state: SessionState) =>
|
(state: SessionState) =>
|
||||||
async (block: IntegrationBlock): Promise<ExecuteIntegrationResponse> => {
|
async (block: IntegrationBlock): Promise<ExecuteIntegrationResponse> => {
|
||||||
console.log('HI')
|
|
||||||
switch (block.type) {
|
switch (block.type) {
|
||||||
case IntegrationBlockType.GOOGLE_SHEETS:
|
case IntegrationBlockType.GOOGLE_SHEETS:
|
||||||
return {
|
return {
|
||||||
|
@ -27,7 +27,6 @@ export const executeForgedBlock = async (
|
|||||||
const blockDef = forgedBlocks[block.type]
|
const blockDef = forgedBlocks[block.type]
|
||||||
if (!blockDef) return { outgoingEdgeId: block.outgoingEdgeId }
|
if (!blockDef) return { outgoingEdgeId: block.outgoingEdgeId }
|
||||||
const action = blockDef.actions.find((a) => a.name === block.options.action)
|
const action = blockDef.actions.find((a) => a.name === block.options.action)
|
||||||
console.log('test', action)
|
|
||||||
const noCredentialsError = {
|
const noCredentialsError = {
|
||||||
status: 'error',
|
status: 'error',
|
||||||
description: 'Credentials not provided for integration',
|
description: 'Credentials not provided for integration',
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
"@typebot.io/env": "workspace:*",
|
"@typebot.io/env": "workspace:*",
|
||||||
"@typebot.io/lib": "workspace:*",
|
"@typebot.io/lib": "workspace:*",
|
||||||
"@typebot.io/prisma": "workspace:*",
|
"@typebot.io/prisma": "workspace:*",
|
||||||
|
"@typebot.io/results": "workspace:*",
|
||||||
"@typebot.io/schemas": "workspace:*",
|
"@typebot.io/schemas": "workspace:*",
|
||||||
"@typebot.io/tsconfig": "workspace:*",
|
"@typebot.io/tsconfig": "workspace:*",
|
||||||
"@typebot.io/variables": "workspace:*",
|
"@typebot.io/variables": "workspace:*",
|
||||||
@ -24,19 +25,18 @@
|
|||||||
"date-fns-tz": "2.0.0",
|
"date-fns-tz": "2.0.0",
|
||||||
"google-auth-library": "8.9.0",
|
"google-auth-library": "8.9.0",
|
||||||
"google-spreadsheet": "4.1.1",
|
"google-spreadsheet": "4.1.1",
|
||||||
"got": "12.6.0",
|
"ky": "1.2.3",
|
||||||
"ky": "^1.1.3",
|
|
||||||
"libphonenumber-js": "1.10.37",
|
"libphonenumber-js": "1.10.37",
|
||||||
"node-html-parser": "6.1.5",
|
"node-html-parser": "6.1.5",
|
||||||
"nodemailer": "6.9.8",
|
"nodemailer": "6.9.8",
|
||||||
"openai": "4.28.4",
|
"openai": "4.28.4",
|
||||||
"qs": "6.11.2",
|
"qs": "6.11.2",
|
||||||
"stripe": "12.13.0",
|
"stripe": "12.13.0"
|
||||||
"@typebot.io/results": "workspace:*"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typebot.io/forge": "workspace:*",
|
"@typebot.io/forge": "workspace:*",
|
||||||
"@typebot.io/forge-repository": "workspace:*",
|
"@typebot.io/forge-repository": "workspace:*",
|
||||||
|
"@types/node": "^20.12.3",
|
||||||
"@types/nodemailer": "6.4.14",
|
"@types/nodemailer": "6.4.14",
|
||||||
"@types/qs": "6.9.7"
|
"@types/qs": "6.9.7"
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { env } from '@typebot.io/env'
|
import { env } from '@typebot.io/env'
|
||||||
import got from 'got'
|
import ky from 'ky'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
mediaId: string
|
mediaId: string
|
||||||
@ -10,21 +10,24 @@ export const downloadMedia = async ({
|
|||||||
mediaId,
|
mediaId,
|
||||||
systemUserAccessToken,
|
systemUserAccessToken,
|
||||||
}: Props): Promise<{ file: Buffer; mimeType: string }> => {
|
}: Props): Promise<{ file: Buffer; mimeType: string }> => {
|
||||||
const { body } = await got.get({
|
const { url, mime_type } = await ky
|
||||||
url: `${env.WHATSAPP_CLOUD_API_URL}/v17.0/${mediaId}`,
|
.get(`${env.WHATSAPP_CLOUD_API_URL}/v17.0/${mediaId}`, {
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${systemUserAccessToken}`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
const parsedBody = JSON.parse(body) as { url: string; mime_type: string }
|
|
||||||
|
|
||||||
return {
|
|
||||||
file: await got(parsedBody.url, {
|
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${systemUserAccessToken}`,
|
Authorization: `Bearer ${systemUserAccessToken}`,
|
||||||
},
|
},
|
||||||
}).buffer(),
|
})
|
||||||
mimeType: parsedBody.mime_type,
|
.json<{ url: string; mime_type: string }>()
|
||||||
|
|
||||||
|
return {
|
||||||
|
file: Buffer.from(
|
||||||
|
await ky
|
||||||
|
.get(url, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${systemUserAccessToken}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.arrayBuffer()
|
||||||
|
),
|
||||||
|
mimeType: mime_type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
import { convertMessageToWhatsAppMessage } from './convertMessageToWhatsAppMessage'
|
import { convertMessageToWhatsAppMessage } from './convertMessageToWhatsAppMessage'
|
||||||
import { sendWhatsAppMessage } from './sendWhatsAppMessage'
|
import { sendWhatsAppMessage } from './sendWhatsAppMessage'
|
||||||
import * as Sentry from '@sentry/nextjs'
|
import * as Sentry from '@sentry/nextjs'
|
||||||
import { HTTPError } from 'got'
|
import { HTTPError } from 'ky'
|
||||||
import { convertInputToWhatsAppMessages } from './convertInputToWhatsAppMessage'
|
import { convertInputToWhatsAppMessages } from './convertInputToWhatsAppMessage'
|
||||||
import { isNotDefined } from '@typebot.io/lib/utils'
|
import { isNotDefined } from '@typebot.io/lib/utils'
|
||||||
import { computeTypingDuration } from '../computeTypingDuration'
|
import { computeTypingDuration } from '../computeTypingDuration'
|
||||||
@ -141,7 +141,7 @@ export const sendChatReplyToWhatsApp = async ({
|
|||||||
Sentry.captureException(err, { extra: { message } })
|
Sentry.captureException(err, { extra: { message } })
|
||||||
console.log('Failed to send message:', JSON.stringify(message, null, 2))
|
console.log('Failed to send message:', JSON.stringify(message, null, 2))
|
||||||
if (err instanceof HTTPError)
|
if (err instanceof HTTPError)
|
||||||
console.log('HTTPError', err.response.statusCode, err.response.body)
|
console.log('HTTPError', err.response.status, await err.response.text())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +172,11 @@ export const sendChatReplyToWhatsApp = async ({
|
|||||||
Sentry.captureException(err, { extra: { message } })
|
Sentry.captureException(err, { extra: { message } })
|
||||||
console.log('Failed to send message:', JSON.stringify(message, null, 2))
|
console.log('Failed to send message:', JSON.stringify(message, null, 2))
|
||||||
if (err instanceof HTTPError)
|
if (err instanceof HTTPError)
|
||||||
console.log('HTTPError', err.response.statusCode, err.response.body)
|
console.log(
|
||||||
|
'HTTPError',
|
||||||
|
err.response.status,
|
||||||
|
await err.response.text()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -253,7 +257,11 @@ const executeClientSideAction =
|
|||||||
Sentry.captureException(err, { extra: { message } })
|
Sentry.captureException(err, { extra: { message } })
|
||||||
console.log('Failed to send message:', JSON.stringify(message, null, 2))
|
console.log('Failed to send message:', JSON.stringify(message, null, 2))
|
||||||
if (err instanceof HTTPError)
|
if (err instanceof HTTPError)
|
||||||
console.log('HTTPError', err.response.statusCode, err.response.body)
|
console.log(
|
||||||
|
'HTTPError',
|
||||||
|
err.response.status,
|
||||||
|
await err.response.text()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ import {
|
|||||||
WhatsAppSendingMessage,
|
WhatsAppSendingMessage,
|
||||||
} from '@typebot.io/schemas/features/whatsapp'
|
} from '@typebot.io/schemas/features/whatsapp'
|
||||||
import { env } from '@typebot.io/env'
|
import { env } from '@typebot.io/env'
|
||||||
import got from 'got'
|
import ky from 'ky'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
to: string
|
to: string
|
||||||
@ -16,7 +16,7 @@ export const sendWhatsAppMessage = async ({
|
|||||||
message,
|
message,
|
||||||
credentials,
|
credentials,
|
||||||
}: Props) =>
|
}: Props) =>
|
||||||
got.post(
|
ky.post(
|
||||||
`${env.WHATSAPP_CLOUD_API_URL}/v17.0/${credentials.phoneNumberId}/messages`,
|
`${env.WHATSAPP_CLOUD_API_URL}/v17.0/${credentials.phoneNumberId}/messages`,
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { createAction, option } from '@typebot.io/forge'
|
import { createAction, option } from '@typebot.io/forge'
|
||||||
import { auth } from '../auth'
|
import { auth } from '../auth'
|
||||||
|
import { Anthropic } from '@anthropic-ai/sdk'
|
||||||
import { AnthropicStream } from 'ai'
|
import { AnthropicStream } from 'ai'
|
||||||
import { anthropicModels, defaultAnthropicOptions } from '../constants'
|
import { anthropicModels, defaultAnthropicOptions } from '../constants'
|
||||||
import { parseChatMessages } from '../helpers/parseChatMessages'
|
import { parseChatMessages } from '../helpers/parseChatMessages'
|
||||||
@ -103,8 +104,6 @@ export const createChatMessage = createAction({
|
|||||||
responseMapping?.map((res) => res.variableId).filter(isDefined) ?? [],
|
responseMapping?.map((res) => res.variableId).filter(isDefined) ?? [],
|
||||||
run: {
|
run: {
|
||||||
server: async ({ credentials: { apiKey }, options, variables, logs }) => {
|
server: async ({ credentials: { apiKey }, options, variables, logs }) => {
|
||||||
const { Anthropic } = await import('@anthropic-ai/sdk')
|
|
||||||
|
|
||||||
const client = new Anthropic({
|
const client = new Anthropic({
|
||||||
apiKey: apiKey,
|
apiKey: apiKey,
|
||||||
})
|
})
|
||||||
@ -150,8 +149,6 @@ export const createChatMessage = createAction({
|
|||||||
(res) => res.item === 'Message Content' || !res.item
|
(res) => res.item === 'Message Content' || !res.item
|
||||||
)?.variableId,
|
)?.variableId,
|
||||||
run: async ({ credentials: { apiKey }, options, variables }) => {
|
run: async ({ credentials: { apiKey }, options, variables }) => {
|
||||||
const { Anthropic } = await import('@anthropic-ai/sdk')
|
|
||||||
|
|
||||||
const client = new Anthropic({
|
const client = new Anthropic({
|
||||||
apiKey: apiKey,
|
apiKey: apiKey,
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { createAction, option } from '@typebot.io/forge'
|
import { createAction, option } from '@typebot.io/forge'
|
||||||
import { isDefined, isEmpty } from '@typebot.io/lib'
|
import { isDefined, isEmpty } from '@typebot.io/lib'
|
||||||
import { HTTPError, got } from 'got'
|
import ky, { HTTPError } from 'ky'
|
||||||
import { apiBaseUrl } from '../constants'
|
import { apiBaseUrl } from '../constants'
|
||||||
import { auth } from '../auth'
|
import { auth } from '../auth'
|
||||||
import { ChatNodeResponse } from '../types'
|
import { ChatNodeResponse } from '../types'
|
||||||
@ -40,7 +40,7 @@ export const sendMessage = createAction({
|
|||||||
logs,
|
logs,
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
try {
|
||||||
const res: ChatNodeResponse = await got
|
const res: ChatNodeResponse = await ky
|
||||||
.post(apiBaseUrl + botId, {
|
.post(apiBaseUrl + botId, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${apiKey}`,
|
Authorization: `Bearer ${apiKey}`,
|
||||||
@ -66,7 +66,7 @@ export const sendMessage = createAction({
|
|||||||
return logs.add({
|
return logs.add({
|
||||||
status: 'error',
|
status: 'error',
|
||||||
description: error.message,
|
description: error.message,
|
||||||
details: error.response.body,
|
details: await error.response.text(),
|
||||||
})
|
})
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,6 @@
|
|||||||
"@typebot.io/tsconfig": "workspace:*",
|
"@typebot.io/tsconfig": "workspace:*",
|
||||||
"@types/react": "18.2.15",
|
"@types/react": "18.2.15",
|
||||||
"typescript": "5.3.2",
|
"typescript": "5.3.2",
|
||||||
"got": "12.6.0"
|
"ky": "1.2.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { createAction, option } from '@typebot.io/forge'
|
import { createAction, option } from '@typebot.io/forge'
|
||||||
import { isDefined, isEmpty, isNotEmpty } from '@typebot.io/lib'
|
import { isDefined, isEmpty, isNotEmpty } from '@typebot.io/lib'
|
||||||
import { HTTPError, got } from 'got'
|
|
||||||
import { auth } from '../auth'
|
import { auth } from '../auth'
|
||||||
import { defaultBaseUrl } from '../constants'
|
import { defaultBaseUrl } from '../constants'
|
||||||
import { Chunk } from '../types'
|
import { Chunk } from '../types'
|
||||||
|
import ky from 'ky'
|
||||||
|
|
||||||
export const createChatMessage = createAction({
|
export const createChatMessage = createAction({
|
||||||
auth,
|
auth,
|
||||||
@ -44,13 +44,15 @@ export const createChatMessage = createAction({
|
|||||||
logs,
|
logs,
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
try {
|
||||||
const stream = got.post(
|
const response = await ky(
|
||||||
(apiEndpoint ?? defaultBaseUrl) + '/v1/chat-messages',
|
(apiEndpoint ?? defaultBaseUrl) + '/v1/chat-messages',
|
||||||
{
|
{
|
||||||
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${apiKey}`,
|
Authorization: `Bearer ${apiKey}`,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
json: {
|
body: JSON.stringify({
|
||||||
inputs:
|
inputs:
|
||||||
inputs?.reduce((acc, { key, value }) => {
|
inputs?.reduce((acc, { key, value }) => {
|
||||||
if (isEmpty(key) || isEmpty(value)) return acc
|
if (isEmpty(key) || isEmpty(value)) return acc
|
||||||
@ -64,56 +66,70 @@ export const createChatMessage = createAction({
|
|||||||
conversation_id,
|
conversation_id,
|
||||||
user,
|
user,
|
||||||
files: [],
|
files: [],
|
||||||
},
|
}),
|
||||||
isStream: true,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const reader = response.body?.getReader()
|
||||||
|
|
||||||
|
if (!reader)
|
||||||
|
return logs.add({
|
||||||
|
status: 'error',
|
||||||
|
description: 'Failed to read response stream',
|
||||||
|
})
|
||||||
|
|
||||||
const { answer, conversationId, totalTokens } = await new Promise<{
|
const { answer, conversationId, totalTokens } = await new Promise<{
|
||||||
answer: string
|
answer: string
|
||||||
conversationId: string | undefined
|
conversationId: string | undefined
|
||||||
totalTokens: number | undefined
|
totalTokens: number | undefined
|
||||||
}>((resolve, reject) => {
|
}>(async (resolve, reject) => {
|
||||||
let jsonChunk = ''
|
let jsonChunk = ''
|
||||||
let answer = ''
|
let answer = ''
|
||||||
let conversationId: string | undefined
|
let conversationId: string | undefined
|
||||||
let totalTokens: number | undefined
|
let totalTokens: number | undefined
|
||||||
|
|
||||||
stream.on('data', (chunk) => {
|
try {
|
||||||
const lines = chunk.toString().split('\n') as string[]
|
while (true) {
|
||||||
lines
|
const { value, done } = await reader.read()
|
||||||
.filter((line) => line.length > 0 && line !== '\n')
|
if (done) {
|
||||||
.forEach((line) => {
|
resolve({ answer, conversationId, totalTokens })
|
||||||
jsonChunk += line
|
return
|
||||||
if (jsonChunk.startsWith('event: ')) {
|
}
|
||||||
|
|
||||||
|
const chunk = new TextDecoder().decode(value)
|
||||||
|
|
||||||
|
const lines = chunk.toString().split('\n') as string[]
|
||||||
|
lines
|
||||||
|
.filter((line) => line.length > 0 && line !== '\n')
|
||||||
|
.forEach((line) => {
|
||||||
|
jsonChunk += line
|
||||||
|
if (jsonChunk.startsWith('event: ')) {
|
||||||
|
jsonChunk = ''
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
!jsonChunk.startsWith('data: ') ||
|
||||||
|
!jsonChunk.endsWith('}')
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
const data = JSON.parse(jsonChunk.slice(6)) as Chunk
|
||||||
jsonChunk = ''
|
jsonChunk = ''
|
||||||
return
|
if (
|
||||||
}
|
data.event === 'message' ||
|
||||||
if (!jsonChunk.startsWith('data: ') || !jsonChunk.endsWith('}'))
|
data.event === 'agent_message'
|
||||||
return
|
) {
|
||||||
|
answer += data.answer
|
||||||
const data = JSON.parse(jsonChunk.slice(6)) as Chunk
|
}
|
||||||
jsonChunk = ''
|
if (data.event === 'message_end') {
|
||||||
if (
|
totalTokens = data.metadata.usage.total_tokens
|
||||||
data.event === 'message' ||
|
conversationId = data.conversation_id
|
||||||
data.event === 'agent_message'
|
}
|
||||||
) {
|
})
|
||||||
answer += data.answer
|
}
|
||||||
}
|
} catch (e) {
|
||||||
if (data.event === 'message_end') {
|
reject(e)
|
||||||
totalTokens = data.metadata.usage.total_tokens
|
}
|
||||||
conversationId = data.conversation_id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
stream.on('end', () => {
|
|
||||||
resolve({ answer, conversationId, totalTokens })
|
|
||||||
})
|
|
||||||
|
|
||||||
stream.on('error', (error) => {
|
|
||||||
reject(error)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
responseMapping?.forEach((mapping) => {
|
responseMapping?.forEach((mapping) => {
|
||||||
@ -130,12 +146,10 @@ export const createChatMessage = createAction({
|
|||||||
variables.set(mapping.variableId, totalTokens)
|
variables.set(mapping.variableId, totalTokens)
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof HTTPError)
|
logs.add({
|
||||||
return logs.add({
|
status: 'error',
|
||||||
status: 'error',
|
description: 'Failed to create chat message',
|
||||||
description: error.message,
|
})
|
||||||
details: error.response.body,
|
|
||||||
})
|
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
"@typebot.io/lib": "workspace:*",
|
"@typebot.io/lib": "workspace:*",
|
||||||
"@typebot.io/tsconfig": "workspace:*",
|
"@typebot.io/tsconfig": "workspace:*",
|
||||||
"@types/react": "18.2.15",
|
"@types/react": "18.2.15",
|
||||||
"got": "12.6.0",
|
"ky": "1.2.3",
|
||||||
"typescript": "5.3.2"
|
"typescript": "5.3.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import { createAction, option } from '@typebot.io/forge'
|
|||||||
import { auth } from '../auth'
|
import { auth } from '../auth'
|
||||||
import { baseUrl } from '../constants'
|
import { baseUrl } from '../constants'
|
||||||
import { ModelsResponse, VoicesResponse } from '../type'
|
import { ModelsResponse, VoicesResponse } from '../type'
|
||||||
import got, { HTTPError } from 'got'
|
import got, { HTTPError } from 'ky'
|
||||||
import { uploadFileToBucket } from '@typebot.io/lib/s3/uploadFileToBucket'
|
import { uploadFileToBucket } from '@typebot.io/lib/s3/uploadFileToBucket'
|
||||||
import { createId } from '@typebot.io/lib/createId'
|
import { createId } from '@typebot.io/lib/createId'
|
||||||
|
|
||||||
@ -93,10 +93,10 @@ export const convertTextToSpeech = createAction({
|
|||||||
text: options.text,
|
text: options.text,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.buffer()
|
.arrayBuffer()
|
||||||
|
|
||||||
const url = await uploadFileToBucket({
|
const url = await uploadFileToBucket({
|
||||||
file: response,
|
file: Buffer.from(response),
|
||||||
key: `tmp/elevenlabs/audio/${createId() + createId()}.mp3`,
|
key: `tmp/elevenlabs/audio/${createId() + createId()}.mp3`,
|
||||||
mimeType: 'audio/mpeg',
|
mimeType: 'audio/mpeg',
|
||||||
})
|
})
|
||||||
@ -107,7 +107,7 @@ export const convertTextToSpeech = createAction({
|
|||||||
return logs.add({
|
return logs.add({
|
||||||
status: 'error',
|
status: 'error',
|
||||||
description: err.message,
|
description: err.message,
|
||||||
details: err.response.body,
|
details: await err.response.text(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
"typescript": "5.3.2"
|
"typescript": "5.3.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"got": "12.6.0",
|
"ky": "1.2.3",
|
||||||
"@typebot.io/lib": "workspace:*"
|
"@typebot.io/lib": "workspace:*"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ import { isDefined } from '@typebot.io/lib'
|
|||||||
import { auth } from '../auth'
|
import { auth } from '../auth'
|
||||||
import { parseMessages } from '../helpers/parseMessages'
|
import { parseMessages } from '../helpers/parseMessages'
|
||||||
import { OpenAIStream } from 'ai'
|
import { OpenAIStream } from 'ai'
|
||||||
|
// @ts-ignore
|
||||||
|
import MistralClient from '../helpers/client'
|
||||||
|
|
||||||
const nativeMessageContentSchema = {
|
const nativeMessageContentSchema = {
|
||||||
content: option.string.layout({
|
content: option.string.layout({
|
||||||
@ -95,15 +97,17 @@ export const createChatCompletion = createAction({
|
|||||||
id: 'fetchModels',
|
id: 'fetchModels',
|
||||||
dependencies: [],
|
dependencies: [],
|
||||||
fetch: async ({ credentials }) => {
|
fetch: async ({ credentials }) => {
|
||||||
const MistralClient = (await import('@mistralai/mistralai')).default
|
|
||||||
const client = new MistralClient(credentials.apiKey)
|
const client = new MistralClient(credentials.apiKey)
|
||||||
|
|
||||||
const listModelsResponse = await client.listModels()
|
const listModelsResponse: any = await client.listModels()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
listModelsResponse.data
|
listModelsResponse.data
|
||||||
.sort((a, b) => b.created - a.created)
|
.sort(
|
||||||
.map((model) => model.id) ?? []
|
(a: { created: number }, b: { created: number }) =>
|
||||||
|
b.created - a.created
|
||||||
|
)
|
||||||
|
.map((model: { id: any }) => model.id) ?? []
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -111,10 +115,9 @@ export const createChatCompletion = createAction({
|
|||||||
run: {
|
run: {
|
||||||
server: async ({ credentials: { apiKey }, options, variables, logs }) => {
|
server: async ({ credentials: { apiKey }, options, variables, logs }) => {
|
||||||
if (!options.model) return logs.add('No model selected')
|
if (!options.model) return logs.add('No model selected')
|
||||||
const MistralClient = (await import('@mistralai/mistralai')).default
|
|
||||||
const client = new MistralClient(apiKey)
|
const client = new MistralClient(apiKey)
|
||||||
|
|
||||||
const response = await client.chat({
|
const response: any = await client.chat({
|
||||||
model: options.model,
|
model: options.model,
|
||||||
messages: parseMessages({ options, variables }),
|
messages: parseMessages({ options, variables }),
|
||||||
})
|
})
|
||||||
@ -132,15 +135,13 @@ export const createChatCompletion = createAction({
|
|||||||
)?.variableId,
|
)?.variableId,
|
||||||
run: async ({ credentials: { apiKey }, options, variables }) => {
|
run: async ({ credentials: { apiKey }, options, variables }) => {
|
||||||
if (!options.model) return
|
if (!options.model) return
|
||||||
const MistralClient = (await import('@mistralai/mistralai')).default
|
|
||||||
const client = new MistralClient(apiKey)
|
const client = new MistralClient(apiKey)
|
||||||
|
|
||||||
const response = client.chatStream({
|
const response: any = client.chatStream({
|
||||||
model: options.model,
|
model: options.model,
|
||||||
messages: parseMessages({ options, variables }),
|
messages: parseMessages({ options, variables }),
|
||||||
})
|
})
|
||||||
|
|
||||||
// @ts-ignore https://github.com/vercel/ai/issues/936
|
|
||||||
return OpenAIStream(response)
|
return OpenAIStream(response)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
341
packages/forge/blocks/mistral/helpers/client.js
Normal file
341
packages/forge/blocks/mistral/helpers/client.js
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
// Taken from https://github.com/mistralai/client-js/blob/main/src/client.js
|
||||||
|
// Lib seems not actively maintained, and we need this patch: https://github.com/mistralai/client-js/pull/42
|
||||||
|
|
||||||
|
let isNode = false
|
||||||
|
|
||||||
|
let fetch
|
||||||
|
|
||||||
|
const VERSION = '0.0.3'
|
||||||
|
const RETRY_STATUS_CODES = [429, 500, 502, 503, 504]
|
||||||
|
const ENDPOINT = 'https://api.mistral.ai'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize fetch
|
||||||
|
* @return {Promise<void>}
|
||||||
|
*/
|
||||||
|
async function initializeFetch() {
|
||||||
|
if (typeof globalThis.fetch === 'undefined')
|
||||||
|
throw new Error('No fetch implementation found')
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
isNode = true
|
||||||
|
}
|
||||||
|
fetch = globalThis.fetch
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeFetch()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MistralAPIError
|
||||||
|
* @return {MistralAPIError}
|
||||||
|
* @extends {Error}
|
||||||
|
*/
|
||||||
|
class MistralAPIError extends Error {
|
||||||
|
/**
|
||||||
|
* A simple error class for Mistral API errors
|
||||||
|
* @param {*} message
|
||||||
|
*/
|
||||||
|
constructor(message) {
|
||||||
|
super(message)
|
||||||
|
this.name = 'MistralAPIError'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MistralClient
|
||||||
|
* @return {MistralClient}
|
||||||
|
*/
|
||||||
|
class MistralClient {
|
||||||
|
/**
|
||||||
|
* A simple and lightweight client for the Mistral API
|
||||||
|
* @param {*} apiKey can be set as an environment variable MISTRAL_API_KEY,
|
||||||
|
* or provided in this parameter
|
||||||
|
* @param {*} endpoint defaults to https://api.mistral.ai
|
||||||
|
* @param {*} maxRetries defaults to 5
|
||||||
|
* @param {*} timeout defaults to 120 seconds
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
apiKey = process.env.MISTRAL_API_KEY,
|
||||||
|
endpoint = ENDPOINT,
|
||||||
|
maxRetries = 5,
|
||||||
|
timeout = 120
|
||||||
|
) {
|
||||||
|
this.endpoint = endpoint
|
||||||
|
this.apiKey = apiKey
|
||||||
|
|
||||||
|
this.maxRetries = maxRetries
|
||||||
|
this.timeout = timeout
|
||||||
|
|
||||||
|
if (this.endpoint.indexOf('inference.azure.com')) {
|
||||||
|
this.modelDefault = 'mistral'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} method
|
||||||
|
* @param {*} path
|
||||||
|
* @param {*} request
|
||||||
|
* @return {Promise<*>}
|
||||||
|
*/
|
||||||
|
_request = async function (method, path, request) {
|
||||||
|
const url = `${this.endpoint}/${path}`
|
||||||
|
const options = {
|
||||||
|
method: method,
|
||||||
|
headers: {
|
||||||
|
'User-Agent': `mistral-client-js/${VERSION}`,
|
||||||
|
Accept: request?.stream ? 'text/event-stream' : 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: `Bearer ${this.apiKey}`,
|
||||||
|
},
|
||||||
|
body: method !== 'get' ? JSON.stringify(request) : null,
|
||||||
|
timeout: this.timeout * 1000,
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let attempts = 0; attempts < this.maxRetries; attempts++) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, options)
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
if (request?.stream) {
|
||||||
|
if (isNode) {
|
||||||
|
return response.body
|
||||||
|
} else {
|
||||||
|
const reader = response.body.getReader()
|
||||||
|
// Chrome does not support async iterators yet, so polyfill it
|
||||||
|
const asyncIterator = async function* () {
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
// Read from the stream
|
||||||
|
const { done, value } = await reader.read()
|
||||||
|
// Exit if we're done
|
||||||
|
if (done) return
|
||||||
|
// Else yield the chunk
|
||||||
|
yield value
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
reader.releaseLock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return asyncIterator()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return await response.json()
|
||||||
|
} else if (RETRY_STATUS_CODES.includes(response.status)) {
|
||||||
|
console.debug(
|
||||||
|
`Retrying request on response status: ${response.status}`,
|
||||||
|
`Response: ${await response.text()}`,
|
||||||
|
`Attempt: ${attempts + 1}`
|
||||||
|
)
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
|
await new Promise((resolve) =>
|
||||||
|
setTimeout(resolve, Math.pow(2, attempts + 1) * 500)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
throw new MistralAPIError(
|
||||||
|
`HTTP error! status: ${response.status} ` +
|
||||||
|
`Response: \n${await response.text()}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Request failed: ${error.message}`)
|
||||||
|
if (error.name === 'MistralAPIError') {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
if (attempts === this.maxRetries - 1) throw error
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
|
await new Promise((resolve) =>
|
||||||
|
setTimeout(resolve, Math.pow(2, attempts + 1) * 500)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error('Max retries reached')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a chat completion request
|
||||||
|
* @param {*} model
|
||||||
|
* @param {*} messages
|
||||||
|
* @param {*} tools
|
||||||
|
* @param {*} temperature
|
||||||
|
* @param {*} maxTokens
|
||||||
|
* @param {*} topP
|
||||||
|
* @param {*} randomSeed
|
||||||
|
* @param {*} stream
|
||||||
|
* @param {*} safeMode deprecated use safePrompt instead
|
||||||
|
* @param {*} safePrompt
|
||||||
|
* @param {*} toolChoice
|
||||||
|
* @param {*} responseFormat
|
||||||
|
* @return {Promise<Object>}
|
||||||
|
*/
|
||||||
|
_makeChatCompletionRequest = function (
|
||||||
|
model,
|
||||||
|
messages,
|
||||||
|
tools,
|
||||||
|
temperature,
|
||||||
|
maxTokens,
|
||||||
|
topP,
|
||||||
|
randomSeed,
|
||||||
|
stream,
|
||||||
|
safeMode,
|
||||||
|
safePrompt,
|
||||||
|
toolChoice,
|
||||||
|
responseFormat
|
||||||
|
) {
|
||||||
|
// if modelDefault and model are undefined, throw an error
|
||||||
|
if (!model && !this.modelDefault) {
|
||||||
|
throw new MistralAPIError('You must provide a model name')
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
model: model ?? this.modelDefault,
|
||||||
|
messages: messages,
|
||||||
|
tools: tools ?? undefined,
|
||||||
|
temperature: temperature ?? undefined,
|
||||||
|
max_tokens: maxTokens ?? undefined,
|
||||||
|
top_p: topP ?? undefined,
|
||||||
|
random_seed: randomSeed ?? undefined,
|
||||||
|
stream: stream ?? undefined,
|
||||||
|
safe_prompt: (safeMode || safePrompt) ?? undefined,
|
||||||
|
tool_choice: toolChoice ?? undefined,
|
||||||
|
response_format: responseFormat ?? undefined,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of the available models
|
||||||
|
* @return {Promise<Object>}
|
||||||
|
*/
|
||||||
|
listModels = async function () {
|
||||||
|
const response = await this._request('get', 'v1/models')
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A chat endpoint without streaming
|
||||||
|
* @param {*} model the name of the model to chat with, e.g. mistral-tiny
|
||||||
|
* @param {*} messages an array of messages to chat with, e.g.
|
||||||
|
* [{role: 'user', content: 'What is the best French cheese?'}]
|
||||||
|
* @param {*} tools a list of tools to use.
|
||||||
|
* @param {*} temperature the temperature to use for sampling, e.g. 0.5
|
||||||
|
* @param {*} maxTokens the maximum number of tokens to generate, e.g. 100
|
||||||
|
* @param {*} topP the cumulative probability of tokens to generate, e.g. 0.9
|
||||||
|
* @param {*} randomSeed the random seed to use for sampling, e.g. 42
|
||||||
|
* @param {*} safeMode deprecated use safePrompt instead
|
||||||
|
* @param {*} safePrompt whether to use safe mode, e.g. true
|
||||||
|
* @param {*} toolChoice the tool to use, e.g. 'auto'
|
||||||
|
* @param {*} responseFormat the format of the response, e.g. 'json_format'
|
||||||
|
* @return {Promise<Object>}
|
||||||
|
*/
|
||||||
|
chat = async function ({
|
||||||
|
model,
|
||||||
|
messages,
|
||||||
|
tools,
|
||||||
|
temperature,
|
||||||
|
maxTokens,
|
||||||
|
topP,
|
||||||
|
randomSeed,
|
||||||
|
safeMode,
|
||||||
|
safePrompt,
|
||||||
|
toolChoice,
|
||||||
|
responseFormat,
|
||||||
|
}) {
|
||||||
|
const request = this._makeChatCompletionRequest(
|
||||||
|
model,
|
||||||
|
messages,
|
||||||
|
tools,
|
||||||
|
temperature,
|
||||||
|
maxTokens,
|
||||||
|
topP,
|
||||||
|
randomSeed,
|
||||||
|
false,
|
||||||
|
safeMode,
|
||||||
|
safePrompt,
|
||||||
|
toolChoice,
|
||||||
|
responseFormat
|
||||||
|
)
|
||||||
|
const response = await this._request('post', 'v1/chat/completions', request)
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A chat endpoint that streams responses.
|
||||||
|
* @param {*} model the name of the model to chat with, e.g. mistral-tiny
|
||||||
|
* @param {*} messages an array of messages to chat with, e.g.
|
||||||
|
* [{role: 'user', content: 'What is the best French cheese?'}]
|
||||||
|
* @param {*} tools a list of tools to use.
|
||||||
|
* @param {*} temperature the temperature to use for sampling, e.g. 0.5
|
||||||
|
* @param {*} maxTokens the maximum number of tokens to generate, e.g. 100
|
||||||
|
* @param {*} topP the cumulative probability of tokens to generate, e.g. 0.9
|
||||||
|
* @param {*} randomSeed the random seed to use for sampling, e.g. 42
|
||||||
|
* @param {*} safeMode deprecated use safePrompt instead
|
||||||
|
* @param {*} safePrompt whether to use safe mode, e.g. true
|
||||||
|
* @param {*} toolChoice the tool to use, e.g. 'auto'
|
||||||
|
* @param {*} responseFormat the format of the response, e.g. 'json_format'
|
||||||
|
* @return {Promise<Object>}
|
||||||
|
*/
|
||||||
|
chatStream = async function* ({
|
||||||
|
model,
|
||||||
|
messages,
|
||||||
|
tools,
|
||||||
|
temperature,
|
||||||
|
maxTokens,
|
||||||
|
topP,
|
||||||
|
randomSeed,
|
||||||
|
safeMode,
|
||||||
|
safePrompt,
|
||||||
|
toolChoice,
|
||||||
|
responseFormat,
|
||||||
|
}) {
|
||||||
|
const request = this._makeChatCompletionRequest(
|
||||||
|
model,
|
||||||
|
messages,
|
||||||
|
tools,
|
||||||
|
temperature,
|
||||||
|
maxTokens,
|
||||||
|
topP,
|
||||||
|
randomSeed,
|
||||||
|
true,
|
||||||
|
safeMode,
|
||||||
|
safePrompt,
|
||||||
|
toolChoice,
|
||||||
|
responseFormat
|
||||||
|
)
|
||||||
|
const response = await this._request('post', 'v1/chat/completions', request)
|
||||||
|
|
||||||
|
let buffer = ''
|
||||||
|
const decoder = new TextDecoder()
|
||||||
|
for await (const chunk of response) {
|
||||||
|
buffer += decoder.decode(chunk, { stream: true })
|
||||||
|
let firstNewline
|
||||||
|
while ((firstNewline = buffer.indexOf('\n')) !== -1) {
|
||||||
|
const chunkLine = buffer.substring(0, firstNewline)
|
||||||
|
buffer = buffer.substring(firstNewline + 1)
|
||||||
|
if (chunkLine.startsWith('data:')) {
|
||||||
|
const json = chunkLine.substring(6).trim()
|
||||||
|
if (json !== '[DONE]') {
|
||||||
|
yield JSON.parse(json)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An embeddings endpoint that returns embeddings for a single,
|
||||||
|
* or batch of inputs
|
||||||
|
* @param {*} model The embedding model to use, e.g. mistral-embed
|
||||||
|
* @param {*} input The input to embed,
|
||||||
|
* e.g. ['What is the best French cheese?']
|
||||||
|
* @return {Promise<Object>}
|
||||||
|
*/
|
||||||
|
embeddings = async function ({ model, input }) {
|
||||||
|
const request = {
|
||||||
|
model: model,
|
||||||
|
input: input,
|
||||||
|
}
|
||||||
|
const response = await this._request('post', 'v1/embeddings', request)
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MistralClient
|
@ -9,11 +9,11 @@
|
|||||||
"@typebot.io/forge": "workspace:*",
|
"@typebot.io/forge": "workspace:*",
|
||||||
"@typebot.io/lib": "workspace:*",
|
"@typebot.io/lib": "workspace:*",
|
||||||
"@typebot.io/tsconfig": "workspace:*",
|
"@typebot.io/tsconfig": "workspace:*",
|
||||||
|
"@types/node": "^20.12.4",
|
||||||
"@types/react": "18.2.15",
|
"@types/react": "18.2.15",
|
||||||
"typescript": "5.3.2"
|
"typescript": "5.3.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mistralai/mistralai": "0.1.3",
|
|
||||||
"ai": "3.0.12"
|
"ai": "3.0.12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "@typebot.io/tsconfig/base.json",
|
"extends": "@typebot.io/tsconfig/base.json",
|
||||||
"include": ["**/*.ts", "**/*.tsx"],
|
"include": ["**/*.ts", "**/*.tsx", "helpers/client.ts"],
|
||||||
"exclude": ["node_modules"],
|
"exclude": ["node_modules"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"lib": ["ESNext", "DOM"],
|
"lib": ["ESNext", "DOM"],
|
||||||
|
@ -6,7 +6,7 @@ import { getChatCompletionStreamVarId } from '@typebot.io/openai-block/shared/ge
|
|||||||
import { runChatCompletion } from '@typebot.io/openai-block/shared/runChatCompletion'
|
import { runChatCompletion } from '@typebot.io/openai-block/shared/runChatCompletion'
|
||||||
import { runChatCompletionStream } from '@typebot.io/openai-block/shared/runChatCompletionStream'
|
import { runChatCompletionStream } from '@typebot.io/openai-block/shared/runChatCompletionStream'
|
||||||
import { defaultOpenRouterOptions } from '../constants'
|
import { defaultOpenRouterOptions } from '../constants'
|
||||||
import { got } from 'got'
|
import ky from 'ky'
|
||||||
import { ModelsResponse } from '../types'
|
import { ModelsResponse } from '../types'
|
||||||
|
|
||||||
export const createChatCompletion = createAction({
|
export const createChatCompletion = createAction({
|
||||||
@ -42,7 +42,7 @@ export const createChatCompletion = createAction({
|
|||||||
id: 'fetchModels',
|
id: 'fetchModels',
|
||||||
dependencies: [],
|
dependencies: [],
|
||||||
fetch: async () => {
|
fetch: async () => {
|
||||||
const response = await got
|
const response = await ky
|
||||||
.get(defaultOpenRouterOptions.baseUrl + '/models')
|
.get(defaultOpenRouterOptions.baseUrl + '/models')
|
||||||
.json<ModelsResponse>()
|
.json<ModelsResponse>()
|
||||||
|
|
||||||
|
@ -12,6 +12,6 @@
|
|||||||
"typescript": "5.3.2",
|
"typescript": "5.3.2",
|
||||||
"@typebot.io/lib": "workspace:*",
|
"@typebot.io/lib": "workspace:*",
|
||||||
"@typebot.io/openai-block": "workspace:*",
|
"@typebot.io/openai-block": "workspace:*",
|
||||||
"got": "12.6.0"
|
"ky": "1.2.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { createAction, option } from '@typebot.io/forge'
|
import { createAction, option } from '@typebot.io/forge'
|
||||||
|
import { toBuffer as generateQrCodeBuffer } from 'qrcode'
|
||||||
import { uploadFileToBucket } from '@typebot.io/lib/s3/uploadFileToBucket'
|
import { uploadFileToBucket } from '@typebot.io/lib/s3/uploadFileToBucket'
|
||||||
import { createId } from '@typebot.io/lib/createId'
|
import { createId } from '@typebot.io/lib/createId'
|
||||||
|
|
||||||
@ -28,8 +29,6 @@ export const generateQrCode = createAction({
|
|||||||
'QR code image URL is not specified. Please select a variable to save the generated QR code image.'
|
'QR code image URL is not specified. Please select a variable to save the generated QR code image.'
|
||||||
)
|
)
|
||||||
|
|
||||||
const generateQrCodeBuffer = (await import('qrcode')).toBuffer
|
|
||||||
|
|
||||||
const url = await uploadFileToBucket({
|
const url = await uploadFileToBucket({
|
||||||
file: await generateQrCodeBuffer(options.data),
|
file: await generateQrCodeBuffer(options.data),
|
||||||
key: `tmp/qrcodes/${createId() + createId()}.png`,
|
key: `tmp/qrcodes/${createId() + createId()}.png`,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { createAction, option } from '@typebot.io/forge'
|
import { createAction, option } from '@typebot.io/forge'
|
||||||
import { isDefined } from '@typebot.io/lib'
|
import { isDefined } from '@typebot.io/lib'
|
||||||
import { ZemanticAiResponse } from '../types'
|
import { ZemanticAiResponse } from '../types'
|
||||||
import { got } from 'got'
|
import ky from 'ky'
|
||||||
import { apiBaseUrl } from '../constants'
|
import { apiBaseUrl } from '../constants'
|
||||||
import { auth } from '../auth'
|
import { auth } from '../auth'
|
||||||
import { baseOptions } from '../baseOptions'
|
import { baseOptions } from '../baseOptions'
|
||||||
@ -63,7 +63,7 @@ export const searchDocuments = createAction({
|
|||||||
},
|
},
|
||||||
variables,
|
variables,
|
||||||
}) => {
|
}) => {
|
||||||
const res: ZemanticAiResponse = await got
|
const res = await ky
|
||||||
.post(apiBaseUrl, {
|
.post(apiBaseUrl, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${apiKey}`,
|
Authorization: `Bearer ${apiKey}`,
|
||||||
@ -79,7 +79,7 @@ export const searchDocuments = createAction({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.json()
|
.json<ZemanticAiResponse>()
|
||||||
|
|
||||||
responseMapping?.forEach((mapping) => {
|
responseMapping?.forEach((mapping) => {
|
||||||
if (!mapping.variableId || !mapping.item) return
|
if (!mapping.variableId || !mapping.item) return
|
||||||
|
@ -8,6 +8,7 @@ export const auth = {
|
|||||||
label: 'API key',
|
label: 'API key',
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
placeholder: 'ze...',
|
placeholder: 'ze...',
|
||||||
|
inputType: 'password',
|
||||||
helperText:
|
helperText:
|
||||||
'You can generate an API key [here](https://zemantic.ai/dashboard/settings).',
|
'You can generate an API key [here](https://zemantic.ai/dashboard/settings).',
|
||||||
isDebounceDisabled: true,
|
isDebounceDisabled: true,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { createBlock } from '@typebot.io/forge'
|
import { createBlock } from '@typebot.io/forge'
|
||||||
import { ZemanticAiLogo } from './logo'
|
import { ZemanticAiLogo } from './logo'
|
||||||
import { got } from 'got'
|
import ky from 'ky'
|
||||||
import { searchDocuments } from './actions/searchDocuments'
|
import { searchDocuments } from './actions/searchDocuments'
|
||||||
import { auth } from './auth'
|
import { auth } from './auth'
|
||||||
import { baseOptions } from './baseOptions'
|
import { baseOptions } from './baseOptions'
|
||||||
@ -19,7 +19,7 @@ export const zemanticAiBlock = createBlock({
|
|||||||
fetch: async ({ credentials: { apiKey } }) => {
|
fetch: async ({ credentials: { apiKey } }) => {
|
||||||
const url = 'https://api.zemantic.ai/v1/projects'
|
const url = 'https://api.zemantic.ai/v1/projects'
|
||||||
|
|
||||||
const response = await got
|
const response = await ky
|
||||||
.get(url, {
|
.get(url, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${apiKey}`,
|
Authorization: `Bearer ${apiKey}`,
|
||||||
|
@ -11,6 +11,6 @@
|
|||||||
"@types/react": "18.2.15",
|
"@types/react": "18.2.15",
|
||||||
"typescript": "5.3.2",
|
"typescript": "5.3.2",
|
||||||
"@typebot.io/lib": "workspace:*",
|
"@typebot.io/lib": "workspace:*",
|
||||||
"got": "12.6.0"
|
"ky": "1.2.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
"@udecode/plate-paragraph": "30.5.3",
|
"@udecode/plate-paragraph": "30.5.3",
|
||||||
"escape-html": "1.0.3",
|
"escape-html": "1.0.3",
|
||||||
"google-auth-library": "8.9.0",
|
"google-auth-library": "8.9.0",
|
||||||
"got": "12.6.0",
|
"ky": "1.2.3",
|
||||||
"minio": "7.1.3",
|
"minio": "7.1.3",
|
||||||
"posthog-node": "3.1.1",
|
"posthog-node": "3.1.1",
|
||||||
"remark-parse": "11.0.0",
|
"remark-parse": "11.0.0",
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { PrismaClient } from '@typebot.io/prisma'
|
import { PrismaClient } from '@typebot.io/prisma'
|
||||||
import { promptAndSetEnvironment } from './utils'
|
import { promptAndSetEnvironment } from './utils'
|
||||||
import got, { HTTPError } from 'got'
|
import ky, { HTTPError } from 'ky'
|
||||||
import { confirm, text, isCancel } from '@clack/prompts'
|
import { confirm, text, isCancel } from '@clack/prompts'
|
||||||
import { writeFileSync } from 'fs'
|
|
||||||
|
|
||||||
const insertUsersInBrevoList = async () => {
|
const insertUsersInBrevoList = async () => {
|
||||||
await promptAndSetEnvironment('production')
|
await promptAndSetEnvironment('production')
|
||||||
@ -44,7 +43,7 @@ const insertUsersInBrevoList = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await got.post('https://api.brevo.com/v3/contacts/import', {
|
await ky.post('https://api.brevo.com/v3/contacts/import', {
|
||||||
headers: {
|
headers: {
|
||||||
'api-key': process.env.BREVO_API_KEY,
|
'api-key': process.env.BREVO_API_KEY,
|
||||||
},
|
},
|
||||||
@ -58,7 +57,7 @@ const insertUsersInBrevoList = async () => {
|
|||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof HTTPError) {
|
if (err instanceof HTTPError) {
|
||||||
console.log(err.response.body)
|
console.log(await err.response.text())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
console.log(err)
|
console.log(err)
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
"@types/papaparse": "5.3.7",
|
"@types/papaparse": "5.3.7",
|
||||||
"@types/prompts": "2.4.4",
|
"@types/prompts": "2.4.4",
|
||||||
"deep-object-diff": "1.1.9",
|
"deep-object-diff": "1.1.9",
|
||||||
"got": "12.6.0",
|
"ky": "1.2.3",
|
||||||
"prompts": "2.4.2",
|
"prompts": "2.4.2",
|
||||||
"stripe": "12.13.0",
|
"stripe": "12.13.0",
|
||||||
"tsx": "3.12.7",
|
"tsx": "3.12.7",
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typebot.io/schemas": "workspace:*",
|
"@typebot.io/schemas": "workspace:*",
|
||||||
"got": "12.6.0",
|
"ky": "1.2.3",
|
||||||
"posthog-node": "3.1.1",
|
"posthog-node": "3.1.1",
|
||||||
"@typebot.io/env": "workspace:*"
|
"@typebot.io/env": "workspace:*"
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { env } from '@typebot.io/env'
|
import { env } from '@typebot.io/env'
|
||||||
import { TelemetryEvent } from '@typebot.io/schemas/features/telemetry'
|
import { TelemetryEvent } from '@typebot.io/schemas/features/telemetry'
|
||||||
import { PostHog } from 'posthog-node'
|
import { PostHog } from 'posthog-node'
|
||||||
import got from 'got'
|
import ky from 'ky'
|
||||||
|
|
||||||
export const trackEvents = async (events: TelemetryEvent[]) => {
|
export const trackEvents = async (events: TelemetryEvent[]) => {
|
||||||
if (!env.NEXT_PUBLIC_POSTHOG_KEY) return
|
if (!env.NEXT_PUBLIC_POSTHOG_KEY) return
|
||||||
@ -17,7 +17,7 @@ export const trackEvents = async (events: TelemetryEvent[]) => {
|
|||||||
})
|
})
|
||||||
if (env.USER_CREATED_WEBHOOK_URL) {
|
if (env.USER_CREATED_WEBHOOK_URL) {
|
||||||
try {
|
try {
|
||||||
await got.post(env.USER_CREATED_WEBHOOK_URL, {
|
await ky.post(env.USER_CREATED_WEBHOOK_URL, {
|
||||||
json: {
|
json: {
|
||||||
email: event.data.email,
|
email: event.data.email,
|
||||||
name: event.data.name ? event.data.name.split(' ')[0] : undefined,
|
name: event.data.name ? event.data.name.split(' ')[0] : undefined,
|
||||||
|
186
pnpm-lock.yaml
generated
186
pnpm-lock.yaml
generated
@ -191,15 +191,15 @@ importers:
|
|||||||
google-spreadsheet:
|
google-spreadsheet:
|
||||||
specifier: 4.1.1
|
specifier: 4.1.1
|
||||||
version: 4.1.1(google-auth-library@8.9.0)
|
version: 4.1.1(google-auth-library@8.9.0)
|
||||||
got:
|
|
||||||
specifier: 12.6.0
|
|
||||||
version: 12.6.0
|
|
||||||
immer:
|
immer:
|
||||||
specifier: 10.0.2
|
specifier: 10.0.2
|
||||||
version: 10.0.2
|
version: 10.0.2
|
||||||
jsonwebtoken:
|
jsonwebtoken:
|
||||||
specifier: 9.0.1
|
specifier: 9.0.1
|
||||||
version: 9.0.1
|
version: 9.0.1
|
||||||
|
ky:
|
||||||
|
specifier: 1.2.3
|
||||||
|
version: 1.2.3
|
||||||
libphonenumber-js:
|
libphonenumber-js:
|
||||||
specifier: 1.10.37
|
specifier: 1.10.37
|
||||||
version: 1.10.37
|
version: 1.10.37
|
||||||
@ -593,6 +593,9 @@ importers:
|
|||||||
got:
|
got:
|
||||||
specifier: 12.6.0
|
specifier: 12.6.0
|
||||||
version: 12.6.0
|
version: 12.6.0
|
||||||
|
ky:
|
||||||
|
specifier: 1.2.3
|
||||||
|
version: 1.2.3
|
||||||
next:
|
next:
|
||||||
specifier: 14.1.0
|
specifier: 14.1.0
|
||||||
version: 14.1.0(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0)
|
version: 14.1.0(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0)
|
||||||
@ -781,12 +784,9 @@ importers:
|
|||||||
google-spreadsheet:
|
google-spreadsheet:
|
||||||
specifier: 4.1.1
|
specifier: 4.1.1
|
||||||
version: 4.1.1(google-auth-library@8.9.0)
|
version: 4.1.1(google-auth-library@8.9.0)
|
||||||
got:
|
|
||||||
specifier: 12.6.0
|
|
||||||
version: 12.6.0
|
|
||||||
ky:
|
ky:
|
||||||
specifier: ^1.1.3
|
specifier: 1.2.3
|
||||||
version: 1.2.0
|
version: 1.2.3
|
||||||
libphonenumber-js:
|
libphonenumber-js:
|
||||||
specifier: 1.10.37
|
specifier: 1.10.37
|
||||||
version: 1.10.37
|
version: 1.10.37
|
||||||
@ -812,6 +812,9 @@ importers:
|
|||||||
'@typebot.io/forge-repository':
|
'@typebot.io/forge-repository':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../forge/repository
|
version: link:../forge/repository
|
||||||
|
'@types/node':
|
||||||
|
specifier: ^20.12.3
|
||||||
|
version: 20.12.3
|
||||||
'@types/nodemailer':
|
'@types/nodemailer':
|
||||||
specifier: 6.4.14
|
specifier: 6.4.14
|
||||||
version: 6.4.14
|
version: 6.4.14
|
||||||
@ -1334,9 +1337,9 @@ importers:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: 18.2.15
|
specifier: 18.2.15
|
||||||
version: 18.2.15
|
version: 18.2.15
|
||||||
got:
|
ky:
|
||||||
specifier: 12.6.0
|
specifier: 1.2.3
|
||||||
version: 12.6.0
|
version: 1.2.3
|
||||||
typescript:
|
typescript:
|
||||||
specifier: 5.3.2
|
specifier: 5.3.2
|
||||||
version: 5.3.2
|
version: 5.3.2
|
||||||
@ -1355,9 +1358,9 @@ importers:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: 18.2.15
|
specifier: 18.2.15
|
||||||
version: 18.2.15
|
version: 18.2.15
|
||||||
got:
|
ky:
|
||||||
specifier: 12.6.0
|
specifier: 1.2.3
|
||||||
version: 12.6.0
|
version: 1.2.3
|
||||||
typescript:
|
typescript:
|
||||||
specifier: 5.3.2
|
specifier: 5.3.2
|
||||||
version: 5.3.2
|
version: 5.3.2
|
||||||
@ -1367,9 +1370,9 @@ importers:
|
|||||||
'@typebot.io/lib':
|
'@typebot.io/lib':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../../lib
|
version: link:../../../lib
|
||||||
got:
|
ky:
|
||||||
specifier: 12.6.0
|
specifier: 1.2.3
|
||||||
version: 12.6.0
|
version: 1.2.3
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@typebot.io/forge':
|
'@typebot.io/forge':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
@ -1386,9 +1389,6 @@ importers:
|
|||||||
|
|
||||||
packages/forge/blocks/mistral:
|
packages/forge/blocks/mistral:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@mistralai/mistralai':
|
|
||||||
specifier: 0.1.3
|
|
||||||
version: 0.1.3
|
|
||||||
ai:
|
ai:
|
||||||
specifier: 3.0.12
|
specifier: 3.0.12
|
||||||
version: 3.0.12(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4)
|
version: 3.0.12(react@18.2.0)(solid-js@1.7.8)(svelte@4.2.12)(vue@3.4.21)(zod@3.22.4)
|
||||||
@ -1402,6 +1402,9 @@ importers:
|
|||||||
'@typebot.io/tsconfig':
|
'@typebot.io/tsconfig':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../../tsconfig
|
version: link:../../../tsconfig
|
||||||
|
'@types/node':
|
||||||
|
specifier: ^20.12.4
|
||||||
|
version: 20.12.4
|
||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: 18.2.15
|
specifier: 18.2.15
|
||||||
version: 18.2.15
|
version: 18.2.15
|
||||||
@ -1426,9 +1429,9 @@ importers:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: 18.2.15
|
specifier: 18.2.15
|
||||||
version: 18.2.15
|
version: 18.2.15
|
||||||
got:
|
ky:
|
||||||
specifier: 12.6.0
|
specifier: 1.2.3
|
||||||
version: 12.6.0
|
version: 1.2.3
|
||||||
typescript:
|
typescript:
|
||||||
specifier: 5.3.2
|
specifier: 5.3.2
|
||||||
version: 5.3.2
|
version: 5.3.2
|
||||||
@ -1524,9 +1527,9 @@ importers:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: 18.2.15
|
specifier: 18.2.15
|
||||||
version: 18.2.15
|
version: 18.2.15
|
||||||
got:
|
ky:
|
||||||
specifier: 12.6.0
|
specifier: 1.2.3
|
||||||
version: 12.6.0
|
version: 1.2.3
|
||||||
typescript:
|
typescript:
|
||||||
specifier: 5.3.2
|
specifier: 5.3.2
|
||||||
version: 5.3.2
|
version: 5.3.2
|
||||||
@ -1645,9 +1648,9 @@ importers:
|
|||||||
google-auth-library:
|
google-auth-library:
|
||||||
specifier: 8.9.0
|
specifier: 8.9.0
|
||||||
version: 8.9.0
|
version: 8.9.0
|
||||||
got:
|
ky:
|
||||||
specifier: 12.6.0
|
specifier: 1.2.3
|
||||||
version: 12.6.0
|
version: 1.2.3
|
||||||
minio:
|
minio:
|
||||||
specifier: 7.1.3
|
specifier: 7.1.3
|
||||||
version: 7.1.3
|
version: 7.1.3
|
||||||
@ -1884,9 +1887,9 @@ importers:
|
|||||||
deep-object-diff:
|
deep-object-diff:
|
||||||
specifier: 1.1.9
|
specifier: 1.1.9
|
||||||
version: 1.1.9
|
version: 1.1.9
|
||||||
got:
|
ky:
|
||||||
specifier: 12.6.0
|
specifier: 1.2.3
|
||||||
version: 12.6.0
|
version: 1.2.3
|
||||||
prompts:
|
prompts:
|
||||||
specifier: 2.4.2
|
specifier: 2.4.2
|
||||||
version: 2.4.2
|
version: 2.4.2
|
||||||
@ -1911,9 +1914,9 @@ importers:
|
|||||||
'@typebot.io/schemas':
|
'@typebot.io/schemas':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../schemas
|
version: link:../schemas
|
||||||
got:
|
ky:
|
||||||
specifier: 12.6.0
|
specifier: 1.2.3
|
||||||
version: 12.6.0
|
version: 1.2.3
|
||||||
posthog-node:
|
posthog-node:
|
||||||
specifier: 3.1.1
|
specifier: 3.1.1
|
||||||
version: 3.1.1
|
version: 3.1.1
|
||||||
@ -6838,7 +6841,7 @@ packages:
|
|||||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
jest-message-util: 29.7.0
|
jest-message-util: 29.7.0
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
@ -6859,14 +6862,14 @@ packages:
|
|||||||
'@jest/test-result': 29.7.0
|
'@jest/test-result': 29.7.0
|
||||||
'@jest/transform': 29.7.0
|
'@jest/transform': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
ansi-escapes: 4.3.2
|
ansi-escapes: 4.3.2
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
ci-info: 3.9.0
|
ci-info: 3.9.0
|
||||||
exit: 0.1.2
|
exit: 0.1.2
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
jest-changed-files: 29.7.0
|
jest-changed-files: 29.7.0
|
||||||
jest-config: 29.7.0(@types/node@20.11.26)
|
jest-config: 29.7.0(@types/node@20.12.3)
|
||||||
jest-haste-map: 29.7.0
|
jest-haste-map: 29.7.0
|
||||||
jest-message-util: 29.7.0
|
jest-message-util: 29.7.0
|
||||||
jest-regex-util: 29.6.3
|
jest-regex-util: 29.6.3
|
||||||
@ -6894,7 +6897,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@jest/fake-timers': 29.7.0
|
'@jest/fake-timers': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
jest-mock: 29.7.0
|
jest-mock: 29.7.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
@ -6921,7 +6924,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@sinonjs/fake-timers': 10.3.0
|
'@sinonjs/fake-timers': 10.3.0
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
jest-message-util: 29.7.0
|
jest-message-util: 29.7.0
|
||||||
jest-mock: 29.7.0
|
jest-mock: 29.7.0
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
@ -6954,7 +6957,7 @@ packages:
|
|||||||
'@jest/transform': 29.7.0
|
'@jest/transform': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@jridgewell/trace-mapping': 0.3.25
|
'@jridgewell/trace-mapping': 0.3.25
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
collect-v8-coverage: 1.0.2
|
collect-v8-coverage: 1.0.2
|
||||||
exit: 0.1.2
|
exit: 0.1.2
|
||||||
@ -7042,7 +7045,7 @@ packages:
|
|||||||
'@jest/schemas': 29.6.3
|
'@jest/schemas': 29.6.3
|
||||||
'@types/istanbul-lib-coverage': 2.0.6
|
'@types/istanbul-lib-coverage': 2.0.6
|
||||||
'@types/istanbul-reports': 3.0.4
|
'@types/istanbul-reports': 3.0.4
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
'@types/yargs': 17.0.32
|
'@types/yargs': 17.0.32
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
dev: true
|
dev: true
|
||||||
@ -7461,14 +7464,6 @@ packages:
|
|||||||
zod-to-json-schema: 3.22.4(zod@3.22.4)
|
zod-to-json-schema: 3.22.4(zod@3.22.4)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@mistralai/mistralai@0.1.3:
|
|
||||||
resolution: {integrity: sha512-WUHxC2xdeqX9PTXJEqdiNY54vT2ir72WSJrZTTBKRnkfhX6zIfCYA24faRlWjUB5WTpn+wfdGsTMl3ArijlXFA==}
|
|
||||||
dependencies:
|
|
||||||
node-fetch: 2.7.0
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- encoding
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@next/env@14.0.5-canary.46:
|
/@next/env@14.0.5-canary.46:
|
||||||
resolution: {integrity: sha512-dvNzrArTfe3VY1VIscpb3E2e7SZ1qwFe82WGzpOVbxilT3JcsnVGYF/uq8Jj1qKWPI5C/aePNXwA97JRNAXpRQ==}
|
resolution: {integrity: sha512-dvNzrArTfe3VY1VIscpb3E2e7SZ1qwFe82WGzpOVbxilT3JcsnVGYF/uq8Jj1qKWPI5C/aePNXwA97JRNAXpRQ==}
|
||||||
dev: false
|
dev: false
|
||||||
@ -7827,7 +7822,7 @@ packages:
|
|||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
playwright-core: 1.36.0
|
playwright-core: 1.36.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents: 2.3.2
|
fsevents: 2.3.2
|
||||||
@ -9453,7 +9448,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==}
|
resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/connect': 3.4.38
|
'@types/connect': 3.4.38
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@types/canvas-confetti@1.6.0:
|
/@types/canvas-confetti@1.6.0:
|
||||||
@ -9463,13 +9458,13 @@ packages:
|
|||||||
/@types/cli-progress@3.11.5:
|
/@types/cli-progress@3.11.5:
|
||||||
resolution: {integrity: sha512-D4PbNRbviKyppS5ivBGyFO29POlySLmA2HyUFE4p5QGazAMM3CwkKWcvTl8gvElSuxRh6FPKL8XmidX873ou4g==}
|
resolution: {integrity: sha512-D4PbNRbviKyppS5ivBGyFO29POlySLmA2HyUFE4p5QGazAMM3CwkKWcvTl8gvElSuxRh6FPKL8XmidX873ou4g==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/connect@3.4.38:
|
/@types/connect@3.4.38:
|
||||||
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
|
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@types/content-type@1.1.8:
|
/@types/content-type@1.1.8:
|
||||||
@ -9482,7 +9477,7 @@ packages:
|
|||||||
/@types/cors@2.8.13:
|
/@types/cors@2.8.13:
|
||||||
resolution: {integrity: sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==}
|
resolution: {integrity: sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
|
|
||||||
/@types/debug@4.1.12:
|
/@types/debug@4.1.12:
|
||||||
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
|
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
|
||||||
@ -9528,7 +9523,7 @@ packages:
|
|||||||
/@types/express-serve-static-core@4.17.43:
|
/@types/express-serve-static-core@4.17.43:
|
||||||
resolution: {integrity: sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==}
|
resolution: {integrity: sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
'@types/qs': 6.9.7
|
'@types/qs': 6.9.7
|
||||||
'@types/range-parser': 1.2.7
|
'@types/range-parser': 1.2.7
|
||||||
'@types/send': 0.17.4
|
'@types/send': 0.17.4
|
||||||
@ -9546,7 +9541,7 @@ packages:
|
|||||||
/@types/graceful-fs@4.1.9:
|
/@types/graceful-fs@4.1.9:
|
||||||
resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==}
|
resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/hast@2.3.10:
|
/@types/hast@2.3.10:
|
||||||
@ -9602,7 +9597,7 @@ packages:
|
|||||||
/@types/jsdom@20.0.1:
|
/@types/jsdom@20.0.1:
|
||||||
resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==}
|
resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
'@types/tough-cookie': 4.0.5
|
'@types/tough-cookie': 4.0.5
|
||||||
parse5: 7.1.2
|
parse5: 7.1.2
|
||||||
dev: true
|
dev: true
|
||||||
@ -9617,7 +9612,7 @@ packages:
|
|||||||
/@types/jsonwebtoken@9.0.2:
|
/@types/jsonwebtoken@9.0.2:
|
||||||
resolution: {integrity: sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==}
|
resolution: {integrity: sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/katex@0.16.7:
|
/@types/katex@0.16.7:
|
||||||
@ -9655,7 +9650,7 @@ packages:
|
|||||||
/@types/micro@7.3.7:
|
/@types/micro@7.3.7:
|
||||||
resolution: {integrity: sha512-MFsX7eCj0Tg3TtphOQvANNvNtFpya+s/rYOCdV6o+DFjOQPFi2EVRbBALjbbgZTXUaJP1Q281MJiJOD40d0UxQ==}
|
resolution: {integrity: sha512-MFsX7eCj0Tg3TtphOQvANNvNtFpya+s/rYOCdV6o+DFjOQPFi2EVRbBALjbbgZTXUaJP1Q281MJiJOD40d0UxQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/mime@1.3.5:
|
/@types/mime@1.3.5:
|
||||||
@ -9676,7 +9671,7 @@ packages:
|
|||||||
/@types/node-fetch@2.6.11:
|
/@types/node-fetch@2.6.11:
|
||||||
resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==}
|
resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
form-data: 4.0.0
|
form-data: 4.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
@ -9687,6 +9682,18 @@ packages:
|
|||||||
resolution: {integrity: sha512-YwOMmyhNnAWijOBQweOJnQPl068Oqd4K3OFbTc6AHJwzweUwwWG3GIFY74OKks2PJUDkQPeddOQES9mLn1CTEQ==}
|
resolution: {integrity: sha512-YwOMmyhNnAWijOBQweOJnQPl068Oqd4K3OFbTc6AHJwzweUwwWG3GIFY74OKks2PJUDkQPeddOQES9mLn1CTEQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 5.26.5
|
undici-types: 5.26.5
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@types/node@20.12.3:
|
||||||
|
resolution: {integrity: sha512-sD+ia2ubTeWrOu+YMF+MTAB7E+O7qsMqAbMfW7DG3K1URwhZ5hN1pLlRVGbf4wDFzSfikL05M17EyorS86jShw==}
|
||||||
|
dependencies:
|
||||||
|
undici-types: 5.26.5
|
||||||
|
|
||||||
|
/@types/node@20.12.4:
|
||||||
|
resolution: {integrity: sha512-E+Fa9z3wSQpzgYQdYmme5X3OTuejnnTx88A6p6vkkJosR3KBz+HpE3kqNm98VE6cfLFcISx7zW7MsJkH6KwbTw==}
|
||||||
|
dependencies:
|
||||||
|
undici-types: 5.26.5
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/node@20.4.2:
|
/@types/node@20.4.2:
|
||||||
resolution: {integrity: sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==}
|
resolution: {integrity: sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==}
|
||||||
@ -9698,13 +9705,13 @@ packages:
|
|||||||
/@types/nodemailer@6.4.14:
|
/@types/nodemailer@6.4.14:
|
||||||
resolution: {integrity: sha512-fUWthHO9k9DSdPCSPRqcu6TWhYyxTBg382vlNIttSe9M7XfsT06y0f24KHXtbnijPGGRIcVvdKHTNikOI6qiHA==}
|
resolution: {integrity: sha512-fUWthHO9k9DSdPCSPRqcu6TWhYyxTBg382vlNIttSe9M7XfsT06y0f24KHXtbnijPGGRIcVvdKHTNikOI6qiHA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/nodemailer@6.4.8:
|
/@types/nodemailer@6.4.8:
|
||||||
resolution: {integrity: sha512-oVsJSCkqViCn8/pEu2hfjwVO+Gb3e+eTWjg3PcjeFKRItfKpKwHphQqbYmPQrlMk+op7pNNWPbsJIEthpFN/OQ==}
|
resolution: {integrity: sha512-oVsJSCkqViCn8/pEu2hfjwVO+Gb3e+eTWjg3PcjeFKRItfKpKwHphQqbYmPQrlMk+op7pNNWPbsJIEthpFN/OQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/normalize-package-data@2.4.4:
|
/@types/normalize-package-data@2.4.4:
|
||||||
@ -9717,7 +9724,7 @@ packages:
|
|||||||
/@types/papaparse@5.3.7:
|
/@types/papaparse@5.3.7:
|
||||||
resolution: {integrity: sha512-f2HKmlnPdCvS0WI33WtCs5GD7X1cxzzS/aduaxSu3I7TbhWlENjSPs6z5TaB9K0J+BH1jbmqTaM+ja5puis4wg==}
|
resolution: {integrity: sha512-f2HKmlnPdCvS0WI33WtCs5GD7X1cxzzS/aduaxSu3I7TbhWlENjSPs6z5TaB9K0J+BH1jbmqTaM+ja5puis4wg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/parse-json@4.0.2:
|
/@types/parse-json@4.0.2:
|
||||||
@ -9735,7 +9742,7 @@ packages:
|
|||||||
/@types/prompts@2.4.4:
|
/@types/prompts@2.4.4:
|
||||||
resolution: {integrity: sha512-p5N9uoTH76lLvSAaYSZtBCdEXzpOOufsRjnhjVSrZGXikVGHX9+cc9ERtHRV4hvBKHyZb1bg4K+56Bd2TqUn4A==}
|
resolution: {integrity: sha512-p5N9uoTH76lLvSAaYSZtBCdEXzpOOufsRjnhjVSrZGXikVGHX9+cc9ERtHRV4hvBKHyZb1bg4K+56Bd2TqUn4A==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
kleur: 3.0.3
|
kleur: 3.0.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
@ -9745,7 +9752,7 @@ packages:
|
|||||||
/@types/qrcode@1.5.5:
|
/@types/qrcode@1.5.5:
|
||||||
resolution: {integrity: sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==}
|
resolution: {integrity: sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/qs@6.9.7:
|
/@types/qs@6.9.7:
|
||||||
@ -9801,7 +9808,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==}
|
resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/mime': 1.3.5
|
'@types/mime': 1.3.5
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@types/serve-static@1.15.5:
|
/@types/serve-static@1.15.5:
|
||||||
@ -9809,7 +9816,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@types/http-errors': 2.0.4
|
'@types/http-errors': 2.0.4
|
||||||
'@types/mime': 3.0.4
|
'@types/mime': 3.0.4
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@types/stack-utils@2.0.3:
|
/@types/stack-utils@2.0.3:
|
||||||
@ -9841,7 +9848,7 @@ packages:
|
|||||||
/@types/webpack@5.28.5(@swc/core@1.3.101)(esbuild@0.19.11):
|
/@types/webpack@5.28.5(@swc/core@1.3.101)(esbuild@0.19.11):
|
||||||
resolution: {integrity: sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw==}
|
resolution: {integrity: sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
tapable: 2.2.1
|
tapable: 2.2.1
|
||||||
webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)
|
webpack: 5.90.3(@swc/core@1.3.101)(esbuild@0.19.11)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@ -12457,7 +12464,7 @@ packages:
|
|||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
exit: 0.1.2
|
exit: 0.1.2
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
jest-config: 29.7.0(@types/node@20.11.26)
|
jest-config: 29.7.0(@types/node@20.12.3)
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
prompts: 2.4.2
|
prompts: 2.4.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@ -13170,7 +13177,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@types/cookie': 0.4.1
|
'@types/cookie': 0.4.1
|
||||||
'@types/cors': 2.8.13
|
'@types/cors': 2.8.13
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
accepts: 1.3.8
|
accepts: 1.3.8
|
||||||
base64id: 2.0.0
|
base64id: 2.0.0
|
||||||
cookie: 0.4.2
|
cookie: 0.4.2
|
||||||
@ -15928,7 +15935,7 @@ packages:
|
|||||||
'@jest/expect': 29.7.0
|
'@jest/expect': 29.7.0
|
||||||
'@jest/test-result': 29.7.0
|
'@jest/test-result': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
co: 4.6.0
|
co: 4.6.0
|
||||||
dedent: 1.5.1
|
dedent: 1.5.1
|
||||||
@ -15966,7 +15973,7 @@ packages:
|
|||||||
create-jest: 29.7.0
|
create-jest: 29.7.0
|
||||||
exit: 0.1.2
|
exit: 0.1.2
|
||||||
import-local: 3.1.0
|
import-local: 3.1.0
|
||||||
jest-config: 29.7.0(@types/node@20.11.26)
|
jest-config: 29.7.0(@types/node@20.12.3)
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
jest-validate: 29.7.0
|
jest-validate: 29.7.0
|
||||||
yargs: 17.7.2
|
yargs: 17.7.2
|
||||||
@ -15977,7 +15984,7 @@ packages:
|
|||||||
- ts-node
|
- ts-node
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/jest-config@29.7.0(@types/node@20.11.26):
|
/jest-config@29.7.0(@types/node@20.12.3):
|
||||||
resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==}
|
resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==}
|
||||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -15992,7 +15999,7 @@ packages:
|
|||||||
'@babel/core': 7.22.9
|
'@babel/core': 7.22.9
|
||||||
'@jest/test-sequencer': 29.7.0
|
'@jest/test-sequencer': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
babel-jest: 29.7.0(@babel/core@7.22.9)
|
babel-jest: 29.7.0(@babel/core@7.22.9)
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
ci-info: 3.9.0
|
ci-info: 3.9.0
|
||||||
@ -16058,7 +16065,7 @@ packages:
|
|||||||
'@jest/fake-timers': 29.7.0
|
'@jest/fake-timers': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/jsdom': 20.0.1
|
'@types/jsdom': 20.0.1
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
jest-mock: 29.7.0
|
jest-mock: 29.7.0
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
jsdom: 20.0.3
|
jsdom: 20.0.3
|
||||||
@ -16075,7 +16082,7 @@ packages:
|
|||||||
'@jest/environment': 29.7.0
|
'@jest/environment': 29.7.0
|
||||||
'@jest/fake-timers': 29.7.0
|
'@jest/fake-timers': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
jest-mock: 29.7.0
|
jest-mock: 29.7.0
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
dev: true
|
dev: true
|
||||||
@ -16091,7 +16098,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/graceful-fs': 4.1.9
|
'@types/graceful-fs': 4.1.9
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
anymatch: 3.1.3
|
anymatch: 3.1.3
|
||||||
fb-watchman: 2.0.2
|
fb-watchman: 2.0.2
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
@ -16142,7 +16149,7 @@ packages:
|
|||||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
@ -16197,7 +16204,7 @@ packages:
|
|||||||
'@jest/test-result': 29.7.0
|
'@jest/test-result': 29.7.0
|
||||||
'@jest/transform': 29.7.0
|
'@jest/transform': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
emittery: 0.13.1
|
emittery: 0.13.1
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
@ -16228,7 +16235,7 @@ packages:
|
|||||||
'@jest/test-result': 29.7.0
|
'@jest/test-result': 29.7.0
|
||||||
'@jest/transform': 29.7.0
|
'@jest/transform': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
cjs-module-lexer: 1.2.3
|
cjs-module-lexer: 1.2.3
|
||||||
collect-v8-coverage: 1.0.2
|
collect-v8-coverage: 1.0.2
|
||||||
@ -16280,7 +16287,7 @@ packages:
|
|||||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
ci-info: 3.9.0
|
ci-info: 3.9.0
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
@ -16305,7 +16312,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@jest/test-result': 29.7.0
|
'@jest/test-result': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
ansi-escapes: 4.3.2
|
ansi-escapes: 4.3.2
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
emittery: 0.13.1
|
emittery: 0.13.1
|
||||||
@ -16317,7 +16324,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
|
resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
|
||||||
engines: {node: '>= 10.13.0'}
|
engines: {node: '>= 10.13.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
merge-stream: 2.0.0
|
merge-stream: 2.0.0
|
||||||
supports-color: 8.1.1
|
supports-color: 8.1.1
|
||||||
dev: false
|
dev: false
|
||||||
@ -16326,7 +16333,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==}
|
resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==}
|
||||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
merge-stream: 2.0.0
|
merge-stream: 2.0.0
|
||||||
supports-color: 8.1.1
|
supports-color: 8.1.1
|
||||||
@ -16658,10 +16665,9 @@ packages:
|
|||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/ky@1.2.0:
|
/ky@1.2.3:
|
||||||
resolution: {integrity: sha512-dnPW+T78MuJ9tLAiF/apJV7bP7RRRCARXQxsCmsWiKLXqGtMBOgDVOFRYzCAfNe/OrRyFyor5ESgvvC+QWEqOA==}
|
resolution: {integrity: sha512-2IM3VssHfG2zYz2FsHRUqIp8chhLc9uxDMcK2THxgFfv8pQhnMfN8L0ul+iW4RdBl5AglF8ooPIflRm3yNH0IA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
dev: false
|
|
||||||
|
|
||||||
/language-subtag-registry@0.3.22:
|
/language-subtag-registry@0.3.22:
|
||||||
resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==}
|
resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==}
|
||||||
@ -18540,7 +18546,7 @@ packages:
|
|||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/express': 4.17.21
|
'@types/express': 4.17.21
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
accepts: 1.3.8
|
accepts: 1.3.8
|
||||||
content-disposition: 0.5.4
|
content-disposition: 0.5.4
|
||||||
depd: 1.1.2
|
depd: 1.1.2
|
||||||
@ -21400,7 +21406,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-mn7CxL71FCRWkQp33jcJ7+xfRF7HGzPYZlq2c87U+6kxL1qd7f/N3S1g1E5uaSWe83V5v3jN/IiWqg9y8+kWRw==}
|
resolution: {integrity: sha512-mn7CxL71FCRWkQp33jcJ7+xfRF7HGzPYZlq2c87U+6kxL1qd7f/N3S1g1E5uaSWe83V5v3jN/IiWqg9y8+kWRw==}
|
||||||
engines: {node: '>=12.*'}
|
engines: {node: '>=12.*'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.11.26
|
'@types/node': 20.12.3
|
||||||
qs: 6.11.2
|
qs: 6.11.2
|
||||||
|
|
||||||
/strnum@1.0.5:
|
/strnum@1.0.5:
|
||||||
|
Reference in New Issue
Block a user