import { useState, useMemo } from 'react'; import { useQuery } from '@tanstack/react-query'; import { HardDrive, RefreshCw, MemoryStick, } from 'lucide-react'; import { formatBytes, formatRelativeTime } from '@/lib/utils'; import { agentApi } from '@/lib/api'; import toast from 'react-hot-toast'; import { cn } from '@/lib/utils'; interface AgentStorageProps { agentId: string; } interface DiskInfo { mountpoint: string; total: number; available: number; used: number; used_percent: number; filesystem: string; is_root: boolean; is_largest: boolean; disk_type: string; device: string; } interface StorageMetrics { cpu_percent: number; memory_percent: number; memory_used_gb: number; memory_total_gb: number; disk_used_gb: number; disk_total_gb: number; disk_percent: number; largest_disk_used_gb: number; largest_disk_total_gb: number; largest_disk_percent: number; largest_disk_mount: string; uptime: string; } export function AgentStorage({ agentId }: AgentStorageProps) { const [isScanning, setIsScanning] = useState(false); // Fetch agent details and storage metrics const { data: agentData } = useQuery({ queryKey: ['agent', agentId], queryFn: async () => { return await agentApi.getAgent(agentId); }, refetchInterval: 30000, // Refresh every 30 seconds }); // Fetch storage metrics from dedicated endpoint const { data: storageData, refetch: refetchStorage } = useQuery({ queryKey: ['storage-metrics', agentId], queryFn: async () => { return await agentApi.getStorageMetrics(agentId); }, refetchInterval: 30000, // Refresh every 30 seconds }); const handleFullStorageScan = async () => { setIsScanning(true); try { // Trigger storage scan only (not full system scan) await agentApi.triggerSubsystem(agentId, 'storage'); toast.success('Storage scan initiated'); // Refresh data after a short delay setTimeout(() => { refetchStorage(); setIsScanning(false); }, 3000); } catch (error) { toast.error('Failed to initiate storage scan'); setIsScanning(false); } }; // Process storage metrics data const storageMetrics: StorageMetrics | null = useMemo(() => { if (!storageData?.metrics || storageData.metrics.length === 0) { return null; } // Find root disk for summary metrics const rootDisk = storageData.metrics.find((m: any) => m.is_root) || storageData.metrics[0]; const largestDisk = storageData.metrics.find((m: any) => m.is_largest) || rootDisk; return { cpu_percent: 0, // CPU not included in storage metrics, comes from system metrics memory_percent: 0, // Memory not included in storage metrics, comes from system metrics memory_used_gb: 0, memory_total_gb: 0, disk_used_gb: largestDisk ? largestDisk.used_bytes / (1024 * 1024 * 1024) : 0, disk_total_gb: largestDisk ? largestDisk.total_bytes / (1024 * 1024 * 1024) : 0, disk_percent: largestDisk ? largestDisk.used_percent : 0, largest_disk_used_gb: largestDisk ? largestDisk.used_bytes / (1024 * 1024 * 1024) : 0, largest_disk_total_gb: largestDisk ? largestDisk.total_bytes / (1024 * 1024 * 1024) : 0, largest_disk_percent: largestDisk ? largestDisk.used_percent : 0, largest_disk_mount: largestDisk ? largestDisk.mountpoint : '', uptime: '', // Uptime not included in storage metrics }; }, [storageData]); // Parse disk info from storage metrics const parseDiskInfo = (): DiskInfo[] => { if (!storageData?.metrics) return []; return storageData.metrics.map((disk: any) => ({ mountpoint: disk.mountpoint, device: disk.device, disk_type: disk.disk_type, total: disk.total_bytes, available: disk.available_bytes, used: disk.used_bytes, used_percent: disk.used_percent, filesystem: disk.filesystem, is_root: disk.is_root || false, is_largest: disk.is_largest || false, })); }; if (!agentData) { return (
{[...Array(4)].map((_, i) => (
))}
); } const disks = parseDiskInfo(); return (
{/* Clean minimal header */}

System Resources

{/* Memory & Disk - matching Overview styling */}
{/* Memory - GREEN to differentiate from disks */} {storageMetrics && storageMetrics.memory_total_gb > 0 && (

Memory

{storageMetrics.memory_used_gb.toFixed(1)} GB / {storageMetrics.memory_total_gb.toFixed(1)} GB

{storageMetrics.memory_percent.toFixed(0)}% used

)} {/* Quick Overview - Simple disk bars for at-a-glance view */} {disks.length > 0 && (

Disk Usage (Overview)

{disks.map((disk, index) => (

{disk.mountpoint} ({disk.filesystem})

{formatBytes(disk.used)} / {formatBytes(disk.total)} ({disk.used_percent.toFixed(0)}%)

))}
)} {/* Enhanced Disk Table - Shows all partitions with full details */} {disks.length > 0 && (

Disk Partitions (Detailed)

{disks.length} {disks.length === 1 ? 'partition' : 'partitions'} detected
{disks.map((disk, index) => ( ))}
Mount Device Type FS Size Used % Flags
{disk.mountpoint} {disk.is_root && ROOT} {disk.is_largest && LARGEST}
{disk.device} {disk.disk_type.toLowerCase()} {disk.filesystem} {formatBytes(disk.total)} {formatBytes(disk.used)}
{disk.used_percent.toFixed(0)}%
{disk.severity !== 'low' && ( {disk.severity.toUpperCase()} )}
Showing {disks.length} disk partitions • Auto-refreshes every 30 seconds
)} {/* Fallback if no disk array but we have metadata */} {disks.length === 0 && storageMetrics && storageMetrics.disk_total_gb > 0 && (

Disk (/)

{storageMetrics.disk_used_gb.toFixed(1)} GB / {storageMetrics.disk_total_gb.toFixed(1)} GB

{storageMetrics.disk_percent.toFixed(0)}% used

)}
{/* Refresh info */}
Auto-refreshes every 30 seconds • Last updated {agentData?.last_seen ? formatRelativeTime(agentData.last_seen) : 'unknown'}
); }