import { useEffect, useRef, useState, type ReactNode } from "react"; import type { Agent } from "@paperclipai/shared"; import { AgentIcon } from "@/components/AgentIconPicker"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog"; import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from "@/components/ui/command"; export interface AgentChatPickerProps { agents: Agent[]; open: boolean; onOpenChange: (open: boolean) => void; onSelect: (agent: Agent, signal?: AbortSignal) => void | Promise; loading?: boolean; error?: Error | null; onRetry?: () => void; existingChatAgentIds?: readonly string[]; renderAgentIcon?: (agent: Agent) => ReactNode; } export function AgentChatPicker({ open, onOpenChange, ...props }: AgentChatPickerProps) { return (
Chat with an agent {props.existingChatAgentIds &&

One conversation per agent. Pick up where you left off.

}
{/* The dialog unmounts its content on close, so each search starts empty. */} onOpenChange(false)} />
); } function AgentChatPickerResults({ agents, onSelect, onComplete, loading, error, onRetry, existingChatAgentIds, renderAgentIcon }: Omit & { onComplete: () => void }) { const mounted = useRef(false); const selection = useRef(null); useEffect(() => { mounted.current = true; return () => { mounted.current = false; selection.current?.abort(); }; }, []); const [search, setSearch] = useState(""); const [openingId, setOpeningId] = useState(null); const [selectionError, setSelectionError] = useState(null); async function selectAgent(agent: Agent) { if (openingId) return; setOpeningId(agent.id); setSelectionError(null); const request = new AbortController(); selection.current = request; try { await onSelect(agent, request.signal); if (mounted.current) onComplete(); } catch (error) { setSelectionError(error instanceof Error ? error.message : "Couldn’t open chat. Try again."); } finally { setOpeningId(null); } } return ( {selectionError &&

{selectionError}

} {openingId &&

Opening conversation…

} {error ? (

Couldn’t load agents. Try again.

{onRetry && }
) : loading ? (

Loading agents…

) : (
{agents.length ? `No agents match “${search}”` : "No agents yet."} {agents.length ? <> Try another name or role. : Create an agent from the Agents page to start chatting.}
{agents.map((agent) => ( { void selectAgent(agent); }} disabled={openingId !== null} className="gap-3 px-3 py-3" > {renderAgentIcon ? renderAgentIcon(agent) : } {agent.name} {agent.title ?? agent.role} {existingChatAgentIds && {existingChatAgentIds.includes(agent.id) ? "Open chat" : "New chat"}} {agent.status === "paused" && Paused} {agent.status === "terminated" && Terminated} {agent.status === "pending_approval" && Awaiting approval} ))}
)}
); }