import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { TeamModelSelector } from '@renderer/components/team/dialogs/TeamModelSelector'; import { RoleSelect } from '@renderer/components/team/RoleSelect'; import { Button } from '@renderer/components/ui/button'; import { Input } from '@renderer/components/ui/input'; import { MentionableTextarea } from '@renderer/components/ui/MentionableTextarea'; import { getTeamColorSet } from '@renderer/constants/teamColors'; import { useDraftPersistence } from '@renderer/hooks/useDraftPersistence'; import { useFileListCacheWarmer } from '@renderer/hooks/useFileListCacheWarmer'; import { reconcileChips, removeChipTokenFromText } from '@renderer/utils/chipUtils'; import { getMemberColorByName } from '@shared/constants/memberColors'; import { ChevronDown, ChevronRight, Info } from 'lucide-react'; import type { MemberDraft } from './membersEditorTypes'; import type { InlineChip } from '@renderer/types/inlineChip'; import type { MentionSuggestion } from '@renderer/types/mention'; interface MemberDraftRowProps { member: MemberDraft; index: number; nameError: string | null; onNameChange: (id: string, name: string) => void; onRoleChange: (id: string, roleSelection: string) => void; onCustomRoleChange: (id: string, customRole: string) => void; onRemove: (id: string) => void; showWorkflow?: boolean; onWorkflowChange?: (id: string, workflow: string) => void; onWorkflowChipsChange?: (id: string, chips: InlineChip[]) => void; draftKeyPrefix?: string; projectPath?: string | null; mentionSuggestions?: MentionSuggestion[]; } export const MemberDraftRow = ({ member, index, nameError, onNameChange, onRoleChange, onCustomRoleChange, onRemove, showWorkflow = false, onWorkflowChange, onWorkflowChipsChange, draftKeyPrefix, projectPath, mentionSuggestions = [], }: MemberDraftRowProps): React.JSX.Element => { const memberColorSet = getTeamColorSet( getMemberColorByName(member.name.trim() || `member-${index}`) ); const [workflowExpanded, setWorkflowExpanded] = useState(false); const [modelExpanded, setModelExpanded] = useState(false); // Pre-warm file list cache when workflow section is expanded useFileListCacheWarmer(workflowExpanded && projectPath ? projectPath : null); const draftKey = draftKeyPrefix && (member.name.trim() || member.id) ? `${draftKeyPrefix}:workflow:${member.name.trim() || member.id}` : null; const workflowDraft = useDraftPersistence({ key: draftKey ?? `workflow:${member.id}`, initialValue: member.workflow?.trim() ? member.workflow : undefined, enabled: !!draftKey, }); const chips = useMemo(() => member.workflowChips ?? [], [member.workflowChips]); const handleWorkflowChange = useCallback( (v: string) => { const reconciled = reconcileChips(chips, v); if (reconciled.length !== chips.length) { onWorkflowChipsChange?.(member.id, reconciled); } workflowDraft.setValue(v); onWorkflowChange?.(member.id, v); }, [member.id, chips, onWorkflowChange, onWorkflowChipsChange, workflowDraft] ); const handleFileChipInsert = useCallback( (chip: InlineChip) => { onWorkflowChipsChange?.(member.id, [...chips, chip]); }, [member.id, chips, onWorkflowChipsChange] ); const handleChipRemove = useCallback( (chipId: string) => { const chip = chips.find((c) => c.id === chipId); if (!chip) return; const newChips = chips.filter((c) => c.id !== chipId); const newValue = removeChipTokenFromText(workflowDraft.value, chip); onWorkflowChipsChange?.(member.id, newChips); workflowDraft.setValue(newValue); onWorkflowChange?.(member.id, newValue); }, [chips, member.id, onWorkflowChange, onWorkflowChipsChange, workflowDraft] ); useEffect(() => { if ( onWorkflowChange && workflowDraft.value && workflowDraft.value !== (member.workflow ?? '') ) { onWorkflowChange(member.id, workflowDraft.value); } }, [workflowDraft.value, member.id, member.workflow, onWorkflowChange]); const suggestionsExcludingSelf = mentionSuggestions.filter( (s) => s.name.toLowerCase() !== member.name.trim().toLowerCase() ); return (
onNameChange(member.id, event.target.value)} placeholder="member-name" style={ member.name.trim() ? { color: memberColorSet.text, } : undefined } /> {nameError ?

{nameError}

: null}
onRoleChange(member.id, roleSelection)} customRole={member.customRole} onCustomRoleChange={(customRole) => onCustomRoleChange(member.id, customRole)} triggerClassName="h-8 text-xs" inputClassName="h-8 text-xs" />
{showWorkflow && onWorkflowChange ? ( ) : null}
{showWorkflow && onWorkflowChange && workflowExpanded ? (
Draft saved ) : null } />
) : null} {modelExpanded && (
{}} />

Claude Code doesn't support per-member model selection yet — all teammates inherit the team launch model. We plan to solve this via a local proxy.

)}
); };