import { useState, useMemo } from "react"; import { useQuery } from "@tanstack/react-query"; import { useNavigate } from "@/lib/router"; import { useDialog } from "../context/DialogContext"; import { useCompany } from "../context/CompanyContext"; import { agentsApi } from "../api/agents"; import { adaptersApi } from "../api/adapters"; import { queryKeys } from "@/lib/queryKeys"; import { Dialog, DialogContent, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { ArrowLeft, Bot, } from "lucide-react"; import { cn } from "@/lib/utils"; import { listUIAdapters } from "../adapters"; import { getAdapterDisplay } from "../adapters/adapter-display-registry"; import { useDisabledAdaptersSync } from "../adapters/use-disabled-adapters"; /** * Adapter types that are suitable for agent creation (excludes internal * system adapters like "process" and "http"). */ const SYSTEM_ADAPTER_TYPES = new Set(["process", "http"]); function isAgentAdapterType(type: string): boolean { return !SYSTEM_ADAPTER_TYPES.has(type); } export function NewAgentDialog() { const { newAgentOpen, closeNewAgent, openNewIssue } = useDialog(); const { selectedCompanyId } = useCompany(); const navigate = useNavigate(); const [showAdvancedCards, setShowAdvancedCards] = useState(false); const disabledTypes = useDisabledAdaptersSync(); // Fetch registered adapters from server (syncs disabled store + provides data) const { data: serverAdapters } = useQuery({ queryKey: queryKeys.adapters.all, queryFn: () => adaptersApi.list(), staleTime: 5 * 60 * 1000, }); // Fetch existing agents for the "Ask CEO" flow const { data: agents } = useQuery({ queryKey: queryKeys.agents.list(selectedCompanyId!), queryFn: () => agentsApi.list(selectedCompanyId!), enabled: !!selectedCompanyId && newAgentOpen, }); const ceoAgent = (agents ?? []).find((a) => a.role === "ceo"); // Build the adapter grid from the UI registry merged with display metadata. // This automatically includes external/plugin adapters. const adapterGrid = useMemo(() => { const registered = listUIAdapters() .filter((a) => isAgentAdapterType(a.type) && !disabledTypes.has(a.type)); // Sort: recommended first, then alphabetical return registered .map((a) => { const display = getAdapterDisplay(a.type); return { value: a.type, label: display.label, desc: display.description, icon: display.icon, recommended: display.recommended, comingSoon: display.comingSoon, disabledLabel: display.disabledLabel, }; }) .sort((a, b) => { if (a.recommended && !b.recommended) return -1; if (!a.recommended && b.recommended) return 1; return a.label.localeCompare(b.label); }); }, [disabledTypes, serverAdapters]); function handleAskCeo() { closeNewAgent(); openNewIssue({ assigneeAgentId: ceoAgent?.id, title: "Create a new agent", description: "(type in what kind of agent you want here)", }); } function handleAdvancedConfig() { setShowAdvancedCards(true); } function handleAdvancedAdapterPick(adapterType: string) { closeNewAgent(); setShowAdvancedCards(false); navigate(`/agents/new?adapterType=${encodeURIComponent(adapterType)}`); } return ( { if (!open) { setShowAdvancedCards(false); closeNewAgent(); } }} > {/* Header */}
Add a new agent
{!showAdvancedCards ? ( <> {/* Recommendation */}

We recommend letting your CEO handle agent setup — they know the org structure and can configure reporting, permissions, and adapters.

{/* Advanced link */}
) : ( <>

Choose your adapter type for advanced setup.

{adapterGrid.map((opt) => ( ))}
)}
); }