Files
Momento/memento-note/app/api/brainstorm/[sessionId]/summarize/route.ts
Antigravity 4fe31ebc99
All checks were successful
CI / Lint, Unit Tests & Build (push) Successful in 6m55s
CI / Deploy production (on server) (push) Successful in 36s
fix(quotas): unifier le décompte IA (BYOK, rollback) et combler les fuites
Centralise la réserve via ai-quota, corrige admin unavailable (-1), brancher les routes sans quota et le host-pays brainstorm, avec usage-meter élargi, noms de clusters, MCP et ajustements dashboard/insights.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-15 20:42:25 +00:00

113 lines
3.6 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server'
import prisma from '@/lib/prisma'
import { auth } from '@/auth'
import { runLaneWithBillingUser } from '@/lib/ai/provider-for-user'
import { getSystemConfig } from '@/lib/config'
import { billingOwnerFromSession, verifyParticipant } from '@/lib/brainstorm-collab'
import { withSessionAiQuota, handleQuotaHttpError } from '@/lib/ai-quota'
function localeToLanguageName(locale?: string): string {
const map: Record<string, string> = {
en: 'English', fr: 'French', es: 'Spanish', de: 'German',
it: 'Italian', pt: 'Portuguese', nl: 'Dutch', ru: 'Russian',
zh: 'Chinese', ja: 'Japanese', ko: 'Korean', ar: 'Arabic',
fa: 'Farsi', hi: 'Hindi', pl: 'Polish',
}
return map[locale ?? ''] ?? 'English'
}
export async function POST(
request: NextRequest,
{ params }: { params: Promise<{ sessionId: string }> }
) {
const session = await auth()
if (!session?.user?.id) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
try {
const { sessionId } = await params
const body = await request.json().catch(() => ({}))
const locale: string = body.locale || 'en'
const brainstormSession = await prisma.brainstormSession.findFirst({
where: { id: sessionId },
include: {
ideas: {
where: { status: { not: 'dismissed' } },
orderBy: [{ waveNumber: 'asc' }, { createdAt: 'asc' }],
},
},
})
if (!brainstormSession) {
return NextResponse.json({ error: 'Session not found' }, { status: 404 })
}
const { isParticipant } = await verifyParticipant(sessionId, session.user.id, 'viewer')
if (!isParticipant) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 403 })
}
const ideas = brainstormSession.ideas
if (ideas.length === 0) {
return NextResponse.json({ error: 'No ideas to summarize' }, { status: 400 })
}
const { billingOwnerId, isGuestActor } = billingOwnerFromSession(
brainstormSession.userId,
session.user.id,
)
const ideasText = ideas
.map((idea, i) => `${i + 1}. [Wave ${idea.waveNumber}] ${idea.title}: ${idea.description}`)
.join('\n')
const starredIdeas = ideas.filter(i => i.isStarred)
const starredText = starredIdeas.length > 0
? `\nStarred/favorite ideas: ${starredIdeas.map(i => i.title).join(', ')}`
: ''
const language = localeToLanguageName(locale)
const prompt = `You are summarizing a brainstorming session. Respond in ${language}.
Seed idea: "${brainstormSession.seedIdea}"
Ideas generated (${ideas.length} total):
${ideasText}${starredText}
Write a concise synthesis (4-6 sentences) that:
1. Captures the main themes and directions explored
2. Highlights the most promising ideas or clusters
3. Suggests a concrete next step
Be direct and action-oriented. No bullet points, just flowing prose.`
const config = await getSystemConfig()
const summary = await withSessionAiQuota(
billingOwnerId,
session.user.id,
isGuestActor,
'brainstorm_enrich',
async () => {
const { result } = await runLaneWithBillingUser(
'tags',
config,
billingOwnerId,
(provider) => provider.generateText(prompt),
)
return result
},
{ lane: 'tags' },
)
return NextResponse.json({ success: true, data: { summary: summary.trim() } })
} catch (error) {
const quotaResp = handleQuotaHttpError(error)
if (quotaResp) return quotaResp
console.error('Error summarizing brainstorm:', error)
return NextResponse.json({ error: 'Failed to summarize' }, { status: 500 })
}
}