"use client" import { useState, useEffect } from "react" import { useRouter } from "next/navigation" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { Badge } from "@/components/ui/badge" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Textarea } from "@/components/ui/textarea" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Switch } from "@/components/ui/switch" import { Slider } from "@/components/ui/slider" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog" import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog" import { MessageCircle, Plus, Settings, Trash2, Play, Bot, Brain, Users, BookOpen, Palette, Key, Globe, Copy, Link } from "lucide-react" import { useToast } from "@/hooks/use-toast" import { ChatInterface } from "./ChatInterface" import ModelSelector from "@/components/playground/ModelSelector" import { config } from "@/lib/config" import { apiClient } from "@/lib/api-client" interface ChatbotConfig { name: string chatbot_type: string model: string system_prompt: string use_rag: boolean rag_collection?: string rag_top_k: number temperature: number max_tokens: number memory_length: number fallback_responses: string[] } interface ChatbotInstance { id: string name: string config: ChatbotConfig created_by: string created_at: string updated_at: string is_active: boolean } interface RagCollection { id: string name: string description: string document_count: number } const CHATBOT_TYPES = [ { value: "assistant", label: "General Assistant", description: "Helpful AI assistant for general questions", icon: Bot, color: "bg-blue-500" }, { value: "customer_support", label: "Customer Support", description: "Professional customer service chatbot", icon: Users, color: "bg-green-500" }, { value: "teacher", label: "Teacher", description: "Educational tutor and learning assistant", icon: BookOpen, color: "bg-purple-500" }, { value: "researcher", label: "Researcher", description: "Research assistant with fact-checking focus", icon: Brain, color: "bg-indigo-500" }, { value: "creative_writer", label: "Creative Writer", description: "Creative writing and storytelling assistant", icon: Palette, color: "bg-pink-500" }, { value: "custom", label: "Custom", description: "Custom chatbot with user-defined personality", icon: Settings, color: "bg-gray-500" } ] interface PromptTemplate { id: string name: string type_key: string description?: string system_prompt: string is_default: boolean is_active: boolean version: number } export function ChatbotManager() { const router = useRouter() const [chatbots, setChatbots] = useState([]) const [ragCollections, setRagCollections] = useState([]) const [promptTemplates, setPromptTemplates] = useState([]) const [loading, setLoading] = useState(true) const [showCreateDialog, setShowCreateDialog] = useState(false) const [showEditDialog, setShowEditDialog] = useState(false) const [showDeleteDialog, setShowDeleteDialog] = useState(false) const [deletingChatbot, setDeletingChatbot] = useState(null) const [selectedChatbot, setSelectedChatbot] = useState(null) const [editingChatbot, setEditingChatbot] = useState(null) const [showChatInterface, setShowChatInterface] = useState(false) const [testingChatbot, setTestingChatbot] = useState(null) const { toast } = useToast() // New chatbot form state const [newChatbot, setNewChatbot] = useState({ name: "", chatbot_type: "assistant", model: "", system_prompt: "", use_rag: false, rag_collection: "", rag_top_k: 5, temperature: 0.7, max_tokens: 1000, memory_length: 10, fallback_responses: [ "I'm not sure how to help with that. Could you please rephrase your question?", "I don't have enough information to answer that question accurately.", "That's outside my knowledge area. Is there something else I can help you with?" ] }) // Edit chatbot form state const [editChatbot, setEditChatbot] = useState({ name: "", chatbot_type: "assistant", model: "", system_prompt: "", use_rag: false, rag_collection: "", rag_top_k: 5, temperature: 0.7, max_tokens: 1000, memory_length: 10, fallback_responses: [] }) useEffect(() => { loadChatbots() loadRagCollections() loadPromptTemplates() }, []) // Auto-populate system prompt when templates are loaded useEffect(() => { if (promptTemplates.length > 0 && !newChatbot.system_prompt) { const defaultTemplate = loadTemplateForType('assistant') setNewChatbot(prev => ({ ...prev, system_prompt: defaultTemplate })) } }, [promptTemplates]) const handleTestChat = (chatbot: ChatbotInstance) => { setTestingChatbot(chatbot) setShowChatInterface(true) } const handleEditChat = (chatbot: ChatbotInstance) => { setEditingChatbot(chatbot) setEditChatbot({ name: chatbot.config.name, chatbot_type: chatbot.config.chatbot_type, model: chatbot.config.model, system_prompt: chatbot.config.system_prompt, use_rag: chatbot.config.use_rag, rag_collection: chatbot.config.rag_collection ? String(chatbot.config.rag_collection) : "", rag_top_k: chatbot.config.rag_top_k, temperature: chatbot.config.temperature, max_tokens: chatbot.config.max_tokens, memory_length: chatbot.config.memory_length, fallback_responses: chatbot.config.fallback_responses || [] }) setShowEditDialog(true) } const loadChatbots = async () => { try { const data = await apiClient.get('/api-internal/v1/chatbot/list') setChatbots(data) } catch (error) { console.error('Failed to load chatbots:', error) toast({ title: "Error", description: "Failed to load chatbots", variant: "destructive" }) } finally { setLoading(false) } } const loadRagCollections = async () => { try { const data = await apiClient.get('/api-internal/v1/rag/collections') setRagCollections(data.collections || []) } catch (error) { console.error('Failed to load RAG collections:', error) } } const loadPromptTemplates = async () => { try { const templates = await apiClient.get('/api-internal/v1/prompt-templates/templates') setPromptTemplates(templates) } catch (error) { console.error('Failed to load prompt templates:', error) } } const loadTemplateForType = (chatbotType: string) => { const template = promptTemplates.find(t => t.type_key === chatbotType) return template?.system_prompt || "" } const createChatbot = async () => { try { const chatbot = await apiClient.post('/api-internal/v1/chatbot/create', newChatbot) setChatbots(prev => [...prev, chatbot]) setShowCreateDialog(false) resetForm() toast({ title: "Success", description: "Chatbot created successfully" }) } catch (error) { toast({ title: "Error", description: "Failed to create chatbot", variant: "destructive" }) } } const updateChatbot = async () => { if (!editingChatbot) return try { const updatedChatbot = await apiClient.put(`/api-internal/v1/chatbot/update/${editingChatbot.id}`, editChatbot) setChatbots(prev => prev.map(cb => cb.id === updatedChatbot.id ? updatedChatbot : cb)) setShowEditDialog(false) setEditingChatbot(null) resetEditForm() toast({ title: "Success", description: "Chatbot updated successfully" }) } catch (error) { toast({ title: "Error", description: "Failed to update chatbot", variant: "destructive" }) } } const resetForm = () => { setNewChatbot({ name: "", chatbot_type: "assistant", model: "", system_prompt: "", use_rag: false, rag_collection: "", rag_top_k: 5, temperature: 0.7, max_tokens: 1000, memory_length: 10, fallback_responses: [ "I'm not sure how to help with that. Could you please rephrase your question?", "I don't have enough information to answer that question accurately.", "That's outside my knowledge area. Is there something else I can help you with?" ] }) } const resetEditForm = () => { setEditChatbot({ name: "", chatbot_type: "assistant", model: "", system_prompt: "", use_rag: false, rag_collection: "", rag_top_k: 5, temperature: 0.7, max_tokens: 1000, memory_length: 10, fallback_responses: [] }) } const handleDeleteChat = (chatbot: ChatbotInstance) => { setDeletingChatbot(chatbot) setShowDeleteDialog(true) } const deleteChatbot = async () => { if (!deletingChatbot) return try { await apiClient.delete(`/api-internal/v1/chatbot/delete/${deletingChatbot.id}`) setChatbots(prev => prev.filter(c => c.id !== deletingChatbot.id)) setShowDeleteDialog(false) setDeletingChatbot(null) toast({ title: "Success", description: `${deletingChatbot.name} has been deleted` }) } catch (error) { console.error('Failed to delete chatbot:', error) toast({ title: "Error", description: error instanceof Error ? error.message : "Failed to delete chatbot", variant: "destructive" }) } } const handleManageApiKeys = (chatbot: ChatbotInstance) => { // Navigate to unified API keys page with chatbot context router.push(`/api-keys?chatbot=${chatbot.id}&chatbot_name=${encodeURIComponent(chatbot.name)}`) } const getChatbotTypeInfo = (type: string) => { const dynamicTypes = getDynamicChatbotTypes() return dynamicTypes.find(t => t.value === type) || dynamicTypes[0] || CHATBOT_TYPES[0] } // Convert prompt templates to chatbot type UI format const getDynamicChatbotTypes = () => { if (promptTemplates.length === 0) { return CHATBOT_TYPES // Fallback to static types while loading } return promptTemplates.map(template => { // Try to find existing type info for known types const existingType = CHATBOT_TYPES.find(t => t.value === template.type_key) if (existingType) { // Use existing icon and color for known types return { ...existingType, name: template.name, // Use the template name which might be customized description: template.description || existingType.description } } else { // Create new type for custom templates return { value: template.type_key, label: template.name, description: template.description || `Custom ${template.name} chatbot`, icon: Bot, // Default icon for custom types color: "bg-slate-500" // Default color for custom types } } }) } return (

Chatbot Manager

Create and manage AI chatbots with custom personalities and knowledge bases.

Create New Chatbot Configure your AI chatbot with custom personality, knowledge base, and behavior. Basic Personality Knowledge Advanced
setNewChatbot(prev => ({ ...prev, name: e.target.value }))} placeholder="e.g., Customer Support Bot" />
{getDynamicChatbotTypes().map((type) => { const Icon = type.icon return ( { const templatePrompt = loadTemplateForType(type.value) setNewChatbot(prev => ({ ...prev, chatbot_type: type.value, system_prompt: templatePrompt })) }} >

{type.label}

{type.description}

) })}
setNewChatbot(prev => ({ ...prev, model: value }))} filter="chat" />

Define your chatbot's personality, expertise, and response style. This prompt shapes how your chatbot behaves and responds to users.