import { useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import apiClient from '../../api/client'; import { Save, Plus, Edit2, Trash2, X, Bot, Loader2, Users } from 'lucide-react'; import type { Provider } from '../../types'; interface WorkerIndividual { agent_id: string; agent_name: string; agent_type: string; description?: string; provider_title: string; model_id: string; system_prompt?: string; output_template?: string; bound_skill?: string; workspace?: string; tools?: string; } export function WorkerIndividualSettings() { const { t } = useTranslation(); const [providers, setProviders] = useState([]); const [workers, setWorkers] = useState([]); const [systemNodes, setSystemNodes] = useState([]); const [availableSkills, setAvailableSkills] = useState([]); const [availableTools, setAvailableTools] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [isEditing, setIsEditing] = useState(false); const [editData, setEditData] = useState>({}); const [isNew, setIsNew] = useState(false); const [modalMessage, setModalMessage] = useState(''); const [submitLoading, setSubmitLoading] = useState(false); const fetchData = async () => { setLoading(true); try { const [provRes, workRes, sysRes, toolsRes, skillsRes] = await Promise.all([ apiClient.get('/api/v1/provider/list'), apiClient.get('/api/v1/agent/worker'), apiClient.get('/api/v1/agent'), apiClient.get('/api/v1/resource/tool'), apiClient.get('/api/v1/resource/skill') ]); setProviders(Object.values(provRes.data.provider_list || {})); setWorkers(workRes.data.workers || []); setAvailableTools(toolsRes.data.tools || []); setAvailableSkills(Object.keys(skillsRes.data.skills || {})); const providersList = Object.values(provRes.data.provider_list || {}) as Provider[]; const defaultProvider = providersList.length > 0 ? providersList[0].provider_title : ''; const sysNodesData = sysRes.data.system_nodes || []; const defaultSysNodes = ['regulatory_node', 'consciousness_node']; setSystemNodes(defaultSysNodes.map(nodeName => { const found = sysNodesData.find((n: any) => n.node_name === nodeName); return { agent_id: nodeName, agent_name: nodeName, agent_type: 'System Node', display_name: found?.display_name || '', provider_title: found?.provider_title || defaultProvider, model_id: found?.model_id || '', tools: found?.tools ? JSON.stringify(found.tools) : '[]', custom_system_prompt: found?.custom_system_prompt || '', is_system: true }; })); } catch (err: any) { setError(t('agent.loadFailed')); } finally { setLoading(false); } }; useEffect(() => { fetchData(); }, []); const handleEdit = (worker: any) => { setEditData({ ...worker, output_template: typeof worker.output_template === 'string' ? worker.output_template : JSON.stringify(worker.output_template || {}), bound_skill: typeof worker.bound_skill === 'string' ? worker.bound_skill : JSON.stringify(worker.bound_skill || {}), workspace: typeof worker.workspace === 'string' ? worker.workspace : JSON.stringify(worker.workspace || []), tools: typeof worker.tools === 'string' ? worker.tools : JSON.stringify(worker.tools || []) }); setIsNew(false); setIsEditing(true); setModalMessage(''); }; const handleAddNew = () => { setEditData({ agent_name: '', agent_type: 'ordinary_individual', description: '', provider_title: providers.length > 0 ? providers[0].provider_title : '', model_id: '', system_prompt: '', output_template: '{}', bound_skill: '{}', workspace: '[]', tools: '[]' }); setIsNew(true); setIsEditing(true); setModalMessage(''); }; const handleDelete = async (agent_id: string) => { if (!confirm(t('agent.deleteWorkerConfirm'))) return; try { await apiClient.delete(`/api/v1/agent/worker/${agent_id}`); fetchData(); } catch { alert(t('common.deleteFailed')); } }; const handleModalSave = async (e: React.FormEvent) => { e.preventDefault(); setModalMessage(''); setSubmitLoading(true); try { if ((editData as any).is_system) { await apiClient.post('/api/v1/agent', { individual_name: editData.agent_name, provider_title: editData.provider_title, model_id: editData.model_id, tools: JSON.parse(editData.tools || '[]'), custom_system_prompt: (editData as any).custom_system_prompt || null, display_name: (editData as any).display_name || null }); } else { const payload = { ...editData, output_template: JSON.parse(editData.output_template || '{}'), bound_skill: JSON.parse(editData.bound_skill || '{}'), workspace: JSON.parse(editData.workspace || '[]'), tools: JSON.parse(editData.tools || '[]') }; if (isNew) await apiClient.post('/api/v1/agent/worker', payload); else await apiClient.put(`/api/v1/agent/worker/${editData.agent_id}`, payload); } setIsEditing(false); fetchData(); } catch (err: any) { setModalMessage(err.response?.data?.detail || err.message || t('common.saveFailed')); } finally { setSubmitLoading(false); } }; const getTypeBadge = (type: string, isSystem?: boolean) => { if (isSystem) return {t('agent.system')}; const colors: Record = { ordinary_individual: 'bg-bg-secondary text-text-muted', skill_individual: 'bg-success-bg text-success', special_individual: 'bg-warning-bg text-warning', }; return {t(`agent.type.${type}`, type.replace('_', ' '))}; }; return (

{t('agent.individual')}

{t('agent.individualDesc')}

{error &&
{error}
}
{loading ? (
{t('common.loading')}
) : (workers.length === 0 && systemNodes.length === 0) ? (
{t('agent.noIndividuals')}
) : ( {systemNodes.map((w) => ( ))} {workers.map((w) => ( ))}
{t('agent.name')} {t('agent.type')} {t('agent.providerModel')} {t('common.actions')}
{w.display_name || w.agent_name} {w.display_name && {w.agent_name}}
{getTypeBadge(w.agent_type, true)} {w.provider_title} / {w.model_id}
{w.agent_name}
{getTypeBadge(w.agent_type)} {w.provider_title} / {w.model_id}
)}
{/* Modal */} {isEditing && (

{(editData as any).is_system ? t('agent.editSystemNode') : (isNew ? t('agent.createWorker') : t('agent.editWorker'))}

{ if ((editData as any).is_system) setEditData({...editData, display_name: e.target.value} as any); else setEditData({...editData, agent_name: e.target.value}); }} placeholder={(editData as any).is_system ? editData.agent_name : ''} className="w-full px-3 py-2 bg-bg-input border border-border-primary rounded-xl text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-accent/20 focus:border-accent" />
{(() => { const sp = providers.find(p => p.provider_title === editData.provider_title); const models = sp?.provider_models || []; return ( ); })()}
{(editData as any).is_system && (