import { useMemo, useState } from "react"; import { NavLink, useLocation } from "@/lib/router"; import { useQuery } from "@tanstack/react-query"; import { ChevronRight, Plus } from "lucide-react"; import { useCompany } from "../context/CompanyContext"; import { useDialog } from "../context/DialogContext"; import { useSidebar } from "../context/SidebarContext"; import { agentsApi } from "../api/agents"; import { authApi } from "../api/auth"; import { heartbeatsApi } from "../api/heartbeats"; import { queryKeys } from "../lib/queryKeys"; import { cn, agentRouteRef, agentUrl } from "../lib/utils"; import { useAgentOrder } from "../hooks/useAgentOrder"; import { AgentIcon } from "./AgentIconPicker"; import { BudgetSidebarMarker } from "./BudgetSidebarMarker"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible"; import type { Agent } from "@paperclipai/shared"; export function SidebarAgents() { const [open, setOpen] = useState(true); const { selectedCompanyId } = useCompany(); const { openNewAgent } = useDialog(); const { isMobile, setSidebarOpen } = useSidebar(); const location = useLocation(); const { data: agents } = useQuery({ queryKey: queryKeys.agents.list(selectedCompanyId!), queryFn: () => agentsApi.list(selectedCompanyId!), enabled: !!selectedCompanyId, }); const { data: session } = useQuery({ queryKey: queryKeys.auth.session, queryFn: () => authApi.getSession(), }); const { data: liveRuns } = useQuery({ queryKey: queryKeys.liveRuns(selectedCompanyId!), queryFn: () => heartbeatsApi.liveRunsForCompany(selectedCompanyId!), enabled: !!selectedCompanyId, refetchInterval: 10_000, }); const liveCountByAgent = useMemo(() => { const counts = new Map(); for (const run of liveRuns ?? []) { counts.set(run.agentId, (counts.get(run.agentId) ?? 0) + 1); } return counts; }, [liveRuns]); const visibleAgents = useMemo(() => { const filtered = (agents ?? []).filter( (a: Agent) => a.status !== "terminated" ); return filtered; }, [agents]); const currentUserId = session?.user?.id ?? session?.session?.userId ?? null; const { orderedAgents } = useAgentOrder({ agents: visibleAgents, companyId: selectedCompanyId, userId: currentUserId, }); const agentMatch = location.pathname.match(/^\/(?:[^/]+\/)?agents\/([^/]+)(?:\/([^/]+))?/); const activeAgentId = agentMatch?.[1] ?? null; const activeTab = agentMatch?.[2] ?? null; return (
Agents
{orderedAgents.map((agent: Agent) => { const runCount = liveCountByAgent.get(agent.id) ?? 0; return ( { if (isMobile) setSidebarOpen(false); }} className={cn( "flex items-center gap-2.5 px-3 py-1.5 text-[13px] font-medium transition-colors", activeAgentId === agentRouteRef(agent) ? "bg-accent text-foreground" : "text-foreground/80 hover:bg-accent/50 hover:text-foreground" )} > {agent.name} {(agent.pauseReason === "budget" || runCount > 0) && ( {agent.pauseReason === "budget" ? ( ) : null} {runCount > 0 ? ( ) : null} {runCount > 0 ? ( {runCount} live ) : null} )} ); })}
); }