From 6b1a0136b0159b57803fa827a1001ed062b7886f Mon Sep 17 00:00:00 2001 From: GW_MC <72297530+GWMCwing@users.noreply.github.com> Date: Mon, 23 Feb 2026 21:04:50 +0800 Subject: [PATCH] feat: add initial backend and frontend structure with models, DTOs, and WebSocket events --- apps/backend/prisma/models/character.prisma | 56 ++++++++++++ .../backend/prisma/models/conversation.prisma | 38 ++++++++ .../prisma/models/importDocument.prisma | 21 +++++ apps/backend/prisma/models/message.prisma | 24 ++++++ apps/backend/prisma/models/storyBranch.prisma | 21 +++++ apps/backend/prisma/models/user.prisma | 25 ++++++ .../backend/prisma/models/vectorMemory.prisma | 29 +++++++ apps/backend/src/app.module.ts | 8 ++ apps/backend/src/main.ts | 20 +++++ apps/frontend/index.html | 13 +++ apps/frontend/postcss.config.js | 6 ++ apps/frontend/public/vite.svg | 0 apps/frontend/src/App.tsx | 14 +++ apps/frontend/src/main.tsx | 10 +++ apps/frontend/src/styles/globals.css | 59 +++++++++++++ apps/frontend/tailwind.config.ts | 38 ++++++++ packages/shared/src/api/dto.ts | 86 +++++++++++++++++++ packages/shared/src/api/index.ts | 1 + packages/shared/src/index.ts | 2 + packages/shared/src/websocket/events.ts | 84 ++++++++++++++++++ packages/shared/src/websocket/index.ts | 1 + 21 files changed, 556 insertions(+) create mode 100644 apps/backend/prisma/models/character.prisma create mode 100644 apps/backend/prisma/models/conversation.prisma create mode 100644 apps/backend/prisma/models/importDocument.prisma create mode 100644 apps/backend/prisma/models/message.prisma create mode 100644 apps/backend/prisma/models/storyBranch.prisma create mode 100644 apps/backend/prisma/models/user.prisma create mode 100644 apps/backend/prisma/models/vectorMemory.prisma create mode 100644 apps/backend/src/app.module.ts create mode 100644 apps/backend/src/main.ts create mode 100644 apps/frontend/index.html create mode 100644 apps/frontend/postcss.config.js create mode 100644 apps/frontend/public/vite.svg create mode 100644 apps/frontend/src/App.tsx create mode 100644 apps/frontend/src/main.tsx create mode 100644 apps/frontend/src/styles/globals.css create mode 100644 apps/frontend/tailwind.config.ts create mode 100644 packages/shared/src/api/dto.ts create mode 100644 packages/shared/src/api/index.ts create mode 100644 packages/shared/src/index.ts create mode 100644 packages/shared/src/websocket/events.ts create mode 100644 packages/shared/src/websocket/index.ts diff --git a/apps/backend/prisma/models/character.prisma b/apps/backend/prisma/models/character.prisma new file mode 100644 index 0000000..68adf30 --- /dev/null +++ b/apps/backend/prisma/models/character.prisma @@ -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]) +} diff --git a/apps/backend/prisma/models/conversation.prisma b/apps/backend/prisma/models/conversation.prisma new file mode 100644 index 0000000..1d63197 --- /dev/null +++ b/apps/backend/prisma/models/conversation.prisma @@ -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]) +} diff --git a/apps/backend/prisma/models/importDocument.prisma b/apps/backend/prisma/models/importDocument.prisma new file mode 100644 index 0000000..71f4670 --- /dev/null +++ b/apps/backend/prisma/models/importDocument.prisma @@ -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]) +} diff --git a/apps/backend/prisma/models/message.prisma b/apps/backend/prisma/models/message.prisma new file mode 100644 index 0000000..d6295c1 --- /dev/null +++ b/apps/backend/prisma/models/message.prisma @@ -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]) +} diff --git a/apps/backend/prisma/models/storyBranch.prisma b/apps/backend/prisma/models/storyBranch.prisma new file mode 100644 index 0000000..fd152e5 --- /dev/null +++ b/apps/backend/prisma/models/storyBranch.prisma @@ -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]) +} diff --git a/apps/backend/prisma/models/user.prisma b/apps/backend/prisma/models/user.prisma new file mode 100644 index 0000000..38ea73d --- /dev/null +++ b/apps/backend/prisma/models/user.prisma @@ -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]) +} diff --git a/apps/backend/prisma/models/vectorMemory.prisma b/apps/backend/prisma/models/vectorMemory.prisma new file mode 100644 index 0000000..094ad1e --- /dev/null +++ b/apps/backend/prisma/models/vectorMemory.prisma @@ -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]) +} diff --git a/apps/backend/src/app.module.ts b/apps/backend/src/app.module.ts new file mode 100644 index 0000000..ee5f2c9 --- /dev/null +++ b/apps/backend/src/app.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; + +@Module({ + imports: [], + controllers: [], + providers: [], +}) +export class AppModule {} diff --git a/apps/backend/src/main.ts b/apps/backend/src/main.ts new file mode 100644 index 0000000..8bdaff5 --- /dev/null +++ b/apps/backend/src/main.ts @@ -0,0 +1,20 @@ +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; + +async function bootstrap() { + const app = await NestFactory.create(AppModule); + + app.enableCors({ + origin: ['http://localhost:5173'], + credentials: true, + }); + + app.setGlobalPrefix('api'); + + const port = process.env.PORT || 3000; + await app.listen(port); + + console.log(`🚀 Backend running on: http://localhost:${port}/api`); +} + +bootstrap(); diff --git a/apps/frontend/index.html b/apps/frontend/index.html new file mode 100644 index 0000000..8356551 --- /dev/null +++ b/apps/frontend/index.html @@ -0,0 +1,13 @@ + + +
+ + + ++ Character simulation and interactive storytelling platform +
+