From 8f2d346e10c47b57bf6b5a6aa02d453488a88b89 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Wed, 20 May 2026 01:39:22 +0400 Subject: [PATCH] refac --- backend/open_webui/routers/knowledge.py | 7 ++++ .../workspace/Knowledge/KnowledgeBase.svelte | 34 +++++++++---------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/backend/open_webui/routers/knowledge.py b/backend/open_webui/routers/knowledge.py index 69f0ae33e3..9fdb8b539e 100644 --- a/backend/open_webui/routers/knowledge.py +++ b/backend/open_webui/routers/knowledge.py @@ -1,5 +1,6 @@ from __future__ import annotations +import asyncio import io import logging import zipfile @@ -1007,6 +1008,7 @@ class SyncDiffResponse(BaseModel): mkdir: list[str] # directory paths to create rmdir: list[str] # directory IDs to remove unmodified_count: int + directory_map: dict[str, str] # existing path → directory ID @router.post('/{id}/sync/diff', response_model=SyncDiffResponse) @@ -1101,6 +1103,7 @@ async def sync_knowledge_diff( mkdir=mkdir, rmdir=rmdir, unmodified_count=unmodified_count, + directory_map=directory_id_by_path, ) @@ -1154,6 +1157,10 @@ async def sync_knowledge_cleanup( if file.user_id == user.id or user.role == 'admin': await Files.delete_file_by_id(file_id, db=db) + try: + await asyncio.to_thread(Storage.delete_file, file.path) + except Exception: + pass # ── Remove orphaned directories (children before parents) ── for dir_id in reversed(form_data.dir_ids): diff --git a/src/lib/components/workspace/Knowledge/KnowledgeBase.svelte b/src/lib/components/workspace/Knowledge/KnowledgeBase.svelte index e9dbbe5a0d..26cef03a5f 100644 --- a/src/lib/components/workspace/Knowledge/KnowledgeBase.svelte +++ b/src/lib/components/workspace/Knowledge/KnowledgeBase.svelte @@ -651,13 +651,24 @@ return; } - // ── 4. mkdir — create missing directories (parents first) ── - const createdDirectoryIds: Record = {}; + // ── 4. Cleanup — remove deleted + stale modified files first ── + const staleFileIds = [ + ...diff.deleted.map((d: any) => d.file_id), + ...diff.modified.map((m: any) => m.stale_file_id) + ]; + + if (staleFileIds.length > 0 || diff.rmdir.length > 0) { + syncing = $i18n.t('Removing {{count}} stale files...', { count: staleFileIds.length }); + await syncKnowledgeCleanup(localStorage.token, id, staleFileIds, diff.rmdir); + } + + // ── 5. mkdir — create missing directories (parents first) ── + const directoryIdByPath: Record = { ...(diff.directory_map || {}) }; for (const dirPath of diff.mkdir) { const segments = dirPath.split('/'); const name = segments.at(-1)!; const parentPath = segments.slice(0, -1).join('/'); - const parentId = parentPath ? createdDirectoryIds[parentPath] : null; + const parentId = parentPath ? directoryIdByPath[parentPath] : null; const directory = await createKnowledgeDirectory( localStorage.token, @@ -666,11 +677,11 @@ parentId ); if (directory) { - createdDirectoryIds[dirPath] = directory.id; + directoryIdByPath[dirPath] = directory.id; } } - // ── 5. Upload added + modified files ── + // ── 6. Upload added + modified files ── const filesToUpload = manifest.filter( (entry) => diff.added.some((a: any) => a.filename === entry.filename && a.path === entry.path) || @@ -691,21 +702,10 @@ await uploadFile(localStorage.token, fileObject, { knowledge_id: knowledge.id, file_hash: entry.checksum, - directory_id: entry.path ? createdDirectoryIds[entry.path] : null + directory_id: entry.path ? directoryIdByPath[entry.path] : null }).catch(() => null); } - // ── 6. Cleanup — remove deleted files + rmdir orphaned directories ── - const staleFileIds = [ - ...diff.deleted.map((d: any) => d.file_id), - ...diff.modified.map((m: any) => m.stale_file_id) - ]; - - if (staleFileIds.length > 0 || diff.rmdir.length > 0) { - syncing = $i18n.t('Removing {{count}} stale files...', { count: staleFileIds.length }); - await syncKnowledgeCleanup(localStorage.token, id, staleFileIds, diff.rmdir); - } - // ── 7. Report ── toast.success( $i18n.t(