import { z } from "zod"; const textPartSchema = z.object({ type: z.enum(["text"]), text: z.string().min(1).max(2000), }); const filePartSchema = z.object({ type: z.enum(["file"]), mediaType: z.enum(["image/jpeg", "image/png", "image/webp", "image/gif", "image/jpg", "image/bmp", "image/svg+xml"]), name: z.string().min(1).max(100), url: z.string().url(), assetId: z.string().uuid().optional(), width: z.number().positive().optional(), height: z.number().positive().optional(), }); const partSchema = z.union([textPartSchema, filePartSchema]); // 视频参数 schema const videoParamsSchema = z.object({ mode: z.enum(["text-to-video", "first-frame", "first-last-frame", "reference-images"]), resolution: z.enum(["480p", "720p", "1080p"]).optional(), ratio: z.string().optional(), duration: z.number().optional(), generateAudio: z.boolean().optional(), watermark: z.boolean().optional(), cameraFixed: z.boolean().optional(), cameraMove: z.string().optional(), fps: z.number().optional(), seed: z.number().optional(), returnLastFrame: z.boolean().optional(), }).optional(); const imageSizeValues = ["1K", "2K", "4K"] as const; function normalizeImageSizeInput(value: unknown) { if (typeof value !== "string") return undefined; const normalized = value.trim().toUpperCase(); return imageSizeValues.includes(normalized as (typeof imageSizeValues)[number]) ? normalized : undefined; } // 🆕 图片生成参数 schema const imageParamsSchema = z.object({ aspectRatio: z.string().optional(), imageSize: z.preprocess(normalizeImageSizeInput, z.enum(imageSizeValues).optional()), imageCount: z.number().min(1).max(10).optional(), // 阿里生图专用参数 size: z.string().optional(), // 自定义分辨率,如 "1024*1024" negativePrompt: z.string().optional(), // 反向提示词 promptExtend: z.boolean().optional(), // 提示词智能优化 watermark: z.boolean().optional(), // 水印 seed: z.number().optional(), // 随机种子 n: z.number().min(1).max(10).optional(), // 兼容 n 参数 }).optional(); const contextPayloadSchema = z .object({ source: z.enum(["chat", "canvas", "realtime-canvas"]).optional(), projectId: z.string().uuid().optional(), selectedNodeIds: z.array(z.string().min(1).max(128)).max(20).optional(), selectedAssetIds: z.array(z.string().uuid()).max(20).optional(), focusPolicy: z.enum(["auto", "selected", "latest_result", "original"]).optional(), canvasImageNodes: z .array( z.object({ nodeId: z.string().min(1).max(128), assetId: z.string().uuid().optional(), url: z.string().url(), title: z.string().max(256).optional(), prompt: z.string().max(2000).optional(), x: z.number(), y: z.number(), width: z.number().optional(), height: z.number().optional(), isSelected: z.boolean().optional(), }), ) .max(20) .optional(), }) .optional(); const agentModeReferenceSchema = z.object({ id: z.string().min(1).max(128), label: z.string().min(1).max(255), imageUrl: z.string().url(), candidateId: z.string().min(1).max(128).nullable().optional(), sortOrder: z.number().min(0).max(999).optional(), assignedProductIndex: z.number().min(0).max(9).nullable().optional(), passthrough: z.boolean().nullable().optional(), }); const agentModeSourceImageSchema = z.object({ url: z.string().url(), label: z.string().max(255).optional(), name: z.string().max(255).optional(), assetId: z.string().min(1).max(128).nullable().optional(), }); const agentModePayloadSchema = z .object({ modeType: z.enum(["detail_replacement", "sku_replacement"]), replacementStrategy: z.enum(["scene_replace", "product_only"]).optional(), query: z.string().max(64).optional(), queryType: z.enum(["sku", "spu", "productId"]).optional(), selectedCandidateId: z.string().min(1).max(128).nullable().optional(), references: z.array(agentModeReferenceSchema).max(40), sourceImages: z .object({ productImages: z.array(agentModeSourceImageSchema).max(16).optional(), modelImage: agentModeSourceImageSchema.nullable().optional(), }) .optional(), }) .optional(); export const postRequestBodySchema = z.object({ id: z.string().uuid(), message: z.object({ id: z.string().uuid(), role: z.enum(["user"]), parts: z.array(partSchema), }), hiddenPrompt: z.string().max(4000).optional(), workflowPromptOptimizationEnabled: z.boolean().optional(), autoContext: z.string().max(4000).optional(), agentPresetId: z.string().uuid().optional(), // 支持预定义模型名称或数据库中的模型 UUID selectedChatModel: z.string().min(1).max(128), selectedVisibilityType: z.enum(["public", "private"]), composerMode: z.enum(["agent", "image", "video", "detail"]).optional(), deepThinkingEnabled: z.boolean().optional(), debugProtocol: z.boolean().optional(), videoParams: videoParamsSchema, // 视频参数 imageParams: imageParamsSchema, // 🆕 图片生成参数 contextPayload: contextPayloadSchema, agentModePayload: agentModePayloadSchema, }); export type PostRequestBody = z.infer;