import { useMemo, useState } from 'react'; import { Badge } from '@renderer/components/ui/badge'; import { DialogDescription, DialogTitle } from '@renderer/components/ui/dialog'; import { getTeamColorSet } from '@renderer/constants/teamColors'; import { useStore } from '@renderer/store'; import { selectResolvedMembersForTeamName } from '@renderer/store/slices/teamSlice'; import { formatAgentRole } from '@renderer/utils/formatAgentRole'; import { agentAvatarUrl, buildMemberAvatarMap, buildMemberLaunchPresentation, displayMemberName, } from '@renderer/utils/memberHelpers'; import { isLeadMember } from '@shared/utils/leadDetection'; import { Pencil } from 'lucide-react'; import { MemberPresenceDot } from './MemberPresenceDot'; import { MemberRoleEditor } from './MemberRoleEditor'; import type { LeadActivityState, MemberLaunchState, MemberSpawnLivenessSource, MemberSpawnStatus, ResolvedTeamMember, TeamAgentRuntimeEntry, } from '@shared/types'; interface MemberDetailHeaderProps { member: ResolvedTeamMember; runtimeSummary?: string; runtimeEntry?: TeamAgentRuntimeEntry; isTeamAlive?: boolean; isTeamProvisioning?: boolean; leadActivity?: LeadActivityState; spawnStatus?: MemberSpawnStatus; spawnLaunchState?: MemberLaunchState; spawnLivenessSource?: MemberSpawnLivenessSource; spawnRuntimeAlive?: boolean; spawnBootstrapConfirmed?: boolean; spawnBootstrapStalled?: boolean; isLaunchSettling?: boolean; onUpdateRole?: (newRole: string | undefined) => Promise | void; updatingRole?: boolean; } export const MemberDetailHeader = ({ member, runtimeSummary, runtimeEntry, isTeamAlive, isTeamProvisioning, leadActivity, spawnStatus, spawnLaunchState, spawnLivenessSource, spawnRuntimeAlive, spawnBootstrapConfirmed, spawnBootstrapStalled, isLaunchSettling, onUpdateRole, updatingRole, }: MemberDetailHeaderProps): React.JSX.Element => { const [editing, setEditing] = useState(false); const selectedTeamName = useStore((s) => s.selectedTeamName); const teamMembers = useStore((s) => selectedTeamName ? selectResolvedMembersForTeamName(s, selectedTeamName) : [] ); const avatarMap = useMemo(() => buildMemberAvatarMap(teamMembers), [teamMembers]); // NOTE: lead context display disabled — usage formula is inaccurate // const teamName = useStore((s) => s.selectedTeamName); // const leadContext = useStore((s) => // member.agentType === 'team-lead' && teamName ? s.leadContextByTeam[teamName] : undefined // ); const colors = getTeamColorSet(member.color ?? ''); const role = member.role || formatAgentRole(member.agentType); const launchPresentation = buildMemberLaunchPresentation({ member, spawnStatus, spawnLaunchState, spawnLivenessSource, spawnRuntimeAlive, spawnBootstrapConfirmed, spawnBootstrapStalled, runtimeEntry, runtimeAdvisory: member.runtimeAdvisory, isLaunchSettling, isTeamAlive, isTeamProvisioning, leadActivity, }); const presenceLabel = launchPresentation.presenceLabel; const launchVisualState = launchPresentation.launchVisualState; const launchStatusLabel = launchPresentation.launchStatusLabel; const dotClass = launchPresentation.dotClass; const runtimeAdvisoryLabel = launchPresentation.runtimeAdvisoryLabel; const runtimeAdvisoryTitle = launchPresentation.runtimeAdvisoryTitle; const runtimeAdvisoryTone = launchPresentation.runtimeAdvisoryTone; const badgeLabel = runtimeAdvisoryTone === 'error' && runtimeAdvisoryLabel ? runtimeAdvisoryLabel : launchVisualState === 'bootstrap_stalled' || launchVisualState === 'runtime_pending' || launchVisualState === 'permission_pending' || launchVisualState === 'shell_only' || launchVisualState === 'runtime_candidate' || launchVisualState === 'registered_only' || launchVisualState === 'stale_runtime' ? (launchStatusLabel ?? presenceLabel) : presenceLabel; const canEditRole = !isLeadMember(member) && !member.removedAt && !isTeamProvisioning && !!onUpdateRole; return (
{member.name}
{displayMemberName(member.name)}
{editing ? ( { try { await onUpdateRole?.(newRole); setEditing(false); } catch { // stay in editing mode so user can retry } }} onCancel={() => setEditing(false)} /> ) : ( <> {role || 'No role'} {canEditRole && ( )} )} {!editing && ( <> {badgeLabel} {/* NOTE: lead context token display disabled — usage formula is inaccurate */} )} {!editing && runtimeSummary ? (
{runtimeSummary}
) : null}
); };