142 lines
5.1 KiB
TypeScript
142 lines
5.1 KiB
TypeScript
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(),
|
|
});
|
|
|
|
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<typeof postRequestBodySchema>;
|