/** * Swapper Service Integration for Node #1 and Node #2 Admin Consoles * React/TypeScript component example */ import React, { useEffect, useState } from 'react'; // Types interface SwapperStatus { service: string; status: string; mode: string; active_model: { name: string; uptime_hours: number; request_count: number; loaded_at: string | null; } | null; total_models: number; available_models: string[]; loaded_models: string[]; models: Array<{ name: string; ollama_name: string; type: string; size_gb: number; priority: string; status: string; is_active: boolean; uptime_hours: number; request_count: number; total_uptime_seconds: number; }>; timestamp: string; } interface SwapperMetrics { summary: { total_models: number; active_models: number; available_models: number; total_uptime_hours: number; total_requests: number; }; most_used_model: { name: string; uptime_hours: number; request_count: number; } | null; active_model: { name: string; uptime_hours: number | null; } | null; timestamp: string; } // API Service const SWAPPER_API_BASE = process.env.NEXT_PUBLIC_SWAPPER_URL || 'http://localhost:8890'; export const swapperService = { async getStatus(): Promise { const response = await fetch(`${SWAPPER_API_BASE}/api/cabinet/swapper/status`); if (!response.ok) throw new Error('Failed to fetch Swapper status'); return response.json(); }, async getMetrics(): Promise { const response = await fetch(`${SWAPPER_API_BASE}/api/cabinet/swapper/metrics/summary`); if (!response.ok) throw new Error('Failed to fetch Swapper metrics'); return response.json(); }, async loadModel(modelName: string): Promise { const response = await fetch(`${SWAPPER_API_BASE}/models/${modelName}/load`, { method: 'POST', }); if (!response.ok) throw new Error(`Failed to load model: ${modelName}`); }, async unloadModel(modelName: string): Promise { const response = await fetch(`${SWAPPER_API_BASE}/models/${modelName}/unload`, { method: 'POST', }); if (!response.ok) throw new Error(`Failed to unload model: ${modelName}`); }, }; // Main Swapper Status Component export const SwapperStatusCard: React.FC = () => { const [status, setStatus] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const fetchStatus = async () => { try { const data = await swapperService.getStatus(); setStatus(data); setError(null); } catch (err) { setError(err instanceof Error ? err.message : 'Unknown error'); } finally { setLoading(false); } }; useEffect(() => { fetchStatus(); const interval = setInterval(fetchStatus, 30000); // Update every 30 seconds return () => clearInterval(interval); }, []); if (loading) return
Loading Swapper status...
; if (error) return
Error: {error}
; if (!status) return
No status data
; return (

🔄 Swapper Service

{status.status}
Mode: {status.mode}
Total Models: {status.total_models}
Loaded Models: {status.loaded_models.length}
{status.active_model && (

✨ Active Model

{status.active_model.name}
Uptime: {status.active_model.uptime_hours.toFixed(2)}h
Requests: {status.active_model.request_count}
{status.active_model.loaded_at && (
Loaded: {new Date(status.active_model.loaded_at).toLocaleString()}
)}
)}

Available Models

{status.models.map((model) => ( ))}
Name Type Size (GB) Status Uptime (h) Actions
{model.name} {model.type} {model.size_gb.toFixed(1)} {model.status} {model.uptime_hours.toFixed(2)} {model.status === 'unloaded' && ( )} {model.status === 'loaded' && !model.is_active && ( )} {model.is_active && ( ● Active )}
Last updated: {new Date(status.timestamp).toLocaleString()}
); }; // Metrics Summary Component export const SwapperMetricsSummary: React.FC = () => { const [metrics, setMetrics] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { const fetchMetrics = async () => { try { const data = await swapperService.getMetrics(); setMetrics(data); } catch (err) { console.error('Error fetching metrics:', err); } finally { setLoading(false); } }; fetchMetrics(); const interval = setInterval(fetchMetrics, 60000); // Update every minute return () => clearInterval(interval); }, []); if (loading || !metrics) return
Loading metrics...
; return (

📊 Metrics Summary

Total Models
{metrics.summary.total_models}
Active Models
{metrics.summary.active_models}
Total Uptime
{metrics.summary.total_uptime_hours.toFixed(2)}h
Total Requests
{metrics.summary.total_requests}
{metrics.most_used_model && (
Most Used Model
{metrics.most_used_model.name} {metrics.most_used_model.uptime_hours.toFixed(2)}h
)}
); }; // Main Swapper Page Component export const SwapperPage: React.FC = () => { return (

Swapper Service

Dynamic model loading and management

); }; export default SwapperPage;