This commit is contained in:
2025-09-17 12:33:50 +02:00
parent bd7b2348ce
commit 49a2b9f09b
3 changed files with 50 additions and 25 deletions

View File

@@ -11,7 +11,7 @@ import { Separator } from "@/components/ui/separator"
import { MessageCircle, Send, Bot, User, Loader2, Copy, ThumbsUp, ThumbsDown } from "lucide-react" import { MessageCircle, Send, Bot, User, Loader2, Copy, ThumbsUp, ThumbsDown } from "lucide-react"
import { useToast } from "@/hooks/use-toast" import { useToast } from "@/hooks/use-toast"
import { generateTimestampId } from "@/lib/id-utils" import { generateTimestampId } from "@/lib/id-utils"
import { chatbotApi, type AppError } from "@/lib/api-client" import { chatbotApi } from "@/lib/api-client"
import ReactMarkdown from "react-markdown" import ReactMarkdown from "react-markdown"
import remarkGfm from "remark-gfm" import remarkGfm from "remark-gfm"
import rehypeHighlight from "rehype-highlight" import rehypeHighlight from "rehype-highlight"
@@ -126,11 +126,10 @@ export function ChatInterface({ chatbotId, chatbotName, onClose }: ChatInterface
content: msg.content content: msg.content
})) }))
const data = await chatbotApi.sendMessage( const data = await chatbotApi.chat(
chatbotId, chatbotId,
messageToSend, messageToSend,
conversationId || undefined, { conversation_id: conversationId || undefined }
conversationHistory
) )
// Update conversation ID if it's a new conversation // Update conversation ID if it's a new conversation
@@ -149,15 +148,36 @@ export function ChatInterface({ chatbotId, chatbotName, onClose }: ChatInterface
setMessages(prev => [...prev, assistantMessage]) setMessages(prev => [...prev, assistantMessage])
} catch (error) { } catch (error) {
const appError = error as AppError console.error('Chat error:', error)
// More specific error handling // Handle different error types
if (appError.code === 'UNAUTHORIZED') { if (error && typeof error === 'object') {
if ('response' in error) {
// Axios error
const status = error.response?.status
if (status === 401) {
toast.error("Authentication Required", "Please log in to continue chatting.") toast.error("Authentication Required", "Please log in to continue chatting.")
} else if (appError.code === 'NETWORK_ERROR') { } else if (status === 429) {
toast.error("Rate Limit", "Too many requests. Please wait and try again.")
} else {
toast.error("Message Failed", error.response?.data?.detail || "Failed to send message. Please try again.")
}
} else if ('code' in error) {
// Custom error with code
if (error.code === 'UNAUTHORIZED') {
toast.error("Authentication Required", "Please log in to continue chatting.")
} else if (error.code === 'NETWORK_ERROR') {
toast.error("Connection Error", "Please check your internet connection and try again.") toast.error("Connection Error", "Please check your internet connection and try again.")
} else { } else {
toast.error("Message Failed", appError.message || "Failed to send message. Please try again.") toast.error("Message Failed", error.message || "Failed to send message. Please try again.")
}
} else {
// Generic error
toast.error("Message Failed", error.message || "Failed to send message. Please try again.")
}
} else {
// Fallback for unknown error types
toast.error("Message Failed", "An unexpected error occurred. Please try again.")
} }
} finally { } finally {
setIsLoading(false) setIsLoading(false)

View File

@@ -4,7 +4,7 @@
import { useState, useCallback, useMemo } from 'react' import { useState, useCallback, useMemo } from 'react'
import { generateId } from '@/lib/id-utils' import { generateId } from '@/lib/id-utils'
import { chatbotApi, type AppError } from '@/lib/api-client' import { chatbotApi } from '@/lib/api-client'
import { useToast } from './use-toast' import { useToast } from './use-toast'
export interface ChatbotConfig { export interface ChatbotConfig {
@@ -59,10 +59,10 @@ export function useChatbotForm() {
const loadChatbots = useCallback(async () => { const loadChatbots = useCallback(async () => {
setIsLoading(true) setIsLoading(true)
try { try {
const data = await chatbotApi.listChatbots() const data = await chatbotApi.list()
setChatbots(data) setChatbots(data)
} catch (error) { } catch (error) {
const appError = error as AppError console.error('Load chatbots error:', error)
toast.error("Loading Failed", "Failed to load chatbots") toast.error("Loading Failed", "Failed to load chatbots")
} finally { } finally {
setIsLoading(false) setIsLoading(false)
@@ -73,15 +73,20 @@ export function useChatbotForm() {
const createChatbot = useCallback(async (config: ChatbotConfig) => { const createChatbot = useCallback(async (config: ChatbotConfig) => {
setIsSubmitting(true) setIsSubmitting(true)
try { try {
const newChatbot = await chatbotApi.createChatbot(config) const newChatbot = await chatbotApi.create(config)
setChatbots(prev => [...prev, newChatbot]) setChatbots(prev => [...prev, newChatbot])
toast.success("Success", `Chatbot "${config.name}" created successfully`) toast.success("Success", `Chatbot "${config.name}" created successfully`)
return newChatbot return newChatbot
} catch (error) { } catch (error) {
const appError = error as AppError console.error('Create chatbot error:', error)
if (appError.code === 'VALIDATION_ERROR') { if (error && typeof error === 'object' && 'response' in error) {
toast.error("Validation Error", appError.details || "Please check your input") const detail = error.response?.data?.detail || error.response?.data?.error
if (detail) {
toast.error("Validation Error", detail)
} else {
toast.error("Creation Failed", "Failed to create chatbot")
}
} else { } else {
toast.error("Creation Failed", "Failed to create chatbot") toast.error("Creation Failed", "Failed to create chatbot")
} }
@@ -95,12 +100,12 @@ export function useChatbotForm() {
const updateChatbot = useCallback(async (id: string, config: ChatbotConfig) => { const updateChatbot = useCallback(async (id: string, config: ChatbotConfig) => {
setIsSubmitting(true) setIsSubmitting(true)
try { try {
const updatedChatbot = await chatbotApi.updateChatbot(id, config) const updatedChatbot = await chatbotApi.update(id, config)
setChatbots(prev => prev.map(bot => bot.id === id ? updatedChatbot : bot)) setChatbots(prev => prev.map(bot => bot.id === id ? updatedChatbot : bot))
toast.success("Success", `Chatbot "${config.name}" updated successfully`) toast.success("Success", `Chatbot "${config.name}" updated successfully`)
return updatedChatbot return updatedChatbot
} catch (error) { } catch (error) {
const appError = error as AppError console.error('Update chatbot error:', error)
toast.error("Update Failed", "Failed to update chatbot") toast.error("Update Failed", "Failed to update chatbot")
throw error throw error
} finally { } finally {
@@ -112,11 +117,11 @@ export function useChatbotForm() {
const deleteChatbot = useCallback(async (id: string) => { const deleteChatbot = useCallback(async (id: string) => {
setIsSubmitting(true) setIsSubmitting(true)
try { try {
await chatbotApi.deleteChatbot(id) await chatbotApi.delete(id)
setChatbots(prev => prev.filter(bot => bot.id !== id)) setChatbots(prev => prev.filter(bot => bot.id !== id))
toast.success("Success", "Chatbot deleted successfully") toast.success("Success", "Chatbot deleted successfully")
} catch (error) { } catch (error) {
const appError = error as AppError console.error('Delete chatbot error:', error)
toast.error("Deletion Failed", "Failed to delete chatbot") toast.error("Deletion Failed", "Failed to delete chatbot")
throw error throw error
} finally { } finally {

View File

@@ -106,5 +106,5 @@ export const chatbotApi = {
update: async (id: string, data: any) => apiClient.put(`/api/chatbot/update/${id}`, data), update: async (id: string, data: any) => apiClient.put(`/api/chatbot/update/${id}`, data),
delete: async (id: string) => apiClient.delete(`/api/chatbot/delete/${id}`), delete: async (id: string) => apiClient.delete(`/api/chatbot/delete/${id}`),
chat: async (id: string, message: string, config?: any) => chat: async (id: string, message: string, config?: any) =>
apiClient.post(`/api/chatbot/chat`, { chatbot_id: id, message, ...config }), apiClient.post(`/api/chatbot/chat/${id}`, { message, ...config }),
}; };