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

@@ -41,9 +41,16 @@ import { cn } from '@/lib/utils'
interface McpSettingsPanelProps {
initialKeys: McpKeyInfo[]
serverStatus: McpServerStatus
mcpAllowed?: boolean
tier?: string
}
export function McpSettingsPanel({ initialKeys, serverStatus }: McpSettingsPanelProps) {
export function McpSettingsPanel({
initialKeys,
serverStatus,
mcpAllowed = true,
tier = 'PRO',
}: McpSettingsPanelProps) {
const [keys, setKeys] = useState<McpKeyInfo[]>(initialKeys)
const [createOpen, setCreateOpen] = useState(false)
const [isPending, startTransition] = useTransition()
@@ -69,7 +76,7 @@ export function McpSettingsPanel({ initialKeys, serverStatus }: McpSettingsPanel
...prev,
])
} catch (err) {
toast.error(err instanceof Error ? err.message : 'Failed to generate key')
toast.error(err instanceof Error ? err.message : t('mcpSettings.apiKeys.errors.generate'))
}
})
}
@@ -84,7 +91,7 @@ export function McpSettingsPanel({ initialKeys, serverStatus }: McpSettingsPanel
)
toast.success(t('toast.operationSuccess'))
} catch (err) {
toast.error(err instanceof Error ? err.message : 'Failed to revoke key')
toast.error(err instanceof Error ? err.message : t('mcpSettings.apiKeys.errors.revoke'))
}
})
}
@@ -97,7 +104,7 @@ export function McpSettingsPanel({ initialKeys, serverStatus }: McpSettingsPanel
setKeys(prev => prev.filter(k => k.shortId !== shortId))
toast.success(t('toast.operationSuccess'))
} catch (err) {
toast.error(err instanceof Error ? err.message : 'Failed to delete key')
toast.error(err instanceof Error ? err.message : t('mcpSettings.apiKeys.errors.delete'))
}
})
}
@@ -183,6 +190,11 @@ export function McpSettingsPanel({ initialKeys, serverStatus }: McpSettingsPanel
<p className="text-[10px] text-concrete mt-0.5">{t('mcpSettings.apiKeys.description')}</p>
</div>
</div>
{!mcpAllowed ? (
<p className="text-[10px] text-concrete max-w-[200px] text-end leading-relaxed">
{t('mcpSettings.tierRequired', { tier })}
</p>
) : (
<Dialog open={createOpen} onOpenChange={setCreateOpen}>
<DialogTrigger asChild>
<button className="flex items-center gap-1.5 px-4 py-2 rounded-xl bg-ink text-paper text-[10px] font-bold uppercase tracking-[0.15em] hover:scale-[1.02] active:scale-95 transition-all duration-300 shadow-lg shadow-ink/20">
@@ -192,8 +204,17 @@ export function McpSettingsPanel({ initialKeys, serverStatus }: McpSettingsPanel
</DialogTrigger>
<CreateKeyDialog onGenerate={handleGenerate} isPending={isPending} />
</Dialog>
)}
</div>
{!mcpAllowed && (
<div className="px-6 pb-4">
<p className="text-[11px] text-amber-800 dark:text-amber-200 bg-amber-500/10 border border-amber-500/20 rounded-xl px-4 py-3 leading-relaxed">
{t('mcpSettings.upgradeHint')}
</p>
</div>
)}
<div className="p-6">
{keys.length === 0 ? (
<div className="text-center py-8">