import { useState } from 'react'; import { View, Text, Pressable } from 'react-native'; import { StyleSheet } from 'react-native-unistyles'; import { Fonts } from "@/constants/theme"; import type { AgentActivity, GroupedTextMessage, MergedToolCall, SessionUpdate } from '@/types/agent-activity'; interface AgentActivityItemProps { item: GroupedTextMessage | MergedToolCall | AgentActivity; } function formatTimestamp(date: Date): string { return new Intl.DateTimeFormat('en-US', { hour: 'numeric', minute: '2-digit', second: '2-digit', hour12: true, }).format(date); } function getToolIcon(toolKind?: string): string { switch (toolKind) { case 'read': return '📖'; case 'edit': return '✏️'; case 'delete': return '🗑️'; case 'move': return '📦'; case 'search': return '🔍'; case 'execute': return '▶️'; case 'think': return '💭'; case 'fetch': return '🌐'; case 'switch_mode': return '🔄'; default: return '🔧'; } } function getStatusColor(status?: string): string { switch (status) { case 'pending': return '#9ca3af'; case 'in_progress': return '#fbbf24'; case 'completed': return '#22c55e'; case 'failed': return '#ef4444'; default: return '#6b7280'; } } function GroupedTextItem({ item }: { item: GroupedTextMessage }) { const isThought = item.messageType === 'thought'; return ( {formatTimestamp(item.startTimestamp)} {isThought && ( 💭 Thinking )} {item.text} ); } function MergedToolCallItem({ item }: { item: MergedToolCall }) { const [isExpanded, setIsExpanded] = useState(false); return ( setIsExpanded(!isExpanded)} style={stylesheet.toolHeader} > {formatTimestamp(item.startTimestamp)} {getToolIcon(item.toolKind)} {item.title} {item.status} {isExpanded ? '▼' : '▶'} {isExpanded && ( {item.rawInput && ( Input: {JSON.stringify(item.rawInput, null, 2)} )} {item.rawOutput && ( Output: {JSON.stringify(item.rawOutput, null, 2)} )} {!item.rawInput && !item.rawOutput && ( No details available )} )} ); } function PlanItem({ update, timestamp }: { update: SessionUpdate; timestamp: Date }) { const [isExpanded, setIsExpanded] = useState(true); if (update.kind !== 'plan') { return null; } return ( setIsExpanded(!isExpanded)} style={stylesheet.planHeader} > {formatTimestamp(timestamp)} 📋 Tasks ({update.entries.length}) {isExpanded ? '▼' : '▶'} {isExpanded && ( {update.entries.map((entry, idx) => ( {entry.status === 'completed' ? '✓' : entry.status === 'in_progress' ? '⏳' : '○'} {entry.content} ))} )} ); } function UnknownActivityItem({ update, timestamp }: { update: SessionUpdate; timestamp: Date }) { const [showDrawer, setShowDrawer] = useState(false); return ( setShowDrawer(!showDrawer)} style={stylesheet.unknownHeader} > {formatTimestamp(timestamp)} {update.kind} {showDrawer && ( {JSON.stringify(update, null, 2)} )} ); } export function AgentActivityItem({ item }: AgentActivityItemProps) { // Grouped text message if ('kind' in item && item.kind === 'grouped_text') { return ; } // Merged tool call if ('kind' in item && item.kind === 'merged_tool_call') { return ; } // Individual activity const activity = item as AgentActivity; const update = activity.update; // Tasks if (update.kind === 'plan') { return ; } // Available commands update if (update.kind === 'available_commands_update') { return ( {formatTimestamp(activity.timestamp)} Commands updated ({update.availableCommands.length} available) ); } // Current mode update if (update.kind === 'current_mode_update') { return ( {formatTimestamp(activity.timestamp)} Mode changed to: {update.currentModeId} ); } // Unknown activity type return ; } const stylesheet = StyleSheet.create((theme) => ({ card: { backgroundColor: theme.colors.surface2, borderRadius: theme.borderRadius.lg, padding: theme.spacing[3], marginBottom: theme.spacing[2], }, thoughtCard: { backgroundColor: theme.colors.surface2, borderLeftWidth: 3, borderLeftColor: theme.colors.palette.purple[500], paddingVertical: theme.spacing[2], }, timestamp: { color: theme.colors.foregroundMuted, fontSize: theme.fontSize.xs, marginBottom: theme.spacing[1], }, thoughtTimestamp: { marginBottom: theme.spacing[0], }, thoughtLabel: { color: theme.colors.palette.purple[500], fontSize: theme.fontSize.xs, fontWeight: theme.fontWeight.semibold, marginBottom: theme.spacing[0], }, text: { color: theme.colors.foreground, fontSize: theme.fontSize.sm, lineHeight: 20, }, thoughtText: { color: theme.colors.foregroundMuted, fontStyle: 'italic', }, toolCard: { backgroundColor: theme.colors.surface2, borderRadius: theme.borderRadius.lg, marginBottom: theme.spacing[2], overflow: 'hidden', }, toolHeader: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', padding: theme.spacing[3], }, toolHeaderLeft: { flex: 1, }, toolTitleRow: { flexDirection: 'row', alignItems: 'center', gap: theme.spacing[2], marginTop: theme.spacing[1], }, toolIcon: { fontSize: theme.fontSize.base, }, toolTitle: { color: theme.colors.palette.blue[400], fontSize: theme.fontSize.sm, fontWeight: theme.fontWeight.semibold, flex: 1, }, statusBadge: { paddingHorizontal: theme.spacing[2], paddingVertical: theme.spacing[1], borderRadius: theme.borderRadius.md, }, statusText: { color: theme.colors.foreground, fontSize: theme.fontSize.xs, fontWeight: theme.fontWeight.semibold, }, expandIcon: { color: theme.colors.foregroundMuted, fontSize: theme.fontSize.xs, }, toolContent: { borderTopWidth: theme.borderWidth[1], borderTopColor: theme.colors.border, padding: theme.spacing[3], }, section: { marginBottom: theme.spacing[3], }, sectionTitle: { color: theme.colors.foreground, fontSize: theme.fontSize.xs, fontWeight: theme.fontWeight.semibold, marginBottom: theme.spacing[1], }, code: { color: theme.colors.foregroundMuted, fontSize: theme.fontSize.xs, fontFamily: Fonts.mono, backgroundColor: theme.colors.surface2, padding: theme.spacing[2], borderRadius: theme.borderRadius.md, }, emptyText: { color: theme.colors.foregroundMuted, fontSize: theme.fontSize.sm, fontStyle: 'italic', }, planCard: { backgroundColor: theme.colors.surface2, borderRadius: theme.borderRadius.lg, marginBottom: theme.spacing[2], overflow: 'hidden', }, planHeader: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', padding: theme.spacing[3], }, planHeaderLeft: { flex: 1, }, planTitle: { color: theme.colors.palette.green[400], fontSize: theme.fontSize.sm, fontWeight: theme.fontWeight.semibold, marginTop: theme.spacing[1], }, planContent: { borderTopWidth: theme.borderWidth[1], borderTopColor: theme.colors.border, padding: theme.spacing[3], }, planEntry: { flexDirection: 'row', alignItems: 'flex-start', gap: theme.spacing[2], marginBottom: theme.spacing[2], }, planEntryStatus: { fontSize: theme.fontSize.sm, marginTop: 2, }, planEntryText: { color: theme.colors.foreground, fontSize: theme.fontSize.sm, flex: 1, }, infoText: { color: theme.colors.foregroundMuted, fontSize: theme.fontSize.sm, }, unknownCard: { backgroundColor: theme.colors.surface2, borderRadius: theme.borderRadius.lg, marginBottom: theme.spacing[2], overflow: 'hidden', }, unknownHeader: { padding: theme.spacing[3], }, unknownBadge: { backgroundColor: theme.colors.palette.orange[600], paddingHorizontal: theme.spacing[3], paddingVertical: theme.spacing[2], borderRadius: theme.borderRadius.md, marginTop: theme.spacing[2], alignSelf: 'flex-start', }, unknownBadgeText: { color: theme.colors.foreground, fontSize: theme.fontSize.xs, fontWeight: theme.fontWeight.semibold, }, drawerContent: { borderTopWidth: theme.borderWidth[1], borderTopColor: theme.colors.border, padding: theme.spacing[3], backgroundColor: theme.colors.surface2, }, }));