mirror of
https://github.com/infinilabs/coco-app.git
synced 2025-12-16 11:37:47 +01:00
fixed: chat message confusion (#782)
* fix: chat * fix: chat * chore: add session id * fix: fixed incorrect taskbar icon display on linux (#783) * fix: fixed incorrect taskbar icon display on linux * docs: update changelog * fix: fix data inconsistency issue on secondary pages (#784) * chore: chat * chore: chat * chore: add logging message * chore: chat * chore: chat * chore: add * feat: add * chore: chat end * style: message width --------- Co-authored-by: ayangweb <75017711+ayangweb@users.noreply.github.com> Co-authored-by: medcl <m@medcl.net>
This commit is contained in:
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@@ -62,6 +62,7 @@
|
||||
"traptitech",
|
||||
"unlisten",
|
||||
"unlistener",
|
||||
"unlisteners",
|
||||
"unminimize",
|
||||
"uuidv",
|
||||
"VITE",
|
||||
|
||||
@@ -163,6 +163,7 @@ pub async fn chat_create<R: Runtime>(
|
||||
server_id: String,
|
||||
message: String,
|
||||
query_params: Option<HashMap<String, Value>>,
|
||||
client_id: String,
|
||||
) -> Result<(), String> {
|
||||
let body = if !message.is_empty() {
|
||||
let message = ChatRequestMessage {
|
||||
@@ -202,10 +203,12 @@ pub async fn chat_create<R: Runtime>(
|
||||
);
|
||||
let mut lines = tokio::io::BufReader::new(reader).lines();
|
||||
|
||||
while let Ok(Some(line)) = lines.next_line().await {
|
||||
log::debug!("Received chat stream line: {}", &line);
|
||||
log::info!("client_id_create: {}", &client_id);
|
||||
|
||||
if let Err(err) = app_handle.emit("chat-create-stream", line) {
|
||||
while let Ok(Some(line)) = lines.next_line().await {
|
||||
log::info!("Received chat stream line: {}", &line);
|
||||
|
||||
if let Err(err) = app_handle.emit(&client_id, line) {
|
||||
log::error!("Emit failed: {:?}", err);
|
||||
|
||||
print!("Error sending message: {:?}", err);
|
||||
@@ -255,6 +258,7 @@ pub async fn chat_chat<R: Runtime>(
|
||||
session_id: String,
|
||||
message: String,
|
||||
query_params: Option<HashMap<String, Value>>, //search,deep_thinking
|
||||
client_id: String,
|
||||
) -> Result<(), String> {
|
||||
let body = if !message.is_empty() {
|
||||
let message = ChatRequestMessage {
|
||||
@@ -295,11 +299,18 @@ pub async fn chat_chat<R: Runtime>(
|
||||
stream.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e)),
|
||||
);
|
||||
let mut lines = tokio::io::BufReader::new(reader).lines();
|
||||
let mut first_log = true;
|
||||
|
||||
log::info!("client_id: {}", &client_id);
|
||||
|
||||
while let Ok(Some(line)) = lines.next_line().await {
|
||||
log::debug!("Received chat stream line: {}", &line);
|
||||
log::info!("Received chat stream line: {}", &line);
|
||||
if first_log {
|
||||
log::info!("first stream line: {}", &line);
|
||||
first_log = false;
|
||||
}
|
||||
|
||||
if let Err(err) = app_handle.emit("chat-create-stream", line) {
|
||||
if let Err(err) = app_handle.emit(&client_id, line) {
|
||||
log::error!("Emit failed: {:?}", err);
|
||||
let _ = app_handle.emit("chat-create-error", format!("Emit failed: {:?}", err));
|
||||
}
|
||||
|
||||
@@ -249,15 +249,18 @@ export function chat_create({
|
||||
serverId,
|
||||
message,
|
||||
queryParams,
|
||||
clientId,
|
||||
}: {
|
||||
serverId: string;
|
||||
message: string;
|
||||
queryParams?: Record<string, any>;
|
||||
clientId: string;
|
||||
}): Promise<GetResponse> {
|
||||
return invokeWithErrorHandler(`chat_create`, {
|
||||
serverId,
|
||||
message,
|
||||
queryParams,
|
||||
clientId,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -288,17 +291,20 @@ export function chat_chat({
|
||||
sessionId,
|
||||
message,
|
||||
queryParams,
|
||||
clientId,
|
||||
}: {
|
||||
serverId: string;
|
||||
sessionId: string;
|
||||
message: string;
|
||||
queryParams?: Record<string, any>;
|
||||
clientId: string;
|
||||
}): Promise<string> {
|
||||
return invokeWithErrorHandler(`chat_chat`, {
|
||||
serverId,
|
||||
sessionId,
|
||||
message,
|
||||
queryParams,
|
||||
clientId,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ interface ChatAIProps {
|
||||
assistantIDs?: string[];
|
||||
startPage?: StartPage;
|
||||
formatUrl?: (data: any) => string;
|
||||
instanceId?: string;
|
||||
}
|
||||
|
||||
export interface ChatAIRef {
|
||||
@@ -66,6 +67,7 @@ const ChatAI = memo(
|
||||
assistantIDs,
|
||||
startPage,
|
||||
formatUrl,
|
||||
instanceId,
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
@@ -91,7 +93,7 @@ const ChatAI = memo(
|
||||
const [activeChat, setActiveChat] = useState<Chat>();
|
||||
const [timedoutShow, setTimedoutShow] = useState(false);
|
||||
|
||||
const curIdRef = useRef("");
|
||||
const curSessionIdRef = useRef("");
|
||||
|
||||
const [isSidebarOpenChat, setIsSidebarOpenChat] = useState(isSidebarOpen);
|
||||
const [chats, setChats] = useState<Chat[]>([]);
|
||||
@@ -174,18 +176,19 @@ const ChatAI = memo(
|
||||
setTimedoutShow,
|
||||
clearAllChunkData,
|
||||
setQuestion,
|
||||
curIdRef,
|
||||
curSessionIdRef,
|
||||
setChats,
|
||||
dealMsgRef,
|
||||
isChatPage,
|
||||
isSearchActive,
|
||||
isDeepThinkActive,
|
||||
isMCPActive,
|
||||
changeInput,
|
||||
showChatHistory
|
||||
showChatHistory,
|
||||
);
|
||||
|
||||
const { dealMsg } = useMessageHandler(
|
||||
curIdRef,
|
||||
curSessionIdRef,
|
||||
setCurChatEnd,
|
||||
setTimedoutShow,
|
||||
(chat) => cancelChat(chat || activeChat),
|
||||
@@ -359,6 +362,7 @@ const ChatAI = memo(
|
||||
)}
|
||||
<div
|
||||
data-tauri-drag-region
|
||||
data-chat-instance={instanceId}
|
||||
className={`flex flex-col rounded-md h-full overflow-hidden relative`}
|
||||
>
|
||||
<ChatHeader
|
||||
@@ -392,6 +396,7 @@ const ChatAI = memo(
|
||||
}
|
||||
getFileUrl={getFileUrl}
|
||||
formatUrl={formatUrl}
|
||||
curSessionIdRef={curSessionIdRef}
|
||||
/>
|
||||
<Splash assistantIDs={assistantIDs} startPage={startPage} />
|
||||
</>
|
||||
|
||||
@@ -27,6 +27,7 @@ interface ChatContentProps {
|
||||
handleSendMessage: (content: string, newChat?: Chat) => void;
|
||||
getFileUrl: (path: string) => string;
|
||||
formatUrl?: (data: any) => string;
|
||||
curSessionIdRef: React.MutableRefObject<string>;
|
||||
}
|
||||
|
||||
export const ChatContent = ({
|
||||
@@ -44,7 +45,9 @@ export const ChatContent = ({
|
||||
Question,
|
||||
handleSendMessage,
|
||||
formatUrl,
|
||||
curSessionIdRef,
|
||||
}: ChatContentProps) => {
|
||||
console.log("curSessionIdRef", curSessionIdRef.current === activeChat?._id);
|
||||
// const sessionId = useConnectStore((state) => state.currentSessionId);
|
||||
const setCurrentSessionId = useConnectStore((state) => {
|
||||
return state.setCurrentSessionId;
|
||||
@@ -68,7 +71,7 @@ export const ChatContent = ({
|
||||
useEffect(() => {
|
||||
scrollToBottom();
|
||||
}, [
|
||||
activeChat?.id,
|
||||
activeChat?._id,
|
||||
query_intent?.message_chunk,
|
||||
fetch_source?.message_chunk,
|
||||
pick_source?.message_chunk,
|
||||
@@ -122,7 +125,7 @@ export const ChatContent = ({
|
||||
deep_read ||
|
||||
think ||
|
||||
response) &&
|
||||
activeChat?._id ? (
|
||||
activeChat?._id === curSessionIdRef.current ? (
|
||||
<ChatMessage
|
||||
key={"current"}
|
||||
message={{
|
||||
|
||||
@@ -43,17 +43,21 @@ export const QueryIntent = ({
|
||||
useEffect(() => {
|
||||
if (!ChunkData?.message_chunk) return;
|
||||
if (!loading) {
|
||||
const cleanContent = ChunkData.message_chunk.replace(/^"|"$/g, "");
|
||||
const allMatches = cleanContent.match(/<JSON>([\s\S]*?)<\/JSON>/g);
|
||||
if (allMatches) {
|
||||
const lastMatch = allMatches[allMatches.length - 1];
|
||||
const jsonString = lastMatch.replace(/<JSON>|<\/JSON>/g, "");
|
||||
const data = JSON.parse(jsonString);
|
||||
//console.log("QueryIntent", data);
|
||||
if (data?.suggestion && getSuggestion) {
|
||||
getSuggestion(data?.suggestion);
|
||||
try {
|
||||
const cleanContent = ChunkData.message_chunk.replace(/^"|"$/g, "");
|
||||
const allMatches = cleanContent.match(/<JSON>([\s\S]*?)<\/JSON>/g);
|
||||
if (allMatches) {
|
||||
const lastMatch = allMatches[allMatches.length - 1];
|
||||
const jsonString = lastMatch.replace(/<JSON>|<\/JSON>/g, "");
|
||||
const data = JSON.parse(jsonString);
|
||||
//console.log("QueryIntent", data);
|
||||
if (data?.suggestion && getSuggestion) {
|
||||
getSuggestion(data?.suggestion);
|
||||
}
|
||||
setData(data);
|
||||
}
|
||||
setData(data);
|
||||
} catch (error) {
|
||||
console.error("Failed to process message chunk in QueryIntent:", error);
|
||||
}
|
||||
}
|
||||
}, [ChunkData?.message_chunk, loading]);
|
||||
@@ -79,14 +83,22 @@ export const QueryIntent = ({
|
||||
<>
|
||||
<Loader className="w-4 h-4 animate-spin text-[#1990FF]" />
|
||||
<span className="text-xs text-[#999999] italic">
|
||||
{t(`assistant.message.steps.${ChunkData?.chunk_type || Detail.type}`)}
|
||||
{t(
|
||||
`assistant.message.steps.${
|
||||
ChunkData?.chunk_type || Detail.type
|
||||
}`
|
||||
)}
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<UnderstandIcon className="w-4 h-4 text-[#38C200]" />
|
||||
<span className="text-xs text-[#999999]">
|
||||
{t(`assistant.message.steps.${ChunkData?.chunk_type || Detail.type}`)}
|
||||
{t(
|
||||
`assistant.message.steps.${
|
||||
ChunkData?.chunk_type || Detail.type
|
||||
}`
|
||||
)}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -29,7 +29,7 @@ export const UserMessage = ({ messageContent }: UserMessageProps) => {
|
||||
|
||||
return (
|
||||
<div
|
||||
className="flex gap-1 items-center justify-end"
|
||||
className="max-w-full flex gap-1 items-center justify-end"
|
||||
onMouseEnter={() => setShowCopyButton(true)}
|
||||
onMouseLeave={() => setShowCopyButton(false)}
|
||||
>
|
||||
|
||||
@@ -176,13 +176,13 @@ export const ChatMessage = memo(function ChatMessage({
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"py-8 flex",
|
||||
"w-full py-8 flex",
|
||||
[isAssistant ? "justify-start" : "justify-end"],
|
||||
rootClassName
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={`px-4 flex gap-4 ${
|
||||
className={`w-full px-4 flex gap-4 ${
|
||||
isAssistant ? "w-full" : "flex-row-reverse"
|
||||
}`}
|
||||
>
|
||||
|
||||
@@ -271,6 +271,7 @@ function SearchChat({
|
||||
<ChatAI
|
||||
ref={chatAIRef}
|
||||
key="ChatAI"
|
||||
instanceId="search-chat"
|
||||
changeInput={setInput}
|
||||
isSearchActive={isSearchActive}
|
||||
isDeepThinkActive={isDeepThinkActive}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCallback, useEffect, useState, useRef } from "react";
|
||||
import { useCallback, useEffect, useState, useRef, useMemo } from "react";
|
||||
|
||||
import type { Chat } from "@/types/chat";
|
||||
import { useAppStore } from "@/stores/appStore";
|
||||
@@ -16,9 +16,10 @@ export function useChatActions(
|
||||
setTimedoutShow: (value: boolean) => void,
|
||||
clearAllChunkData: () => void,
|
||||
setQuestion: (value: string) => void,
|
||||
curIdRef: React.MutableRefObject<string>,
|
||||
curSessionIdRef: React.MutableRefObject<string>,
|
||||
setChats: (chats: Chat[]) => void,
|
||||
dealMsgRef: React.MutableRefObject<((msg: string) => void) | null>,
|
||||
isChatPage?: boolean,
|
||||
isSearchActive?: boolean,
|
||||
isDeepThinkActive?: boolean,
|
||||
isMCPActive?: boolean,
|
||||
@@ -40,6 +41,13 @@ export function useChatActions(
|
||||
|
||||
const [keyword, setKeyword] = useState("");
|
||||
|
||||
// Add a ref at the beginning of the useChatActions function to store the listener.
|
||||
const unlistenersRef = useRef<{
|
||||
message?: () => void;
|
||||
chatMessage?: () => void;
|
||||
error?: () => void;
|
||||
}>({});
|
||||
|
||||
const chatClose = useCallback(
|
||||
async (activeChat?: Chat) => {
|
||||
if (!activeChat?._id) return;
|
||||
@@ -61,9 +69,16 @@ export function useChatActions(
|
||||
[currentService?.id, isTauri]
|
||||
);
|
||||
|
||||
// 1. onSelectChat
|
||||
// 2. dealMsg setTimedoutShow
|
||||
// 3. disabledChange Manual shutdown
|
||||
const cancelChat = useCallback(
|
||||
async (activeChat?: Chat) => {
|
||||
setCurChatEnd(true);
|
||||
|
||||
// Stop listening for streaming data.
|
||||
cleanupListeners();
|
||||
|
||||
if (!activeChat?._id) return;
|
||||
let response: any;
|
||||
if (isTauri) {
|
||||
@@ -93,6 +108,7 @@ export function useChatActions(
|
||||
async (chat: Chat, callback?: (chat: Chat) => void) => {
|
||||
if (!chat?._id) return;
|
||||
|
||||
curSessionIdRef.current = chat?._id;
|
||||
let response: any;
|
||||
if (isTauri) {
|
||||
if (!currentService?.id) return;
|
||||
@@ -100,13 +116,13 @@ export function useChatActions(
|
||||
serverId: currentService?.id,
|
||||
sessionId: chat?._id,
|
||||
from: 0,
|
||||
size: 100,
|
||||
size: 1000,
|
||||
});
|
||||
response = response ? JSON.parse(response) : null;
|
||||
} else {
|
||||
const [_error, res] = await Get(`/chat/${chat?._id}/_history`, {
|
||||
from: 0,
|
||||
size: 100,
|
||||
size: 1000,
|
||||
});
|
||||
response = res;
|
||||
}
|
||||
@@ -134,14 +150,32 @@ export function useChatActions(
|
||||
[currentService?.id, isTauri, assistantList]
|
||||
);
|
||||
|
||||
// Modify the clientId generation logic to include the instance ID.
|
||||
const clientId = useMemo(() => {
|
||||
const timestamp = Date.now();
|
||||
const pageType = isChatPage ? "standalone-chat" : "search-chat";
|
||||
return `${pageType}-${timestamp}`;
|
||||
}, [isChatPage]);
|
||||
|
||||
const createNewChat = useCallback(
|
||||
async (value: string = "", activeChat?: Chat) => {
|
||||
if (!value) return;
|
||||
|
||||
// 1. Set up the listener first
|
||||
await setupListeners();
|
||||
|
||||
// 2. Update the status again
|
||||
changeInput && changeInput("");
|
||||
setCurChatEnd(false);
|
||||
setVisibleStartPage(false);
|
||||
setTimedoutShow(false);
|
||||
|
||||
// 3. Cleaning and preparation
|
||||
await chatClose(activeChat);
|
||||
clearAllChunkData();
|
||||
setQuestion(value);
|
||||
|
||||
//console.log("sourceDataIds", sourceDataIds, MCPIds, id);
|
||||
// 4. request API
|
||||
const queryParams = {
|
||||
search: isSearchActive,
|
||||
deep_thinking: isDeepThinkActive,
|
||||
@@ -150,13 +184,17 @@ export function useChatActions(
|
||||
mcp_servers: MCPIds?.join(",") || "",
|
||||
assistant_id: currentAssistant?._id || "",
|
||||
};
|
||||
|
||||
if (isTauri) {
|
||||
if (!currentService?.id) return;
|
||||
await platformAdapter.commands("chat_create", {
|
||||
serverId: currentService?.id,
|
||||
message: value,
|
||||
queryParams,
|
||||
clientId: `chat-stream-${clientId}`,
|
||||
});
|
||||
console.log("_create end", value);
|
||||
setCurChatEnd(true);
|
||||
} else {
|
||||
await streamPost({
|
||||
url: "/chat/_create",
|
||||
@@ -169,7 +207,6 @@ export function useChatActions(
|
||||
},
|
||||
});
|
||||
}
|
||||
console.log("_create", currentService?.id, value, queryParams);
|
||||
},
|
||||
[
|
||||
isTauri,
|
||||
@@ -179,9 +216,9 @@ export function useChatActions(
|
||||
isSearchActive,
|
||||
isDeepThinkActive,
|
||||
isMCPActive,
|
||||
curIdRef,
|
||||
currentAssistant,
|
||||
chatClose,
|
||||
clientId,
|
||||
]
|
||||
);
|
||||
|
||||
@@ -189,7 +226,18 @@ export function useChatActions(
|
||||
async (content: string, newChat: Chat) => {
|
||||
if (!newChat?._id || !content) return;
|
||||
|
||||
// 1.
|
||||
await setupListeners();
|
||||
|
||||
// 2.
|
||||
changeInput && changeInput("");
|
||||
setCurChatEnd(false);
|
||||
setVisibleStartPage(false);
|
||||
setTimedoutShow(false);
|
||||
|
||||
// 3.
|
||||
clearAllChunkData();
|
||||
setQuestion(content);
|
||||
|
||||
const queryParams = {
|
||||
search: isSearchActive,
|
||||
@@ -199,6 +247,7 @@ export function useChatActions(
|
||||
mcp_servers: MCPIds?.join(",") || "",
|
||||
assistant_id: currentAssistant?._id || "",
|
||||
};
|
||||
|
||||
if (isTauri) {
|
||||
if (!currentService?.id) return;
|
||||
await platformAdapter.commands("chat_chat", {
|
||||
@@ -206,7 +255,10 @@ export function useChatActions(
|
||||
sessionId: newChat?._id,
|
||||
queryParams,
|
||||
message: content,
|
||||
clientId: `chat-stream-${clientId}`,
|
||||
});
|
||||
console.log("chat_chat end", content);
|
||||
setCurChatEnd(true);
|
||||
} else {
|
||||
await streamPost({
|
||||
url: `/chat/${newChat?._id}/_chat`,
|
||||
@@ -219,14 +271,6 @@ export function useChatActions(
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log(
|
||||
"chat_chat",
|
||||
currentService?.id,
|
||||
newChat?._id,
|
||||
queryParams,
|
||||
content
|
||||
);
|
||||
},
|
||||
[
|
||||
isTauri,
|
||||
@@ -236,18 +280,15 @@ export function useChatActions(
|
||||
isSearchActive,
|
||||
isDeepThinkActive,
|
||||
isMCPActive,
|
||||
curIdRef,
|
||||
changeInput,
|
||||
currentAssistant,
|
||||
clientId,
|
||||
]
|
||||
);
|
||||
|
||||
const handleSendMessage = useCallback(
|
||||
async (content: string, activeChat?: Chat) => {
|
||||
if (!activeChat?._id || !content) return;
|
||||
setQuestion(content);
|
||||
|
||||
setTimedoutShow(false);
|
||||
|
||||
await chatHistory(activeChat, (chat) => sendMessage(content, chat));
|
||||
},
|
||||
@@ -257,80 +298,110 @@ export function useChatActions(
|
||||
const handleChatCreateStreamMessage = useCallback(
|
||||
(msg: string) => {
|
||||
if (
|
||||
msg.includes("_id") &&
|
||||
msg.includes(`"user"`) &&
|
||||
msg.includes("_source") &&
|
||||
msg.includes("result")
|
||||
) {
|
||||
const response = JSON.parse(msg);
|
||||
console.log("first", response);
|
||||
let updatedChat: Chat;
|
||||
if (Array.isArray(response)) {
|
||||
curIdRef.current = response[0]?._id;
|
||||
updatedChat = {
|
||||
...updatedChatRef.current,
|
||||
messages: [
|
||||
...(updatedChatRef.current?.messages || []),
|
||||
...(response || []),
|
||||
],
|
||||
};
|
||||
console.log("array", updatedChat, updatedChatRef.current?.messages);
|
||||
} else {
|
||||
const newChat: Chat = response;
|
||||
curIdRef.current = response?.payload?.id;
|
||||
try {
|
||||
const response = JSON.parse(msg);
|
||||
console.log("first", response);
|
||||
|
||||
newChat._source = {
|
||||
...response?.payload,
|
||||
};
|
||||
updatedChat = {
|
||||
...newChat,
|
||||
messages: [newChat],
|
||||
};
|
||||
let updatedChat: Chat;
|
||||
if (Array.isArray(response)) {
|
||||
curSessionIdRef.current = response[0]?._source?.session_id;
|
||||
console.log("first-curSessionIdRef-Array", curSessionIdRef.current);
|
||||
updatedChat = {
|
||||
...updatedChatRef.current,
|
||||
messages: [
|
||||
...(updatedChatRef.current?.messages || []),
|
||||
...(response || []),
|
||||
],
|
||||
};
|
||||
console.log("array", updatedChat, updatedChatRef.current?.messages);
|
||||
} else {
|
||||
const newChat: Chat = response;
|
||||
curSessionIdRef.current = response?.payload?.session_id;
|
||||
console.log("first-curSessionIdRef", curSessionIdRef.current);
|
||||
|
||||
newChat._source = {
|
||||
...response?.payload,
|
||||
};
|
||||
updatedChat = {
|
||||
...newChat,
|
||||
messages: [newChat],
|
||||
};
|
||||
}
|
||||
|
||||
setActiveChat(updatedChat);
|
||||
return;
|
||||
} catch (error) {
|
||||
console.error("Failed to parse JSON:", error, "Raw message:", msg);
|
||||
return;
|
||||
}
|
||||
|
||||
changeInput && changeInput("");
|
||||
setActiveChat(updatedChat);
|
||||
setCurChatEnd(false);
|
||||
setVisibleStartPage(false);
|
||||
return;
|
||||
}
|
||||
|
||||
dealMsgRef.current?.(msg);
|
||||
},
|
||||
[
|
||||
curIdRef,
|
||||
updatedChatRef,
|
||||
changeInput,
|
||||
setActiveChat,
|
||||
setCurChatEnd,
|
||||
setVisibleStartPage,
|
||||
dealMsgRef,
|
||||
]
|
||||
[changeInput, setActiveChat, setCurChatEnd, setVisibleStartPage]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isTauri || !currentService?.id) return;
|
||||
const cleanupListeners = useCallback(() => {
|
||||
if (unlistenersRef.current.chatMessage) {
|
||||
unlistenersRef.current.chatMessage();
|
||||
}
|
||||
if (unlistenersRef.current.error) {
|
||||
unlistenersRef.current.error();
|
||||
}
|
||||
unlistenersRef.current = {};
|
||||
}, []);
|
||||
|
||||
const unlisten_message = platformAdapter.listenEvent(
|
||||
`chat-create-stream`,
|
||||
const setupListeners = useCallback(async () => {
|
||||
cleanupListeners();
|
||||
|
||||
console.log("setupListeners", clientId);
|
||||
const unlisten_chat_message = await platformAdapter.listenEvent(
|
||||
`chat-stream-${clientId}`,
|
||||
(event) => {
|
||||
const msg = event.payload as string;
|
||||
//console.log("chat-create-stream", msg);
|
||||
try {
|
||||
console.log("msg:", JSON.parse(msg));
|
||||
console.log("user:", msg.includes(`"user"`));
|
||||
console.log("_source:", msg.includes("_source"));
|
||||
console.log("result:", msg.includes("result"));
|
||||
console.log("");
|
||||
console.log("");
|
||||
console.log("");
|
||||
console.log("");
|
||||
console.log("");
|
||||
} catch (error) {
|
||||
console.error("Failed to parse JSON in listener:", error);
|
||||
}
|
||||
|
||||
handleChatCreateStreamMessage(msg);
|
||||
}
|
||||
);
|
||||
|
||||
const unlisten_error = platformAdapter.listenEvent(
|
||||
const unlisten_error = await platformAdapter.listenEvent(
|
||||
`chat-create-error`,
|
||||
(event) => {
|
||||
console.error("chat-create-error", event.payload);
|
||||
}
|
||||
);
|
||||
|
||||
return () => {
|
||||
unlisten_message.then((fn) => fn());
|
||||
unlisten_error.then((fn) => fn());
|
||||
// Store the listener references.
|
||||
unlistenersRef.current = {
|
||||
chatMessage: unlisten_chat_message,
|
||||
error: unlisten_error,
|
||||
};
|
||||
}, [currentService?.id, dealMsgRef, updatedChatRef.current]);
|
||||
}, [currentService?.id, clientId, handleChatCreateStreamMessage]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isTauri || !currentService?.id) return;
|
||||
|
||||
return () => {
|
||||
cleanupListeners();
|
||||
};
|
||||
}, [currentService?.id]);
|
||||
|
||||
const openSessionChat = useCallback(
|
||||
async (chat: Chat) => {
|
||||
@@ -366,7 +437,7 @@ export function useChatActions(
|
||||
response = await platformAdapter.commands("chat_history", {
|
||||
serverId: currentService?.id,
|
||||
from: 0,
|
||||
size: 100,
|
||||
size: 1000,
|
||||
query: keyword,
|
||||
});
|
||||
|
||||
@@ -374,7 +445,7 @@ export function useChatActions(
|
||||
} else {
|
||||
const [_error, res] = await Get(`/chat/_history`, {
|
||||
from: 0,
|
||||
size: 100,
|
||||
size: 1000,
|
||||
});
|
||||
response = res;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { IChunkData, Chat } from "@/types/chat";
|
||||
import { useConnectStore } from "@/stores/connectStore";
|
||||
|
||||
export function useMessageHandler(
|
||||
curIdRef: React.MutableRefObject<string>,
|
||||
curSessionIdRef: React.MutableRefObject<string>,
|
||||
setCurChatEnd: (value: boolean) => void,
|
||||
setTimedoutShow: (value: boolean) => void,
|
||||
onCancel: (chat?: Chat) => void,
|
||||
@@ -41,8 +41,9 @@ export function useMessageHandler(
|
||||
|
||||
try {
|
||||
const chunkData = JSON.parse(msg);
|
||||
// console.log("chunkData", chunkData);
|
||||
|
||||
if (chunkData.reply_to_message !== curIdRef.current) return;
|
||||
if (chunkData.session_id !== curSessionIdRef.current) return;
|
||||
|
||||
setLoadingStep(() => ({
|
||||
query_intent: false,
|
||||
@@ -55,8 +56,6 @@ export function useMessageHandler(
|
||||
[chunkData.chunk_type]: true,
|
||||
}));
|
||||
|
||||
|
||||
|
||||
if (chunkData.chunk_type === "query_intent") {
|
||||
handlers.deal_query_intent(chunkData);
|
||||
} else if (chunkData.chunk_type === "tools") {
|
||||
@@ -87,7 +86,7 @@ export function useMessageHandler(
|
||||
}
|
||||
|
||||
if (inThinkRef.current) {
|
||||
handlers.deal_think({...chunkData, chunk_type: "think"});
|
||||
handlers.deal_think({ ...chunkData, chunk_type: "think" });
|
||||
} else {
|
||||
handlers.deal_response(chunkData);
|
||||
}
|
||||
@@ -105,13 +104,7 @@ export function useMessageHandler(
|
||||
console.error("parse error:", error);
|
||||
}
|
||||
},
|
||||
[
|
||||
onCancel,
|
||||
setCurChatEnd,
|
||||
setTimedoutShow,
|
||||
curIdRef.current,
|
||||
connectionTimeout,
|
||||
]
|
||||
[onCancel, setCurChatEnd, setTimedoutShow, connectionTimeout]
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -31,9 +31,9 @@ import { useSyncStore } from "@/hooks/useSyncStore";
|
||||
import { useAppStore } from "@/stores/appStore";
|
||||
import { unrequitable } from "@/utils";
|
||||
|
||||
interface ChatProps {}
|
||||
interface StandaloneChatProps {}
|
||||
|
||||
export default function Chat({}: ChatProps) {
|
||||
export default function StandaloneChat({}: StandaloneChatProps) {
|
||||
const setIsTauri = useAppStore((state) => state.setIsTauri);
|
||||
useEffect(() => {
|
||||
setIsTauri(true);
|
||||
@@ -77,7 +77,7 @@ export default function Chat({}: ChatProps) {
|
||||
let response: any = await chat_history({
|
||||
serverId: currentService?.id,
|
||||
from: 0,
|
||||
size: 100,
|
||||
size: 1000,
|
||||
query: keyword,
|
||||
});
|
||||
response = response ? JSON.parse(response) : null;
|
||||
@@ -122,7 +122,7 @@ export default function Chat({}: ChatProps) {
|
||||
serverId: currentService?.id,
|
||||
sessionId: chat?._id || "",
|
||||
from: 0,
|
||||
size: 100,
|
||||
size: 1000,
|
||||
});
|
||||
response = response ? JSON.parse(response) : null;
|
||||
console.log("id_history", response);
|
||||
@@ -304,6 +304,7 @@ export default function Chat({}: ChatProps) {
|
||||
<ChatAI
|
||||
ref={chatAIRef}
|
||||
key="ChatAI"
|
||||
instanceId="standalone-chat"
|
||||
activeChatProp={activeChat}
|
||||
isSearchActive={isSearchActive}
|
||||
isDeepThinkActive={isDeepThinkActive}
|
||||
|
||||
@@ -4,7 +4,7 @@ import Layout from "./layout";
|
||||
import ErrorPage from "@/pages/error/index";
|
||||
import DesktopApp from "@/pages/main/index";
|
||||
import SettingsPage from "@/pages/settings/index";
|
||||
import ChatAI from "@/pages/chat/index";
|
||||
import StandaloneChat from "@/pages/chat/index";
|
||||
import WebPage from "@/pages/web/index";
|
||||
import CheckPage from "@/pages/check/index";
|
||||
|
||||
@@ -25,7 +25,7 @@ export const router = createBrowserRouter(
|
||||
children: [
|
||||
{ path: "/ui", element: <DesktopApp /> },
|
||||
{ path: "/ui/settings", element: <SettingsPage /> },
|
||||
{ path: "/ui/chat", element: <ChatAI /> },
|
||||
{ path: "/ui/chat", element: <StandaloneChat /> },
|
||||
{ path: "/ui/check", element: <CheckPage /> },
|
||||
{ path: "/web", element: <WebPage /> },
|
||||
],
|
||||
|
||||
@@ -14,9 +14,10 @@ export interface ISource {
|
||||
message?: any;
|
||||
title?: string;
|
||||
question?: string;
|
||||
details?: any[];
|
||||
details?: any[] | null;
|
||||
assistant_id?: string;
|
||||
assistant_item?: any;
|
||||
[key: string]: any;
|
||||
}
|
||||
export interface Chat {
|
||||
_id?: string;
|
||||
|
||||
@@ -48,7 +48,7 @@ export interface EventPayloads {
|
||||
"install-extension": void;
|
||||
"uninstall-extension": void;
|
||||
"config-extension": string;
|
||||
"chat-create-stream": string;
|
||||
[key: `chat-stream-${string}`]: string;
|
||||
"chat-create-error": string;
|
||||
[key: `synthesize-${string}`]: any;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user