import React, { useEffect, useRef, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { useNavigate, useParams } from 'react-router-dom'; import userService from '../api/services/userService'; import ArrowLeft from '../assets/arrow-left.svg'; import SourceIcon from '../assets/source.svg'; import Dropdown from '../components/Dropdown'; import MultiSelectPopup, { OptionType } from '../components/MultiSelectPopup'; import AgentDetailsModal from '../modals/AgentDetailsModal'; import ConfirmationModal from '../modals/ConfirmationModal'; import { ActiveState, Doc, Prompt } from '../models/misc'; import { selectSelectedAgent, selectSourceDocs, selectToken, setSelectedAgent, } from '../preferences/preferenceSlice'; import PromptsModal from '../preferences/PromptsModal'; import { UserToolType } from '../settings/types'; import AgentPreview from './AgentPreview'; import { Agent } from './types'; const embeddingsName = import.meta.env.VITE_EMBEDDINGS_NAME || 'huggingface_sentence-transformers/all-mpnet-base-v2'; export default function NewAgent({ mode }: { mode: 'new' | 'edit' | 'draft' }) { const navigate = useNavigate(); const dispatch = useDispatch(); const { agentId } = useParams(); const token = useSelector(selectToken); const sourceDocs = useSelector(selectSourceDocs); const selectedAgent = useSelector(selectSelectedAgent); const [effectiveMode, setEffectiveMode] = useState(mode); const [agent, setAgent] = useState({ id: agentId || '', name: '', description: '', image: '', source: '', chunks: '', retriever: '', prompt_id: '', tools: [], agent_type: '', status: '', }); const [prompts, setPrompts] = useState< { name: string; id: string; type: string }[] >([]); const [userTools, setUserTools] = useState([]); const [isSourcePopupOpen, setIsSourcePopupOpen] = useState(false); const [isToolsPopupOpen, setIsToolsPopupOpen] = useState(false); const [selectedSourceIds, setSelectedSourceIds] = useState< Set >(new Set()); const [selectedToolIds, setSelectedToolIds] = useState>( new Set(), ); const [deleteConfirmation, setDeleteConfirmation] = useState('INACTIVE'); const [agentDetails, setAgentDetails] = useState('INACTIVE'); const [addPromptModal, setAddPromptModal] = useState('INACTIVE'); const sourceAnchorButtonRef = useRef(null); const toolAnchorButtonRef = useRef(null); const modeConfig = { new: { heading: 'New Agent', buttonText: 'Create Agent', showDelete: false, showSaveDraft: true, showLogs: false, showAccessDetails: false, }, edit: { heading: 'Edit Agent', buttonText: 'Save Changes', showDelete: true, showSaveDraft: false, showLogs: true, showAccessDetails: true, }, draft: { heading: 'New Agent (Draft)', buttonText: 'Publish Draft', showDelete: true, showSaveDraft: true, showLogs: false, showAccessDetails: false, }, }; const chunks = ['0', '2', '4', '6', '8', '10']; const agentTypes = [ { label: 'Classic', value: 'classic' }, { label: 'ReAct', value: 'react' }, ]; const isPublishable = () => { return ( agent.name && agent.description && agent.prompt_id && agent.agent_type ); }; const handleCancel = () => { if (selectedAgent) dispatch(setSelectedAgent(null)); navigate('/agents'); }; const handleDelete = async (agentId: string) => { const response = await userService.deleteAgent(agentId, token); if (!response.ok) throw new Error('Failed to delete agent'); navigate('/agents'); }; const handleSaveDraft = async () => { const response = effectiveMode === 'new' ? await userService.createAgent({ ...agent, status: 'draft' }, token) : await userService.updateAgent( agent.id || '', { ...agent, status: 'draft' }, token, ); if (!response.ok) throw new Error('Failed to create agent draft'); const data = await response.json(); if (effectiveMode === 'new') { setEffectiveMode('draft'); setAgent((prev) => ({ ...prev, id: data.id })); } }; const handlePublish = async () => { const response = effectiveMode === 'new' ? await userService.createAgent( { ...agent, status: 'published' }, token, ) : await userService.updateAgent( agent.id || '', { ...agent, status: 'published' }, token, ); if (!response.ok) throw new Error('Failed to publish agent'); const data = await response.json(); if (data.id) setAgent((prev) => ({ ...prev, id: data.id })); if (data.key) setAgent((prev) => ({ ...prev, key: data.key })); if (effectiveMode === 'new' || effectiveMode === 'draft') { setEffectiveMode('edit'); setAgent((prev) => ({ ...prev, status: 'published' })); setAgentDetails('ACTIVE'); } }; useEffect(() => { const getTools = async () => { const response = await userService.getUserTools(token); if (!response.ok) throw new Error('Failed to fetch tools'); const data = await response.json(); const tools: OptionType[] = data.tools.map((tool: UserToolType) => ({ id: tool.id, label: tool.displayName, icon: `/toolIcons/tool_${tool.name}.svg`, })); setUserTools(tools); }; const getPrompts = async () => { const response = await userService.getPrompts(token); if (!response.ok) { throw new Error('Failed to fetch prompts'); } const data = await response.json(); setPrompts(data); }; getTools(); getPrompts(); }, [token]); useEffect(() => { if ((mode === 'edit' || mode === 'draft') && agentId) { const getAgent = async () => { const response = await userService.getAgent(agentId, token); if (!response.ok) { navigate('/agents'); throw new Error('Failed to fetch agent'); } const data = await response.json(); if (data.source) setSelectedSourceIds(new Set([data.source])); else if (data.retriever) setSelectedSourceIds(new Set([data.retriever])); if (data.tools) setSelectedToolIds(new Set(data.tools)); if (data.status === 'draft') setEffectiveMode('draft'); setAgent(data); }; getAgent(); } }, [agentId, mode, token]); useEffect(() => { const selectedSource = Array.from(selectedSourceIds).map((id) => sourceDocs?.find( (source) => source.id === id || source.retriever === id || source.name === id, ), ); if (selectedSource[0]?.model === embeddingsName) { if (selectedSource[0] && 'id' in selectedSource[0]) { setAgent((prev) => ({ ...prev, source: selectedSource[0]?.id || 'default', retriever: '', })); } else setAgent((prev) => ({ ...prev, source: '', retriever: selectedSource[0]?.retriever || 'classic', })); } }, [selectedSourceIds]); useEffect(() => { const selectedTool = Array.from(selectedToolIds).map((id) => userTools.find((tool) => tool.id === id), ); setAgent((prev) => ({ ...prev, tools: selectedTool .map((tool) => tool?.id) .filter((id): id is string => typeof id === 'string'), })); }, [selectedToolIds]); useEffect(() => { if (isPublishable()) dispatch(setSelectedAgent(agent)); }, [agent, dispatch]); return (

Back to all agents

{modeConfig[effectiveMode].heading}

{modeConfig[effectiveMode].showDelete && agent.id && ( )} {modeConfig[effectiveMode].showSaveDraft && ( )} {modeConfig[effectiveMode].showAccessDetails && ( )} {modeConfig[effectiveMode].showAccessDetails && ( )}

Meta

setAgent({ ...agent, name: e.target.value })} />