import * as React from 'react'; import { useNavigate } from 'react-router-dom'; import { Check, ChevronDown, Plus, Search, SquareArrowOutUpRight } from 'lucide-react'; import { cn } from '@/lib/utils'; import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; import { searchAgents } from '@/lib/agents/registry'; import { agentIconFor } from '@/components/agents/icons'; import OwliverAvatar from '@/components/krow/OwliverAvatar'; import { useActiveAgent } from './AgentContext'; /** * The agent switcher, inside Owliver's own header. * * Designed with high-density Krow Control Tower aesthetics: clean popover * geometry, smooth row hover/active states, and legible status indicators. */ /** The avatar for the primary agent; a lucide glyph for the rest. */ function AgentGlyph({ agent, className = 'h-7 w-7' }) { const Icon = agentIconFor(agent?.icon); if (!Icon) return ; return ( ); } /** The label a constrained agent carries, in the switcher and in the header. */ function ConstrainedTag({ className = '' }) { return ( Constrained ); } /** One row in the list. */ function AgentRow({ agent, active, covers, onSelect }) { return ( ); } export function AgentSwitcher({ page }) { const navigate = useNavigate(); const { agents, agent, covers, select, coversPage } = useActiveAgent(); const [open, setOpen] = React.useState(false); const [query, setQuery] = React.useState(''); const listRef = React.useRef(null); React.useEffect(() => { if (!open) setQuery(''); }, [open]); const matches = React.useMemo(() => { const found = searchAgents(agents, query); return [...found].sort((a, b) => Number(coversPage(b)) - Number(coversPage(a))); }, [agents, query, coversPage]); const choose = (id) => { select(id); setOpen(false); }; const onListKeyDown = (event) => { const step = event.key === 'ArrowDown' ? 1 : event.key === 'ArrowUp' ? -1 : 0; if (!step) return; const rows = [...(listRef.current?.querySelectorAll('[role="option"]') ?? [])]; if (!rows.length) return; event.preventDefault(); const at = rows.indexOf(document.activeElement); rows[Math.max(0, Math.min(rows.length - 1, (at === -1 ? 0 : at + step)))]?.focus(); }; if (!agent) { return ( <>

Owliver

{page}

); } return (

Switch agent

Choose an agent to focus Owliver's scope on this page.

{matches.map((candidate) => ( ))} {!matches.length && (

No agents match that.

)}
); } export default AgentSwitcher;