fix(quotas): unifier le décompte IA (BYOK, rollback) et combler les fuites
All checks were successful
CI / Lint, Unit Tests & Build (push) Successful in 6m55s
CI / Deploy production (on server) (push) Successful in 36s

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>
This commit is contained in:
Antigravity
2026-07-15 20:42:25 +00:00
parent 30da592ba2
commit 4fe31ebc99
75 changed files with 2949 additions and 785 deletions

View File

@@ -3,7 +3,8 @@ import prisma from '@/lib/prisma'
import { auth } from '@/auth'
import { runLaneWithBillingUser } from '@/lib/ai/provider-for-user'
import { getSystemConfig } from '@/lib/config'
import { verifyParticipant } from '@/lib/brainstorm-collab'
import { billingOwnerFromSession, verifyParticipant } from '@/lib/brainstorm-collab'
import { withSessionAiQuota, handleQuotaHttpError } from '@/lib/ai-quota'
function localeToLanguageName(locale?: string): string {
const map: Record<string, string> = {
@@ -53,6 +54,11 @@ export async function POST(
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')
@@ -79,15 +85,27 @@ Write a concise synthesis (4-6 sentences) that:
Be direct and action-oriented. No bullet points, just flowing prose.`
const config = await getSystemConfig()
const { result: summary } = await runLaneWithBillingUser(
'tags',
config,
const summary = await withSessionAiQuota(
billingOwnerId,
session.user.id,
(provider) => provider.generateText(prompt),
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 })
}