/** * Hugging Face Hub Storage Integration * * NOTE: This still goes through Vercel serverless functions, * so it won't bypass Vercel's 4.5MB/50MB request size limits. * For true 2GB uploads, you need direct client uploads (S3, R2, etc.) */ export interface HuggingFaceFileResult { file_id: string; file_url: string; repo_path: string; } const HF_API_BASE = 'https://huggingface.co/api'; /** * Upload a file to Hugging Face Hub using the commit endpoint */ export async function uploadToHuggingFace( file: Blob, fileName: string, fileId: string ): Promise { const token = process.env.HF_TOKEN; const repoId = process.env.HF_REPO_ID; const repoType = process.env.HF_REPO_TYPE || 'dataset'; if (!token || !repoId) { throw new Error('Hugging Face credentials not configured. Set HF_TOKEN and HF_REPO_ID'); } // Convert Blob to base64 for the commit API const arrayBuffer = await file.arrayBuffer(); const buffer = Buffer.from(arrayBuffer); const base64Content = buffer.toString('base64'); // Determine file extension const ext = fileName.split('.').pop() || 'bin'; const pathInRepo = `files/${fileId}.${ext}`; // Use the commit endpoint (new API) // Format: POST /api/{repo_type}s/{repo_id}/commit/{revision} const repoTypePlural = repoType === 'dataset' ? 'datasets' : 'models'; const commitUrl = `${HF_API_BASE}/${repoTypePlural}/${repoId}/commit/main`; // The commit API expects operations in a specific format const commitData = { operations: [ { operation: 'add', path: pathInRepo, content: base64Content, } ], commit_message: `Upload ${fileName}`, }; const response = await fetch(commitUrl, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', }, body: JSON.stringify(commitData), }); if (!response.ok) { const errorText = await response.text(); throw new Error(`Hugging Face API error: ${response.status} - ${errorText}`); } // Get the public URL const fileUrl = `https://huggingface.co/${repoType === 'dataset' ? 'datasets' : repoType}/${repoId}/resolve/main/${pathInRepo}`; // Alternative CDN URL (may be faster) const cdnUrl = `https://cdn.huggingface.co/${repoId}/main/${pathInRepo}`; return { file_id: fileId, file_url: cdnUrl, // Use CDN URL for faster access repo_path: pathInRepo, }; } /** * Get file URL from Hugging Face Hub */ export async function getHuggingFaceUrl( fileId: string, extension: string = 'jpg' ): Promise { const repoId = process.env.HF_REPO_ID; const repoType = process.env.HF_REPO_TYPE || 'dataset'; const pathInRepo = `files/${fileId}.${extension}`; // Try CDN first (faster) return `https://cdn.huggingface.co/${repoId}/main/${pathInRepo}`; } /** * Check if Hugging Face is configured */ export function isHuggingFaceConfigured(): boolean { return !!(process.env.HF_TOKEN && process.env.HF_REPO_ID); }