import { prisma } from '@/lib/prisma' import { getAIProvider } from '@/lib/ai/factory' import { getSystemConfig } from '@/lib/config' export interface NotebookSummary { notebookId: string notebookName: string notebookIcon: string | null summary: string // Markdown formatted summary stats: { totalNotes: number totalLabels: number labelsUsed: string[] } generatedAt: Date } /** * Service for generating AI-powered notebook summaries * (Story 5.6 - IA6) */ export class NotebookSummaryService { /** * Generate a summary for a notebook * @param notebookId - Notebook ID * @param userId - User ID (for authorization) * @returns Notebook summary or null */ async generateSummary(notebookId: string, userId: string, language: string = 'en'): Promise { // 1. Get notebook with notes and labels const notebook = await prisma.notebook.findFirst({ where: { id: notebookId, userId, }, include: { labels: { select: { id: true, name: true, }, }, _count: { select: { notes: true }, }, }, }) if (!notebook) { throw new Error('Notebook not found') } // Get all notes in this notebook const notes = await prisma.note.findMany({ where: { notebookId, userId, }, select: { id: true, title: true, content: true, createdAt: true, updatedAt: true, labelRelations: { select: { name: true, }, }, }, orderBy: { updatedAt: 'desc', }, take: 100, // Limit to 100 most recent notes for summary }) if (notes.length === 0) { return null } // 2. Generate summary using AI const summary = await this.generateAISummary(notes, notebook, language) // 3. Get labels used in this notebook const labelsUsed = Array.from( new Set( notes.flatMap(note => note.labelRelations.map(l => l.name) ) ) ) return { notebookId: notebook.id, notebookName: notebook.name, notebookIcon: notebook.icon, summary, stats: { totalNotes: notebook._count.notes, totalLabels: notebook.labels.length, labelsUsed, }, generatedAt: new Date(), } } /** * Use AI to generate notebook summary */ private async generateAISummary(notes: any[], notebook: any, language: string): Promise { // Build notes summary for AI const notesSummary = notes .map((note, index) => { const title = note.title || 'Sans titre' const content = note.content.substring(0, 200) // Limit content length const labels = note.labelRelations.map((l: any) => l.name).join(', ') const date = new Date(note.createdAt).toLocaleDateString('fr-FR') return `[${index + 1}] **${title}** (${date}) ${labels ? `Labels: ${labels}` : ''} ${content}...` }) .join('\n\n') const prompt = this.buildPrompt(notesSummary, notebook.name, language) try { const config = await getSystemConfig() const provider = getAIProvider(config) const summary = await provider.generateText(prompt) return summary.trim() } catch (error) { console.error('Failed to generate notebook summary:', error) throw error } } /** * Build prompt for AI (localized) */ private buildPrompt(notesSummary: string, notebookName: string, language: string = 'en'): string { const instructions: Record = { fr: ` Tu es un assistant qui génère des synthèses structurées de carnets de notes. CARNET: ${notebookName} NOTES DU CARNET: ${notesSummary} TÂCHE: Génère une synthèse structurée et organisée de ce carnet en analysant toutes les notes. FORMAT DE LA RÉPONSE (Markdown avec emojis): # 📊 Synthèse du Carnet ${notebookName} ## 🌍 Thèmes Principaux • Identifie 3-5 thèmes récurrents ou sujets abordés ## 📝 Statistiques • Nombre total de notes analysées • Principales catégories de contenu ## 📅 Éléments Temporels • Dates ou périodes importantes mentionnées • Événements planifiés vs passés ## ⚠️ Points d'Attention / Actions Requises • Tâches ou actions identifiées dans les notes • Rappels ou échéances importantes • Éléments nécessitant une attention particulière ## 💡 Insights Clés • Résumé des informations les plus importantes • Tendances ou patterns observés • Connexions entre les différentes notes RÈGLES: - Utilise le format Markdown avec emojis comme dans l'exemple - Sois concis et organise l'information de manière claire - Identifie les vraies tendances, ne pas inventer d'informations - Si une section n'est pas pertinente, utilise "N/A" ou omets-la - Ton: professionnel mais accessible - TA RÉPONSE DOIT ÊTRE EN FRANÇAIS Ta réponse : `.trim(), en: ` You are an assistant that generates structured summaries of notebooks. NOTEBOOK: ${notebookName} NOTEBOOK NOTES: ${notesSummary} TASK: Generate a structured and organized summary of this notebook by analyzing all notes. RESPONSE FORMAT (Markdown with emojis): # 📊 Summary of Notebook ${notebookName} ## 🌍 Main Themes • Identify 3-5 recurring themes or topics covered ## 📝 Statistics • Total number of notes analyzed • Main content categories ## 📅 Temporal Elements • Important dates or periods mentioned • Planned vs past events ## ⚠️ Action Items / Attention Points • Tasks or actions identified in notes • Important reminders or deadlines • Items requiring special attention ## 💡 Key Insights • Summary of most important information • Observed trends or patterns • Connections between different notes RULES: - Use Markdown format with emojis as in the example - Be concise and organize information clearly - Identify real trends, do not invent information - If a section is not relevant, use "N/A" or omit it - Tone: professional but accessible - YOUR RESPONSE MUST BE IN ENGLISH Your response: `.trim(), fa: ` شما یک دستیار هستید که خلاصه‌های ساختاریافته از دفترچه‌های یادداشت تولید می‌کنید. دفترچه: ${notebookName} یادداشت‌های دفترچه: ${notesSummary} وظیفه: یک خلاصه ساختاریافته و منظم از این دفترچه با تحلیل تمام یادداشت‌ها تولید کنید. فرمت پاسخ (مارک‌داون با ایموجی): # 📊 خلاصه دفترچه ${notebookName} ## 🌍 موضوعات اصلی • ۳-۵ موضوع تکرارشونده یا مبحث پوشش داده شده را شناسایی کنید ## 📝 آمار • تعداد کل یادداشت‌های تحلیل شده • دسته‌بندی‌های اصلی محتوا ## 📅 عناصر زمانی • تاریخ‌ها یا دوره‌های مهم ذکر شده • رویدادهای برنامه‌ریزی شده در مقابل گذشته ## ⚠️ موارد اقدام / نقاط توجه • وظایف یا اقدامات شناسایی شده در یادداشت‌ها • یادآوری‌ها یا مهلت‌های مهم • مواردی که نیاز به توجه ویژه دارند ## 💡 بینش‌های کلیدی • خلاصه مهم‌ترین اطلاعات • روندها یا الگوهای مشاهده شده • ارتباطات بین یادداشت‌های مختلف قوانین: - از فرمت مارک‌داون با ایموجی مانند مثال استفاده کنید - مختصر باشید و اطلاعات را به وضوح سازماندهی کنید - روندهای واقعی را شناسایی کنید، اطلاعات اختراع نکنید - اگر بخش مرتبط نیست، از "N/A" استفاده کنید یا آن را حذف کنید - لحن: حرفه‌ای اما قابل دسترس - پاسخ شما باید به زبان فارسی باشد پاسخ شما: `.trim(), es: ` Eres un asistente que genera resúmenes estructurados de cuadernos de notas. CUADERNO: ${notebookName} NOTAS DEL CUADERNO: ${notesSummary} TAREA: Genera un resumen estructurado y organizado de este cuaderno analizando todas las notas. FORMATO DE RESPUESTA (Markdown con emojis): # 📊 Resumen del Cuaderno ${notebookName} ## 🌍 Temas Principales • Identifica 3-5 temas recurrentes o tópicos cubiertos ## 📝 Estadísticas • Número total de notas analizadas • Categorías principales de contenido ## 📅 Elementos Temporales • Fechas o periodos importantes mencionados • Eventos planificados vs pasados ## ⚠️ Puntos de Atención / Acciones Requeridas • Tareas o acciones identificadas en las notas • Recordatorios o plazos importantes • Elementos que requieren atención especial ## 💡 Insights Clave • Resumen de la información más importante • Tendencias o patrones observados • Conexiones entre las diferentes notas REGLAS: - Usa formato Markdown con emojis como en el ejemplo - Sé conciso y organiza la información claramente - Identifica tendencias reales, no inventes información - Si una sección no es relevante, usa "N/A" u omítela - Tono: profesional pero accesible - TU RESPUESTA DEBE SER EN ESPAÑOL Tu respuesta: `.trim(), de: ` Du bist ein Assistent, der strukturierte Zusammenfassungen von Notizbüchern erstellt. NOTIZBUCH: ${notebookName} NOTIZBUCH-NOTIZEN: ${notesSummary} AUFGABE: Erstelle eine strukturierte und organisierte Zusammenfassung dieses Notizbuchs, indem du alle Notizen analysierst. ANTWORTFORMAT (Markdown mit Emojis): # 📊 Zusammenfassung des Notizbuchs ${notebookName} ## 🌍 Hauptthemen • Identifiziere 3-5 wiederkehrende Themen ## 📝 Statistiken • Gesamtzahl der analysierten Notizen • Hauptinhaltkategorien ## 📅 Zeitliche Elemente • Wichtige erwähnte Daten oder Zeiträume • Geplante vs. vergangene Ereignisse ## ⚠️ Handlungspunkte / Aufmerksamkeitspunkte • In Notizen identifizierte Aufgaben oder Aktionen • Wichtige Erinnerungen oder Fristen • Elemente, die besondere Aufmerksamkeit erfordern ## 💡 Wichtige Erkenntnisse • Zusammenfassung der wichtigsten Informationen • Beobachtete Trends oder Muster • Verbindungen zwischen verschiedenen Notizen REGELN: - Verwende Markdown-Format mit Emojis wie im Beispiel - Sei prägnant und organisiere Informationen klar - Identifiziere echte Trends, erfinde keine Informationen - Wenn ein Abschnitt nicht relevant ist, verwende "N/A" oder lass ihn weg - Ton: professionell aber zugänglich - DEINE ANTWORT MUSS AUF DEUTSCH SEIN Deine Antwort: `.trim() } return instructions[language] || instructions['en'] || instructions['fr'] } } // Export singleton instance export const notebookSummaryService = new NotebookSummaryService()