diff --git a/index.html b/index.html index 56e4c657..0b6a7bcd 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,7 @@ Coco - +
diff --git a/src/components/Assistant/Chat.tsx b/src/components/Assistant/Chat.tsx index 6eedccf5..49ca712c 100644 --- a/src/components/Assistant/Chat.tsx +++ b/src/components/Assistant/Chat.tsx @@ -149,6 +149,9 @@ const ChatAI = memo( openSessionChat, getChatHistory, createChatWindow, + handleSearch, + handleRename, + handleDelete, } = useChatActions( currentService?.id, setActiveChat, @@ -158,6 +161,7 @@ const ChatAI = memo( clearAllChunkData, setQuestion, curIdRef, + setChats, isSearchActive, isDeepThinkActive, sourceDataIds, @@ -210,7 +214,7 @@ const ChatAI = memo( await handleSendMessage(value, activeChat, websocketSessionId); } } catch (error) { - console.error('Failed to initialize chat:', error); + console.error("Failed to initialize chat:", error); } }, [ @@ -265,20 +269,20 @@ const ChatAI = memo( ] ); - const deleteChat = useCallback( - (chatId: string) => { - setChats((prev) => prev.filter((chat) => chat._id !== chatId)); - if (activeChat?._id === chatId) { - const remainingChats = chats.filter((chat) => chat._id !== chatId); - if (remainingChats.length > 0) { - setActiveChat(remainingChats[0]); - } else { - init(""); - } - } - }, - [activeChat, chats, init, setActiveChat] - ); + // const deleteChat = useCallback( + // (chatId: string) => { + // setChats((prev) => prev.filter((chat) => chat._id !== chatId)); + // if (activeChat?._id === chatId) { + // const remainingChats = chats.filter((chat) => chat._id !== chatId); + // if (remainingChats.length > 0) { + // setActiveChat(remainingChats[0]); + // } else { + // init(""); + // } + // } + // }, + // [activeChat, chats, init, setActiveChat] + // ); const handleOutsideClick = useCallback((e: MouseEvent) => { const sidebar = document.querySelector("[data-sidebar]"); @@ -302,25 +306,25 @@ const ChatAI = memo( }; }, [isSidebarOpenChat, handleOutsideClick]); - const fetchChatHistory = useCallback(async () => { - const hits = await getChatHistory(); - setChats(hits); - }, [getChatHistory]); + // const fetchChatHistory = useCallback(async () => { + // const hits = await getChatHistory(); + // setChats(hits); + // }, [getChatHistory]); const setIsLoginChat = useCallback( (value: boolean) => { setIsLogin(value); - value && currentService && !setIsSidebarOpen && fetchChatHistory(); + value && currentService && !setIsSidebarOpen && getChatHistory(); !value && setChats([]); }, - [currentService, setIsSidebarOpen, fetchChatHistory] + [currentService, setIsSidebarOpen, getChatHistory] ); const toggleSidebar = useCallback(() => { setIsSidebarOpenChat(!isSidebarOpenChat); setIsSidebarOpen && setIsSidebarOpen(!isSidebarOpenChat); - !isSidebarOpenChat && fetchChatHistory(); - }, [isSidebarOpenChat, setIsSidebarOpen, fetchChatHistory]); + !isSidebarOpenChat && getChatHistory(); + }, [isSidebarOpenChat, setIsSidebarOpen, getChatHistory]); return (
)} diff --git a/src/components/Assistant/ChatSidebar.tsx b/src/components/Assistant/ChatSidebar.tsx index eba958dc..ee54676b 100644 --- a/src/components/Assistant/ChatSidebar.tsx +++ b/src/components/Assistant/ChatSidebar.tsx @@ -1,26 +1,31 @@ import React from "react"; -import { Sidebar } from "@/components/Assistant/Sidebar"; +// import { Sidebar } from "@/components/Assistant/Sidebar"; import type { Chat } from "./types"; +import HistoryList from "../Common/HistoryList"; interface ChatSidebarProps { isSidebarOpen: boolean; chats: Chat[]; activeChat?: Chat; - onNewChat: () => void; + // onNewChat: () => void; onSelectChat: (chat: any) => void; onDeleteChat: (chatId: string) => void; fetchChatHistory: () => void; + onSearch: (keyword: string) => void; + onRename: (chat: any, title: string) => void; } export const ChatSidebar: React.FC = ({ isSidebarOpen, chats, activeChat, - onNewChat, + // onNewChat, onSelectChat, onDeleteChat, fetchChatHistory, + onSearch, + onRename, }) => { return (
= ({ overflow-hidden `} > - + {/* + /> */}
); }; diff --git a/src/hooks/useChatActions.ts b/src/hooks/useChatActions.ts index 9912a9f0..0c5bb993 100644 --- a/src/hooks/useChatActions.ts +++ b/src/hooks/useChatActions.ts @@ -1,7 +1,17 @@ -import { useCallback } from "react"; +import { useCallback, useEffect, useState } from "react"; import type { Chat } from "@/components/Assistant/types"; -import { close_session_chat, cancel_session_chat, session_chat_history, new_chat, send_message, open_session_chat, chat_history } from "@/commands" +import { + close_session_chat, + cancel_session_chat, + session_chat_history, + new_chat, + send_message, + open_session_chat, + chat_history, + update_session_chat, + delete_session_chat, +} from "@/commands"; import { useAppStore } from "@/stores/appStore"; import { Get, Post } from "@/api/axiosRequest"; @@ -14,104 +24,118 @@ export function useChatActions( clearAllChunkData: () => void, setQuestion: (value: string) => void, curIdRef: React.MutableRefObject, + setChats: (chats: Chat[]) => void, isSearchActive?: boolean, isDeepThinkActive?: boolean, sourceDataIds?: string[], changeInput?: (val: string) => void, - websocketSessionId?: string, + websocketSessionId?: string ) { const isTauri = useAppStore((state) => state.isTauri); + const [keyword, setKeyword] = useState(""); - const chatClose = useCallback(async (activeChat?: Chat) => { - if (!activeChat?._id) return; - try { - let response: any - if (isTauri) { - if (!currentServiceId) return; - response = await close_session_chat({ - serverId: currentServiceId, - sessionId: activeChat?._id, - }); - response = JSON.parse(response || ""); - } else { - const [error, res] = await Post(`/chat/${activeChat?._id}/_close`, {}) - if (error) { - console.error('_close', error); - return + const chatClose = useCallback( + async (activeChat?: Chat) => { + if (!activeChat?._id) return; + try { + let response: any; + if (isTauri) { + if (!currentServiceId) return; + response = await close_session_chat({ + serverId: currentServiceId, + sessionId: activeChat?._id, + }); + response = JSON.parse(response || ""); + } else { + const [error, res] = await Post( + `/chat/${activeChat?._id}/_close`, + {} + ); + if (error) { + console.error("_close", error); + return; + } + response = res; } - response = res + console.log("_close", response); + } catch (error) { + console.error("chatClose:", error); } - console.log("_close", response); - } catch (error) { - console.error("chatClose:", error); - } - }, [currentServiceId]); + }, + [currentServiceId] + ); - const cancelChat = useCallback(async (activeChat?: Chat) => { - setCurChatEnd(true); - if (!activeChat?._id) return; - try { - let response: any - if (isTauri) { - if (!currentServiceId) return; - response = await cancel_session_chat({ - serverId: currentServiceId, - sessionId: activeChat?._id, - }); - response = JSON.parse(response || ""); - } else { - const [error, res] = await Post(`/chat/${activeChat?._id}/_cancel`, {}) - if (error) { - console.error('_cancel', error); - return + const cancelChat = useCallback( + async (activeChat?: Chat) => { + setCurChatEnd(true); + if (!activeChat?._id) return; + try { + let response: any; + if (isTauri) { + if (!currentServiceId) return; + response = await cancel_session_chat({ + serverId: currentServiceId, + sessionId: activeChat?._id, + }); + response = JSON.parse(response || ""); + } else { + const [error, res] = await Post( + `/chat/${activeChat?._id}/_cancel`, + {} + ); + if (error) { + console.error("_cancel", error); + return; + } + response = res; } - response = res + console.log("_cancel", response); + } catch (error) { + console.error("cancelChat:", error); } - console.log("_cancel", response); - } catch (error) { - console.error("cancelChat:", error); - } - }, [currentServiceId, setCurChatEnd]); + }, + [currentServiceId, setCurChatEnd] + ); - const chatHistory = useCallback(async ( - chat: Chat, - callback?: (chat: Chat) => void - ) => { - if (!chat?._id) return; - try { - let response: any - if (isTauri) { - if (!currentServiceId) return; - response = await session_chat_history({ - serverId: currentServiceId, - sessionId: chat?._id, - from: 0, - size: 20, - }); - response = JSON.parse(response || ""); - } else { - const [error, res] = await Get(`/chat/${chat?._id}/_history`, { - from: 0, - size: 20, - }) - if (error) { - console.error('_cancel', error); - return + const chatHistory = useCallback( + async (chat: Chat, callback?: (chat: Chat) => void) => { + if (!chat?._id) return; + try { + let response: any; + if (isTauri) { + if (!currentServiceId) return; + response = await session_chat_history({ + serverId: currentServiceId, + sessionId: chat?._id, + from: 0, + size: 20, + }); + response = JSON.parse(response || ""); + } else { + const [error, res] = await Get(`/chat/${chat?._id}/_history`, { + from: 0, + size: 20, + }); + if (error) { + console.error("_cancel", error); + return; + } + response = res; } - response = res + const hits = response?.hits?.hits || []; + const updatedChat: Chat = { + ...chat, + messages: hits, + }; + console.log("id_history", response, updatedChat); + setActiveChat(updatedChat); + callback && callback(updatedChat); + } catch (error) { + console.error("chatHistory:", error); } - const hits = response?.hits?.hits || []; - const updatedChat: Chat = { - ...chat, - messages: hits, - }; - console.log("id_history", response, updatedChat); - setActiveChat(updatedChat); - callback && callback(updatedChat); - } catch (error) { - console.error("chatHistory:", error); - } - }, [currentServiceId, setActiveChat]); + }, + [currentServiceId, setActiveChat] + ); const createNewChat = useCallback( async (value: string = "", activeChat?: Chat, id?: string) => { @@ -120,14 +144,14 @@ export function useChatActions( setErrorShow(false); await chatClose(activeChat); clearAllChunkData(); - setQuestion(value); + setQuestion(value); if (!(websocketSessionId || id)) { setErrorShow(true); console.error("websocketSessionId", websocketSessionId, id); return; } console.log("sourceDataIds", sourceDataIds, websocketSessionId, id); - let response: any + let response: any; if (isTauri) { if (!currentServiceId) return; response = await new_chat({ @@ -140,24 +164,28 @@ export function useChatActions( datasource: sourceDataIds?.join(",") || "", }, }); - } else { - console.log('websocketSessionId', websocketSessionId, id) - const [error, res] = await Post('/chat/_new', { - message: value, - }, { - search: isSearchActive, - deep_thinking: isDeepThinkActive, - datasource: sourceDataIds?.join(",") || "", - }, { - "WEBSOCKET-SESSION-ID": websocketSessionId || id, - }) + console.log("websocketSessionId", websocketSessionId, id); + const [error, res] = await Post( + "/chat/_new", + { + message: value, + }, + { + search: isSearchActive, + deep_thinking: isDeepThinkActive, + datasource: sourceDataIds?.join(",") || "", + }, + { + "WEBSOCKET-SESSION-ID": websocketSessionId || id, + } + ); if (error) { setErrorShow(true); - console.error('_new', error); - return + console.error("_new", error); + return; } - response = res + response = res; } console.log("_new", response); const newChat: Chat = response; @@ -179,7 +207,14 @@ export function useChatActions( console.error("createNewChat:", error); } }, - [currentServiceId, sourceDataIds, isSearchActive, isDeepThinkActive, curIdRef, websocketSessionId] + [ + currentServiceId, + sourceDataIds, + isSearchActive, + isDeepThinkActive, + curIdRef, + websocketSessionId, + ] ); const sendMessage = useCallback( @@ -193,7 +228,7 @@ export function useChatActions( console.error("websocketSessionId", websocketSessionId, id); return; } - let response: any + let response: any; if (isTauri) { if (!currentServiceId) return; response = await send_message({ @@ -209,23 +244,28 @@ export function useChatActions( }); response = JSON.parse(response || ""); } else { - console.log('websocketSessionId', websocketSessionId, id) - const [error, res] = await Post(`/chat/${newChat?._id}/_send`, { - message: content - }, { - search: isSearchActive, - deep_thinking: isDeepThinkActive, - datasource: sourceDataIds?.join(",") || "", - }, { - "WEBSOCKET-SESSION-ID": websocketSessionId || id, - }) + console.log("websocketSessionId", websocketSessionId, id); + const [error, res] = await Post( + `/chat/${newChat?._id}/_send`, + { + message: content, + }, + { + search: isSearchActive, + deep_thinking: isDeepThinkActive, + datasource: sourceDataIds?.join(",") || "", + }, + { + "WEBSOCKET-SESSION-ID": websocketSessionId || id, + } + ); if (error) { setErrorShow(true); - console.error('_cancel', error); - return + console.error("_cancel", error); + return; } - response = res + response = res; } console.log("_send", response); curIdRef.current = response[0]?._id; @@ -243,7 +283,18 @@ export function useChatActions( console.error("sendMessage:", error); } }, - [currentServiceId, sourceDataIds, isSearchActive, isDeepThinkActive, curIdRef, setActiveChat, setCurChatEnd, setErrorShow, changeInput, websocketSessionId] + [ + currentServiceId, + sourceDataIds, + isSearchActive, + isDeepThinkActive, + curIdRef, + setActiveChat, + setCurChatEnd, + setErrorShow, + changeInput, + websocketSessionId, + ] ); const handleSendMessage = useCallback( @@ -256,88 +307,130 @@ export function useChatActions( await chatHistory(activeChat, (chat) => sendMessage(content, chat, id)); }, - [chatHistory, sendMessage, setQuestion, setTimedoutShow, setErrorShow, clearAllChunkData] + [ + chatHistory, + sendMessage, + setQuestion, + setTimedoutShow, + setErrorShow, + clearAllChunkData, + ] ); - const openSessionChat = useCallback(async (chat: Chat) => { - if (!chat?._id) return; - try { - let response: any - if (isTauri) { - if (!currentServiceId) return; - response = await open_session_chat({ - serverId: currentServiceId, - sessionId: chat?._id, - }); - response = JSON.parse(response || ""); - } else { - const [error, res] = await Post(`/chat/${chat?._id}/_open`, {}) - if (error) { - console.error('_open', error); - return null + const openSessionChat = useCallback( + async (chat: Chat) => { + if (!chat?._id) return; + try { + let response: any; + if (isTauri) { + if (!currentServiceId) return; + response = await open_session_chat({ + serverId: currentServiceId, + sessionId: chat?._id, + }); + response = JSON.parse(response || ""); + } else { + const [error, res] = await Post(`/chat/${chat?._id}/_open`, {}); + if (error) { + console.error("_open", error); + return null; + } + response = res; } - response = res - } - console.log("_open", response); - return response; - } catch (error) { - console.error("open_session_chat:", error); - return null; - } - }, [currentServiceId]); + console.log("_open", response); + return response; + } catch (error) { + console.error("open_session_chat:", error); + return null; + } + }, + [currentServiceId] + ); const getChatHistory = useCallback(async () => { try { - let response: any + let response: any; if (isTauri) { if (!currentServiceId) return []; response = await chat_history({ serverId: currentServiceId, from: 0, size: 20, + query: keyword, }); response = JSON.parse(response || ""); } else { const [error, res] = await Get(`/chat/_history`, { from: 0, size: 20, - }) + }); if (error) { - console.error('_history', error); - return [] + console.error("_history", error); + return []; } - response = res + response = res; } console.log("_history", response); const hits = response?.hits?.hits || []; + + setChats(hits); return hits; } catch (error) { console.error("chat_history:", error); return []; } - }, [currentServiceId]); + }, [currentServiceId, keyword]); + + useEffect(() => { + getChatHistory(); + }, [keyword]); const createChatWindow = useCallback(async (createWin: any) => { if (isTauri) { - createWin && createWin({ - label: "chat", - title: "Coco Chat", - dragDropEnabled: true, - center: true, - width: 1000, - height: 800, - minWidth: 1000, - minHeight: 800, - alwaysOnTop: false, - skipTaskbar: false, - decorations: true, - closable: true, - url: "/ui/chat", - }); + createWin && + createWin({ + label: "chat", + title: "Coco Chat", + dragDropEnabled: true, + center: true, + width: 1000, + height: 800, + minWidth: 1000, + minHeight: 800, + alwaysOnTop: false, + skipTaskbar: false, + decorations: true, + closable: true, + url: "/ui/chat", + }); } }, []); + const handleSearch = (keyword: string) => { + setKeyword(keyword); + }; + + const handleRename = async (chat: Chat, title: string) => { + if (!currentServiceId) return; + + await update_session_chat({ + serverId: currentServiceId, + sessionId: chat?._id, + title, + }); + + getChatHistory(); + }; + + const handleDelete = async (id: string) => { + if (!currentServiceId) return; + + await delete_session_chat(currentServiceId, id); + + getChatHistory(); + }; + return { chatClose, cancelChat, @@ -347,6 +440,9 @@ export function useChatActions( handleSendMessage, openSessionChat, getChatHistory, - createChatWindow + createChatWindow, + handleSearch, + handleRename, + handleDelete, }; -} \ No newline at end of file +} diff --git a/src/pages/chat/index.tsx b/src/pages/chat/index.tsx index 93cd462a..79cf0bf8 100644 --- a/src/pages/chat/index.tsx +++ b/src/pages/chat/index.tsx @@ -214,9 +214,6 @@ export default function Chat({}: ChatProps) { const handleRename = async (chat: typeChat, title: string) => { if (!currentService?.id) return; - console.log("chat", chat); - console.log("title", title); - await update_session_chat({ serverId: currentService.id, sessionId: chat?._id, diff --git a/src/routes/layout.tsx b/src/routes/layout.tsx index e85ec840..58a77184 100644 --- a/src/routes/layout.tsx +++ b/src/routes/layout.tsx @@ -20,7 +20,7 @@ export default function Layout() { function updateBodyClass(path: string) { const body = document.body; - body.className = ""; + body.classList.remove("input-body"); if (path === "/ui") { body.classList.add("input-body"); @@ -28,9 +28,11 @@ export default function Layout() { } useMount(async () => { - const unlistenTheme = await platformAdapter.listenThemeChanged((theme: AppTheme) => { - setTheme(theme); - }); + const unlistenTheme = await platformAdapter.listenThemeChanged( + (theme: AppTheme) => { + setTheme(theme); + } + ); platformAdapter.onThemeChanged(({ payload }) => { if (activeTheme !== "auto") return; @@ -100,9 +102,5 @@ export default function Layout() { event.preventDefault(); }); - return ( -
- -
- ); + return ; } diff --git a/tailwind.config.js b/tailwind.config.js index c36862e1..f504679c 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,7 +1,11 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ["./index.html", "./src/**/*.{html,js,jsx,ts,tsx}", "./src/**/*.css"], - important: '.coco-container', + content: [ + "./index.html", + "./src/**/*.{html,js,jsx,ts,tsx}", + "./src/**/*.css", + ], + important: ".coco-container", theme: { extend: { backgroundColor: {