/* ┌──────────────────────────────────────────────────────────────────────────────┐ │ @author: Davidson Gomes │ │ @file: /app/agents/AgentCard.tsx │ │ Developed by: Davidson Gomes │ │ Creation date: May 13, 2025 │ │ Contact: contato@evolution-api.com │ ├──────────────────────────────────────────────────────────────────────────────┤ │ @copyright © Evolution API 2025. All rights reserved. │ │ Licensed under the Apache License, Version 2.0 │ │ │ │ You may not use this file except in compliance with the License. │ │ You may obtain a copy of the License at │ │ │ │ http://www.apache.org/licenses/LICENSE-2.0 │ │ │ │ Unless required by applicable law or agreed to in writing, software │ │ distributed under the License is distributed on an "AS IS" BASIS, │ │ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │ │ See the License for the specific language governing permissions and │ │ limitations under the License. │ ├──────────────────────────────────────────────────────────────────────────────┤ │ @important │ │ For any future changes to the code in this file, it is recommended to │ │ include, together with the modification, the information of the developer │ │ who changed it and the date of modification. │ └──────────────────────────────────────────────────────────────────────────────┘ */ "use client"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Folder } from "@/services/agentService"; import { Agent, AgentType } from "@/types/agent"; import { MCPServer } from "@/types/mcpServer"; import { ArrowRight, Bot, BookOpenCheck, ChevronDown, ChevronUp, Code, ExternalLink, GitBranch, MoveRight, Pencil, RefreshCw, Settings, Share2, Trash2, Workflow, TextSelect, Download, FlaskConical, } from "lucide-react"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { cn } from "@/lib/utils"; import { exportAsJson } from "@/lib/utils"; interface AgentCardProps { agent: Agent; onEdit: (agent: Agent) => void; onDelete: (agent: Agent) => void; onMove: (agent: Agent) => void; onShare?: (agent: Agent) => void; onWorkflow?: (agentId: string) => void; availableMCPs?: MCPServer[]; getApiKeyNameById?: (id: string | undefined) => string | null; getAgentNameById?: (id: string) => string; folders?: Folder[]; agents: Agent[]; } export function AgentCard({ agent, onEdit, onDelete, onMove, onShare, onWorkflow, availableMCPs = [], getApiKeyNameById = () => null, getAgentNameById = (id) => id, folders = [], agents, }: AgentCardProps) { const [expanded, setExpanded] = useState(false); const router = useRouter(); const getAgentTypeInfo = (type: AgentType) => { const types: Record< string, { label: string; icon: React.ElementType; color: string; bgColor: string; badgeClass: string; } > = { llm: { label: "LLM Agent", icon: Code, color: "#00cc7d", bgColor: "bg-green-500/10", badgeClass: "bg-green-900/30 text-green-400 border-green-600/30 hover:bg-green-900/40", }, a2a: { label: "A2A Agent", icon: ExternalLink, color: "#6366f1", bgColor: "bg-indigo-500/10", badgeClass: "bg-indigo-900/30 text-indigo-400 border-indigo-600/30 hover:bg-indigo-900/40", }, sequential: { label: "Sequential Agent", icon: ArrowRight, color: "#f59e0b", bgColor: "bg-yellow-500/10", badgeClass: "bg-yellow-900/30 text-yellow-400 border-yellow-600/30 hover:bg-yellow-900/40", }, parallel: { label: "Parallel Agent", icon: GitBranch, color: "#8b5cf6", bgColor: "bg-purple-500/10", badgeClass: "bg-purple-900/30 text-purple-400 border-purple-600/30 hover:bg-purple-900/40", }, loop: { label: "Loop Agent", icon: RefreshCw, color: "#ec4899", bgColor: "bg-pink-500/10", badgeClass: "bg-orange-900/30 text-orange-400 border-orange-600/30 hover:bg-orange-900/40", }, workflow: { label: "Workflow Agent", icon: Workflow, color: "#3b82f6", bgColor: "bg-blue-500/10", badgeClass: "bg-blue-900/30 text-blue-400 border-blue-700/40 hover:bg-blue-900/40", }, task: { label: "Task Agent", icon: BookOpenCheck, color: "#ef4444", bgColor: "bg-red-500/10", badgeClass: "bg-red-900/30 text-red-400 border-red-600/30 hover:bg-red-900/40", }, }; return ( types[type] || { label: type, icon: Bot, color: "#94a3b8", bgColor: "bg-slate-500/10", badgeClass: "bg-slate-900/30 text-slate-400 border-slate-600/30 hover:bg-slate-900/40", } ); }; const getAgentTypeIcon = (type: AgentType) => { const typeInfo = getAgentTypeInfo(type); const IconComponent = typeInfo.icon; return ( ); }; const getAgentTypeName = (type: AgentType) => { return getAgentTypeInfo(type).label; }; const getAgentTypeBgColor = (type: AgentType) => { return getAgentTypeInfo(type).bgColor; }; const getAgentTypeBadgeClass = (type: AgentType) => { return getAgentTypeInfo(type).badgeClass; }; const getFolderNameById = (id: string) => { const folder = folders?.find((f) => f.id === id); return folder?.name || id; }; const getTotalTools = () => { if (agent.type === "llm" && agent.config?.mcp_servers) { return agent.config.mcp_servers.reduce( (total, mcp) => total + (mcp.tools?.length || 0), 0 ); } return 0; }; const getCreatedAtFormatted = () => { return new Date(agent.created_at).toLocaleDateString(); }; // Function to export the agent as JSON const handleExportAgent = () => { try { exportAsJson( agent, `agent-${agent.name .replace(/\s+/g, "-") .toLowerCase()}-${agent.id.substring(0, 8)}`, true, agents ); } catch (error) { console.error("Error exporting agent:", error); } }; // Function to test the A2A agent in the lab const handleTestA2A = () => { // Use the agent card URL as base for A2A tests const agentUrl = agent.agent_card_url?.replace( "/.well-known/agent.json", "" ); // Use the API key directly from the agent config const apiKey = agent.config?.api_key; // Build the URL with parameters for the lab tests const params = new URLSearchParams(); if (agentUrl) { params.set("agent_url", agentUrl); } if (apiKey) { params.set("api_key", apiKey); } // Redirect to the lab tests in the "lab" tab const testUrl = `/documentation?${params.toString()}#lab`; router.push(testUrl); }; return (
{getAgentTypeIcon(agent.type)}

{agent.name}

{getAgentTypeName(agent.type)}

{agent.description && agent.description.length > 100 ? `${agent.description.substring(0, 100)}...` : agent.description}

Model: {agent.type === "llm" ? agent.model : "N/A"}
{expanded && (
{agent.folder_id && (
Folder: {getFolderNameById(agent.folder_id)}
)} {agent.type === "llm" && agent.api_key_id && (
API Key: {getApiKeyNameById(agent.api_key_id)}
)} {getTotalTools() > 0 && (
Tools: {getTotalTools()}
)} {agent.config?.sub_agents && agent.config.sub_agents.length > 0 && (
Sub-agents: {agent.config.sub_agents.length}
)} {agent.type === "workflow" && agent.config?.workflow && (
Elements: {agent.config.workflow.nodes?.length || 0} nodes,{" "} {agent.config.workflow.edges?.length || 0} connections
)}
Created at: {getCreatedAtFormatted()}
ID: {agent.id}
)}
Test A2A onEdit(agent)} > Edit Agent onMove(agent)} > Move Agent {onWorkflow && agent.type === "workflow" && ( onWorkflow(agent.id)} > Open Workflow )} Export as JSON {onShare && ( onShare(agent)} > Share Agent )} onDelete(agent)} > Delete Agent
Agent Card
); }