diff --git a/memento-note/app/api/agents/run-for-note/route.ts b/memento-note/app/api/agents/run-for-note/route.ts index 8d0a444..6789cb7 100644 --- a/memento-note/app/api/agents/run-for-note/route.ts +++ b/memento-note/app/api/agents/run-for-note/route.ts @@ -1,6 +1,7 @@ import { NextRequest, NextResponse } from 'next/server' import { auth } from '@/auth' import { prisma } from '@/lib/prisma' +import { checkEntitlementOrThrow, QuotaExceededError, incrementUsageAsync } from '@/lib/entitlements' type GenerateType = 'slide-generator' | 'excalidraw-generator' @@ -43,6 +44,16 @@ export async function POST(req: NextRequest) { return NextResponse.json({ error: 'Paramètres invalides' }, { status: 400 }) } + // Quota check — slides/excalidraw generation counts as 'reformulate' credit + try { + await checkEntitlementOrThrow(userId, 'reformulate') + } catch (e) { + if (e instanceof QuotaExceededError) { + return NextResponse.json({ error: e.message }, { status: 402 }) + } + throw e + } + const note = await prisma.note.findFirst({ where: { id: noteId, userId }, select: { id: true, title: true, notebookId: true }, diff --git a/memento-note/app/api/canvas/slides/pptx/route.ts b/memento-note/app/api/canvas/slides/pptx/route.ts index 934cc1f..3cb923a 100644 --- a/memento-note/app/api/canvas/slides/pptx/route.ts +++ b/memento-note/app/api/canvas/slides/pptx/route.ts @@ -43,6 +43,12 @@ async function buildPptx(spec: any): Promise { for (const slide of (spec.slides ?? [])) { const s = pptx.addSlide() + // PLG watermark — bottom-right corner of LAYOUT_WIDE (13.33"×7.5") + s.addText('memento-note.com', { + x: 10.0, y: 7.1, w: 3.0, h: 0.25, + fontSize: 7, fontFace: 'Arial', color: 'B8B0A8', + align: 'right', italic: true, + }) switch (slide.type) { case 'title': { diff --git a/memento-note/components/lab/canvas-board.tsx b/memento-note/components/lab/canvas-board.tsx index 46d7029..f5672b9 100644 --- a/memento-note/components/lab/canvas-board.tsx +++ b/memento-note/components/lab/canvas-board.tsx @@ -218,11 +218,10 @@ function SlidesViewer({ data, name, canvasId }: { data: SlidesPayload; name: str - {/* Slides: React renderer (legacy spec) or iframe (new HTML) */} + {/* Slides: iframe (new HTML format) preferred over legacy React renderer */}
- {data.spec ? ( - - ) : ( + {data.html ? ( + // New format: standalone animated HTML served via srcDoc <> {/* Loading overlay — visible until iframe fires onLoad */} {!isLoaded && ( @@ -257,7 +256,10 @@ function SlidesViewer({ data, name, canvasId }: { data: SlidesPayload; name: str - )} + ) : data.spec ? ( + // Legacy format: old React renderer (recharts) + + ) : null}
) diff --git a/memento-note/lib/ai/tools/slides.tool.ts b/memento-note/lib/ai/tools/slides.tool.ts index bd08292..fb19442 100644 --- a/memento-note/lib/ai/tools/slides.tool.ts +++ b/memento-note/lib/ai/tools/slides.tool.ts @@ -5,6 +5,7 @@ import { z } from 'zod' import { toolRegistry } from './registry' import { prisma } from '@/lib/prisma' import { buildPresentationHTML } from './slides-html-builder' +import { incrementUsageAsync } from '@/lib/entitlements' const slideSchema = z.discriminatedUnion('type', [ z.object({ type: z.literal('title'), title: z.string(), subtitle: z.string().optional() }), @@ -80,6 +81,9 @@ RULES: console.log('[Slides Tool] Canvas created:', canvas.id, '| Slides:', slides.length, '| Size:', Math.round(html.length / 1024), 'KB') + // Decrement reformulate quota (agent-based generation consumes credits) + incrementUsageAsync(ctx.userId, 'reformulate') + if (ctx.actionId) { await prisma.agentAction.update({ where: { id: ctx.actionId },