import { useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { useParams } from 'react-router-dom'; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Trash2, Loader2, Bot, Plus, Pencil } from "lucide-react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { subagentApi, type Subagent } from "@/api/subagents"; import { useProjectStore } from "@/store/projectStore"; import { api } from "@/lib/api"; interface ModelConfig { id: string; name: string; model: string; provider: string; } export function Subagents() { const { t } = useTranslation(); const { projectId: routeProjectId } = useParams<{ projectId: string }>(); const { currentProject } = useProjectStore(); // Use projectId from route, or fallback to currentProject const projectId = routeProjectId || currentProject?.id?.toString(); const [subagents, setSubagents] = useState([]); const [availableModels, setAvailableModels] = useState([]); const [isLoading, setIsLoading] = useState(false); const [isDialogOpen, setIsDialogOpen] = useState(false); const [editingSubagent, setEditingSubagent] = useState(null); const [newSubagent, setNewSubagent] = useState>({ name: '', description: '', model: '', instructions: '', status: 'active' }); const fetchInitialData = async () => { if (!projectId) return; setIsLoading(true); try { const [subagentsData, modelsData] = await Promise.all([ subagentApi.list(projectId), api.get('/api/v1/llm') ]); setSubagents(subagentsData || []); setAvailableModels(modelsData || []); } catch (error) { console.error("Failed to fetch initial data", error); } finally { setIsLoading(false); } }; useEffect(() => { if (projectId) { fetchInitialData(); } }, [projectId]); const getModelDisplay = (value?: string) => { if (!value) return '-'; const matched = availableModels.find((m) => m.id === value || m.model === value); if (!matched) return value; const label = matched.name || matched.model; return `${label} (${matched.provider})`; }; const handleSaveSubagent = async () => { if (!projectId) return; if (newSubagent.name && newSubagent.model) { try { if (editingSubagent && editingSubagent.id) { await subagentApi.update(projectId, editingSubagent.id, newSubagent); } else { const payload = { ...newSubagent, instructions: newSubagent.instructions || '' }; await subagentApi.create(projectId, payload); } await fetchInitialData(); setNewSubagent({ name: '', description: '', model: '', instructions: '', status: 'active' }); setEditingSubagent(null); setIsDialogOpen(false); } catch (error) { console.error("Failed to save subagent", error); alert(t('saveFailed')); } } else { alert(t('fillRequiredFields')); } }; const handleEditSubagent = (subagent: Subagent) => { const matched = availableModels.find((m) => m.id === subagent.model || m.model === subagent.model); setEditingSubagent(subagent); setNewSubagent({ ...subagent, model: matched?.id || subagent.model }); setIsDialogOpen(true); }; const handleDeleteSubagent = async (id: string) => { if (!projectId) return; if (!window.confirm(t('confirmDeleteSubagent'))) return; try { await subagentApi.delete(projectId, id); setSubagents(subagents.filter(s => s.id !== id)); } catch (error) { console.error("Failed to delete subagent", error); } }; if (!projectId) { return (

{t('selectProjectToManageSubagents', 'Please select a project to manage subagents')}

); } return (
{t('subagentManagement', 'Subagent Management')}
{t('name')} {t('modelName', 'Model')} {t('description')} {t('actions')} {isLoading ? (
) : ( <> {subagents.map((subagent) => (

{subagent.name}

{getModelDisplay(subagent.model)} {subagent.description || '-'}
))} {subagents.length === 0 && (

{t('noSubagents', 'No subagents configured')}

)} )}
{ setIsDialogOpen(open); if (!open) { setEditingSubagent(null); setNewSubagent({ name: '', description: '', model: '', instructions: '', status: 'active' }); } }}> {editingSubagent ? t('editSubagent', 'Edit Subagent') : t('addSubagent', 'Add Subagent')}
setNewSubagent({...newSubagent, name: e.target.value})} className="rounded-lg border-border h-10" />