feat(ai-note): ajouter boutons Générer slides/diagramme dans le panneau IA
Some checks failed
Deploy to Production / Build and Deploy (push) Failing after 3s
Some checks failed
Deploy to Production / Build and Deploy (push) Failing after 3s
- Nouveau endpoint POST /api/agents/run-for-note : crée un agent one-shot (slide-generator ou excalidraw-generator) avec la note courante comme source et l'exécute immédiatement - ContextualAIChat : prop noteId + section "Générer depuis cette note" avec deux boutons gradient (violet=slides, cyan=diagramme), spinner pendant la génération, bouton de téléchargement .pptx ou lien "Ouvrir dans le Lab" après succès - note-editor.tsx : passage de note.id à ContextualAIChat - i18n fr/en : nouvelles clés ai.generate.* Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
86
memento-note/app/api/agents/run-for-note/route.ts
Normal file
86
memento-note/app/api/agents/run-for-note/route.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { auth } from '@/lib/auth'
|
||||
import { prisma } from '@/lib/prisma'
|
||||
|
||||
type GenerateType = 'slide-generator' | 'excalidraw-generator'
|
||||
|
||||
const TYPE_DEFAULTS: Record<GenerateType, {
|
||||
role: string
|
||||
tools: string[]
|
||||
maxSteps: number
|
||||
}> = {
|
||||
'slide-generator': {
|
||||
role: 'Crée une présentation PowerPoint professionnelle et visuelle à partir du contenu de la note fournie.',
|
||||
tools: JSON.stringify(['note_search', 'note_read', 'generate_pptx']),
|
||||
maxSteps: 8,
|
||||
},
|
||||
'excalidraw-generator': {
|
||||
role: 'Génère un diagramme Excalidraw clair et professionnel à partir du contenu de la note fournie.',
|
||||
tools: JSON.stringify(['note_search', 'note_read', 'generate_excalidraw']),
|
||||
maxSteps: 6,
|
||||
},
|
||||
}
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const session = await auth()
|
||||
if (!session?.user?.id) {
|
||||
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 })
|
||||
}
|
||||
const userId = session.user.id
|
||||
|
||||
const body = await req.json()
|
||||
const { noteId, type, theme, style } = body as {
|
||||
noteId: string
|
||||
type: GenerateType
|
||||
theme?: string
|
||||
style?: string
|
||||
}
|
||||
|
||||
if (!noteId || !type || !TYPE_DEFAULTS[type]) {
|
||||
return NextResponse.json({ error: 'Paramètres invalides' }, { status: 400 })
|
||||
}
|
||||
|
||||
// Verify note belongs to user
|
||||
const note = await prisma.note.findFirst({
|
||||
where: { id: noteId, userId },
|
||||
select: { id: true, title: true, notebookId: true },
|
||||
})
|
||||
if (!note) {
|
||||
return NextResponse.json({ error: 'Note introuvable' }, { status: 404 })
|
||||
}
|
||||
|
||||
const defaults = TYPE_DEFAULTS[type]
|
||||
const agentName = type === 'slide-generator'
|
||||
? `Slides — ${(note.title || 'Note').substring(0, 40)}`
|
||||
: `Diagramme — ${(note.title || 'Note').substring(0, 40)}`
|
||||
|
||||
// Create a dedicated one-shot agent for this note
|
||||
const agent = await prisma.agent.create({
|
||||
data: {
|
||||
name: agentName,
|
||||
type,
|
||||
role: defaults.role,
|
||||
tools: defaults.tools,
|
||||
maxSteps: defaults.maxSteps,
|
||||
frequency: 'manual',
|
||||
isEnabled: true,
|
||||
sourceNoteIds: JSON.stringify([noteId]),
|
||||
targetNotebookId: note.notebookId ?? undefined,
|
||||
slideTheme: theme ?? 'vibrant_tech',
|
||||
slideStyle: style ?? 'soft',
|
||||
userId,
|
||||
},
|
||||
})
|
||||
|
||||
try {
|
||||
const { executeAgent } = await import('@/lib/ai/services/agent-executor.service')
|
||||
const result = await executeAgent(agent.id, userId)
|
||||
return NextResponse.json(result)
|
||||
} catch (err) {
|
||||
console.error('[run-for-note] executeAgent error:', err)
|
||||
return NextResponse.json(
|
||||
{ success: false, error: err instanceof Error ? err.message : 'Erreur inconnue' },
|
||||
{ status: 500 },
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user