Files
simstudioai--sim/apps/sim/lib/api/contracts/chats.ts
T
wehub-resource-sync d25d482dc2
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:20:55 +08:00

280 lines
8.2 KiB
TypeScript

import { z } from 'zod'
import { defineRouteContract } from '@/lib/api/contracts/types'
export const chatAuthTypeSchema = z.enum(['public', 'password', 'email', 'sso'])
export type ChatAuthType = z.output<typeof chatAuthTypeSchema>
export const chatIdParamsSchema = z.object({
id: z.string().min(1),
})
export const chatIdentifierParamsSchema = z.object({
identifier: z.string().min(1),
})
export const chatOutputConfigSchema = z.object({
blockId: z.string().min(1),
path: z.string().min(1),
})
export const deployedChatOutputConfigSchema = z.object({
blockId: z.string(),
path: z.string().optional(),
})
export const chatCustomizationsSchema = z.object({
primaryColor: z.string(),
welcomeMessage: z.string(),
imageUrl: z.string().optional(),
})
export const createChatBodySchema = z.object({
workflowId: z.string().min(1, 'Workflow ID is required'),
identifier: z
.string()
.min(1, 'Identifier is required')
.regex(/^[a-z0-9-]+$/, 'Identifier can only contain lowercase letters, numbers, and hyphens'),
title: z.string().min(1, 'Title is required'),
description: z.string().optional(),
customizations: chatCustomizationsSchema,
authType: chatAuthTypeSchema.default('public'),
password: z.string().optional(),
allowedEmails: z.array(z.string()).optional().default([]),
outputConfigs: z.array(chatOutputConfigSchema).optional().default([]),
})
export type CreateChatBody = z.input<typeof createChatBodySchema>
export const updateChatBodySchema = z.object({
workflowId: z.string().min(1, 'Workflow ID is required').optional(),
identifier: z
.string()
.min(1, 'Identifier is required')
.regex(/^[a-z0-9-]+$/, 'Identifier can only contain lowercase letters, numbers, and hyphens')
.optional(),
title: z.string().min(1, 'Title is required').optional(),
description: z.string().optional(),
customizations: chatCustomizationsSchema.optional(),
authType: chatAuthTypeSchema.optional(),
password: z.string().optional(),
allowedEmails: z.array(z.string()).optional(),
outputConfigs: z.array(chatOutputConfigSchema).optional(),
})
export type UpdateChatBody = z.input<typeof updateChatBodySchema>
export const createChatResponseSchema = z.object({
id: z.string(),
chatId: z.string(),
chatUrl: z.string(),
message: z.string(),
})
export type CreateChatResponse = z.output<typeof createChatResponseSchema>
export const updateChatResponseSchema = z.object({
id: z.string(),
chatUrl: z.string(),
message: z.string(),
})
export type UpdateChatResponse = z.output<typeof updateChatResponseSchema>
export const deleteChatResponseSchema = z.object({
message: z.string(),
})
export const deployedChatConfigSchema = z.object({
id: z.string(),
title: z.string(),
description: z.preprocess((value) => value ?? '', z.string()),
customizations: z.preprocess(
(value) => value ?? {},
z
.object({
primaryColor: z.string().optional(),
logoUrl: z.string().optional(),
imageUrl: z.string().optional(),
welcomeMessage: z.string().optional(),
headerText: z.string().optional(),
})
.passthrough()
),
authType: z.preprocess((value) => value ?? 'public', chatAuthTypeSchema),
outputConfigs: z.preprocess(
(value) => value ?? undefined,
z.array(deployedChatOutputConfigSchema).optional()
),
})
export type DeployedChatConfig = z.output<typeof deployedChatConfigSchema>
export const deployedChatAuthBodySchema = z.object({
password: z.string().max(1024, 'Password is too long').optional(),
email: z.string().email('Invalid email format').optional().or(z.literal('')),
})
export type DeployedChatAuthBody = z.input<typeof deployedChatAuthBodySchema>
const MAX_CHAT_INPUT_CHARS = 1_000_000
const MAX_CHAT_FILE_DATA_CHARS = 14 * 1024 * 1024
const MAX_CHAT_FILES = 15
export const deployedChatFileSchema = z.object({
name: z.string().min(1, 'File name is required').max(255, 'File name is too long'),
type: z.string().min(1, 'File type is required').max(255, 'File type is too long'),
size: z.number().positive('File size must be positive'),
data: z
.string()
.min(1, 'File data is required')
.max(MAX_CHAT_FILE_DATA_CHARS, 'File data exceeds the maximum allowed size'),
lastModified: z.number().optional(),
})
export const deployedChatPostBodySchema = z.object({
input: z.string().max(MAX_CHAT_INPUT_CHARS, 'Input is too long').optional(),
password: z.string().max(1024, 'Password is too long').optional(),
email: z.string().email('Invalid email format').optional().or(z.literal('')),
conversationId: z.string().max(256, 'Conversation ID is too long').optional(),
files: z
.array(deployedChatFileSchema)
.max(MAX_CHAT_FILES, `A maximum of ${MAX_CHAT_FILES} files is allowed`)
.optional()
.default([]),
})
export type DeployedChatPostBody = z.input<typeof deployedChatPostBodySchema>
export const chatSSOBodySchema = z.object({
email: z.string().email('Invalid email address'),
})
export const chatSSOResponseSchema = z.object({
eligible: z.boolean(),
})
export type ChatSSOResponse = z.output<typeof chatSSOResponseSchema>
export const chatEmailOtpRequestBodySchema = z.object({
email: z.string().email('Invalid email address'),
})
export const chatEmailOtpVerifyBodySchema = chatEmailOtpRequestBodySchema.extend({
otp: z.string().length(6, 'OTP must be 6 digits'),
})
export const chatEmailOtpRequestResponseSchema = z.object({
message: z.string(),
})
export const identifierValidationQuerySchema = z.object({
identifier: z
.string()
.min(1, 'Identifier is required')
.regex(/^[a-z0-9-]+$/, 'Identifier can only contain lowercase letters, numbers, and hyphens')
.max(100, 'Identifier must be 100 characters or less'),
})
export const identifierValidationResponseSchema = z.object({
available: z.boolean(),
error: z.string().nullable().optional(),
})
export const createChatContract = defineRouteContract({
method: 'POST',
path: '/api/chat',
body: createChatBodySchema,
response: {
mode: 'json',
schema: createChatResponseSchema,
},
})
export const getDeployedChatConfigContract = defineRouteContract({
method: 'GET',
path: '/api/chat/[identifier]',
params: chatIdentifierParamsSchema,
response: {
mode: 'json',
schema: deployedChatConfigSchema,
},
})
export const authenticateDeployedChatContract = defineRouteContract({
method: 'POST',
path: '/api/chat/[identifier]',
params: chatIdentifierParamsSchema,
body: deployedChatAuthBodySchema,
response: {
mode: 'json',
schema: deployedChatConfigSchema,
},
})
export const deployedChatPostContract = defineRouteContract({
method: 'POST',
path: '/api/chat/[identifier]',
params: chatIdentifierParamsSchema,
body: deployedChatPostBodySchema,
response: {
mode: 'json',
schema: deployedChatConfigSchema,
},
})
export const chatSSOContract = defineRouteContract({
method: 'POST',
path: '/api/chat/[identifier]/sso',
params: chatIdentifierParamsSchema,
body: chatSSOBodySchema,
response: {
mode: 'json',
schema: chatSSOResponseSchema,
},
})
export const requestChatEmailOtpContract = defineRouteContract({
method: 'POST',
path: '/api/chat/[identifier]/otp',
params: chatIdentifierParamsSchema,
body: chatEmailOtpRequestBodySchema,
response: {
mode: 'json',
schema: chatEmailOtpRequestResponseSchema,
},
})
export const verifyChatEmailOtpContract = defineRouteContract({
method: 'PUT',
path: '/api/chat/[identifier]/otp',
params: chatIdentifierParamsSchema,
body: chatEmailOtpVerifyBodySchema,
response: {
mode: 'json',
schema: deployedChatConfigSchema,
},
})
export const validateChatIdentifierContract = defineRouteContract({
method: 'GET',
path: '/api/chat/validate',
query: identifierValidationQuerySchema,
response: {
mode: 'json',
schema: identifierValidationResponseSchema,
},
})
export const updateChatContract = defineRouteContract({
method: 'PATCH',
path: '/api/chat/manage/[id]',
params: chatIdParamsSchema,
body: updateChatBodySchema,
response: {
mode: 'json',
schema: updateChatResponseSchema,
},
})
export const deleteChatContract = defineRouteContract({
method: 'DELETE',
path: '/api/chat/manage/[id]',
params: chatIdParamsSchema,
response: {
mode: 'json',
schema: deleteChatResponseSchema,
},
})