import React, { useState } from 'react'; import { Box, Typography, Card, Chip, Button, Alert, Dialog, DialogTitle, DialogContent, DialogActions, Snackbar, } from '@mui/material'; import { CloudDownload as CloudDownloadIcon, Trash2 as DeleteIcon } from 'lucide-react'; import api from '../api'; import { checkpointManagerStyles } from '../theme'; export default function CheckpointManager({ model, onRefresh }) { const [loadingStates, setLoadingStates] = useState({}); const [error, setError] = useState(null); const [deleteTarget, setDeleteTarget] = useState(null); const [toast, setToast] = useState({ open: false, message: '', severity: 'success' }); const handleUnwrapCheckpoint = async (checkpoint) => { const checkpointId = checkpoint.path; setLoadingStates(prev => ({ ...prev, [checkpointId]: { unwrapping: true } })); setError(null); try { await api.post('/api/unwrap-model', { model_config: model.config_path, ckpt_path: checkpoint.path, name: `${checkpoint.name}_unwrapped` }); setError(null); setToast({ open: true, message: `Checkpoint "${checkpoint.name}" unwrapped successfully.`, severity: 'success' }); onRefresh(); } catch (err) { setError(`Failed to unwrap ${checkpoint.name}: ${err.response?.data?.error || err.message}`); } finally { setLoadingStates(prev => ({ ...prev, [checkpointId]: { unwrapping: false } })); } }; const handleDeleteCheckpoint = async () => { if (!deleteTarget) { return; } const checkpointId = deleteTarget.path; setLoadingStates(prev => ({ ...prev, [checkpointId]: { deleting: true } })); setError(null); try { await api.post('/api/delete-checkpoint', { checkpoint_path: deleteTarget.path }); setToast({ open: true, message: `Checkpoint "${deleteTarget.name}" deleted successfully.`, severity: 'success' }); onRefresh(); } catch (err) { setError(`Failed to delete ${deleteTarget.name}: ${err.response?.data?.error || err.message}`); } finally { setDeleteTarget(null); setLoadingStates(prev => ({ ...prev, [checkpointId]: { deleting: false } })); } }; const closeToast = (_, reason) => { if (reason === 'clickaway') { return; } setToast(prev => ({ ...prev, open: false })); }; const checkpoints = model.checkpoints || []; return ( <> Checkpoints ({checkpoints.length}) {checkpoints.length === 0 ? ( No checkpoints yet. ) : ( {checkpoints.map((checkpoint, index) => { const checkpointId = checkpoint.path; const isUnwrapping = loadingStates[checkpointId]?.unwrapping; const isDeleting = loadingStates[checkpointId]?.deleting; const hasUnwrappedVersion = model.unwrapped_models?.some(unwrapped => unwrapped.name.includes(checkpoint.name) || checkpoint.name.includes(unwrapped.name.replace('_unwrapped', '')) ); return ( {checkpoint.name} {hasUnwrappedVersion && ( )} {checkpoint.size_mb} MB {!hasUnwrappedVersion && ( )} {hasUnwrappedVersion && ( )} ); })} )} {error && ( {error} )} setDeleteTarget(null)} aria-labelledby="delete-checkpoint-dialog-title" > Delete Wrapped Checkpoint {deleteTarget ? `Delete "${deleteTarget.name}"? This action cannot be undone.` : 'Delete this checkpoint?'} {toast.message} ); }