generator client { provider = "prisma-client-js" binaryTargets = ["debian-openssl-3.0.x", "native"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id String @id @default(cuid()) name String? email String @unique emailVerified DateTime? password String? role String @default("USER") image String? theme String @default("light") resetToken String? @unique resetTokenExpiry DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt cardSizeMode String @default("variable") accounts Account[] agents Agent[] aiFeedback AiFeedback[] canvases Canvas[] conversations Conversation[] labels Label[] memoryEchoInsights MemoryEchoInsight[] notes Note[] noteHistories NoteHistory[] sentShares NoteShare[] @relation("SentShares") receivedShares NoteShare[] @relation("ReceivedShares") notebooks Notebook[] sessions Session[] aiSettings UserAISettings? workflows Workflow[] notifications Notification[] } model Account { userId String type String provider String providerAccountId String refresh_token String? access_token String? expires_at Int? token_type String? scope String? id_token String? session_state String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@id([provider, providerAccountId]) } model Session { sessionToken String @unique userId String expires DateTime createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) } model VerificationToken { identifier String token String expires DateTime @@id([identifier, token]) } model Notebook { id String @id @default(cuid()) name String icon String? color String? order Int parentId String? trashedAt DateTime? userId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt agents Agent[] conversations Conversation[] labels Label[] notes Note[] user User @relation(fields: [userId], references: [id], onDelete: Cascade) workflows Workflow[] parent Notebook? @relation("NotebookTree", fields: [parentId], references: [id], onDelete: Cascade) children Notebook[] @relation("NotebookTree") @@index([userId, order]) @@index([userId]) @@index([parentId]) @@index([trashedAt]) } model Label { id String @id @default(cuid()) name String color String @default("gray") type String @default("user") // "ai" or "user" notebookId String? userId String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt notebook Notebook? @relation(fields: [notebookId], references: [id], onDelete: Cascade) user User? @relation(fields: [userId], references: [id], onDelete: Cascade) notes Note[] @relation("LabelToNote") @@unique([notebookId, name]) @@index([notebookId]) @@index([userId]) } model Note { id String @id @default(cuid()) title String? content String color String @default("default") isPinned Boolean @default(false) isArchived Boolean @default(false) type String @default("richtext") dismissedFromRecent Boolean @default(false) checkItems String? labels String? images String? /// Illustration SVG (sanitized) for editorial feed thumbnail — optional, peut être généré par IA illustrationSvg String? links String? reminder DateTime? isReminderDone Boolean @default(false) reminderRecurrence String? reminderLocation String? isMarkdown Boolean @default(false) // DEPRECATED: use type = 'markdown' instead size String @default("small") sharedWith String? userId String? order Int @default(0) notebookId String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt contentUpdatedAt DateTime @default(now()) autoGenerated Boolean? aiProvider String? aiConfidence Int? language String? languageConfidence Float? lastAiAnalysis DateTime? trashedAt DateTime? tsv Unsupported("tsvector")? aiFeedback AiFeedback[] memoryEchoAsNote1 MemoryEchoInsight[] @relation("EchoNote1") memoryEchoAsNote2 MemoryEchoInsight[] @relation("EchoNote2") notebook Notebook? @relation(fields: [notebookId], references: [id]) user User? @relation(fields: [userId], references: [id], onDelete: Cascade) noteEmbedding NoteEmbedding? shares NoteShare[] labelRelations Label[] @relation("LabelToNote") historyEntries NoteHistory[] historyEnabled Boolean @default(false) @@index([isPinned]) @@index([isArchived]) @@index([trashedAt]) @@index([order]) @@index([reminder]) @@index([userId]) @@index([userId, notebookId]) } model NoteHistory { id String @id @default(cuid()) noteId String userId String version Int reason String? title String? content String color String isPinned Boolean isArchived Boolean type String checkItems String? labels String? images String? links String? isMarkdown Boolean size String notebookId String? createdAt DateTime @default(now()) note Note @relation(fields: [noteId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([noteId, version]) @@index([noteId, createdAt(sort: Desc)]) @@index([userId, noteId, createdAt(sort: Desc)]) } model NoteShare { id String @id @default(cuid()) noteId String userId String sharedBy String status String @default("pending") permission String @default("view") notifiedAt DateTime? respondedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt note Note @relation(fields: [noteId], references: [id], onDelete: Cascade) sharer User @relation("SentShares", fields: [sharedBy], references: [id], onDelete: Cascade) user User @relation("ReceivedShares", fields: [userId], references: [id], onDelete: Cascade) @@unique([noteId, userId]) @@index([userId]) @@index([status]) @@index([sharedBy]) } model SystemConfig { key String @id value String } model AiFeedback { id String @id @default(cuid()) noteId String userId String? feedbackType String feature String originalContent String correctedContent String? metadata String? createdAt DateTime @default(now()) note Note @relation(fields: [noteId], references: [id], onDelete: Cascade) user User? @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([noteId]) @@index([userId]) @@index([feature]) } model MemoryEchoInsight { id String @id @default(cuid()) userId String? note1Id String note2Id String similarityScore Float insight String insightDate DateTime @default(now()) viewed Boolean @default(false) feedback String? dismissed Boolean @default(false) note1 Note @relation("EchoNote1", fields: [note1Id], references: [id], onDelete: Cascade) note2 Note @relation("EchoNote2", fields: [note2Id], references: [id], onDelete: Cascade) user User? @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([userId, insightDate]) @@index([userId, insightDate]) @@index([userId, dismissed]) } model UserAISettings { userId String @id titleSuggestions Boolean @default(true) semanticSearch Boolean @default(true) paragraphRefactor Boolean @default(true) memoryEcho Boolean @default(true) memoryEchoFrequency String @default("daily") aiProvider String @default("auto") preferredLanguage String @default("auto") fontSize String @default("medium") demoMode Boolean @default(false) showRecentNotes Boolean @default(true) emailNotifications Boolean @default(false) desktopNotifications Boolean @default(false) anonymousAnalytics Boolean @default(false) autoLabeling Boolean @default(true) noteHistory Boolean @default(false) noteHistoryMode String @default("manual") languageDetection Boolean @default(true) fontFamily String @default("inter") autoSave Boolean @default(true) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([memoryEcho]) @@index([aiProvider]) @@index([memoryEchoFrequency]) @@index([preferredLanguage]) } model NoteEmbedding { id String @id @default(cuid()) noteId String @unique embedding Unsupported("vector(1536)") createdAt DateTime @default(now()) updatedAt DateTime @default(now()) @updatedAt note Note @relation(fields: [noteId], references: [id], onDelete: Cascade) @@index([noteId]) } model Agent { id String @id @default(cuid()) name String description String? type String? @default("scraper") role String sourceUrls String? frequency String @default("manual") lastRun DateTime? nextRun DateTime? isEnabled Boolean @default(true) targetNotebookId String? sourceNotebookId String? sourceNoteIds String? slideTheme String? slideStyle String? tools String? @default("[]") maxSteps Int @default(10) notifyEmail Boolean @default(false) includeImages Boolean @default(false) userId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt scheduledTime String? @default("08:00") scheduledDay Int? timezone String? notebook Notebook? @relation(fields: [targetNotebookId], references: [id]) user User @relation(fields: [userId], references: [id], onDelete: Cascade) actions AgentAction[] @@index([userId]) @@index([isEnabled]) } model AgentAction { id String @id @default(cuid()) agentId String status String @default("pending") result String? log String? input String? toolLog String? tokensUsed Int? createdAt DateTime @default(now()) agent Agent @relation(fields: [agentId], references: [id], onDelete: Cascade) @@index([agentId]) } model Conversation { id String @id @default(cuid()) title String? userId String notebookId String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt messages ChatMessage[] notebook Notebook? @relation(fields: [notebookId], references: [id]) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId]) @@index([notebookId]) } model ChatMessage { id String @id @default(cuid()) conversationId String role String content String createdAt DateTime @default(now()) conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade) @@index([conversationId]) } model Canvas { id String @id @default(cuid()) name String data String userId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId]) } model Workflow { id String @id @default(cuid()) name String description String? graph String @default("{\"nodes\":[],\"edges\":[]}") isEnabled Boolean @default(true) userId String notebookId String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt notebook Notebook? @relation(fields: [notebookId], references: [id]) user User @relation(fields: [userId], references: [id], onDelete: Cascade) runs WorkflowRun[] @@index([userId]) @@index([isEnabled]) } model WorkflowRun { id String @id @default(cuid()) workflowId String status String @default("running") log String? createdAt DateTime @default(now()) workflow Workflow @relation(fields: [workflowId], references: [id], onDelete: Cascade) @@index([workflowId]) @@index([status]) } model Notification { id String @id @default(cuid()) userId String type String // "agent_success", "agent_failure", "share", "reminder", "system" title String message String? read Boolean @default(false) actionUrl String? // e.g. "/agents" or "/notes/xxx" relatedId String? // e.g. agentId or noteId createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId, read]) @@index([userId, createdAt]) }