import { getChatProvider } from '../factory' import { getSystemConfig } from '@/lib/config' export interface NoteAnalysisResult { noteId: string include: boolean reason: string } export interface NotebookAnalysis { notes: NoteAnalysisResult[] description: string } export class NotebookPublishAnalyzerService { async analyze( notebookName: string, notes: Array<{ id: string; title: string; wordCount: number; preview: string }>, language: string, ): Promise { const lang = language || 'fr' const langName = lang === 'fr' ? 'français' : lang === 'en' ? 'English' : lang === 'fa' ? 'فارسی' : lang === 'ar' ? 'العربية' : lang === 'de' ? 'Deutsch' : lang === 'es' ? 'Español' : lang const notesList = notes.map((n, i) => `${i + 1}. [${n.id}] "${n.title || 'Sans titre'}" — ${n.wordCount} mots — "${n.preview}"` ).join('\n') const prompt = `Tu es un éditeur web expert. Analyse ce carnet de notes "${notebookName}" et décide quelles notes méritent d'être publiées sur un site web professionnel. NOTES DU CARNET : ${notesList} CRITÈRES D'INCLUSION : - Note complète (>150 mots), structurée, sans fautes évidentes - Contenu utile pour un lecteur externe (pas juste des notes personnelles) - Titre clair et représentatif du contenu CRITÈRES D'EXCLUSION : - Brouillon ou note vide (<50 mots) - Contenu incomplet ("à compléter", "TODO", "...") - Note purement personnelle ou de travail interne Réponds en JSON strict : { "description": "Résumé du carnet en 1-2 phrases percutantes en ${langName}", "notes": [ { "noteId": "id_ici", "include": true, "reason": "Courte justification en ${langName}" } ] } Inclus toutes les notes dans le tableau "notes", même celles exclues.` const config = await getSystemConfig() const provider = getChatProvider(config) const raw = await provider.generateText(prompt) return this.parseResponse(raw, notes) } private parseResponse( raw: string, notes: Array<{ id: string }>, ): NotebookAnalysis { const jsonMatch = raw.match(/```json\s*([\s\S]+?)\s*```/) let jsonStr = jsonMatch ? jsonMatch[1] : raw const s = jsonStr.indexOf('{') const e = jsonStr.lastIndexOf('}') if (s >= 0 && e > s) jsonStr = jsonStr.slice(s, e + 1) try { const parsed = JSON.parse(jsonStr) const noteIds = new Set(notes.map(n => n.id)) const analysisNotes: NoteAnalysisResult[] = (parsed.notes || []) .filter((n: any) => noteIds.has(n.noteId)) .map((n: any) => ({ noteId: String(n.noteId), include: Boolean(n.include), reason: String(n.reason || ''), })) // Include any notes missing from AI response with include=true as default const analyzedIds = new Set(analysisNotes.map(n => n.noteId)) for (const note of notes) { if (!analyzedIds.has(note.id)) { analysisNotes.push({ noteId: note.id, include: true, reason: '' }) } } return { notes: analysisNotes, description: String(parsed.description || ''), } } catch { return { notes: notes.map(n => ({ noteId: n.id, include: true, reason: '' })), description: '', } } } } export const notebookPublishAnalyzerService = new NotebookPublishAnalyzerService()