import React, { useState, useEffect } from "react"; import { motion, AnimatePresence } from "framer-motion"; import { Plus, Edit, Trash2, Play, Bot, Brain, Code, Sparkles, Zap, Cpu, Rocket, Shield, Terminal, ArrowLeft, History } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardFooter } from "@/components/ui/card"; import { api, type Agent, type AgentRunWithMetrics } from "@/lib/api"; import { cn } from "@/lib/utils"; import { Toast, ToastContainer } from "@/components/ui/toast"; import { CreateAgent } from "./CreateAgent"; import { AgentExecution } from "./AgentExecution"; import { AgentRunsList } from "./AgentRunsList"; import { AgentRunView } from "./AgentRunView"; import { RunningSessionsView } from "./RunningSessionsView"; interface CCAgentsProps { /** * Callback to go back to the main view */ onBack: () => void; /** * Optional className for styling */ className?: string; } // Available icons for agents export const AGENT_ICONS = { bot: Bot, brain: Brain, code: Code, sparkles: Sparkles, zap: Zap, cpu: Cpu, rocket: Rocket, shield: Shield, terminal: Terminal, }; export type AgentIconName = keyof typeof AGENT_ICONS; /** * CCAgents component for managing Claude Code agents * * @example * setView('home')} /> */ export const CCAgents: React.FC = ({ onBack, className }) => { const [agents, setAgents] = useState([]); const [runs, setRuns] = useState([]); const [loading, setLoading] = useState(true); const [runsLoading, setRunsLoading] = useState(false); const [error, setError] = useState(null); const [toast, setToast] = useState<{ message: string; type: "success" | "error" } | null>(null); const [currentPage, setCurrentPage] = useState(1); const [view, setView] = useState<"list" | "create" | "edit" | "execute" | "viewRun">("list"); const [activeTab, setActiveTab] = useState<"agents" | "running">("agents"); const [selectedAgent, setSelectedAgent] = useState(null); const [selectedRunId, setSelectedRunId] = useState(null); const AGENTS_PER_PAGE = 9; // 3x3 grid useEffect(() => { loadAgents(); loadRuns(); }, []); const loadAgents = async () => { try { setLoading(true); setError(null); const agentsList = await api.listAgents(); setAgents(agentsList); } catch (err) { console.error("Failed to load agents:", err); setError("Failed to load agents"); setToast({ message: "Failed to load agents", type: "error" }); } finally { setLoading(false); } }; const loadRuns = async () => { try { setRunsLoading(true); const runsList = await api.listAgentRuns(); setRuns(runsList); } catch (err) { console.error("Failed to load runs:", err); } finally { setRunsLoading(false); } }; const handleDeleteAgent = async (id: number) => { if (!confirm("Are you sure you want to delete this agent?")) return; try { await api.deleteAgent(id); setToast({ message: "Agent deleted successfully", type: "success" }); await loadAgents(); await loadRuns(); // Reload runs as they might be affected } catch (err) { console.error("Failed to delete agent:", err); setToast({ message: "Failed to delete agent", type: "error" }); } }; const handleEditAgent = (agent: Agent) => { setSelectedAgent(agent); setView("edit"); }; const handleExecuteAgent = (agent: Agent) => { setSelectedAgent(agent); setView("execute"); }; const handleAgentCreated = async () => { setView("list"); await loadAgents(); setToast({ message: "Agent created successfully", type: "success" }); }; const handleAgentUpdated = async () => { setView("list"); await loadAgents(); setToast({ message: "Agent updated successfully", type: "success" }); }; const handleRunClick = (run: AgentRunWithMetrics) => { if (run.id) { setSelectedRunId(run.id); setView("viewRun"); } }; const handleExecutionComplete = async () => { // Reload runs when returning from execution await loadRuns(); }; // Pagination calculations const totalPages = Math.ceil(agents.length / AGENTS_PER_PAGE); const startIndex = (currentPage - 1) * AGENTS_PER_PAGE; const paginatedAgents = agents.slice(startIndex, startIndex + AGENTS_PER_PAGE); const renderIcon = (iconName: string) => { const Icon = AGENT_ICONS[iconName as AgentIconName] || Bot; return ; }; if (view === "create") { return ( setView("list")} onAgentCreated={handleAgentCreated} /> ); } if (view === "edit" && selectedAgent) { return ( setView("list")} onAgentCreated={handleAgentUpdated} /> ); } if (view === "execute" && selectedAgent) { return ( { setView("list"); handleExecutionComplete(); }} /> ); } if (view === "viewRun" && selectedRunId) { return ( setView("list")} /> ); } return (
{/* Header */}

CC Agents

Manage your Claude Code agents

{/* Error display */} {error && ( {error} )} {/* Tab Navigation */}
{/* Tab Content */}
{activeTab === "agents" && ( {/* Agents Grid */}
{loading ? (
) : agents.length === 0 ? (

No agents yet

Create your first CC Agent to get started

) : ( <>
{paginatedAgents.map((agent, index) => (
{renderIcon(agent.icon)}

{agent.name}

Created: {new Date(agent.created_at).toLocaleDateString()}

))}
{/* Pagination */} {totalPages > 1 && (
Page {currentPage} of {totalPages}
)} )}
{/* Execution History */} {!loading && agents.length > 0 && (

Recent Executions

{runsLoading ? (
) : ( )}
)}
)} {activeTab === "running" && ( )}
{/* Toast Notification */} {toast && ( setToast(null)} /> )}
); };