From a1036e544d573e3d35e05c1c2472ba762c32431b Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 1 Jan 2026 02:51:35 +0400 Subject: [PATCH] enh: folder_max_file_count --- backend/open_webui/config.py | 6 +++++ backend/open_webui/main.py | 3 +++ backend/open_webui/routers/auths.py | 4 ++++ .../components/admin/Settings/General.svelte | 22 +++++++++++++++++++ .../layout/Sidebar/Folders/FolderModal.svelte | 10 ++++++++- src/lib/stores/index.ts | 1 + 6 files changed, 45 insertions(+), 1 deletion(-) diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py index b8f92a26c..9ed61fbb9 100644 --- a/backend/open_webui/config.py +++ b/backend/open_webui/config.py @@ -1543,6 +1543,12 @@ ENABLE_FOLDERS = PersistentConfig( os.environ.get("ENABLE_FOLDERS", "True").lower() == "true", ) +FOLDER_MAX_FILE_COUNT = PersistentConfig( + "FOLDER_MAX_FILE_COUNT", + "folders.max_file_count", + int(os.environ.get("FOLDER_MAX_FILE_COUNT", "100")), +) + ENABLE_CHANNELS = PersistentConfig( "ENABLE_CHANNELS", "channels.enable", diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py index 516056ada..320e5c5cf 100644 --- a/backend/open_webui/main.py +++ b/backend/open_webui/main.py @@ -363,6 +363,7 @@ from open_webui.config import ( ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS, API_KEYS_ALLOWED_ENDPOINTS, ENABLE_FOLDERS, + FOLDER_MAX_FILE_COUNT, ENABLE_CHANNELS, ENABLE_NOTES, ENABLE_COMMUNITY_SHARING, @@ -779,6 +780,7 @@ app.state.config.BANNERS = WEBUI_BANNERS app.state.config.ENABLE_FOLDERS = ENABLE_FOLDERS +app.state.config.FOLDER_MAX_FILE_COUNT = FOLDER_MAX_FILE_COUNT app.state.config.ENABLE_CHANNELS = ENABLE_CHANNELS app.state.config.ENABLE_NOTES = ENABLE_NOTES app.state.config.ENABLE_COMMUNITY_SHARING = ENABLE_COMMUNITY_SHARING @@ -1913,6 +1915,7 @@ async def get_app_config(request: Request): { "enable_direct_connections": app.state.config.ENABLE_DIRECT_CONNECTIONS, "enable_folders": app.state.config.ENABLE_FOLDERS, + "folder_max_file_count": app.state.config.FOLDER_MAX_FILE_COUNT, "enable_channels": app.state.config.ENABLE_CHANNELS, "enable_notes": app.state.config.ENABLE_NOTES, "enable_web_search": app.state.config.ENABLE_WEB_SEARCH, diff --git a/backend/open_webui/routers/auths.py b/backend/open_webui/routers/auths.py index c9e736850..34cb41727 100644 --- a/backend/open_webui/routers/auths.py +++ b/backend/open_webui/routers/auths.py @@ -989,6 +989,7 @@ async def get_admin_config(request: Request, user=Depends(get_admin_user)): "ENABLE_COMMUNITY_SHARING": request.app.state.config.ENABLE_COMMUNITY_SHARING, "ENABLE_MESSAGE_RATING": request.app.state.config.ENABLE_MESSAGE_RATING, "ENABLE_FOLDERS": request.app.state.config.ENABLE_FOLDERS, + "FOLDER_MAX_FILE_COUNT": request.app.state.config.FOLDER_MAX_FILE_COUNT, "ENABLE_CHANNELS": request.app.state.config.ENABLE_CHANNELS, "ENABLE_NOTES": request.app.state.config.ENABLE_NOTES, "ENABLE_USER_WEBHOOKS": request.app.state.config.ENABLE_USER_WEBHOOKS, @@ -1012,6 +1013,7 @@ class AdminConfig(BaseModel): ENABLE_COMMUNITY_SHARING: bool ENABLE_MESSAGE_RATING: bool ENABLE_FOLDERS: bool + FOLDER_MAX_FILE_COUNT: int ENABLE_CHANNELS: bool ENABLE_NOTES: bool ENABLE_USER_WEBHOOKS: bool @@ -1038,6 +1040,7 @@ async def update_admin_config( ) request.app.state.config.ENABLE_FOLDERS = form_data.ENABLE_FOLDERS + request.app.state.config.FOLDER_MAX_FILE_COUNT = form_data.FOLDER_MAX_FILE_COUNT request.app.state.config.ENABLE_CHANNELS = form_data.ENABLE_CHANNELS request.app.state.config.ENABLE_NOTES = form_data.ENABLE_NOTES @@ -1082,6 +1085,7 @@ async def update_admin_config( "ENABLE_COMMUNITY_SHARING": request.app.state.config.ENABLE_COMMUNITY_SHARING, "ENABLE_MESSAGE_RATING": request.app.state.config.ENABLE_MESSAGE_RATING, "ENABLE_FOLDERS": request.app.state.config.ENABLE_FOLDERS, + "FOLDER_MAX_FILE_COUNT": request.app.state.config.FOLDER_MAX_FILE_COUNT, "ENABLE_CHANNELS": request.app.state.config.ENABLE_CHANNELS, "ENABLE_NOTES": request.app.state.config.ENABLE_NOTES, "ENABLE_USER_WEBHOOKS": request.app.state.config.ENABLE_USER_WEBHOOKS, diff --git a/src/lib/components/admin/Settings/General.svelte b/src/lib/components/admin/Settings/General.svelte index 60e66fe35..554951c8d 100644 --- a/src/lib/components/admin/Settings/General.svelte +++ b/src/lib/components/admin/Settings/General.svelte @@ -701,6 +701,28 @@ + {#if adminConfig.ENABLE_FOLDERS} +
+
+
{$i18n.t('Folder Max File Count')}
+
+ +
+ +
+ +
+ {$i18n.t('Maximum number of files allowed per folder.')} +
+
+ {/if} +
{$i18n.t('Notes')} ({$i18n.t('Beta')}) diff --git a/src/lib/components/layout/Sidebar/Folders/FolderModal.svelte b/src/lib/components/layout/Sidebar/Folders/FolderModal.svelte index cb743b5c7..55c0dbaef 100644 --- a/src/lib/components/layout/Sidebar/Folders/FolderModal.svelte +++ b/src/lib/components/layout/Sidebar/Folders/FolderModal.svelte @@ -8,7 +8,7 @@ import { toast } from 'svelte-sonner'; import { page } from '$app/stores'; import { goto } from '$app/navigation'; - import { user } from '$lib/stores'; + import { user, config } from '$lib/stores'; import Textarea from '$lib/components/common/Textarea.svelte'; import Knowledge from '$lib/components/workspace/Models/Knowledge.svelte'; @@ -42,6 +42,14 @@ return; } + // Check folder max file count limit + const maxFileCount = $config?.features?.folder_max_file_count ?? null; + if (maxFileCount !== null && (data?.files ?? []).length > maxFileCount) { + toast.error($i18n.t('Maximum number of files per folder is {{max}}.', { max: maxFileCount })); + loading = false; + return; + } + await onSubmit({ name, meta, diff --git a/src/lib/stores/index.ts b/src/lib/stores/index.ts index 7d75c3253..9932dba05 100644 --- a/src/lib/stores/index.ts +++ b/src/lib/stores/index.ts @@ -276,6 +276,7 @@ type Config = { enable_autocomplete_generation: boolean; enable_direct_connections: boolean; enable_version_update_check: boolean; + folder_max_file_count?: number; }; oauth: { providers: {