import { type AgentErrorEvent, type AgentStepEvent, type ObservationEvent, type RetryEvent, } from '@page-agent/core' import { CheckCircle, ChevronDown, ChevronRight, Eye, Globe, Keyboard, Mouse, MoveVertical, RefreshCw, Sparkles, XCircle, Zap, } from 'lucide-react' import { Fragment, useState } from 'react' import { cn } from '@/lib/utils' import { AgentActivity, HistoricalEvent } from '@/messaging' // Result card for done action function ResultCard({ success, text, children, }: { success: boolean text: string children?: React.ReactNode }) { return (
{success ? ( ) : ( )} Result: {success ? 'Success' : 'Failed'}

{text}

{children}
) } // Single reflection item with truncation function ReflectionItem({ icon, value }: { icon: string; value: string }) { const [expanded, setExpanded] = useState(false) return ( {icon} setExpanded(!expanded)} > {value} ) } // Reflection section in step card function ReflectionSection({ reflection, }: { reflection: { evaluation_previous_goal?: string memory?: string next_goal?: string } }) { const items = [ { icon: '☑️', label: 'eval', value: reflection.evaluation_previous_goal }, { icon: '🧠', label: 'memory', value: reflection.memory }, { icon: '🎯', label: 'goal', value: reflection.next_goal }, ].filter((item) => item.value) if (items.length === 0) return null return (
{/*
Reflection
*/}
{items.map((item) => ( ))}
) } // Get icon for action type function ActionIcon({ name, className }: { name: string; className?: string }) { const icons: Record = { click_element_by_index: , input: , scroll: , go_to_url: , } return icons[name] || } // Raw response section (collapsible, for debugging) function RawResponseSection({ rawResponse }: { rawResponse: unknown }) { const [expanded, setExpanded] = useState(false) return (
{expanded && (
					{JSON.stringify(rawResponse, null, 4)}
				
)}
) } function StepCard({ event }: { event: AgentStepEvent }) { return (
Step #{event.stepIndex! + 1}
{/* Reflection */} {event.reflection && } {/* Action */} {event.action && (
Actions

{event.action.name} {event.action.name !== 'done' && ( {JSON.stringify(event.action.input)} )}

└ {event.action.output}

)} {/* Raw Response */} {!event.rawResponse || }
) } function ObservationCard({ event }: { event: ObservationEvent }) { return (
{/*
Observation
*/}
{event.content}
) } function RetryCard({ event }: { event: RetryEvent }) { return (
{event.message} ({event.attempt}/{event.maxAttempts})
) } function ErrorCard({ event }: { event: AgentErrorEvent }) { return (
{event.message}
{!event.rawResponse || }
) } // History event card component export function EventCard({ event }: { event: HistoricalEvent }) { // Done action - show as result card if (event.type === 'step' && event.action?.name === 'done') { const input = event.action.input as { text?: string; success?: boolean } return ( <> {!event.rawResponse || } ) } if (event.type === 'step') { return } if (event.type === 'observation') { return } if (event.type === 'retry') { return } if (event.type === 'error') { return } return null } // Activity card with animation export function ActivityCard({ activity }: { activity: AgentActivity }) { const getActivityInfo = () => { switch (activity.type) { case 'thinking': return { text: 'Thinking...', color: 'text-blue-500' } case 'executing': return { text: `Executing ${activity.tool}...`, color: 'text-amber-500' } case 'executed': return { text: `Done: ${activity.tool}`, color: 'text-green-500' } case 'retrying': return { text: `Retrying (${activity.attempt}/${activity.maxAttempts})...`, color: 'text-amber-500', } case 'error': return { text: activity.message, color: 'text-destructive' } } } const info = getActivityInfo() return (
{info.text}
) }