规定数据类型
This commit is contained in:
1
shared/schemas/.gitkeep
Normal file
1
shared/schemas/.gitkeep
Normal file
@@ -0,0 +1 @@
|
||||
// Zod Schemas for Validation (v3)
|
||||
6
shared/schemas/index.ts
Normal file
6
shared/schemas/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Shared Schemas 导出
|
||||
*/
|
||||
|
||||
export * from './sillytavern.schemas';
|
||||
export * from './internal.schemas';
|
||||
258
shared/schemas/internal.schemas.ts
Normal file
258
shared/schemas/internal.schemas.ts
Normal file
@@ -0,0 +1,258 @@
|
||||
/**
|
||||
* Zod Schemas - 项目内部格式验证
|
||||
*/
|
||||
|
||||
import { z } from 'zod';
|
||||
|
||||
// ==================== 世界书条目 ====================
|
||||
|
||||
export const ActivationTypeSchema = z.enum([
|
||||
'permanent',
|
||||
'keyword',
|
||||
'rag',
|
||||
'logic',
|
||||
]);
|
||||
|
||||
export const LogicOperatorSchema = z.enum([
|
||||
'equals',
|
||||
'not_equals',
|
||||
'contains',
|
||||
'not_contains',
|
||||
'greater',
|
||||
'less',
|
||||
]);
|
||||
|
||||
export const LogicExpressionSchema = z.object({
|
||||
variable1: z.string(),
|
||||
operator: LogicOperatorSchema,
|
||||
variable2: z.string(),
|
||||
});
|
||||
|
||||
export const RAGConfigSchema = z.object({
|
||||
libraryId: z.string(),
|
||||
threshold: z.number().min(0).max(1).optional(),
|
||||
maxEntries: z.number().min(1).optional(),
|
||||
});
|
||||
|
||||
export const WorldInfoEntrySchema = z.object({
|
||||
uid: z.string(),
|
||||
key: z.array(z.string()).optional(),
|
||||
keysecondary: z.array(z.string()).optional(),
|
||||
content: z.string(),
|
||||
order: z.number(),
|
||||
position: z.enum([
|
||||
'before_char',
|
||||
'after_char',
|
||||
'before_example',
|
||||
'after_example',
|
||||
'author_note_top',
|
||||
'author_note_bottom',
|
||||
'at_depth',
|
||||
]),
|
||||
depth: z.number().optional(),
|
||||
role: z.enum(['system', 'user', 'assistant']).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(),
|
||||
|
||||
// 自定义字段
|
||||
activationType: ActivationTypeSchema,
|
||||
logicExpression: LogicExpressionSchema.optional(),
|
||||
ragConfig: RAGConfigSchema.optional(),
|
||||
createdAt: z.number(),
|
||||
updatedAt: z.number(),
|
||||
});
|
||||
|
||||
export const WorldInfoSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().optional(),
|
||||
entries: z.array(WorldInfoEntrySchema),
|
||||
createdAt: z.number(),
|
||||
updatedAt: z.number(),
|
||||
version: z.number(),
|
||||
});
|
||||
|
||||
// ==================== 角色卡 ====================
|
||||
|
||||
export const OutputSchemaFieldTypeSchema = z.enum([
|
||||
'string',
|
||||
'number',
|
||||
'boolean',
|
||||
'array',
|
||||
'object',
|
||||
]);
|
||||
|
||||
export const OutputSchemaFieldSchema: z.ZodType<any> = z.lazy(() =>
|
||||
z.object({
|
||||
name: z.string(),
|
||||
type: OutputSchemaFieldTypeSchema,
|
||||
description: z.string(),
|
||||
required: z.boolean().optional(),
|
||||
enum: z.array(z.string()).optional(),
|
||||
fields: z.array(OutputSchemaFieldSchema).optional(),
|
||||
})
|
||||
);
|
||||
|
||||
export const CharacterCardSchema = z.object({
|
||||
id: z.string(),
|
||||
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(),
|
||||
|
||||
// 自定义字段
|
||||
categories: z.array(z.string()),
|
||||
worldInfoId: z.string().optional(),
|
||||
outputSchema: z.array(OutputSchemaFieldSchema).optional(),
|
||||
avatarPath: z.string().optional(),
|
||||
createdAt: z.number(),
|
||||
updatedAt: z.number(),
|
||||
lastChatAt: z.number().optional(),
|
||||
isFavorite: z.boolean(),
|
||||
version: z.number(),
|
||||
});
|
||||
|
||||
// ==================== 聊天记录 ====================
|
||||
|
||||
export const ChatHeaderSchema = z.object({
|
||||
id: z.string(),
|
||||
displayName: z.string(),
|
||||
characterId: z.string(),
|
||||
userName: z.string(),
|
||||
characterName: z.string(),
|
||||
tableData: z.record(z.unknown()).optional(),
|
||||
createdAt: z.number(),
|
||||
updatedAt: z.number(),
|
||||
messageCount: z.number(),
|
||||
});
|
||||
|
||||
export const ChatMessageSchema = z.object({
|
||||
id: z.string(),
|
||||
chatId: z.string(),
|
||||
name: z.string(),
|
||||
is_user: z.boolean(),
|
||||
is_system: z.boolean().optional(),
|
||||
sendDate: 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(),
|
||||
tokenCount: z.number().optional(),
|
||||
isTemporary: z.boolean().optional(),
|
||||
});
|
||||
|
||||
export const ChatLogSchema = z.object({
|
||||
header: ChatHeaderSchema,
|
||||
messages: z.array(ChatMessageSchema),
|
||||
});
|
||||
|
||||
// ==================== 预设 ====================
|
||||
|
||||
export const GenerationPresetSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
temperature: z.number(),
|
||||
topP: z.number(),
|
||||
topK: z.number(),
|
||||
repetitionPenalty: z.number(),
|
||||
frequencyPenalty: z.number().optional(),
|
||||
presencePenalty: z.number().optional(),
|
||||
maxLength: z.number().optional(),
|
||||
isDefault: z.boolean(),
|
||||
createdAt: z.number(),
|
||||
updatedAt: z.number(),
|
||||
});
|
||||
|
||||
// ==================== 提示词预设 (Prompt Preset) ====================
|
||||
|
||||
export const PromptRoleSchema = z.enum(['system', 'ai', 'user']);
|
||||
|
||||
export const PromptEntrySchema = z.object({
|
||||
identifier: z.string(),
|
||||
name: z.string(),
|
||||
enabled: z.boolean(),
|
||||
content: z.string(),
|
||||
order: z.number(),
|
||||
role: PromptRoleSchema,
|
||||
tokenCount: z.number(),
|
||||
isSystemNode: z.boolean(),
|
||||
});
|
||||
|
||||
export const PromptPresetViewSchema = z.object({
|
||||
characterId: z.string(),
|
||||
entries: z.array(PromptEntrySchema),
|
||||
updatedAt: z.number(),
|
||||
version: z.number(),
|
||||
});
|
||||
|
||||
// ==================== 工作流 ====================
|
||||
|
||||
export const WorkflowNodeTypeSchema = z.enum([
|
||||
'llm_call',
|
||||
'condition',
|
||||
'data_process',
|
||||
'parallel',
|
||||
'merge',
|
||||
]);
|
||||
|
||||
export const WorkflowNodeSchema = z.object({
|
||||
id: z.string(),
|
||||
type: WorkflowNodeTypeSchema,
|
||||
name: z.string(),
|
||||
config: z.record(z.unknown()),
|
||||
inputMapping: z.record(z.string()).optional(),
|
||||
outputMapping: z.record(z.string()).optional(),
|
||||
});
|
||||
|
||||
export const WorkflowEdgeSchema = z.object({
|
||||
id: z.string(),
|
||||
source: z.string(),
|
||||
target: z.string(),
|
||||
sourcePort: z.string().optional(),
|
||||
targetPort: z.string().optional(),
|
||||
});
|
||||
|
||||
export const WorkflowSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().optional(),
|
||||
nodes: z.array(WorkflowNodeSchema),
|
||||
edges: z.array(WorkflowEdgeSchema),
|
||||
entryNodeId: z.string(),
|
||||
createdAt: z.number(),
|
||||
updatedAt: z.number(),
|
||||
version: z.number(),
|
||||
});
|
||||
|
||||
// ==================== RAG 库 ====================
|
||||
|
||||
export const RAGDocumentSchema = z.object({
|
||||
id: z.string(),
|
||||
content: z.string(),
|
||||
metadata: z.record(z.unknown()).optional(),
|
||||
embedding: z.array(z.number()).optional(),
|
||||
createdAt: z.number(),
|
||||
});
|
||||
|
||||
export const RAGLibrarySchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().optional(),
|
||||
documents: z.array(RAGDocumentSchema),
|
||||
embeddingModel: z.string().optional(),
|
||||
createdAt: z.number(),
|
||||
updatedAt: z.number(),
|
||||
});
|
||||
157
shared/schemas/sillytavern.schemas.ts
Normal file
157
shared/schemas/sillytavern.schemas.ts
Normal file
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* 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(),
|
||||
});
|
||||
Reference in New Issue
Block a user