// src/components/EngineManager.tsx import { useState, useEffect } from 'react'; import apiClient from '../services/api'; interface ModelConfig { model_id: string; display_name: string; provider?: string; model_name?: string; max_tokens?: number; temperature?: number; timeout?: number; is_default?: boolean; supported_domains?: string[]; description?: string; } interface EngineStatus extends ModelConfig { status: 'master' | 'apprentice' | 'available' | 'retired'; unique_id?: string; // For apprentice engines } const EngineManager = () => { const [allEngines, setAllEngines] = useState([]); const [currentMasterId, setCurrentMasterId] = useState(''); const [currentApprenticeId, setCurrentApprenticeId] = useState('none'); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(''); const [newModelProvider, setNewModelProvider] = useState('ollama'); const [newModelId, setNewModelId] = useState(''); const [newModelDisplayName, setNewModelDisplayName] = useState(''); const [newModelModelName, setNewModelModelName] = useState(''); const [newModelSupportedDomains, setNewModelSupportedDomains] = useState(''); // Comma separated const [newModelDescription, setNewModelDescription] = useState(''); const [newModelFile, setNewModelFile] = useState(null); // For GGUF file upload const fetchModelsAndActiveEngines = async () => { try { const [allEnginesResponse, activeEnginesResponse] = await Promise.all([ apiClient.get('/config/engines'), // Fetch all engines with their statuses apiClient.get('/config/engines/active') // Fetch current active master/apprentice ]); setAllEngines(allEnginesResponse.data); const { master_engine_id, apprentice_engine_id } = activeEnginesResponse.data; if (master_engine_id) setCurrentMasterId(master_engine_id); if (apprentice_engine_id) setCurrentApprenticeId(apprentice_engine_id); } catch (err) { setError('Failed to load engines or active engines.'); console.error(err); } finally { setIsLoading(false); } }; useEffect(() => { fetchModelsAndActiveEngines(); }, []); const handleSetActiveEngines = async () => { try { await apiClient.post('/config/engines/active', { master_engine_id: currentMasterId, apprentice_engine_id: currentApprenticeId === 'none' ? null : currentApprenticeId, }); alert('Active engines updated successfully!'); fetchModelsAndActiveEngines(); // Re-fetch to confirm and update UI } catch (err: any) { const errorMessage = err.response?.data?.detail || err.message; alert(`Failed to update active engines: ${errorMessage}`); console.error(err); } }; const handleSubmitNewModel = async () => { if (!newModelId || !newModelDisplayName || !newModelModelName) { alert('Please fill in Model ID, Display Name, and Model Name.'); return; } let actualModelName = newModelModelName; // Default to user-provided model name // Handle GGUF file upload first if applicable if (newModelProvider === 'gguf') { if (!newModelFile) { alert('Please select a GGUF file for the GGUF provider.'); return; } try { const formData = new FormData(); formData.append('file', newModelFile); const uploadResponse = await apiClient.post('/config/upload-gguf', formData, { headers: { 'Content-Type': 'multipart/form-data', }, }); actualModelName = uploadResponse.data.path; // Use the path returned by the backend alert(`GGUF file uploaded successfully to: ${actualModelName}`); } catch (err: any) { const errorMessage = err.response?.data?.detail || err.message; alert(`Failed to upload GGUF file: ${errorMessage}`); console.error(err); return; // Stop processing if file upload fails } } const modelData: ModelConfig = { model_id: newModelId, display_name: newModelDisplayName, provider: newModelProvider, model_name: actualModelName, // Use the actualModelName (might be local file path) max_tokens: 4096, // Default values temperature: 0.7, timeout: 120, is_default: false, supported_domains: newModelSupportedDomains.split(',').map(s => s.trim()).filter(s => s), description: newModelDescription, }; try { await apiClient.post('/config/models', modelData); alert('Model registered successfully!'); fetchModelsAndActiveEngines(); // Refresh the model list // Clear form setNewModelId(''); setNewModelDisplayName(''); setNewModelModelName(''); setNewModelSupportedDomains(''); setNewModelDescription(''); setNewModelFile(null); } catch (err: any) { const errorMessage = err.response?.data?.detail || err.message; alert(`Failed to register model: ${errorMessage}`); console.error(err); } }; if (isLoading) { return

Engine Management

Loading models...

; } if (error) { return

Engine Management

{error}

; } const handleSwapEngines = async (apprenticeModelId: string) => { try { await apiClient.post('/config/engines/swap', { apprentice_model_id: apprenticeModelId }); alert('Engines swapped successfully!'); fetchModelsAndActiveEngines(); // Refresh UI } catch (err: any) { const errorMessage = err.response?.data?.detail || err.message; alert(`Failed to swap engines: ${errorMessage}`); console.error(err); } }; const handlePromoteApprentice = async (apprenticeModelId: string) => { try { await apiClient.post('/config/engines/promote', { apprentice_model_id: apprenticeModelId }); alert('Apprentice promoted to Master successfully!'); fetchModelsAndActiveEngines(); // Refresh UI } catch (err: any) { const errorMessage = err.response?.data?.detail || err.message; alert(`Failed to promote apprentice: ${errorMessage}`); console.error(err); } }; const handleCreateNewApprentice = async () => { try { const response = await apiClient.post('/config/engines/apprentice/new'); alert(response.data.message); fetchModelsAndActiveEngines(); // Refresh UI } catch (err: any) { const errorMessage = err.response?.data?.detail || err.message; alert(`Failed to create new apprentice: ${errorMessage}`); console.error(err); } }; return (

Engine Management

{/* Current Active Engines Display */}

Master Engine:{' '} {allEngines.find(e => e.model_id === currentMasterId)?.display_name || 'Not Set'}

Apprentice Engine:{' '} {allEngines.find(e => e.model_id === currentApprenticeId)?.display_name || 'None'}

{/* Set Active Engines (existing functionality, but updated) */}

Set Current Master/Apprentice

{/* New: Advanced Engine Management */}

Advanced Engine Operations

{/* Swap Master and Apprentice */}
{/* Promote Apprentice */}
{/* Create New Apprentice */}
{/* Register New Model Section (existing functionality) */}

Register New Model

{/* Existing new model registration form content */}
setNewModelId(e.target.value)} placeholder="e.g., 'my-custom-model'" />
setNewModelDisplayName(e.target.value)} placeholder="e.g., 'My Custom Model'" />
setNewModelModelName(e.target.value)} placeholder="e.g., 'gemma2:9b' or 'kofdai/my-hf-model'" />
setNewModelSupportedDomains(e.target.value)} placeholder="e.g., 'medical,general'" />
{newModelProvider === 'gguf' && (
setNewModelFile(e.target.files ? e.target.files[0] : null)} />
)}
); }; export default EngineManager;