import { useState, useEffect } from 'react'; import { useAgentStore } from '../store/agentStore'; import { useConnectionStore } from '../store/connectionStore'; import { useConfigStore } from '../store/configStore'; import { toChatAgent, useChatStore } from '../store/chatStore'; import { Bot, Plus, X, Globe, Cat, Search, BarChart2, Sparkles } from 'lucide-react'; import { AgentOnboardingWizard } from './AgentOnboardingWizard'; import type { Clone } from '../store/agentStore'; export function CloneManager() { const clones = useAgentStore((s) => s.clones); const loadClones = useAgentStore((s) => s.loadClones); const deleteClone = useAgentStore((s) => s.deleteClone); const connectionState = useConnectionStore((s) => s.connectionState); const quickConfig = useConfigStore((s) => s.quickConfig); const { agents, currentAgent, setCurrentAgent } = useChatStore(); const [showWizard, setShowWizard] = useState(false); const connected = connectionState === 'connected'; useEffect(() => { if (connected) { loadClones(); } }, [connected, loadClones]); const handleDelete = async (id: string) => { if (confirm('确定删除该分身?')) { await deleteClone(id); } }; const handleWizardSuccess = (clone: Clone) => { setCurrentAgent(toChatAgent(clone)); setShowWizard(false); }; // Merge gateway clones with local agents for display const displayClones = clones.length > 0 ? clones : agents.map(a => ({ id: a.id, name: a.name, role: '默认助手', nickname: a.name, scenarios: [] as string[], workspaceDir: '~/.openfang/zclaw-workspace', userName: quickConfig.userName || '未设置', userRole: '', restrictFiles: true, privacyOptIn: false, createdAt: '', onboardingCompleted: true, emoji: undefined as string | undefined, personality: undefined as string | undefined, })); // Function to get display emoji or icon for clone const getCloneDisplay = (clone: typeof displayClones[0]) => { // If clone has emoji, use it if (clone.emoji) { return { emoji: clone.emoji, icon: null, bg: 'bg-gradient-to-br from-orange-400 to-red-500', }; } // Fallback to icon based on name if (clone.name.includes('Browser') || clone.name.includes('浏览器')) { return { emoji: null, icon: , bg: 'bg-blue-500 text-white' }; } if (clone.name.includes('AutoClaw') || clone.name.includes('ZCLAW')) { return { emoji: null, icon: , bg: 'bg-gradient-to-br from-orange-400 to-red-500 text-white' }; } if (clone.name.includes('沉思')) { return { emoji: null, icon: , bg: 'bg-blue-100 text-blue-600 dark:bg-blue-900 dark:text-blue-300' }; } if (clone.name.includes('监控')) { return { emoji: null, icon: , bg: 'bg-orange-100 text-orange-600 dark:bg-orange-900 dark:text-orange-300' }; } return { emoji: null, icon: , bg: 'bg-gray-200 text-gray-600 dark:bg-gray-700 dark:text-gray-300' }; }; return (
{/* Clone list */}
{displayClones.map((clone, idx) => { const { emoji, icon, bg } = getCloneDisplay(clone); const isActive = currentAgent ? currentAgent.id === clone.id : idx === 0; const canDelete = clones.length > 0; return (
setCurrentAgent(toChatAgent(clone))} className={`group sidebar-item mx-2 px-3 py-3 rounded-lg cursor-pointer mb-1 flex items-start gap-3 transition-colors ${ isActive ? 'bg-white dark:bg-gray-800 shadow-sm border border-gray-100 dark:border-gray-700' : 'hover:bg-black/5 dark:hover:bg-white/5' }`} >
{emoji ? ( {emoji} ) : ( icon )}
{clone.name} {isActive ? 当前 : null}

{clone.role || clone.personality || '新分身'}

{canDelete && ( )}
); })} {/* Add new clone button */}
{ if (connected) { setShowWizard(true); } }} className={`sidebar-item mx-2 px-3 py-3 rounded-lg mb-1 flex items-center gap-3 transition-colors border border-dashed border-gray-300 dark:border-gray-600 ${ connected ? 'cursor-pointer text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5' : 'cursor-not-allowed text-gray-400 dark:text-gray-500 bg-gray-50 dark:bg-gray-800/50' }`} >
{connected ? ( ) : ( )}
{connected ? '创建新 Agent' : '连接 Gateway 后创建'}
{/* Onboarding Wizard Modal */} setShowWizard(false)} onSuccess={handleWizardSuccess} />
); }