From 4ca064ebdcc97908f2b3714467531791cad9765d Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Tue, 9 May 2023 18:02:43 -0300 Subject: [PATCH] fixed duplicated message --- .../chatModal/chatMessage/codeBlock/index.tsx | 8 + .../modals/chatModal/chatMessage/index.tsx | 8 + src/frontend/src/modals/chatModal/index.tsx | 716 +++++++++--------- 3 files changed, 374 insertions(+), 358 deletions(-) create mode 100644 src/frontend/src/modals/chatModal/chatMessage/codeBlock/index.tsx diff --git a/src/frontend/src/modals/chatModal/chatMessage/codeBlock/index.tsx b/src/frontend/src/modals/chatModal/chatMessage/codeBlock/index.tsx new file mode 100644 index 000000000..2e699a5c7 --- /dev/null +++ b/src/frontend/src/modals/chatModal/chatMessage/codeBlock/index.tsx @@ -0,0 +1,8 @@ +export default function codeBlock() { + // a html custom element for code blocks in markdown texts, it will allow to download the code as a file or copy it to the clipboard + return ( +
+

Code Block

+
+ ) +} diff --git a/src/frontend/src/modals/chatModal/chatMessage/index.tsx b/src/frontend/src/modals/chatModal/chatMessage/index.tsx index 033d02b48..3ae1c6b6a 100644 --- a/src/frontend/src/modals/chatModal/chatMessage/index.tsx +++ b/src/frontend/src/modals/chatModal/chatMessage/index.tsx @@ -65,6 +65,14 @@ export default function ChatMessage({ chat }: { chat: ChatMessageType }) { remarkPlugins={[remarkGfm, remarkMath]} rehypePlugins={[rehypeMathjax]} className="markdown prose" + // components={{ + // code: (props) => ( + // + // ), + // }} > {message} diff --git a/src/frontend/src/modals/chatModal/index.tsx b/src/frontend/src/modals/chatModal/index.tsx index c6caffb26..8070569e2 100644 --- a/src/frontend/src/modals/chatModal/index.tsx +++ b/src/frontend/src/modals/chatModal/index.tsx @@ -14,383 +14,383 @@ import ChatInput from "./chatInput"; const _ = require("lodash"); export default function ChatModal({ - flow, - open, - setOpen, + flow, + open, + setOpen, }: { - open: boolean; - setOpen: Function; - flow: FlowType; + open: boolean; + setOpen: Function; + flow: FlowType; }) { - const [chatValue, setChatValue] = useState(""); - const [chatHistory, setChatHistory] = useState([]); - const { reactFlowInstance } = useContext(typesContext); - const { setErrorData, setNoticeData } = useContext(alertContext); - const ws = useRef(null); - const [lockChat, setLockChat] = useState(false); - const isOpen = useRef(open); + const [chatValue, setChatValue] = useState(""); + const [chatHistory, setChatHistory] = useState([]); + const { reactFlowInstance } = useContext(typesContext); + const { setErrorData, setNoticeData } = useContext(alertContext); + const ws = useRef(null); + const [lockChat, setLockChat] = useState(false); + const isOpen = useRef(open); - useEffect(() => { - isOpen.current = open; - }, [open]); - var isStream = false; + useEffect(() => { + isOpen.current = open; + }, [open]); + var isStream = false; - const addChatHistory = ( - message: string, - isSend: boolean, - thought?: string, - files?: Array - ) => { - setChatHistory((old) => { - let newChat = _.cloneDeep(old); - if (files) { - newChat.push({ message, isSend, files, thought }); - } else if (thought) { - newChat.push({ message, isSend, thought }); - } else { - newChat.push({ message, isSend }); - } - return newChat; - }); - }; + const addChatHistory = ( + message: string, + isSend: boolean, + thought?: string, + files?: Array + ) => { + setChatHistory((old) => { + let newChat = _.cloneDeep(old); + if (files) { + newChat.push({ message, isSend, files, thought }); + } else if (thought) { + newChat.push({ message, isSend, thought }); + } else { + newChat.push({ message, isSend }); + } + return newChat; + }); + }; - //add proper type signature for function + //add proper type signature for function - function updateLastMessage({ - str, - thought, - end = false, - }: { - str?: string; - thought?: string; - // end param default is false - end?: boolean; - }) { - setChatHistory((old) => { - let newChat = [...old]; - if (str) { - if (end && !newChat[newChat.length - 1].message) { - newChat[newChat.length - 1].message = str; - } - newChat[newChat.length - 1].message = - newChat[newChat.length - 1].message + str; - } - if (thought) { - newChat[newChat.length - 1].thought = thought; - } - return newChat; - }); - } + function updateLastMessage({ + str, + thought, + end = false, + }: { + str?: string; + thought?: string; + // end param default is false + end?: boolean; + }) { + setChatHistory((old) => { + let newChat = [...old]; + if (str) { + if (end) { + newChat[newChat.length - 1].message = str; + } else { + newChat[newChat.length - 1].message = + newChat[newChat.length - 1].message + str; + } + } + if (thought) { + newChat[newChat.length - 1].thought = thought; + } + return newChat; + }); + } - function handleOnClose(event: CloseEvent) { - if (isOpen.current) { - setLockChat(false); - setTimeout(() => { - connectWS(); - }, 1000); - } - } + function handleOnClose(event: CloseEvent) { + if (isOpen.current) { + setLockChat(false); + setTimeout(() => { + connectWS(); + }, 1000); + } + } - function handleWsMessage(data: any) { - if (Array.isArray(data)) { - //set chat history - setChatHistory((_) => { - let newChatHistory: ChatMessageType[] = []; - data.forEach( - (chatItem: { - intermediate_steps?: "string"; - is_bot: boolean; - message: string; - type: string; - files?: Array; - }) => { - if (chatItem.message) { - newChatHistory.push( - chatItem.files - ? { - isSend: !chatItem.is_bot, - message: chatItem.message, - thought: chatItem.intermediate_steps, - files: chatItem.files, - } - : { - isSend: !chatItem.is_bot, - message: chatItem.message, - thought: chatItem.intermediate_steps, - } - ); - } - } - ); - return newChatHistory; - }); - } - if (data.type === "start") { - console.log("start"); - addChatHistory("", false); - isStream = true; - } - if (data.type === "end") { - if (data.intermediate_steps) { - updateLastMessage({ - str: data.message, - thought: data.intermediate_steps, - end: true, - }); - - } - setLockChat(false); - isStream = false; - } - if (data.type === "file") { - console.log(data); - } - if (data.type === "stream" && isStream) { - updateLastMessage({ str: data.message }); - } - } + function handleWsMessage(data: any) { + if (Array.isArray(data)) { + //set chat history + setChatHistory((_) => { + let newChatHistory: ChatMessageType[] = []; + data.forEach( + (chatItem: { + intermediate_steps?: "string"; + is_bot: boolean; + message: string; + type: string; + files?: Array; + }) => { + if (chatItem.message) { + newChatHistory.push( + chatItem.files + ? { + isSend: !chatItem.is_bot, + message: chatItem.message, + thought: chatItem.intermediate_steps, + files: chatItem.files, + } + : { + isSend: !chatItem.is_bot, + message: chatItem.message, + thought: chatItem.intermediate_steps, + } + ); + } + } + ); + return newChatHistory; + }); + } + if (data.type === "start") { + console.log("start"); + addChatHistory("", false); + isStream = true; + } + if (data.type === "end") { + if (data.intermediate_steps) { + updateLastMessage({ + str: data.message, + thought: data.intermediate_steps, + end: true, + }); + } + setLockChat(false); + isStream = false; + } + if (data.type === "file") { + console.log(data); + } + if (data.type === "stream" && isStream) { + updateLastMessage({ str: data.message }); + } + } - function connectWS() { - try { - const urlWs = - process.env.NODE_ENV === "development" - ? `ws://localhost:7860/chat/${flow.id}` - : `${window.location.protocol === "https:" ? "wss" : "ws"}://${ - window.location.host - }/chat/${flow.id}`; + function connectWS() { + try { + const urlWs = + process.env.NODE_ENV === "development" + ? `ws://localhost:7860/chat/${flow.id}` + : `${window.location.protocol === "https:" ? "wss" : "ws"}://${ + window.location.host + }/chat/${flow.id}`; - const newWs = new WebSocket(urlWs); - newWs.onopen = () => { - console.log("WebSocket connection established!"); - }; - console.log(flow.id); - newWs.onmessage = (event) => { - const data = JSON.parse(event.data); - console.log("Received data:", data); - handleWsMessage(data); - //get chat history - }; - newWs.onclose = (event) => { - handleOnClose(event); - }; - newWs.onerror = (ev) => { - console.log(ev, "error"); - setErrorData({ - title: "There was an error on web connection, please: ", - list: [ - "Refresh the page", - "Use a new flow tab", - "Check if the backend is up", - ], - }); - }; - ws.current = newWs; - } catch { - setErrorData({ - title: "There was an error on web connection, please: ", - list: [ - "Refresh the page", - "Use a new flow tab", - "Check if the backend is up", - ], - }); - } - } + const newWs = new WebSocket(urlWs); + newWs.onopen = () => { + console.log("WebSocket connection established!"); + }; + console.log(flow.id); + newWs.onmessage = (event) => { + const data = JSON.parse(event.data); + console.log("Received data:", data); + handleWsMessage(data); + //get chat history + }; + newWs.onclose = (event) => { + handleOnClose(event); + }; + newWs.onerror = (ev) => { + console.log(ev, "error"); + setErrorData({ + title: "There was an error on web connection, please: ", + list: [ + "Refresh the page", + "Use a new flow tab", + "Check if the backend is up", + ], + }); + }; + ws.current = newWs; + } catch { + setErrorData({ + title: "There was an error on web connection, please: ", + list: [ + "Refresh the page", + "Use a new flow tab", + "Check if the backend is up", + ], + }); + } + } - useEffect(() => { - connectWS(); - return () => { - console.log("unmount"); - console.log(ws); - if (ws) { - ws.current.close(); - } - }; - }, []); + useEffect(() => { + connectWS(); + return () => { + console.log("unmount"); + console.log(ws); + if (ws) { + ws.current.close(); + } + }; + }, []); - async function sendAll(data: sendAllProps) { - try { - if (ws) { - ws.current.send(JSON.stringify(data)); - } - } catch (error) { - setErrorData({ - title: "There was an erro sending the message", - list: [error.message], - }); - setChatValue(data.message); - connectWS(); - } - } + async function sendAll(data: sendAllProps) { + try { + if (ws) { + ws.current.send(JSON.stringify(data)); + } + } catch (error) { + setErrorData({ + title: "There was an erro sending the message", + list: [error.message], + }); + setChatValue(data.message); + connectWS(); + } + } - useEffect(() => { - if (ref.current) ref.current.scrollIntoView({ behavior: "smooth" }); - }, [chatHistory]); + useEffect(() => { + if (ref.current) ref.current.scrollIntoView({ behavior: "smooth" }); + }, [chatHistory]); - function validateNode(n: NodeType): Array { - if (!n.data?.node?.template || !Object.keys(n.data.node.template)) { - setNoticeData({ - title: - "We've noticed a potential issue with a node in the flow. Please review it and, if necessary, submit a bug report with your exported flow file. Thank you for your help!", - }); - return []; - } + function validateNode(n: NodeType): Array { + if (!n.data?.node?.template || !Object.keys(n.data.node.template)) { + setNoticeData({ + title: + "We've noticed a potential issue with a node in the flow. Please review it and, if necessary, submit a bug report with your exported flow file. Thank you for your help!", + }); + return []; + } - const { - type, - node: { template }, - } = n.data; + const { + type, + node: { template }, + } = n.data; - return Object.keys(template).reduce( - (errors: Array, t) => - errors.concat( - template[t].required && - template[t].show && - (!template[t].value || template[t].value === "") && - !reactFlowInstance - .getEdges() - .some( - (e) => - e.targetHandle.split("|")[1] === t && - e.targetHandle.split("|")[2] === n.id - ) - ? [ - `${type} is missing ${ - template.display_name - ? template.display_name - : toNormalCase(template[t].name) - }.`, - ] - : [] - ), - [] as string[] - ); - } + return Object.keys(template).reduce( + (errors: Array, t) => + errors.concat( + template[t].required && + template[t].show && + (!template[t].value || template[t].value === "") && + !reactFlowInstance + .getEdges() + .some( + (e) => + e.targetHandle.split("|")[1] === t && + e.targetHandle.split("|")[2] === n.id + ) + ? [ + `${type} is missing ${ + template.display_name + ? template.display_name + : toNormalCase(template[t].name) + }.`, + ] + : [] + ), + [] as string[] + ); + } - function validateNodes() { - return reactFlowInstance - .getNodes() - .flatMap((n: NodeType) => validateNode(n)); - } + function validateNodes() { + return reactFlowInstance + .getNodes() + .flatMap((n: NodeType) => validateNode(n)); + } - const ref = useRef(null); + const ref = useRef(null); - function sendMessage() { - if (chatValue !== "") { - let nodeValidationErrors = validateNodes(); - if (nodeValidationErrors.length === 0) { - setLockChat(true); - let message = chatValue; - setChatValue(""); - addChatHistory(message, true); - sendAll({ - ...reactFlowInstance.toObject(), - message, - chatHistory, - name: flow.name, - description: flow.description, - }); - } else { - setErrorData({ - title: "Oops! Looks like you missed some required information:", - list: nodeValidationErrors, - }); - } - } else { - setErrorData({ - title: "Error sending message", - list: ["The message cannot be empty."], - }); - } - } - function clearChat() { - setChatHistory([]); - ws.current.send(JSON.stringify({ clear_history: true })); - } + function sendMessage() { + if (chatValue !== "") { + let nodeValidationErrors = validateNodes(); + if (nodeValidationErrors.length === 0) { + setLockChat(true); + let message = chatValue; + setChatValue(""); + addChatHistory(message, true); + sendAll({ + ...reactFlowInstance.toObject(), + message, + chatHistory, + name: flow.name, + description: flow.description, + }); + } else { + setErrorData({ + title: "Oops! Looks like you missed some required information:", + list: nodeValidationErrors, + }); + } + } else { + setErrorData({ + title: "Error sending message", + list: ["The message cannot be empty."], + }); + } + } + function clearChat() { + setChatHistory([]); + ws.current.send(JSON.stringify({ clear_history: true })); + } - function setModalOpen(x: boolean) { - setOpen(x); - } - return ( - - - -
- + function setModalOpen(x: boolean) { + setOpen(x); + } + return ( + + + +
+ -
-
- - -
- -
-
- {chatHistory.length > 0 ? ( - chatHistory.map((c, i) => ) - ) : ( -
- - 👋{" "} - - LangFlow Chat - - -
-
- - Start a conversation and click the agent’s thoughts{" "} - - - {" "} - to inspect the chaining process. - -
-
- )} -
-
-
-
- -
-
-
-
-
-
-
-
- ); +
+
+ + +
+ +
+
+ {chatHistory.length > 0 ? ( + chatHistory.map((c, i) => ) + ) : ( +
+ + 👋{" "} + + LangFlow Chat + + +
+
+ + Start a conversation and click the agent’s thoughts{" "} + + + {" "} + to inspect the chaining process. + +
+
+ )} +
+
+
+
+ +
+
+
+
+
+
+
+
+ ); }