From b848ea720fdd9bef3ee54c23faec0ad6ff805c15 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Wed, 4 Nov 2026 22:31:06 +0100 Subject: [PATCH] fix: search lists show results of an earlier search when it answers late Typing a search, pausing, and typing more on a slow connection could leave the list showing results for the earlier text. This hit Notes, Archived Chats, Shared Chats, the admin Users list and the # and @ lists in the message box, where Enter could then attach the wrong knowledge base. Each list now ignores answers that do not belong to the latest search. Fixes #33756 --- src/lib/components/admin/Users/UserList.svelte | 4 ++++ .../chat/MessageInput/Commands/AtCommands.svelte | 8 ++++++++ .../chat/MessageInput/Commands/Knowledge.svelte | 8 ++++++++ src/lib/components/chat/Settings/ArchivedChats.svelte | 6 +++++- src/lib/components/layout/SharedChatsModal.svelte | 10 ++++++++-- src/lib/components/notes/Notes.svelte | 5 +++++ 6 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/lib/components/admin/Users/UserList.svelte b/src/lib/components/admin/Users/UserList.svelte index 94e3ff695c..6903ffa078 100644 --- a/src/lib/components/admin/Users/UserList.svelte +++ b/src/lib/components/admin/Users/UserList.svelte @@ -44,6 +44,7 @@ let query = ''; let searchDebounceTimer: ReturnType; + let requestId = 0; let orderBy = 'created_at'; // default sort key let direction = 'asc'; // default sort order @@ -95,6 +96,7 @@ }; const getUserList = async () => { + const activeRequestId = ++requestId; try { const res = await getUsers(localStorage.token, query, orderBy, direction, page).catch( (error) => { @@ -103,6 +105,8 @@ } ); + if (activeRequestId !== requestId) return; + if (res) { users = res.users; total = res.total; diff --git a/src/lib/components/chat/MessageInput/Commands/AtCommands.svelte b/src/lib/components/chat/MessageInput/Commands/AtCommands.svelte index 5022edb4cc..a331dc43e3 100644 --- a/src/lib/components/chat/MessageInput/Commands/AtCommands.svelte +++ b/src/lib/components/chat/MessageInput/Commands/AtCommands.svelte @@ -39,6 +39,7 @@ let selectedIdx = 0; export let filteredItems: any[] = []; let searchDebounceTimer: ReturnType; + let requestId = 0; let filesystemItems: any[] = []; let knowledgeItems: any[] = []; @@ -101,6 +102,7 @@ }); const getItems = () => { + requestId += 1; const terminal = getSelectedTerminal(); getFilesystemItems(terminal); getKnowledgeItems(); @@ -170,8 +172,11 @@ .filter((folder: any) => folder.name.toLowerCase().includes(query.toLowerCase())); const getKnowledgeItems = async () => { + const activeRequestId = requestId; const res = await searchKnowledgeBases(localStorage.token, query).catch(() => null); + if (activeRequestId !== requestId) return; + if (res) { knowledgeItems = res.items.map((item: any) => ({ ...item, @@ -181,8 +186,11 @@ }; const getKnowledgeFileItems = async () => { + const activeRequestId = requestId; const res = await searchKnowledgeFiles(localStorage.token, query).catch(() => null); + if (activeRequestId !== requestId) return; + if (res) { fileItems = res.items.map((item: any) => ({ ...item, diff --git a/src/lib/components/chat/MessageInput/Commands/Knowledge.svelte b/src/lib/components/chat/MessageInput/Commands/Knowledge.svelte index 1bb010707a..82ef6f8aa9 100644 --- a/src/lib/components/chat/MessageInput/Commands/Knowledge.svelte +++ b/src/lib/components/chat/MessageInput/Commands/Knowledge.svelte @@ -27,6 +27,7 @@ let selectedIdx = 0; let items = []; let searchDebounceTimer: ReturnType; + let requestId = 0; export let filteredItems = []; let webUploadEnabled: boolean = true; @@ -86,6 +87,7 @@ }); const getItems = () => { + requestId += 1; getKnowledgeItems(); getKnowledgeFileItems(); }; @@ -100,10 +102,13 @@ .filter((folder) => folder.name.toLowerCase().includes(query.toLowerCase())); const getKnowledgeItems = async () => { + const activeRequestId = requestId; const res = await searchKnowledgeBases(localStorage.token, query).catch(() => { return null; }); + if (activeRequestId !== requestId) return; + if (res) { knowledgeItems = res.items.map((item) => { return { @@ -115,10 +120,13 @@ }; const getKnowledgeFileItems = async () => { + const activeRequestId = requestId; const res = await searchKnowledgeFiles(localStorage.token, query).catch(() => { return null; }); + if (activeRequestId !== requestId) return; + if (res) { fileItems = res.items.map((item) => { return { diff --git a/src/lib/components/chat/Settings/ArchivedChats.svelte b/src/lib/components/chat/Settings/ArchivedChats.svelte index 28a3d1ba02..fa33ba51e5 100644 --- a/src/lib/components/chat/Settings/ArchivedChats.svelte +++ b/src/lib/components/chat/Settings/ArchivedChats.svelte @@ -55,6 +55,7 @@ let allChatsLoaded = false; let chatListLoading = false; let searchDebounceTimeout: ReturnType | null = null; + let requestId = 0; let selectedChatId: string | null = null; let showDeleteConfirmDialog = false; @@ -67,9 +68,12 @@ }); const loadChats = async () => { + const activeRequestId = ++requestId; page = 1; chatList = null; - chatList = await getArchivedChatList(localStorage.token, page, getFilter()); + const res = await getArchivedChatList(localStorage.token, page, getFilter()); + if (activeRequestId !== requestId) return; + chatList = res; allChatsLoaded = (chatList ?? []).length === 0; chatCount = await getArchivedChatCount(localStorage.token); }; diff --git a/src/lib/components/layout/SharedChatsModal.svelte b/src/lib/components/layout/SharedChatsModal.svelte index 54bdb9df3e..aa2245cc49 100644 --- a/src/lib/components/layout/SharedChatsModal.svelte +++ b/src/lib/components/layout/SharedChatsModal.svelte @@ -24,6 +24,7 @@ let allChatsLoaded = false; let chatListLoading = false; let searchDebounceTimeout: any; + let requestId = 0; let showUnshareAllConfirmDialog = false; @@ -47,15 +48,20 @@ clearTimeout(searchDebounceTimeout); } + const activeRequestId = ++requestId; page = 1; chatList = null; if (query === '') { - chatList = await getSharedChatList(localStorage.token, page, filter); + const res = await getSharedChatList(localStorage.token, page, filter); + if (activeRequestId !== requestId) return; + chatList = res; allChatsLoaded = (chatList ?? []).length === 0; } else { searchDebounceTimeout = setTimeout(async () => { - chatList = await getSharedChatList(localStorage.token, page, filter); + const res = await getSharedChatList(localStorage.token, page, filter); + if (activeRequestId !== requestId) return; + chatList = res; allChatsLoaded = (chatList ?? []).length === 0; }, 500); } diff --git a/src/lib/components/notes/Notes.svelte b/src/lib/components/notes/Notes.svelte index 786d03dd9a..fe978f0b4f 100644 --- a/src/lib/components/notes/Notes.svelte +++ b/src/lib/components/notes/Notes.svelte @@ -74,6 +74,7 @@ let query = ''; let searchDebounceTimer: ReturnType; + let requestId = 0; let sortKey = 'updated_at'; let sortDirection = 'desc'; @@ -158,6 +159,7 @@ }; const reset = () => { + requestId += 1; page = 1; items = null; total = null; @@ -202,6 +204,7 @@ : `/notes/${note.id}`; const getItemsPage = async () => { + const activeRequestId = requestId; itemsLoading = true; if (viewOption === 'created') { @@ -220,6 +223,8 @@ return []; }); + if (activeRequestId !== requestId) return res; + if (res) { total = res.total; const pageItems = res.items;