/** * Zod Schemas - SillyTavern 兼容格式验证 */ import { z } from 'zod'; // ==================== 世界书条目 ==================== export const STWorldInfoEntryPositionSchema = z.enum([ 'before_char', 'after_char', 'before_example', 'after_example', 'author_note_top', 'author_note_bottom', 'at_depth', ]); export const STWorldInfoFilterLogicSchema = z.enum([ 'and_any', 'and_all', 'not_any', 'not_all', ]); export const STWorldInfoEntryRoleSchema = z.enum([ 'system', 'user', 'assistant', ]); export const STWorldInfoEntrySchema = z.object({ uid: z.string(), key: z.array(z.string()).optional(), keysecondary: z.array(z.string()).optional(), filter: STWorldInfoFilterLogicSchema.optional(), content: z.string(), constant: z.boolean().optional(), selective: z.boolean().optional(), order: z.number(), position: STWorldInfoEntryPositionSchema, depth: z.number().optional(), role: STWorldInfoEntryRoleSchema.optional(), probability: z.number().min(0).max(100).optional(), group: z.array(z.string()).optional(), groupPrioritize: z.boolean().optional(), useGroupScoring: z.boolean().optional(), automationId: z.string().optional(), disable: z.boolean().optional(), extensions: z.record(z.unknown()).optional(), }); export const STWorldInfoSchema = z.object({ spec: z.string(), name: z.string().optional(), description: z.string().optional(), entries: z.array(STWorldInfoEntrySchema), extensions: z.record(z.unknown()).optional(), }); // ==================== 角色卡 ==================== export const STCharacterCardSpecSchema = z.enum([ 'chara_card_v1', 'chara_card_v2', 'chara_card_v3', ]); export const STCharacterCardDataSchema = z.object({ name: z.string(), description: z.string(), personality: z.string(), scenario: z.string(), first_mes: z.string(), mes_example: z.string(), alternate_greetings: z.array(z.string()).optional(), creator_notes: z.string().optional(), system_prompt: z.string().optional(), post_history_instructions: z.string().optional(), tags: z.array(z.string()).optional(), character_book: STWorldInfoSchema.optional(), extensions: z.object({ world: z.string().optional(), talkativeness: z.number().min(0).max(1).optional(), fav: z.boolean().optional(), }).passthrough().optional(), }); export const STCharacterCardSchema = z.object({ spec: STCharacterCardSpecSchema, spec_version: z.string().optional(), data: STCharacterCardDataSchema, }); // ==================== 聊天记录 ==================== export const STChatHeaderSchema = z.object({ user_name: z.string(), character_name: z.string(), create_date: z.string(), chat_metadata: z.record(z.unknown()).optional(), }).passthrough(); export const STChatMessageSchema = z.object({ name: z.string(), is_user: z.boolean(), is_system: z.boolean().optional(), send_date: z.union([z.number(), z.string()]), mes: z.string(), swipes: z.array(z.string()).optional(), swipe_id: z.number().optional(), is_hidden: z.boolean().optional(), extra: z.record(z.unknown()).optional(), }); // ==================== 预设 ==================== export const STGenerationPresetSchema = z.object({ name: z.string(), temperature: z.number().optional(), top_p: z.number().optional(), top_k: z.number().optional(), repetition_penalty: z.number().optional(), frequency_penalty: z.number().optional(), presence_penalty: z.number().optional(), max_length: z.number().optional(), }).passthrough(); // ==================== 提示词预设 (Prompt Preset) ==================== export const STPromptRoleSchema = z.enum(['system', 'assistant', 'user']); export const STPromptSchema = z.object({ identifier: z.string(), name: z.string().optional(), content: z.string(), role: STPromptRoleSchema, marker: z.boolean().optional(), injection_order: z.number().optional(), extensions: z.record(z.unknown()).optional(), }); export const STPromptOrderItemSchema = z.object({ identifier: z.string(), enabled: z.boolean(), }); export const STPromptOrderConfigSchema = z.object({ order: z.array(STPromptOrderItemSchema), }); export const STPromptPresetSchema = z.object({ name: z.string(), prompts: z.array(STPromptSchema), prompt_order: z.record(STPromptOrderConfigSchema), default_prompt_order: STPromptOrderConfigSchema.optional(), });