From 3aa433f1da3e2ab51964427265e2b30f8a704365 Mon Sep 17 00:00:00 2001 From: BiggerRain <15911122312@163.COM> Date: Tue, 4 Mar 2025 21:20:48 +0800 Subject: [PATCH] chore: message icon update & message history (#239) --- src/components/Assistant/Chat.tsx | 1 + src/components/Assistant/types.ts | 1 + src/components/ChatMessage/DeepRead.tsx | 16 ++- src/components/ChatMessage/FetchSource.tsx | 14 ++- src/components/ChatMessage/PickSource.tsx | 16 ++- src/components/ChatMessage/QueryIntent.tsx | 26 +++-- src/components/ChatMessage/Think.tsx | 13 ++- src/components/ChatMessage/index.tsx | 42 +++++--- src/icons/Reading.tsx | 104 ++++++++++++++++++++ src/icons/Retrieve.tsx | 37 +++++++ src/icons/Selection.tsx | 108 +++++++++++++++++++++ src/icons/Understand.tsx | 103 ++++++++++++++++++++ 12 files changed, 447 insertions(+), 34 deletions(-) create mode 100644 src/icons/Reading.tsx create mode 100644 src/icons/Retrieve.tsx create mode 100644 src/icons/Selection.tsx create mode 100644 src/icons/Understand.tsx diff --git a/src/components/Assistant/Chat.tsx b/src/components/Assistant/Chat.tsx index 43f6f90b..720bb8d9 100644 --- a/src/components/Assistant/Chat.tsx +++ b/src/components/Assistant/Chat.tsx @@ -554,6 +554,7 @@ const ChatAI = memo( ...chat, messages: hits, }; + console.log("id_history2", updatedChat) setActiveChat(updatedChat); callback && callback(updatedChat) } catch (error) { diff --git a/src/components/Assistant/types.ts b/src/components/Assistant/types.ts index b40fcdc4..329eecd3 100644 --- a/src/components/Assistant/types.ts +++ b/src/components/Assistant/types.ts @@ -14,6 +14,7 @@ export interface ISource { message?: any; title?: string; question?: string; + details?: any[]; } export interface Chat { _id: string; diff --git a/src/components/ChatMessage/DeepRead.tsx b/src/components/ChatMessage/DeepRead.tsx index c5d468e4..aa2da799 100644 --- a/src/components/ChatMessage/DeepRead.tsx +++ b/src/components/ChatMessage/DeepRead.tsx @@ -1,14 +1,16 @@ -import { ChevronDown, ChevronUp, Loader, BadgeCheck } from "lucide-react"; +import { ChevronDown, ChevronUp, Loader } from "lucide-react"; import { useState, useEffect } from "react"; import { useTranslation } from "react-i18next"; import type { IChunkData } from "@/components/Assistant/types"; +import ReadingIcon from "@/icons/Reading"; interface DeepReadeProps { + Detail?: any; ChunkData?: IChunkData; } -export const DeepRead = ({ ChunkData }: DeepReadeProps) => { +export const DeepRead = ({ Detail, ChunkData }: DeepReadeProps) => { const { t } = useTranslation(); const [isThinkingExpanded, setIsThinkingExpanded] = useState(false); @@ -18,6 +20,12 @@ export const DeepRead = ({ ChunkData }: DeepReadeProps) => { const [Data, setData] = useState([]); + useEffect(() => { + if (!Detail?.description) return; + setData(Detail?.description); + setLoading(false); + }, [Detail?.description]); + useEffect(() => { if (!ChunkData?.message_chunk) return; const timerID = setTimeout(() => { @@ -47,7 +55,7 @@ export const DeepRead = ({ ChunkData }: DeepReadeProps) => { }, [ChunkData?.message_chunk]); // Must be after hooks !!! - if (!ChunkData) return null; + if (!ChunkData && !Detail) return null; return (
@@ -64,7 +72,7 @@ export const DeepRead = ({ ChunkData }: DeepReadeProps) => { ) : ( <> - + {t(`assistant.message.steps.${ChunkData?.chunk_type}`, { count: Number(Data.length), diff --git a/src/components/ChatMessage/FetchSource.tsx b/src/components/ChatMessage/FetchSource.tsx index 35fdfe0d..10f4a398 100644 --- a/src/components/ChatMessage/FetchSource.tsx +++ b/src/components/ChatMessage/FetchSource.tsx @@ -1,5 +1,4 @@ import { - Search, ChevronUp, ChevronDown, SquareArrowOutUpRight, @@ -10,8 +9,10 @@ import { useTranslation } from "react-i18next"; import { OpenURLWithBrowser } from "@/utils/index"; import type { IChunkData } from "@/components/Assistant/types"; +import RetrieveIcon from "@/icons/Retrieve"; interface FetchSourceProps { + Detail?: any; ChunkData?: IChunkData; } @@ -32,13 +33,18 @@ interface ISourceData { url: string; } -export const FetchSource = ({ ChunkData }: FetchSourceProps) => { +export const FetchSource = ({ Detail, ChunkData }: FetchSourceProps) => { const { t } = useTranslation(); const [isSourceExpanded, setIsSourceExpanded] = useState(false); const [total, setTotal] = useState(0); const [data, setData] = useState([]); + useEffect(() => { + if (!Detail?.payload) return; + setData(Detail?.payload); + }, [Detail?.payload]); + useEffect(() => { if (!ChunkData?.message_chunk) return; @@ -61,7 +67,7 @@ export const FetchSource = ({ ChunkData }: FetchSourceProps) => { }, [ChunkData?.message_chunk]); // Must be after hooks !!! - if (!ChunkData) return null; + if (!ChunkData && !Detail) return null; return (
{ }`} >
- + {t(`assistant.message.steps.${ChunkData?.chunk_type}`, { count: Number(total), diff --git a/src/components/ChatMessage/PickSource.tsx b/src/components/ChatMessage/PickSource.tsx index 7860bf44..e2c5f91b 100644 --- a/src/components/ChatMessage/PickSource.tsx +++ b/src/components/ChatMessage/PickSource.tsx @@ -1,10 +1,12 @@ -import { ChevronDown, ChevronUp, Loader, BadgeCheck } from "lucide-react"; +import { ChevronDown, ChevronUp, Loader } from "lucide-react"; import { useState, useEffect } from "react"; import { useTranslation } from "react-i18next"; import type { IChunkData } from "@/components/Assistant/types"; +import SelectionIcon from "@/icons/Selection"; interface PickSourceProps { + Detail?: any; ChunkData?: IChunkData; } @@ -14,7 +16,7 @@ interface IData { title: string; } -export const PickSource = ({ ChunkData }: PickSourceProps) => { +export const PickSource = ({ Detail, ChunkData }: PickSourceProps) => { const { t } = useTranslation(); const [isThinkingExpanded, setIsThinkingExpanded] = useState(false); @@ -24,6 +26,12 @@ export const PickSource = ({ ChunkData }: PickSourceProps) => { const [Data, setData] = useState([]); + useEffect(() => { + if (!Detail?.payload) return; + setData(Detail?.payload); + setLoading(false) + }, [Detail?.payload]); + useEffect(() => { if (!ChunkData?.message_chunk) return; @@ -78,7 +86,7 @@ export const PickSource = ({ ChunkData }: PickSourceProps) => { }, [ChunkData?.message_chunk]); // Must be after hooks !!! - if (!ChunkData) return null; + if (!ChunkData && !Detail) return null; return (
@@ -95,7 +103,7 @@ export const PickSource = ({ ChunkData }: PickSourceProps) => { ) : ( <> - + {t(`assistant.message.steps.${ChunkData?.chunk_type}`, { count: Data?.length, diff --git a/src/components/ChatMessage/QueryIntent.tsx b/src/components/ChatMessage/QueryIntent.tsx index 27519dea..3f321f59 100644 --- a/src/components/ChatMessage/QueryIntent.tsx +++ b/src/components/ChatMessage/QueryIntent.tsx @@ -1,10 +1,12 @@ -import { ChevronDown, ChevronUp, Loader, BadgeCheck } from "lucide-react"; +import { ChevronDown, ChevronUp, Loader } from "lucide-react"; import { useState, useEffect } from "react"; import { useTranslation } from "react-i18next"; import type { IChunkData } from "@/components/Assistant/types"; +import UnderstandIcon from "@/icons/Understand"; interface QueryIntentProps { + Detail?: any; ChunkData?: IChunkData; getSuggestion?: (suggestion: string[]) => void; } @@ -17,7 +19,11 @@ interface IQueryData { suggestion: string[]; } -export const QueryIntent = ({ ChunkData, getSuggestion }: QueryIntentProps) => { +export const QueryIntent = ({ + Detail, + ChunkData, + getSuggestion, +}: QueryIntentProps) => { const { t } = useTranslation(); const [isThinkingExpanded, setIsThinkingExpanded] = useState(false); @@ -27,6 +33,12 @@ export const QueryIntent = ({ ChunkData, getSuggestion }: QueryIntentProps) => { const [Data, setData] = useState(null); + useEffect(() => { + if (!Detail?.payload) return; + setData(Detail?.payload); + setLoading(false); + }, [Detail?.payload]); + useEffect(() => { if (!ChunkData?.message_chunk) return; const timerID = setTimeout(() => { @@ -39,7 +51,7 @@ export const QueryIntent = ({ ChunkData, getSuggestion }: QueryIntentProps) => { const data = JSON.parse(jsonString); // console.log("QueryIntent", data); if (data?.suggestion && getSuggestion) { - getSuggestion(data?.suggestion) + getSuggestion(data?.suggestion); } setData(data); } @@ -62,7 +74,7 @@ export const QueryIntent = ({ ChunkData, getSuggestion }: QueryIntentProps) => { }, [ChunkData?.message_chunk]); // Must be after hooks !!! - if (!ChunkData) return null; + if (!ChunkData && !Detail) return null; return (
@@ -74,14 +86,14 @@ export const QueryIntent = ({ ChunkData, getSuggestion }: QueryIntentProps) => { <> - {t(`assistant.message.steps.${ChunkData?.chunk_type}`)} + {t(`assistant.message.steps.${ChunkData?.chunk_type || Detail.type}`)} ) : ( <> - + - {t(`assistant.message.steps.${ChunkData?.chunk_type}`)} + {t(`assistant.message.steps.${ChunkData?.chunk_type || Detail.type}`)} )} diff --git a/src/components/ChatMessage/Think.tsx b/src/components/ChatMessage/Think.tsx index 442761af..cf380bcc 100644 --- a/src/components/ChatMessage/Think.tsx +++ b/src/components/ChatMessage/Think.tsx @@ -5,16 +5,23 @@ import { useTranslation } from "react-i18next"; import type { IChunkData } from "@/components/Assistant/types"; interface ThinkProps { + Detail?: any; ChunkData?: IChunkData; } -export const Think = ({ ChunkData }: ThinkProps) => { +export const Think = ({ Detail, ChunkData }: ThinkProps) => { const { t } = useTranslation(); const [isThinkingExpanded, setIsThinkingExpanded] = useState(true); const [loading, setLoading] = useState(true); const [Data, setData] = useState(""); + useEffect(() => { + if (!Detail?.description) return; + setData(Detail?.description); + setLoading(false); + }, [Detail?.description]); + useEffect(() => { if (!ChunkData?.message_chunk) return; const timerID = setTimeout(() => { @@ -30,7 +37,7 @@ export const Think = ({ ChunkData }: ThinkProps) => { }, [ChunkData?.message_chunk, Data, loading]); // Must be after hooks !!! - if (!ChunkData) return null; + if (!ChunkData && !Detail) return null; return (
@@ -40,7 +47,7 @@ export const Think = ({ ChunkData }: ThinkProps) => { > {loading ? ( <> - + {t(`assistant.message.steps.${ChunkData?.chunk_type}`)} diff --git a/src/components/ChatMessage/index.tsx b/src/components/ChatMessage/index.tsx index 5534b904..189c42d2 100644 --- a/src/components/ChatMessage/index.tsx +++ b/src/components/ChatMessage/index.tsx @@ -39,6 +39,7 @@ export const ChatMessage = memo(function ChatMessage({ const isAssistant = message?._source?.type === "assistant"; const messageContent = message?._source?.message || ""; + const details = message?._source?.details || []; const question = message?._source?.question || ""; const showActions = @@ -47,9 +48,8 @@ export const ChatMessage = memo(function ChatMessage({ const [suggestion, setSuggestion] = useState([]); const getSuggestion = (suggestion: string[]) => { - setSuggestion(suggestion) - } - + setSuggestion(suggestion); + }; const renderContent = () => { if (!isAssistant) { @@ -62,11 +62,27 @@ export const ChatMessage = memo(function ChatMessage({ return ( <> - - - - - + item.type === "query_intent")} + ChunkData={query_intent} + getSuggestion={getSuggestion} + /> + item.type === "fetch_source")} + ChunkData={fetch_source} + /> + item.type === "pick_source")} + ChunkData={pick_source} + /> + item.type === "deep_read")} + ChunkData={deep_read} + /> + item.type === "think")} + ChunkData={think} + /> )} - {!isTyping && onResend && onResend(text)} - />} + {!isTyping && ( + onResend && onResend(text)} + /> + )} ); }; diff --git a/src/icons/Reading.tsx b/src/icons/Reading.tsx new file mode 100644 index 00000000..966b9544 --- /dev/null +++ b/src/icons/Reading.tsx @@ -0,0 +1,104 @@ +import SVGWrap from "./SVGWrap"; + +export default function Reading(props: I.SVG) { + return ( + + + + + + + + + + + + + + + + ); +} diff --git a/src/icons/Retrieve.tsx b/src/icons/Retrieve.tsx new file mode 100644 index 00000000..c9352a91 --- /dev/null +++ b/src/icons/Retrieve.tsx @@ -0,0 +1,37 @@ +import SVGWrap from "./SVGWrap"; + +export default function Retrieve(props: I.SVG) { + return ( + + + + + + + ); +} diff --git a/src/icons/Selection.tsx b/src/icons/Selection.tsx new file mode 100644 index 00000000..b2c28db5 --- /dev/null +++ b/src/icons/Selection.tsx @@ -0,0 +1,108 @@ +import SVGWrap from "./SVGWrap"; + +export default function Selection(props: I.SVG) { + return ( + + + + + + + + + + + + + + + + ); +} diff --git a/src/icons/Understand.tsx b/src/icons/Understand.tsx new file mode 100644 index 00000000..93311ac0 --- /dev/null +++ b/src/icons/Understand.tsx @@ -0,0 +1,103 @@ +import SVGWrap from "./SVGWrap"; + +export default function Understand(props: I.SVG) { + return ( + + + + + + + + + + + + + + + + + + ); +}