From 3ee07c5f559628da61f631218d2fe344203e0a26 Mon Sep 17 00:00:00 2001 From: Antigravity Date: Fri, 29 May 2026 12:41:41 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20chart/diagram=20fond=20coh=C3=A9rent=20a?= =?UTF-8?q?vec=20le=20th=C3=A8me=20+=20slides=20strictement=20proportionne?= =?UTF-8?q?ls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - slides-renderer: chart et diagram utilisent bg/text/muted du thème (plus de fond #111827 forcé) - slides.tool: prompt ultra-clair (<50 mots = max 3 slides) + cappedSlides.slice(0,8) côté serveur comme filet de sécurité Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../components/lab/slides-renderer.tsx | 20 ++++++----- memento-note/lib/ai/tools/slides.tool.ts | 33 ++++++++++--------- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/memento-note/components/lab/slides-renderer.tsx b/memento-note/components/lab/slides-renderer.tsx index 7390545..3b004e9 100644 --- a/memento-note/components/lab/slides-renderer.tsx +++ b/memento-note/components/lab/slides-renderer.tsx @@ -390,10 +390,11 @@ function SlideContent({ slide, index, palette, radius }: { slide: SlideSpec; ind // ── CHART ──────────────────────────────────────────────────────────── case 'chart': return ( -
-

{slide.title}

- {slide.subtitle &&

{slide.subtitle}

} -
+
+

{slide.title}

+ {slide.subtitle &&

{slide.subtitle}

} +
+
@@ -402,11 +403,12 @@ function SlideContent({ slide, index, palette, radius }: { slide: SlideSpec; ind // ── DIAGRAM ────────────────────────────────────────────────────────── case 'diagram': return ( -
-

{slide.title}

- {slide.subtitle &&

{slide.subtitle}

} -
- {slide.mermaid ? :

No diagram

} +
+

{slide.title}

+ {slide.subtitle &&

{slide.subtitle}

} +
+
+ {slide.mermaid ? :

No diagram

}
) diff --git a/memento-note/lib/ai/tools/slides.tool.ts b/memento-note/lib/ai/tools/slides.tool.ts index bc13054..b5975bb 100644 --- a/memento-note/lib/ai/tools/slides.tool.ts +++ b/memento-note/lib/ai/tools/slides.tool.ts @@ -45,17 +45,16 @@ Available slide types: - "summary": title, items[] (conclusion with checkmarks) RULES: -- MAXIMUM 8 slides total — NEVER exceed 8, even for long notes -- Count only plain-text words, ignore markdown syntax, URLs, and metadata -- For short notes (<100 plain words): 3-4 slides max -- For medium notes (100-300 plain words): 5-6 slides max -- For any other note: 7-8 slides max — HARD LIMIT +- Count the plain-text words in the note (ignore markdown, URLs, metadata, headers) +- <50 words → 2-3 slides MAXIMUM (title + 1 content + summary) +- 50-150 words → 3-4 slides max +- 150-400 words → 5-6 slides max +- >400 words → 7-8 slides max — HARD LIMIT, NEVER exceed 8 - First slide MUST be type "title" - Last slide MUST be type "summary" -- Include at most 1 "chart" or "stats" slide — only if real numeric data exists in the note +- Include "chart" ONLY if real numeric data exists in the note — otherwise FORBIDDEN - Use VARIED types — never 2 identical types in a row -- All text content must come from the source notes (never invent data) -- Each bullet/card must be a real sentence (15+ words, not generic)`, +- All text must come from the source note — never invent data`, inputSchema: z.object({ title: z.string().describe('Short presentation title (6 words max)'), theme: z.string().optional().describe('Visual recipe: architectural-saas, midnight-cathedral, aurora-borealis, venture-pitch, clinical-precision, coastal-morning, etc.'), @@ -64,9 +63,11 @@ RULES: execute: async ({ title, theme, slides }) => { try { - console.log('[Slides Tool] Building presentation:', title, '| Slides:', slides.length, '| Theme:', theme) + // Hard cap: never more than 8 slides regardless of what the model outputs + const cappedSlides = slides.slice(0, 8) + console.log('[Slides Tool] Building presentation:', title, '| Slides:', cappedSlides.length, '| Theme:', theme) - const html = buildPresentationHTML({ title, theme, slides: slides as any }) + const html = buildPresentationHTML({ title, theme, slides: cappedSlides as any }) const canvas = await prisma.canvas.create({ data: { @@ -75,15 +76,15 @@ RULES: type: 'slides', title: title || 'Présentation', html, - slideCount: slides.length, + slideCount: cappedSlides.length, theme: theme || 'architectural-saas', - spec: { title, theme, slides }, + spec: { title, theme, slides: cappedSlides }, }), userId: ctx.userId, }, }) - console.log('[Slides Tool] Canvas created:', canvas.id, '| Slides:', slides.length, '| Size:', Math.round(html.length / 1024), 'KB') + console.log('[Slides Tool] Canvas created:', canvas.id, '| Slides:', cappedSlides.length, '| Size:', Math.round(html.length / 1024), 'KB') // Decrement slide_generate quota after successful canvas creation incrementUsageAsync(ctx.userId, 'slide_generate') @@ -94,7 +95,7 @@ RULES: data: { status: 'success', result: canvas.id, - log: `Slides generated: ${slides.length} slides, ${Math.round(html.length / 1024)}KB`, + log: `Slides generated: ${cappedSlides.length} slides, ${Math.round(html.length / 1024)}KB`, }, }).catch(err => console.error('[Slides Tool] Failed to update action status:', err)) } @@ -103,8 +104,8 @@ RULES: success: true, canvasId: canvas.id, canvasName: canvas.name, - slideCount: slides.length, - message: `Presentation "${canvas.name}" created with ${slides.length} slides.`, + slideCount: cappedSlides.length, + message: `Presentation "${canvas.name}" created with ${cappedSlides.length} slides.`, } } catch (e: any) { console.error('[Slides Tool] FATAL:', e)