import { useEffect, useMemo, useRef, useState } from 'react'; import { useT } from '../i18n'; import { AgentIcon } from './AgentIcon'; import { Icon } from './Icon'; import type { AgentInfo, AppConfig, ExecMode } from '../types'; interface Props { config: AppConfig; agents: AgentInfo[]; daemonLive: boolean; onModeChange: (mode: ExecMode) => void; onAgentChange: (id: string) => void; onOpenSettings: () => void; onRefreshAgents: () => void; onBack?: () => void; } /** * Compact avatar at the right of the project topbar. Click opens a dropdown * with current execution mode, the agent picker (when in daemon mode), and * a Settings entry — replaces the wide AgentPicker + env-pill row. */ export function AvatarMenu({ config, agents, daemonLive, onModeChange, onAgentChange, onOpenSettings, onRefreshAgents, onBack, }: Props) { const t = useT(); const [open, setOpen] = useState(false); const wrapRef = useRef(null); useEffect(() => { if (!open) return; const onClick = (e: MouseEvent) => { if (!wrapRef.current) return; if (!wrapRef.current.contains(e.target as Node)) setOpen(false); }; const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') setOpen(false); }; document.addEventListener('mousedown', onClick); document.addEventListener('keydown', onKey); return () => { document.removeEventListener('mousedown', onClick); document.removeEventListener('keydown', onKey); }; }, [open]); const currentAgent = useMemo( () => agents.find((a) => a.id === config.agentId) ?? null, [agents, config.agentId], ); const installedAgents = agents.filter((a) => a.available); return (
{open ? (
{config.mode === 'daemon' ? t('avatar.localCli') : t('avatar.anthropicApi')} {config.mode === 'api' ? safeHost(config.baseUrl) : currentAgent ? `${currentAgent.name}${currentAgent.version ? ` · ${currentAgent.version}` : ''}` : t('avatar.noAgentSelected')}
{config.mode === 'daemon' && installedAgents.length > 0 ? ( <>
{t('avatar.codeAgent')}
{installedAgents.map((a) => ( ))} ) : null}
{onBack ? ( ) : null}
) : null}
); } function safeHost(url: string): string { try { return new URL(url).host; } catch { return url; } }