import { useState, createContext, useContext, useCallback, type ReactNode } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { ChevronRight, CheckCircle2, XCircle, Loader2, Circle } from 'lucide-react'; // --------------------------------------------------------------------------- // TaskContext — shared task state for sub-agent orchestration // --------------------------------------------------------------------------- interface TaskContextValue { tasks: Subtask[]; updateTask: (id: string, updates: Partial) => void; } const TaskContext = createContext(null); export function useTaskContext() { const ctx = useContext(TaskContext); if (!ctx) { throw new Error('useTaskContext must be used within TaskProvider'); } return ctx; } export function TaskProvider({ children, initialTasks = [], }: { children: ReactNode; initialTasks?: Subtask[]; }) { const [tasks, setTasks] = useState(initialTasks); const updateTask = useCallback((id: string, updates: Partial) => { setTasks(prev => prev.map(t => (t.id === id ? { ...t, ...updates } : t))); }, []); return ( {children} ); } /** * Subtask progress display for sub-agent orchestration. * * Inspired by DeerFlow's SubtaskCard + ShineBorder pattern: * - Shows task status with animated indicators * - Collapsible details with thinking chain * - Pulsing border animation for active tasks * - Status icons: running (pulse), completed (green), failed (red) */ export interface Subtask { id: string; description: string; status: 'pending' | 'in_progress' | 'completed' | 'failed'; result?: string; error?: string; steps?: Array<{ content: string; status: 'thinking' | 'done' | 'error' }>; } interface TaskProgressProps { tasks: Subtask[]; className?: string; } export function TaskProgress({ tasks, className = '' }: TaskProgressProps) { if (tasks.length === 0) return null; return (
{tasks.map(task => ( ))}
); } function SubtaskCard({ task }: { task: Subtask }) { const [expanded, setExpanded] = useState(task.status === 'in_progress'); const isActive = task.status === 'in_progress'; return (
{/* Header */} {/* Expanded details */} {expanded && (task.result || task.error || (task.steps && task.steps.length > 0)) && (
{/* Steps */} {task.steps?.map((step, i) => (
{step.status === 'thinking' ? ( ) : step.status === 'done' ? ( ) : ( )} {step.content}
))} {/* Result */} {task.result && (
{task.result}
)} {/* Error */} {task.error && (
{task.error}
)}
)}
); }