import { useEffect, useState } from 'react'; import { Check, ChevronDown } from 'lucide-react'; import { toast } from 'sonner'; import { api } from '@/api/client'; import type { Agent, AgentParseError } from '@/api/types'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; interface Props { projectId: string; value: string | null; onChange: (agentId: string | null) => void | Promise; } export function AgentPicker({ projectId, value, onChange }: Props) { const [agents, setAgents] = useState(null); const [parseErrors, setParseErrors] = useState([]); const [error, setError] = useState(null); const [open, setOpen] = useState(false); // v1.8.1: per-agent parse errors are non-blocking. Silent if any agents // loaded successfully; a gray warning toast fires only when EVERY agent // in AGENTS.md failed to parse. Server logs a console.warn either way. useEffect(() => { let cancelled = false; setAgents(null); setParseErrors([]); setError(null); api.agents .list(projectId) .then((res) => { if (cancelled) return; setAgents(res.agents); setParseErrors(res.errors); if (res.errors.length > 0 && res.agents.length === 0) { toast.warning( `AGENTS.md: ${res.errors.length} agent${res.errors.length === 1 ? '' : 's'} failed to parse, none loaded`, ); } }) .catch((err) => { if (cancelled) return; setError(err instanceof Error ? err.message : 'failed to load agents'); }); return () => { cancelled = true; }; }, [projectId]); const selectedAgent = agents?.find((a) => a.id === value) ?? null; const triggerLabel = value === null ? 'No agent' : selectedAgent?.name ?? value; return ( {error && (
{error}
)} {agents === null && !error && (
Loading…
)} {agents !== null && ( <> void onChange(null)} className="text-xs" > No agent {agents.length > 0 && } {agents.map((a) => ( void onChange(a.id)} className="text-xs flex-col items-start gap-0.5" >
{a.name}
{a.description && ( {a.description} )}
))} {parseErrors.length > 0 && (
`${e.agent_name}: ${e.reason}`).join('\n')} > {parseErrors.length} agent{parseErrors.length === 1 ? '' : 's'} skipped
)} )}
); }