'use client' import { Button } from '@/components/ui/button' import { AgentSelector } from '@/components/playground/Sidebar/AgentSelector' import useChatActions from '@/hooks/useChatActions' import { usePlaygroundStore } from '@/store' import { motion, AnimatePresence } from 'framer-motion' import { useState, useEffect } from 'react' import Icon from '@/components/ui/icon' import { getProviderIcon } from '@/lib/modelProvider' import Sessions from './Sessions' import { isValidUrl } from '@/lib/utils' import { toast } from 'sonner' import { useQueryState } from 'nuqs' import { truncateText } from '@/lib/utils' import { Skeleton } from '@/components/ui/skeleton' const ENDPOINT_PLACEHOLDER = 'NO ENDPOINT ADDED' const SidebarHeader = () => (
Agent UI
) const NewChatButton = ({ disabled, onClick }: { disabled: boolean onClick: () => void }) => ( ) const ModelDisplay = ({ model }: { model: string }) => (
{(() => { const icon = getProviderIcon(model) return icon ? : null })()} {model}
) const Endpoint = () => { const { selectedEndpoint, isEndpointActive, setSelectedEndpoint, setAgents, setSessionsData, setMessages } = usePlaygroundStore() const { initializePlayground } = useChatActions() const [isEditing, setIsEditing] = useState(false) const [endpointValue, setEndpointValue] = useState('') const [isMounted, setIsMounted] = useState(false) const [isHovering, setIsHovering] = useState(false) const [isRotating, setIsRotating] = useState(false) const [, setAgentId] = useQueryState('agent') const [, setSessionId] = useQueryState('session') useEffect(() => { setEndpointValue(selectedEndpoint) setIsMounted(true) }, [selectedEndpoint]) const getStatusColor = (isActive: boolean) => isActive ? 'bg-positive' : 'bg-destructive' const handleSave = async () => { if (!isValidUrl(endpointValue)) { toast.error('Please enter a valid URL') return } const cleanEndpoint = endpointValue.replace(/\/$/, '').trim() setSelectedEndpoint(cleanEndpoint) setAgentId(null) setSessionId(null) setIsEditing(false) setIsHovering(false) setAgents([]) setSessionsData([]) setMessages([]) } const handleCancel = () => { setEndpointValue(selectedEndpoint) setIsEditing(false) setIsHovering(false) } const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { handleSave() } else if (e.key === 'Escape') { handleCancel() } } const handleRefresh = async () => { setIsRotating(true) await initializePlayground() setTimeout(() => setIsRotating(false), 500) } return (
Endpoint
{isEditing ? (
setEndpointValue(e.target.value)} onKeyDown={handleKeyDown} className="flex h-9 w-full items-center text-ellipsis rounded-xl border border-primary/15 bg-accent p-3 text-xs font-medium text-muted" autoFocus />
) : (
setIsHovering(true)} onMouseLeave={() => setIsHovering(false)} onClick={() => setIsEditing(true)} transition={{ type: 'spring', stiffness: 400, damping: 10 }} > {isHovering ? (

EDIT ENDPOINT

) : (

{isMounted ? truncateText(selectedEndpoint, 21) || ENDPOINT_PLACEHOLDER : 'http://localhost:7777'}

)}
)}
) } const Sidebar = () => { const [isCollapsed, setIsCollapsed] = useState(false) const { clearChat, focusChatInput, initializePlayground } = useChatActions() const { messages, selectedEndpoint, isEndpointActive, selectedModel, hydrated, isEndpointLoading } = usePlaygroundStore() const [isMounted, setIsMounted] = useState(false) const [agentId] = useQueryState('agent') useEffect(() => { setIsMounted(true) if (hydrated) initializePlayground() }, [selectedEndpoint, initializePlayground, hydrated]) const handleNewChat = () => { clearChat() focusChatInput() } return ( setIsCollapsed(!isCollapsed)} className="absolute right-2 top-2 z-10 p-1" aria-label={isCollapsed ? 'Expand sidebar' : 'Collapse sidebar'} type="button" whileTap={{ scale: 0.95 }} > {isMounted && ( <> {isEndpointActive && ( <>
Agent
{isEndpointLoading ? (
{Array.from({ length: 2 }).map((_, index) => ( ))}
) : ( <> {selectedModel && agentId && ( )} )}
)} )}
) } export default Sidebar