import { useState, useEffect } from 'react' import { motion, AnimatePresence } from 'framer-motion' import { useAuth } from '@clerk/clerk-react' import { API_BASE } from '../config.js' async function* parseSseStream(response) { const reader = response.body.getReader() const decoder = new TextDecoder() let buffer = '' while (true) { const { done, value } = await reader.read() if (done) break buffer += decoder.decode(value, { stream: true }) const lines = buffer.split('\n') buffer = lines.pop() ?? '' let eventType = null for (const line of lines) { if (line.startsWith('event: ')) eventType = line.slice(7).trim() else if (line.startsWith('data: ')) { const raw = line.slice(6).trim() if (raw) { try { yield { type: eventType, data: JSON.parse(raw) } } catch {} } eventType = null } } } } export default function NotebookGuide({ initialGuide, onGuideReady }) { const { getToken } = useAuth() const [guide, setGuide] = useState(initialGuide || null) const [streaming, setStreaming] = useState('') const [status, setStatus] = useState('idle') const [error, setError] = useState('') useEffect(() => { if (initialGuide) setGuide(initialGuide) }, [initialGuide]) const generate = async () => { setStatus('generating') setStreaming('') setError('') try { const token = await getToken() const res = await fetch(`${API_BASE}/notebook/generate`, { method: 'POST', headers: token ? { Authorization: `Bearer ${token}` } : {}, }) if (!res.ok) throw new Error(`Server error ${res.status}`) for await (const event of parseSseStream(res)) { if (event.type === 'token') setStreaming(prev => prev + event.data.content) else if (event.type === 'done') { setGuide(event.data.guide) setStreaming('') setStatus('done') onGuideReady?.(event.data.guide) } else if (event.type === 'error') throw new Error(event.data.message) } } catch (err) { setError(err.message) setStatus('error') } } const isGenerating = status === 'generating' return (
Click Generate to create an AI-powered overview of all your documents.
{streaming}
)}Overview
{guide.overview}
Key Themes
Documents
{error}
}