| 18 | } |
| 19 | |
| 20 | export function useCheckpoints({ sessionId, projectId, projectPath, onToast }: UseCheckpointsOptions) { |
| 21 | const [checkpoints, setCheckpoints] = useState<Checkpoint[]>([]); |
| 22 | const [isLoadingCheckpoints, setIsLoadingCheckpoints] = useState(false); |
| 23 | const [timelineVersion, setTimelineVersion] = useState(0); |
| 24 | |
| 25 | const showToast = useCallback((message: string, type: 'success' | 'error' = 'success') => { |
| 26 | if (onToast) { |
| 27 | onToast(message, type); |
| 28 | } |
| 29 | }, [onToast]); |
| 30 | |
| 31 | const loadCheckpoints = useCallback(async () => { |
| 32 | if (!sessionId) return; |
| 33 | |
| 34 | setIsLoadingCheckpoints(true); |
| 35 | try { |
| 36 | const result = await api.listCheckpoints(sessionId, projectId, projectPath); |
| 37 | // Map API Checkpoint type to local format if needed |
| 38 | const mappedCheckpoints = result.map(cp => ({ |
| 39 | id: cp.id, |
| 40 | sessionId: cp.sessionId, |
| 41 | name: cp.description || `Checkpoint at ${cp.timestamp}`, |
| 42 | createdAt: cp.timestamp, |
| 43 | messageCount: cp.metadata.totalTokens |
| 44 | })); |
| 45 | setCheckpoints(mappedCheckpoints); |
| 46 | setTimelineVersion(prev => prev + 1); |
| 47 | } catch (error) { |
| 48 | console.error("Failed to load checkpoints:", error); |
| 49 | showToast("Failed to load checkpoints", 'error'); |
| 50 | } finally { |
| 51 | setIsLoadingCheckpoints(false); |
| 52 | } |
| 53 | }, [sessionId, projectId, projectPath, showToast]); |
| 54 | |
| 55 | const createCheckpoint = useCallback(async (name: string) => { |
| 56 | if (!sessionId) return; |
| 57 | |
| 58 | try { |
| 59 | await api.createCheckpoint(sessionId, projectId, projectPath, undefined, name); |
| 60 | await loadCheckpoints(); |
| 61 | showToast("Checkpoint created successfully", 'success'); |
| 62 | } catch (error) { |
| 63 | console.error("Failed to create checkpoint:", error); |
| 64 | showToast("Failed to create checkpoint", 'error'); |
| 65 | throw error; |
| 66 | } |
| 67 | }, [sessionId, projectId, projectPath, loadCheckpoints, showToast]); |
| 68 | |
| 69 | const restoreCheckpoint = useCallback(async (checkpointId: string) => { |
| 70 | if (!sessionId) return; |
| 71 | |
| 72 | try { |
| 73 | await api.restoreCheckpoint(checkpointId, sessionId, projectId, projectPath); |
| 74 | showToast("Checkpoint restored successfully", 'success'); |
| 75 | // Return true to indicate success |
| 76 | return true; |
| 77 | } catch (error) { |