From 7723295dc169c77ac7d68a4201053aeeecec98e4 Mon Sep 17 00:00:00 2001 From: Thibaut Patel Date: Thu, 18 Apr 2024 16:21:08 +0200 Subject: [PATCH 01/14] Update thread list on first interaction - re-fetch the thread list on first interaction - navigate to /thread/:id url when creating a new conversation - update the /thread/:id page to allow for displaying the current chat - add `threadId` to `useChatMessages` to get the current conversation thread id - update "back to conversation" links - clear current conversation when deleting the current thread --- .../src/components/organisms/chat/index.tsx | 5 ++- .../organisms/threadHistory/Thread.tsx | 11 ++++- .../threadHistory/sidebar/ThreadList.tsx | 4 +- .../organisms/threadHistory/sidebar/index.tsx | 36 ++++++++++++++-- frontend/src/pages/Thread.tsx | 43 +++++++++++++------ libs/react-client/src/useChatMessages.ts | 3 ++ 6 files changed, 81 insertions(+), 21 deletions(-) diff --git a/frontend/src/components/organisms/chat/index.tsx b/frontend/src/components/organisms/chat/index.tsx index 6933a57988..73f7f82adf 100644 --- a/frontend/src/components/organisms/chat/index.tsx +++ b/frontend/src/components/organisms/chat/index.tsx @@ -10,6 +10,7 @@ import { threadHistoryState, useChatData, useChatInteract, + useChatMessages, useChatSession } from '@chainlit/react-client'; import { sideViewState } from '@chainlit/react-client'; @@ -151,10 +152,12 @@ const Chat = () => { options: { noClick: true } }); + const { threadId } = useChatMessages(); + useEffect(() => { setThreads((prev) => ({ ...prev, - currentThreadId: undefined + currentThreadId: threadId })); }, []); diff --git a/frontend/src/components/organisms/threadHistory/Thread.tsx b/frontend/src/components/organisms/threadHistory/Thread.tsx index 2f113a5397..b41ccc9315 100644 --- a/frontend/src/components/organisms/threadHistory/Thread.tsx +++ b/frontend/src/components/organisms/threadHistory/Thread.tsx @@ -13,7 +13,8 @@ import { IStep, IThread, accessTokenState, - nestMessages + nestMessages, + useChatMessages } from '@chainlit/react-client'; import SideView from 'components/atoms/element/sideView'; @@ -33,6 +34,7 @@ const Thread = ({ thread, error, isLoading }: Props) => { const [steps, setSteps] = useState([]); const apiClient = useRecoilValue(apiClientState); const { t } = useTranslation(); + const { threadId } = useChatMessages(); useEffect(() => { if (!thread) return; @@ -164,7 +166,12 @@ const Thread = ({ thread, error, isLoading }: Props) => { id="thread-info" severity="info" action={ - } diff --git a/frontend/src/components/organisms/threadHistory/sidebar/ThreadList.tsx b/frontend/src/components/organisms/threadHistory/sidebar/ThreadList.tsx index 142f2a6a04..122eed5eaa 100644 --- a/frontend/src/components/organisms/threadHistory/sidebar/ThreadList.tsx +++ b/frontend/src/components/organisms/threadHistory/sidebar/ThreadList.tsx @@ -17,6 +17,7 @@ import Typography from '@mui/material/Typography'; import { ThreadHistory, useChatInteract, + useChatMessages, useChatSession } from '@chainlit/react-client'; @@ -41,6 +42,7 @@ const ThreadList = ({ }: Props) => { const { idToResume } = useChatSession(); const { clear } = useChatInteract(); + const { threadId: currentThreadId } = useChatMessages(); const navigate = useNavigate(); if (isFetching || (!threadHistory?.timeGroupedThreads && isLoadingMore)) { return ( @@ -89,7 +91,7 @@ const ThreadList = ({ } const handleDeleteThread = (threadId: string) => { - if (threadId === idToResume) { + if (threadId === idToResume || threadId === currentThreadId) { clear(); } if (threadId === threadHistory.currentThreadId) { diff --git a/frontend/src/components/organisms/threadHistory/sidebar/index.tsx b/frontend/src/components/organisms/threadHistory/sidebar/index.tsx index 767644bcb1..cecc0db986 100644 --- a/frontend/src/components/organisms/threadHistory/sidebar/index.tsx +++ b/frontend/src/components/organisms/threadHistory/sidebar/index.tsx @@ -2,6 +2,7 @@ import { useAuth } from 'api/auth'; import isEqual from 'lodash/isEqual'; import uniqBy from 'lodash/uniqBy'; import { useEffect, useRef, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; import { useRecoilState, useRecoilValue } from 'recoil'; import Box from '@mui/material/Box'; @@ -13,7 +14,8 @@ import useMediaQuery from '@mui/material/useMediaQuery'; import { IThreadFilters, accessTokenState, - threadHistoryState + threadHistoryState, + useChatMessages } from '@chainlit/react-client'; import { Translator } from 'components/i18n'; @@ -46,6 +48,8 @@ const _ThreadHistorySideBar = () => { const [isLoadingMore, setIsLoadingMore] = useState(false); const [isFetching, setIsFetching] = useState(false); const apiClient = useRecoilValue(apiClientState); + const { firstInteraction, messages, threadId } = useChatMessages(); + const navigate = useNavigate(); const ref = useRef(null); const filtersHasChanged = !isEqual(prevFilters, filters); @@ -62,9 +66,12 @@ const _ThreadHistorySideBar = () => { setShouldLoadMore(atBottom); }; - const fetchThreads = async (cursor?: string | number) => { + const fetchThreads = async ( + cursor?: string | number, + isLoadingMore?: boolean + ) => { try { - if (cursor) { + if (cursor || isLoadingMore) { setIsLoadingMore(true); } else { setIsFetching(true); @@ -129,6 +136,29 @@ const _ThreadHistorySideBar = () => { } }, []); + useEffect(() => { + if (!firstInteraction) { + return; + } + + // distinguish between the first interaction containing the word "resume" + // and the actual resume message + const isActualResume = + firstInteraction === 'resume' && + messages.at(0)?.output.toLowerCase() !== 'resume'; + + if (isActualResume) { + return; + } + + fetchThreads(undefined, true).then(() => { + const currentPage = new URL(window.location.href); + if (threadId && currentPage.pathname === '/') { + navigate(`/thread/${threadId}`); + } + }); + }, [firstInteraction]); + return ( { if (threadHistory?.currentThreadId !== id) { setThreadHistory((prev) => { @@ -38,19 +48,24 @@ export default function ThreadPage() { return ( - - - - - - + <> + {isCurrentThread && } + {!isCurrentThread && ( + + + + + + + )} + ); } diff --git a/libs/react-client/src/useChatMessages.ts b/libs/react-client/src/useChatMessages.ts index 5c3312309a..ad462001b6 100644 --- a/libs/react-client/src/useChatMessages.ts +++ b/libs/react-client/src/useChatMessages.ts @@ -6,7 +6,10 @@ const useChatMessages = () => { const messages = useRecoilValue(messagesState); const firstInteraction = useRecoilValue(firstUserInteraction); + const threadId = messages.find((message) => message.threadId)?.threadId; + return { + threadId, messages, firstInteraction }; From 2c52411010e5eede7b6b4f2b600574363777fa86 Mon Sep 17 00:00:00 2001 From: Thibaut Patel Date: Mon, 22 Apr 2024 11:18:47 +0200 Subject: [PATCH 02/14] navigate back to `/` when switching profile --- frontend/src/components/molecules/chatProfiles.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/src/components/molecules/chatProfiles.tsx b/frontend/src/components/molecules/chatProfiles.tsx index c3f358d54b..4500083b91 100644 --- a/frontend/src/components/molecules/chatProfiles.tsx +++ b/frontend/src/components/molecules/chatProfiles.tsx @@ -1,5 +1,6 @@ import size from 'lodash/size'; import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; import { useRecoilValue } from 'recoil'; import { grey } from 'theme'; @@ -30,10 +31,12 @@ export default function ChatProfiles() { const [newChatProfile, setNewChatProfile] = useState(null); const [openDialog, setOpenDialog] = useState(false); const isDarkMode = useIsDarkMode(); + const navigate = useNavigate(); const handleClose = () => { setOpenDialog(false); setNewChatProfile(null); + navigate('/'); }; const handleConfirm = (newChatProfileWithoutConfirm?: string) => { From f67738fbe51761c82bb562fab010f168fc57e683 Mon Sep 17 00:00:00 2001 From: Thibaut Patel Date: Mon, 22 Apr 2024 16:06:26 +0200 Subject: [PATCH 03/14] fix: only return a `threadId` in `useChatMessages` if the thread was interacted with --- frontend/src/components/organisms/threadHistory/Thread.tsx | 2 +- libs/react-client/src/useChatMessages.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/organisms/threadHistory/Thread.tsx b/frontend/src/components/organisms/threadHistory/Thread.tsx index b41ccc9315..5075806b2f 100644 --- a/frontend/src/components/organisms/threadHistory/Thread.tsx +++ b/frontend/src/components/organisms/threadHistory/Thread.tsx @@ -170,7 +170,7 @@ const Thread = ({ thread, error, isLoading }: Props) => { component={Link} color="inherit" size="small" - to={`/thread/${threadId}`} + to={threadId ? `/thread/${threadId}` : '/'} > diff --git a/libs/react-client/src/useChatMessages.ts b/libs/react-client/src/useChatMessages.ts index ad462001b6..fc76455767 100644 --- a/libs/react-client/src/useChatMessages.ts +++ b/libs/react-client/src/useChatMessages.ts @@ -6,7 +6,9 @@ const useChatMessages = () => { const messages = useRecoilValue(messagesState); const firstInteraction = useRecoilValue(firstUserInteraction); - const threadId = messages.find((message) => message.threadId)?.threadId; + const threadId = firstInteraction + ? messages.find((message) => message.threadId)?.threadId + : undefined; return { threadId, From d86f1a51cf8f027153a2852ad5b27c640311515c Mon Sep 17 00:00:00 2001 From: Thibaut Patel Date: Mon, 22 Apr 2024 17:39:36 +0200 Subject: [PATCH 04/14] fix: resume button doesn't redirect when data persistence is enabled - also fixes redirecting correctly to the `/thread/:threadId` page when the user clicks on "chat" in the navigation --- .../src/components/organisms/chat/index.tsx | 19 +++++++++++++++---- frontend/src/pages/ResumeButton.tsx | 4 +++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/organisms/chat/index.tsx b/frontend/src/components/organisms/chat/index.tsx index 73f7f82adf..15848d8a8d 100644 --- a/frontend/src/components/organisms/chat/index.tsx +++ b/frontend/src/components/organisms/chat/index.tsx @@ -1,5 +1,6 @@ import { useUpload } from 'hooks'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; import { useRecoilValue, useSetRecoilState } from 'recoil'; import { toast } from 'sonner'; import { v4 as uuidv4 } from 'uuid'; @@ -43,6 +44,7 @@ const Chat = () => { const { error, disabled } = useChatData(); const { uploadFile } = useChatInteract(); const uploadFileRef = useRef(uploadFile); + const navigate = useNavigate(); const fileSpec = useMemo( () => ({ @@ -155,10 +157,19 @@ const Chat = () => { const { threadId } = useChatMessages(); useEffect(() => { - setThreads((prev) => ({ - ...prev, - currentThreadId: threadId - })); + const currentPage = new URL(window.location.href); + if ( + projectSettings?.dataPersistence && + threadId && + currentPage.pathname === '/' + ) { + navigate(`/thread/${threadId}`); + } else { + setThreads((prev) => ({ + ...prev, + currentThreadId: threadId + })); + } }, []); const enableMultiModalUpload = diff --git a/frontend/src/pages/ResumeButton.tsx b/frontend/src/pages/ResumeButton.tsx index 22c36a502a..e77b14d538 100644 --- a/frontend/src/pages/ResumeButton.tsx +++ b/frontend/src/pages/ResumeButton.tsx @@ -28,7 +28,9 @@ export default function ResumeButton({ threadId }: Props) { clear(); setIdToResume(threadId!); toast.success('Chat resumed!'); - navigate('/'); + if (!pSettings?.dataPersistence) { + navigate('/'); + } }; return ( From ad5172da887be9ba5e0f2511f20cd7d06834451e Mon Sep 17 00:00:00 2001 From: Thibaut Patel Date: Mon, 22 Apr 2024 18:52:07 +0200 Subject: [PATCH 05/14] fix: correctly redirect when a conversation is initiated by a user - the threadId was missing, and the redirection to `/thread/:threadId` wasn't working - adding the `thread_id` value in the `first_interfaction` socket event enables properly storing the `threadId` in the client - from there we can store the value in the `currentThreadIdState` recoil state - expose it via `useChatMessages` - and clear it on `clear` from `useChatInteract` - e2e testing needed --- backend/chainlit/emitter.py | 16 +++++++++++++++- backend/chainlit/socket.py | 5 ++++- libs/react-client/src/state.ts | 5 +++++ libs/react-client/src/useChatInteract.ts | 3 +++ libs/react-client/src/useChatMessages.ts | 11 ++++++----- libs/react-client/src/useChatSession.ts | 12 +++++++++--- 6 files changed, 42 insertions(+), 10 deletions(-) diff --git a/backend/chainlit/emitter.py b/backend/chainlit/emitter.py index 3ae0b18e00..9165bb3b6d 100644 --- a/backend/chainlit/emitter.py +++ b/backend/chainlit/emitter.py @@ -188,13 +188,27 @@ async def flush_thread_queues(self, interaction: str): tags=tags, ) ) + asyncio.create_task( + data_layer.update_thread( + thread_id=self.session.thread_id, + name=interaction, + user_id=user_id, + tags=tags, + ) + ) except Exception as e: logger.error(f"Error updating thread: {e}") asyncio.create_task(self.session.flush_method_queue()) async def init_thread(self, interaction: str): await self.flush_thread_queues(interaction) - await self.emit("first_interaction", interaction) + await self.emit( + "first_interaction", + { + "interaction": interaction, + "thread_id": self.session.thread_id, + }, + ) async def process_user_message(self, payload: UIMessagePayload): step_dict = payload["message"] diff --git a/backend/chainlit/socket.py b/backend/chainlit/socket.py index 7aa55c4ddb..4e357228e3 100644 --- a/backend/chainlit/socket.py +++ b/backend/chainlit/socket.py @@ -169,7 +169,10 @@ async def connection_successful(sid): thread = await resume_thread(context.session) if thread: context.session.has_first_interaction = True - await context.emitter.emit("first_interaction", "resume") + await context.emitter.emit( + "first_interaction", + {"interaction": "resume", "thread_id": thread.get("id")}, + ) await context.emitter.resume_thread(thread) await config.code.on_chat_resume(thread) return diff --git a/libs/react-client/src/state.ts b/libs/react-client/src/state.ts index dd741425cc..8a47104d35 100644 --- a/libs/react-client/src/state.ts +++ b/libs/react-client/src/state.ts @@ -170,3 +170,8 @@ export const sideViewState = atom({ key: 'SideView', default: undefined }); + +export const currentThreadIdState = atom({ + key: 'CurrentThreadId', + default: undefined +}); diff --git a/libs/react-client/src/useChatInteract.ts b/libs/react-client/src/useChatInteract.ts index c50ae6f74c..363f8481f6 100644 --- a/libs/react-client/src/useChatInteract.ts +++ b/libs/react-client/src/useChatInteract.ts @@ -7,6 +7,7 @@ import { avatarState, chatSettingsInputsState, chatSettingsValueState, + currentThreadIdState, elementState, firstUserInteraction, loadingState, @@ -43,6 +44,7 @@ const useChatInteract = () => { const setTokenCount = useSetRecoilState(tokenCountState); const setIdToResume = useSetRecoilState(threadIdToResumeState); const setSideView = useSetRecoilState(sideViewState); + const setCurrentThreadId = useSetRecoilState(currentThreadIdState); const clear = useCallback(() => { session?.socket.emit('clear_session'); @@ -59,6 +61,7 @@ const useChatInteract = () => { resetChatSettings(); resetChatSettingsValue(); setSideView(undefined); + setCurrentThreadId(undefined); }, [session]); const sendMessage = useCallback( diff --git a/libs/react-client/src/useChatMessages.ts b/libs/react-client/src/useChatMessages.ts index fc76455767..c3b1f5c949 100644 --- a/libs/react-client/src/useChatMessages.ts +++ b/libs/react-client/src/useChatMessages.ts @@ -1,14 +1,15 @@ import { useRecoilValue } from 'recoil'; -import { firstUserInteraction, messagesState } from './state'; +import { + currentThreadIdState, + firstUserInteraction, + messagesState +} from './state'; const useChatMessages = () => { const messages = useRecoilValue(messagesState); const firstInteraction = useRecoilValue(firstUserInteraction); - - const threadId = firstInteraction - ? messages.find((message) => message.threadId)?.threadId - : undefined; + const threadId = useRecoilValue(currentThreadIdState); return { threadId, diff --git a/libs/react-client/src/useChatSession.ts b/libs/react-client/src/useChatSession.ts index 1e20de06f6..51ef2278f5 100644 --- a/libs/react-client/src/useChatSession.ts +++ b/libs/react-client/src/useChatSession.ts @@ -15,6 +15,7 @@ import { chatProfileState, chatSettingsInputsState, chatSettingsValueState, + currentThreadIdState, elementState, firstUserInteraction, loadingState, @@ -64,6 +65,7 @@ const useChatSession = () => { const setTokenCount = useSetRecoilState(tokenCountState); const [chatProfile, setChatProfile] = useRecoilState(chatProfileState); const idToResume = useRecoilValue(threadIdToResumeState); + const setCurrentThreadId = useSetRecoilState(currentThreadIdState); const _connect = useCallback( ({ @@ -147,9 +149,13 @@ const useChatSession = () => { setMessages((oldMessages) => addMessage(oldMessages, message)); }); - socket.on('first_interaction', (interaction: string) => { - setFirstUserInteraction(interaction); - }); + socket.on( + 'first_interaction', + (event: { interaction: string; thread_id: string }) => { + setFirstUserInteraction(event.interaction); + setCurrentThreadId(event.thread_id); + } + ); socket.on('update_message', (message: IStep) => { setMessages((oldMessages) => From 36a9e92c1ebd46c05399bef7ef01cfb88fd0f5f0 Mon Sep 17 00:00:00 2001 From: Thibaut Patel Date: Tue, 23 Apr 2024 10:35:04 +0200 Subject: [PATCH 06/14] added tests - ensure the user is redirected from `/` to `/thread/...` when starting a conversation - ensure resuming a conversation keeps the user on the same url --- cypress/e2e/data_layer/spec.cy.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cypress/e2e/data_layer/spec.cy.ts b/cypress/e2e/data_layer/spec.cy.ts index 61d0832428..c0b6eb8f56 100644 --- a/cypress/e2e/data_layer/spec.cy.ts +++ b/cypress/e2e/data_layer/spec.cy.ts @@ -6,7 +6,14 @@ function login() { } function feedback() { + cy.location('pathname').should((loc) => { + expect(loc).to.eq('/'); + }); submitMessage('Hello'); + cy.location('pathname').should((loc) => { + // starts with /thread/ + expect(loc).to.match(/^\/thread\//); + }); cy.get('.negative-feedback-off').should('have.length', 1); cy.get('.positive-feedback-off').should('have.length', 1).click(); cy.get('#feedbackSubmit').click(); @@ -40,7 +47,14 @@ function resumeThread() { cy.get('#thread-test2').click(); cy.get(`#chat-input`).should('not.exist'); cy.get('#resumeThread').click(); + let initialUrl; + cy.url().then((url) => { + initialUrl = url; + }); cy.get(`#chat-input`).should('exist'); + cy.url().then((newUrl) => { + expect(newUrl).to.equal(initialUrl); + }); cy.get('.step').should('have.length', 4); From 547e91d645f0e4e7f87cb14f1a4aa2b40b41b3b0 Mon Sep 17 00:00:00 2001 From: Thibaut Patel Date: Tue, 23 Apr 2024 10:43:42 +0200 Subject: [PATCH 07/14] update changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db2a279b19..9209ed4e3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). Nothing unreleased! +## [1.0.505] - 2024-04-23 + +### Added + +- The user's browser language configuration is available in `cl.user_session.get("languages")` + +### Changed + +- The thread auto-tagging feature is now opt-in using `auto_tag_thread` in the config.toml file + ## [1.0.504] - 2024-04-16 ### Changed From 30ab2cacc3589b749d81d17999d5c48ab60206de Mon Sep 17 00:00:00 2001 From: Thibaut Patel Date: Tue, 23 Apr 2024 11:20:37 +0200 Subject: [PATCH 08/14] update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9209ed4e3d..3b4415cd8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,11 @@ Nothing unreleased! - The thread auto-tagging feature is now opt-in using `auto_tag_thread` in the config.toml file +### Fixed + +- Enabled having a `storage_provider` set to `None` in SQLAlchemyDataLayer - @mohamedalani +- Correctly serialize `generation` in SQLAlchemyDataLayer - @mohamedalani + ## [1.0.504] - 2024-04-16 ### Changed From d49dc5c2206577175eab40cc6665e77d060acdea Mon Sep 17 00:00:00 2001 From: Thibaut Patel Date: Tue, 23 Apr 2024 11:22:27 +0200 Subject: [PATCH 09/14] removing the bad merge conflict resolution --- backend/chainlit/emitter.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/backend/chainlit/emitter.py b/backend/chainlit/emitter.py index 9165bb3b6d..52deaf20e2 100644 --- a/backend/chainlit/emitter.py +++ b/backend/chainlit/emitter.py @@ -188,14 +188,6 @@ async def flush_thread_queues(self, interaction: str): tags=tags, ) ) - asyncio.create_task( - data_layer.update_thread( - thread_id=self.session.thread_id, - name=interaction, - user_id=user_id, - tags=tags, - ) - ) except Exception as e: logger.error(f"Error updating thread: {e}") asyncio.create_task(self.session.flush_method_queue()) From 57a1cf99ae5919744caa6c7e0b1f1dcb5c5dd6c9 Mon Sep 17 00:00:00 2001 From: Thibaut Patel Date: Tue, 23 Apr 2024 11:25:54 +0200 Subject: [PATCH 10/14] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b4415cd8a..b8f17033f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ Nothing unreleased! ### Fixed +- Fixed incorrect step ancestor in the OpenAI instrumentation - Enabled having a `storage_provider` set to `None` in SQLAlchemyDataLayer - @mohamedalani - Correctly serialize `generation` in SQLAlchemyDataLayer - @mohamedalani From 522b729f7f1eb269351c573fad5440d0aa75ffc1 Mon Sep 17 00:00:00 2001 From: Thibaut Patel Date: Tue, 23 Apr 2024 11:33:54 +0200 Subject: [PATCH 11/14] updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8f17033f0..6db25b04f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Nothing unreleased! ### Added - The user's browser language configuration is available in `cl.user_session.get("languages")` +- Allow html in text elements - @jdb78 ### Changed From 5b810569d0296efcbac1712ce44e24e4734c0eef Mon Sep 17 00:00:00 2001 From: Thibaut Patel Date: Tue, 23 Apr 2024 11:36:41 +0200 Subject: [PATCH 12/14] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6db25b04f4..856a5ab4de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Nothing unreleased! - The user's browser language configuration is available in `cl.user_session.get("languages")` - Allow html in text elements - @jdb78 +- Allow for setting a ChatProfile default - @kevinwmerritt ### Changed From e319e6d080dc72e50efac074e8216cf5ac141a36 Mon Sep 17 00:00:00 2001 From: Thibaut Patel Date: Tue, 23 Apr 2024 15:57:56 +0200 Subject: [PATCH 13/14] fix e2e test - update changelog --- CHANGELOG.md | 1 + cypress/e2e/data_layer/main.py | 21 ++++++++++++++++++++- cypress/e2e/data_layer/spec.cy.ts | 22 ++++++++++++++-------- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 856a5ab4de..6ea6daf03e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Nothing unreleased! ### Changed +- The thread history refreshes right after a new thread is created. - The thread auto-tagging feature is now opt-in using `auto_tag_thread` in the config.toml file ### Fixed diff --git a/cypress/e2e/data_layer/main.py b/cypress/e2e/data_layer/main.py index e325d1d6af..e632ce724a 100644 --- a/cypress/e2e/data_layer/main.py +++ b/cypress/e2e/data_layer/main.py @@ -77,7 +77,7 @@ async def update_thread( metadata: Optional[Dict] = None, tags: Optional[List[str]] = None, ): - thread = next((t for t in thread_history if t["id"] == "test2"), None) + thread = next((t for t in thread_history if t["id"] == thread_id), None) if thread: if name: thread["name"] = name @@ -85,12 +85,31 @@ async def update_thread( thread["metadata"] = metadata if tags: thread["tags"] = tags + else: + thread_history.append( + { + "id": thread_id, + "name": name, + "metadata": metadata, + "tags": tags, + "createdAt": utc_now(), + "userId": user_id, + "userIdentifier": "admin", + "steps": [], + } + ) @cl_data.queue_until_user_message() async def create_step(self, step_dict: StepDict): global create_step_counter create_step_counter += 1 + thread = next( + (t for t in thread_history if t["id"] == step_dict.get("threadId")), None + ) + if thread: + thread["steps"].append(step_dict) + async def get_thread_author(self, thread_id: str): return "admin" diff --git a/cypress/e2e/data_layer/spec.cy.ts b/cypress/e2e/data_layer/spec.cy.ts index c0b6eb8f56..bc4be245a2 100644 --- a/cypress/e2e/data_layer/spec.cy.ts +++ b/cypress/e2e/data_layer/spec.cy.ts @@ -45,25 +45,31 @@ function threadList() { function resumeThread() { cy.get('#thread-test2').click(); - cy.get(`#chat-input`).should('not.exist'); - cy.get('#resumeThread').click(); let initialUrl; cy.url().then((url) => { initialUrl = url; }); + cy.get(`#chat-input`).should('not.exist'); + cy.get('#resumeThread').click(); cy.get(`#chat-input`).should('exist'); cy.url().then((newUrl) => { expect(newUrl).to.equal(initialUrl); }); - cy.get('.step').should('have.length', 4); + // back to the "hello" thread + cy.get('a').contains('Hello').click(); + cy.get(`#chat-input`).should('not.exist'); + cy.get('#resumeThread').click(); + cy.get(`#chat-input`).should('exist'); + + cy.get('.step').should('have.length', 8); - cy.get('.step').eq(0).should('contain', 'Message 3'); - cy.get('.step').eq(1).should('contain', 'Message 4'); + cy.get('.step').eq(0).should('contain', 'Hello'); // Thread name should be renamed with first interaction - cy.get('.step').eq(2).should('contain', 'Welcome back to Hello'); - cy.get('.step').eq(3).should('contain', 'metadata'); - cy.get('.step').eq(3).should('contain', 'chat_profile'); + cy.get('.step').eq(5).should('contain', 'Welcome back to Hello'); + // Because the Thread was closed, the metadata should have been updated automatically + cy.get('.step').eq(6).should('contain', 'metadata'); + cy.get('.step').eq(6).should('contain', 'chat_profile'); } describe('Data Layer', () => { From 9cf8148521ff6ddf4a52fb138b6d99c72056e009 Mon Sep 17 00:00:00 2001 From: Thibaut Patel Date: Tue, 23 Apr 2024 16:29:18 +0200 Subject: [PATCH 14/14] update test comments --- cypress/e2e/data_layer/spec.cy.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cypress/e2e/data_layer/spec.cy.ts b/cypress/e2e/data_layer/spec.cy.ts index bc4be245a2..78b2c7e892 100644 --- a/cypress/e2e/data_layer/spec.cy.ts +++ b/cypress/e2e/data_layer/spec.cy.ts @@ -44,6 +44,7 @@ function threadList() { } function resumeThread() { + // Go to the "thread 2" thread and resume it cy.get('#thread-test2').click(); let initialUrl; cy.url().then((url) => { @@ -52,6 +53,7 @@ function resumeThread() { cy.get(`#chat-input`).should('not.exist'); cy.get('#resumeThread').click(); cy.get(`#chat-input`).should('exist'); + // Make sure the url stays the same after resuming cy.url().then((newUrl) => { expect(newUrl).to.equal(initialUrl); }); @@ -65,7 +67,6 @@ function resumeThread() { cy.get('.step').should('have.length', 8); cy.get('.step').eq(0).should('contain', 'Hello'); - // Thread name should be renamed with first interaction cy.get('.step').eq(5).should('contain', 'Welcome back to Hello'); // Because the Thread was closed, the metadata should have been updated automatically cy.get('.step').eq(6).should('contain', 'metadata');