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>
36 lines
1.2 KiB
TypeScript
36 lines
1.2 KiB
TypeScript
import { getEffectiveTier, QuotaExceededError } from '@/lib/entitlements'
|
|
import { reserveAiUsageOrThrow } from '@/lib/ai-quota'
|
|
import type { SubscriptionTier } from '@/lib/plan-entitlements'
|
|
import type { FeatureName } from '@/lib/quota-utils'
|
|
|
|
/** MCP (clés API + outils externes) réservé aux plans payants + 1 unité chat par invocation. */
|
|
export function isMcpTierAllowed(tier: SubscriptionTier): boolean {
|
|
return tier !== 'BASIC'
|
|
}
|
|
|
|
export class McpTierLimitedError extends Error {
|
|
code = 'MCP_TIER_LIMITED' as const
|
|
|
|
constructor(public tier: SubscriptionTier) {
|
|
super('MCP requires a Pro plan or higher')
|
|
}
|
|
}
|
|
|
|
export async function assertMcpAccess(userId: string): Promise<SubscriptionTier> {
|
|
const tier = await getEffectiveTier(userId)
|
|
if (!isMcpTierAllowed(tier)) {
|
|
throw new McpTierLimitedError(tier)
|
|
}
|
|
return tier
|
|
}
|
|
|
|
/** Tier gate + monthly chat quota (MCP tool calls bill like chat). */
|
|
export async function assertMcpAccessWithQuota(
|
|
userId: string,
|
|
feature: FeatureName = 'chat',
|
|
): Promise<SubscriptionTier> {
|
|
const tier = await assertMcpAccess(userId)
|
|
await reserveAiUsageOrThrow(userId, feature, { lane: 'chat' })
|
|
return tier
|
|
}
|