Keep/keep-notes/lib/ai/services/notebook-summary.service.ts
sepehr 7fb486c9a4 feat: Complete internationalization and code cleanup
## Translation Files
- Add 11 new language files (es, de, pt, ru, zh, ja, ko, ar, hi, nl, pl)
- Add 100+ missing translation keys across all 15 languages
- New sections: notebook, pagination, ai.batchOrganization, ai.autoLabels
- Update nav section with workspace, quickAccess, myLibrary keys

## Component Updates
- Update 15+ components to use translation keys instead of hardcoded text
- Components: notebook dialogs, sidebar, header, note-input, ghost-tags, etc.
- Replace 80+ hardcoded English/French strings with t() calls
- Ensure consistent UI across all supported languages

## Code Quality
- Remove 77+ console.log statements from codebase
- Clean up API routes, components, hooks, and services
- Keep only essential error handling (no debugging logs)

## UI/UX Improvements
- Update Keep logo to yellow post-it style (from-yellow-400 to-amber-500)
- Change selection colors to #FEF3C6 (notebooks) and #EFB162 (nav items)
- Make "+" button permanently visible in notebooks section
- Fix grammar and syntax errors in multiple components

## Bug Fixes
- Fix JSON syntax errors in it.json, nl.json, pl.json, zh.json
- Fix syntax errors in notebook-suggestion-toast.tsx
- Fix syntax errors in use-auto-tagging.ts
- Fix syntax errors in paragraph-refactor.service.ts
- Fix duplicate "fusion" section in nl.json

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

Ou une version plus courte si vous préférez :

feat(i18n): Add 15 languages, remove logs, update UI components

- Create 11 new translation files (es, de, pt, ru, zh, ja, ko, ar, hi, nl, pl)
- Add 100+ translation keys: notebook, pagination, AI features
- Update 15+ components to use translations (80+ strings)
- Remove 77+ console.log statements from codebase
- Fix JSON syntax errors in 4 translation files
- Fix component syntax errors (toast, hooks, services)
- Update logo to yellow post-it style
- Change selection colors (#FEF3C6, #EFB162)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-11 22:26:13 +01:00

190 lines
4.8 KiB
TypeScript

import { prisma } from '@/lib/prisma'
import { getAIProvider } from '@/lib/ai/factory'
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): Promise<NotebookSummary | null> {
// 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)
// 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): Promise<string> {
// 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)
try {
const provider = getAIProvider()
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 (always in French - interface language)
*/
private buildPrompt(notesSummary: string, notebookName: string): string {
return `
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 :
`.trim()
}
}
// Export singleton instance
export const notebookSummaryService = new NotebookSummaryService()