feat: add initial backend and frontend structure with models, DTOs, and WebSocket events

This commit is contained in:
GW_MC
2026-02-23 21:04:50 +08:00
parent 932f384f0d
commit 6b1a0136b0
21 changed files with 556 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
// Character model and character knowledge
enum ImportSourceType {
file
url
manual
}
enum ImportStatus {
pending
processing
completed
failed
}
model Character {
id String @id @default(uuid())
name String
avatarUrl String?
personalityPrompt String
attributes Json @default("{}")
config Json @default("{}")
isPublic Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
conversations Conversation[]
knowledgeSources CharacterKnowledge[]
vectorMemories VectorMemory[]
@@index([userId])
@@index([name])
}
model CharacterKnowledge {
id String @id @default(uuid())
name String
sourceType ImportSourceType
sourceName String
mimeType String?
fileSize BigInt?
rawContent String?
status ImportStatus @default(pending)
processingInfo Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
characterId String
character Character @relation(fields: [characterId], references: [id], onDelete: Cascade)
vectorMemories VectorMemory[]
@@index([characterId])
@@index([status])
}

View File

@@ -0,0 +1,38 @@
// Conversation and participant models
model Conversation {
id String @id @default(uuid())
title String?
messageCount Int @default(0)
totalTokens Int @default(0)
settings Json @default("{}")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
characterId String
character Character @relation(fields: [characterId], references: [id], onDelete: Cascade)
messages Message[]
vectorMemories VectorMemory[]
storyBranches StoryBranch[]
participants ConversationParticipant[]
@@index([userId])
@@index([characterId])
@@index([createdAt])
}
model ConversationParticipant {
id String @id @default(uuid())
isActive Boolean @default(true)
autoRespond Boolean @default(true)
createdAt DateTime @default(now())
conversationId String
conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
characterId String
@@unique([conversationId, characterId])
@@index([conversationId])
}

View File

@@ -0,0 +1,21 @@
// General import documents (not linked to characters)
model ImportDocument {
id String @id @default(uuid())
sourceType ImportSourceType
sourceName String
mimeType String?
fileSize BigInt?
content String?
status ImportStatus @default(pending)
errorMessage String?
metadata Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
@@index([status])
}

View File

@@ -0,0 +1,24 @@
// Message model
enum MessageRole {
user
assistant
system
}
model Message {
id String @id @default(uuid())
role MessageRole
content String
tokensUsed Int?
model String?
metadata Json?
createdAt DateTime @default(now())
conversationId String
conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
@@index([conversationId])
@@index([createdAt])
@@index([conversationId, createdAt])
}

View File

@@ -0,0 +1,21 @@
// Story branching for narrative generation (Phase 2)
model StoryBranch {
id String @id @default(uuid())
title String?
content String
userDirection String
generationParams Json?
depth Int @default(0)
branchOrder Int @default(0)
createdAt DateTime @default(now())
conversationId String
conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
parentId String?
parent StoryBranch? @relation("BranchTree", fields: [parentId], references: [id], onDelete: Cascade)
children StoryBranch[] @relation("BranchTree")
@@index([conversationId])
@@index([parentId])
}

View File

@@ -0,0 +1,25 @@
// User model and related enums
enum UserRole {
USER
ADMIN
}
model User {
id String @id @default(uuid())
email String @unique
username String @unique
passwordHash String?
keycloakSub String? @unique
role UserRole @default(USER)
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
characters Character[]
conversations Conversation[]
importDocs ImportDocument[]
@@index([email])
@@index([keycloakSub])
}

View File

@@ -0,0 +1,29 @@
// Vector memory for embeddings (conversation and character knowledge)
enum MemoryType {
conversation
character
}
model VectorMemory {
id String @id @default(uuid())
content String
embedding Unsupported("vector")?
memoryType MemoryType @default(conversation)
metadata Json?
createdAt DateTime @default(now())
conversationId String?
conversation Conversation? @relation(fields: [conversationId], references: [id], onDelete: Cascade)
characterId String?
character Character? @relation(fields: [characterId], references: [id], onDelete: Cascade)
knowledgeId String?
knowledge CharacterKnowledge? @relation(fields: [knowledgeId], references: [id], onDelete: Cascade)
@@index([conversationId])
@@index([characterId])
@@index([knowledgeId])
@@index([memoryType])
}