diff --git a/collector/utils/extensions/Confluence/index.js b/collector/utils/extensions/Confluence/index.js index 6df06310..22df1c7f 100644 --- a/collector/utils/extensions/Confluence/index.js +++ b/collector/utils/extensions/Confluence/index.js @@ -3,7 +3,7 @@ const path = require("path"); const { default: slugify } = require("slugify"); const { v4 } = require("uuid"); const UrlPattern = require("url-pattern"); -const { writeToServerDocuments } = require("../../files"); +const { writeToServerDocuments, sanitizeFileName } = require("../../files"); const { tokenizeString } = require("../../tokenizer"); const { ConfluencePagesLoader, @@ -98,11 +98,11 @@ async function loadConfluence({ pageUrl, username, accessToken }, response) { console.log( `[Confluence Loader]: Saving ${doc.metadata.title} to ${outFolder}` ); - writeToServerDocuments( - data, - `${slugify(doc.metadata.title)}-${data.id}`, - outFolderPath + + const fileName = sanitizeFileName( + `${slugify(doc.metadata.title)}-${data.id}` ); + writeToServerDocuments(data, fileName, outFolderPath); }); return { diff --git a/collector/utils/files/index.js b/collector/utils/files/index.js index 9b56bb5b..86b50c36 100644 --- a/collector/utils/files/index.js +++ b/collector/utils/files/index.js @@ -129,6 +129,11 @@ function normalizePath(filepath = "") { return result; } +function sanitizeFileName(fileName) { + if (!fileName) return fileName; + return fileName.replace(/[<>:"\/\\|?*]/g, ""); +} + module.exports = { trashFile, isTextType, @@ -137,4 +142,5 @@ module.exports = { wipeCollectorStorage, normalizePath, isWithin, + sanitizeFileName, }; diff --git a/frontend/src/components/EmbeddingSelection/LMStudioOptions/index.jsx b/frontend/src/components/EmbeddingSelection/LMStudioOptions/index.jsx index 1192ce67..8a18fb99 100644 --- a/frontend/src/components/EmbeddingSelection/LMStudioOptions/index.jsx +++ b/frontend/src/components/EmbeddingSelection/LMStudioOptions/index.jsx @@ -1,48 +1,112 @@ import React, { useEffect, useState } from "react"; import System from "@/models/system"; +import PreLoader from "@/components/Preloader"; +import { LMSTUDIO_COMMON_URLS } from "@/utils/constants"; +import { CaretDown, CaretUp } from "@phosphor-icons/react"; +import useProviderEndpointAutoDiscovery from "@/hooks/useProviderEndpointAutoDiscovery"; export default function LMStudioEmbeddingOptions({ settings }) { - const [basePathValue, setBasePathValue] = useState( - settings?.EmbeddingBasePath + const { + autoDetecting: loading, + basePath, + basePathValue, + showAdvancedControls, + setShowAdvancedControls, + handleAutoDetectClick, + } = useProviderEndpointAutoDiscovery({ + provider: "lmstudio", + initialBasePath: settings?.EmbeddingBasePath, + ENDPOINTS: LMSTUDIO_COMMON_URLS, + }); + + const [maxChunkLength, setMaxChunkLength] = useState( + settings?.EmbeddingModelMaxChunkLength || 8192 ); - const [basePath, setBasePath] = useState(settings?.EmbeddingBasePath); + + const handleMaxChunkLengthChange = (e) => { + setMaxChunkLength(Number(e.target.value)); + }; return (
-
+
+
- - setBasePathValue(e.target.value)} - onBlur={() => setBasePath(basePathValue)} - required={true} - autoComplete="off" - spellCheck={false} - /> -
- -
-
+
+
+ +
+ +
@@ -55,14 +119,23 @@ function LMStudioModelSelection({ settings, basePath = null }) { useEffect(() => { async function findCustomModels() { - if (!basePath || !basePath.includes("/v1")) { + if (!basePath) { setCustomModels([]); setLoading(false); return; } setLoading(true); - const { models } = await System.customModels("lmstudio", null, basePath); - setCustomModels(models || []); + try { + const { models } = await System.customModels( + "lmstudio", + null, + basePath + ); + setCustomModels(models || []); + } catch (error) { + console.error("Failed to fetch custom models:", error); + setCustomModels([]); + } setLoading(false); } findCustomModels(); @@ -71,8 +144,8 @@ function LMStudioModelSelection({ settings, basePath = null }) { if (loading || customModels.length == 0) { return (
-
); } return (
-
); } diff --git a/frontend/src/components/EmbeddingSelection/OllamaOptions/index.jsx b/frontend/src/components/EmbeddingSelection/OllamaOptions/index.jsx index 3213f5d3..fca1ae75 100644 --- a/frontend/src/components/EmbeddingSelection/OllamaOptions/index.jsx +++ b/frontend/src/components/EmbeddingSelection/OllamaOptions/index.jsx @@ -1,55 +1,122 @@ import React, { useEffect, useState } from "react"; import System from "@/models/system"; +import PreLoader from "@/components/Preloader"; +import { OLLAMA_COMMON_URLS } from "@/utils/constants"; +import { CaretDown, CaretUp } from "@phosphor-icons/react"; +import useProviderEndpointAutoDiscovery from "@/hooks/useProviderEndpointAutoDiscovery"; export default function OllamaEmbeddingOptions({ settings }) { - const [basePathValue, setBasePathValue] = useState( - settings?.EmbeddingBasePath + const { + autoDetecting: loading, + basePath, + basePathValue, + showAdvancedControls, + setShowAdvancedControls, + handleAutoDetectClick, + } = useProviderEndpointAutoDiscovery({ + provider: "ollama", + initialBasePath: settings?.EmbeddingBasePath, + ENDPOINTS: OLLAMA_COMMON_URLS, + }); + + const [maxChunkLength, setMaxChunkLength] = useState( + settings?.EmbeddingModelMaxChunkLength || 8192 ); - const [basePath, setBasePath] = useState(settings?.EmbeddingBasePath); + + const handleMaxChunkLengthChange = (e) => { + setMaxChunkLength(Number(e.target.value)); + }; return (
-
+
+
- - setBasePathValue(e.target.value)} - onBlur={() => setBasePath(basePathValue)} - required={true} - autoComplete="off" - spellCheck={false} - /> -
- -
-
+
+
+ +
+ +
); } -function OllamaLLMModelSelection({ settings, basePath = null }) { +function OllamaEmbeddingModelSelection({ settings, basePath = null }) { const [customModels, setCustomModels] = useState([]); const [loading, setLoading] = useState(true); @@ -61,8 +128,13 @@ function OllamaLLMModelSelection({ settings, basePath = null }) { return; } setLoading(true); - const { models } = await System.customModels("ollama", null, basePath); - setCustomModels(models || []); + try { + const { models } = await System.customModels("ollama", null, basePath); + setCustomModels(models || []); + } catch (error) { + console.error("Failed to fetch custom models:", error); + setCustomModels([]); + } setLoading(false); } findCustomModels(); @@ -71,33 +143,37 @@ function OllamaLLMModelSelection({ settings, basePath = null }) { if (loading || customModels.length == 0) { return (
-
); } return (
-
); } diff --git a/frontend/src/components/LLMSelection/LMStudioOptions/index.jsx b/frontend/src/components/LLMSelection/LMStudioOptions/index.jsx index 9a1c59bc..d3e1df58 100644 --- a/frontend/src/components/LLMSelection/LMStudioOptions/index.jsx +++ b/frontend/src/components/LLMSelection/LMStudioOptions/index.jsx @@ -1,13 +1,32 @@ import { useEffect, useState } from "react"; -import { Info } from "@phosphor-icons/react"; +import { Info, CaretDown, CaretUp } from "@phosphor-icons/react"; import paths from "@/utils/paths"; import System from "@/models/system"; +import PreLoader from "@/components/Preloader"; +import { LMSTUDIO_COMMON_URLS } from "@/utils/constants"; +import useProviderEndpointAutoDiscovery from "@/hooks/useProviderEndpointAutoDiscovery"; export default function LMStudioOptions({ settings, showAlert = false }) { - const [basePathValue, setBasePathValue] = useState( - settings?.LMStudioBasePath + const { + autoDetecting: loading, + basePath, + basePathValue, + showAdvancedControls, + setShowAdvancedControls, + handleAutoDetectClick, + } = useProviderEndpointAutoDiscovery({ + provider: "lmstudio", + initialBasePath: settings?.LMStudioBasePath, + ENDPOINTS: LMSTUDIO_COMMON_URLS, + }); + + const [maxTokens, setMaxTokens] = useState( + settings?.LMStudioTokenLimit || 4096 ); - const [basePath, setBasePath] = useState(settings?.LMStudioBasePath); + + const handleMaxTokensChange = (e) => { + setMaxTokens(Number(e.target.value)); + }; return (
@@ -28,45 +47,86 @@ export default function LMStudioOptions({ settings, showAlert = false }) {
)} -
+
+
-
- {!settings?.credentialsOnly && ( - <> - -
-
+
+ +
+ +
); @@ -78,14 +138,23 @@ function LMStudioModelSelection({ settings, basePath = null }) { useEffect(() => { async function findCustomModels() { - if (!basePath || !basePath.includes("/v1")) { + if (!basePath) { setCustomModels([]); setLoading(false); return; } setLoading(true); - const { models } = await System.customModels("lmstudio", null, basePath); - setCustomModels(models || []); + try { + const { models } = await System.customModels( + "lmstudio", + null, + basePath + ); + setCustomModels(models || []); + } catch (error) { + console.error("Failed to fetch custom models:", error); + setCustomModels([]); + } setLoading(false); } findCustomModels(); @@ -94,8 +163,8 @@ function LMStudioModelSelection({ settings, basePath = null }) { if (loading || customModels.length == 0) { return (
-
); } return (
-
); } diff --git a/frontend/src/components/LLMSelection/OllamaLLMOptions/index.jsx b/frontend/src/components/LLMSelection/OllamaLLMOptions/index.jsx index b08f2944..84194393 100644 --- a/frontend/src/components/LLMSelection/OllamaLLMOptions/index.jsx +++ b/frontend/src/components/LLMSelection/OllamaLLMOptions/index.jsx @@ -1,53 +1,117 @@ -import { useEffect, useState } from "react"; +import React, { useEffect, useState } from "react"; import System from "@/models/system"; +import PreLoader from "@/components/Preloader"; +import { OLLAMA_COMMON_URLS } from "@/utils/constants"; +import { CaretDown, CaretUp } from "@phosphor-icons/react"; +import useProviderEndpointAutoDiscovery from "@/hooks/useProviderEndpointAutoDiscovery"; export default function OllamaLLMOptions({ settings }) { - const [basePathValue, setBasePathValue] = useState( - settings?.OllamaLLMBasePath + const { + autoDetecting: loading, + basePath, + basePathValue, + showAdvancedControls, + setShowAdvancedControls, + handleAutoDetectClick, + } = useProviderEndpointAutoDiscovery({ + provider: "ollama", + initialBasePath: settings?.OllamaLLMBasePath, + ENDPOINTS: OLLAMA_COMMON_URLS, + }); + + const [maxTokens, setMaxTokens] = useState( + settings?.OllamaLLMTokenLimit || 4096 ); - const [basePath, setBasePath] = useState(settings?.OllamaLLMBasePath); + + const handleMaxTokensChange = (e) => { + setMaxTokens(Number(e.target.value)); + }; return (
-
+
+
-
- {!settings?.credentialsOnly && ( - <> - -
-
+
+ +
+ +
); @@ -65,8 +129,13 @@ function OllamaLLMModelSelection({ settings, basePath = null }) { return; } setLoading(true); - const { models } = await System.customModels("ollama", null, basePath); - setCustomModels(models || []); + try { + const { models } = await System.customModels("ollama", null, basePath); + setCustomModels(models || []); + } catch (error) { + console.error("Failed to fetch custom models:", error); + setCustomModels([]); + } setLoading(false); } findCustomModels(); @@ -75,8 +144,8 @@ function OllamaLLMModelSelection({ settings, basePath = null }) { if (loading || customModels.length == 0) { return (
-
); } return (
-
); } diff --git a/frontend/src/hooks/useProviderEndpointAutoDiscovery.js b/frontend/src/hooks/useProviderEndpointAutoDiscovery.js new file mode 100644 index 00000000..956b0907 --- /dev/null +++ b/frontend/src/hooks/useProviderEndpointAutoDiscovery.js @@ -0,0 +1,99 @@ +import { useEffect, useState } from "react"; +import System from "@/models/system"; +import showToast from "@/utils/toast"; + +export default function useProviderEndpointAutoDiscovery({ + provider = null, + initialBasePath = "", + ENDPOINTS = [], +}) { + const [loading, setLoading] = useState(false); + const [basePath, setBasePath] = useState(initialBasePath); + const [basePathValue, setBasePathValue] = useState(initialBasePath); + const [autoDetectAttempted, setAutoDetectAttempted] = useState(false); + const [showAdvancedControls, setShowAdvancedControls] = useState(true); + + async function autoDetect(isInitialAttempt = false) { + setLoading(true); + setAutoDetectAttempted(true); + const possibleEndpoints = []; + ENDPOINTS.forEach((endpoint) => { + possibleEndpoints.push( + new Promise((resolve, reject) => { + System.customModels(provider, null, endpoint, 2_000) + .then((results) => { + if (!results?.models || results.models.length === 0) + throw new Error("No models"); + resolve({ endpoint, models: results.models }); + }) + .catch(() => { + reject(`${provider} @ ${endpoint} did not resolve.`); + }); + }) + ); + }); + + const { endpoint, models } = await Promise.any(possibleEndpoints) + .then((resolved) => resolved) + .catch(() => { + console.error("All endpoints failed to resolve."); + return { endpoint: null, models: null }; + }); + + if (models !== null) { + setBasePath(endpoint); + setBasePathValue(endpoint); + setLoading(false); + showToast("Provider endpoint discovered automatically.", "success", { + clear: true, + }); + setShowAdvancedControls(false); + return; + } + + setLoading(false); + setShowAdvancedControls(true); + showToast( + "Couldn't automatically discover the provider endpoint. Please enter it manually.", + "info", + { clear: true } + ); + } + + function handleAutoDetectClick(e) { + e.preventDefault(); + autoDetect(); + } + + function handleBasePathChange(e) { + const value = e.target.value; + setBasePathValue(value); + } + + function handleBasePathBlur() { + setBasePath(basePathValue); + } + + useEffect(() => { + if (!initialBasePath && !autoDetectAttempted) autoDetect(true); + }, [initialBasePath, autoDetectAttempted]); + + return { + autoDetecting: loading, + autoDetectAttempted, + showAdvancedControls, + setShowAdvancedControls, + basePath: { + value: basePath, + set: setBasePathValue, + onChange: handleBasePathChange, + onBlur: handleBasePathBlur, + }, + basePathValue: { + value: basePathValue, + set: setBasePathValue, + }, + handleAutoDetectClick, + runAutoDetect: autoDetect, + }; +} diff --git a/frontend/src/locales/en/common.js b/frontend/src/locales/en/common.js index 5254e3bd..a851f4cf 100644 --- a/frontend/src/locales/en/common.js +++ b/frontend/src/locales/en/common.js @@ -85,6 +85,9 @@ const TRANSLATIONS = { remove: "Remove Workspace Image", }, delete: { + title: "Delete Workspace", + description: + "Delete this workspace and all of its data. This will delete the workspace for all users.", delete: "Delete Workspace", deleting: "Deleting Workspace...", "confirm-start": "You are about to delete your entire", diff --git a/frontend/src/locales/es/common.js b/frontend/src/locales/es/common.js index d0609e9a..5dc2daad 100644 --- a/frontend/src/locales/es/common.js +++ b/frontend/src/locales/es/common.js @@ -82,6 +82,9 @@ const TRANSLATIONS = { remove: "Eliminar imagen del espacio de trabajo", }, delete: { + title: "Eliminar Espacio de Trabajo", + description: + "Eliminar este espacio de trabajo y todos sus datos. Esto eliminará el espacio de trabajo para todos los usuarios.", delete: "Eliminar espacio de trabajo", deleting: "Eliminando espacio de trabajo...", "confirm-start": "Estás a punto de eliminar tu", diff --git a/frontend/src/locales/fr/common.js b/frontend/src/locales/fr/common.js index 9e7a82e8..71c37a7e 100644 --- a/frontend/src/locales/fr/common.js +++ b/frontend/src/locales/fr/common.js @@ -87,6 +87,9 @@ const TRANSLATIONS = { remove: "Supprimer l'image de l'espace de travail", }, delete: { + title: "Supprimer l'Espace de Travail", + description: + "Supprimer cet espace de travail et toutes ses données. Cela supprimera l'espace de travail pour tous les utilisateurs.", delete: "Supprimer l'espace de travail", deleting: "Suppression de l'espace de travail...", "confirm-start": "Vous êtes sur le point de supprimer votre", diff --git a/frontend/src/locales/ru/common.js b/frontend/src/locales/ru/common.js index 34f9591c..da3b49f1 100644 --- a/frontend/src/locales/ru/common.js +++ b/frontend/src/locales/ru/common.js @@ -78,6 +78,9 @@ const TRANSLATIONS = { remove: "Удалить изображение рабочего пространства", }, delete: { + title: "Удалить Рабочее Пространство", + description: + "Удалите это рабочее пространство и все его данные. Это удалит рабочее пространство для всех пользователей.", delete: "Удалить рабочее пространство", deleting: "Удаление рабочего пространства...", "confirm-start": "Вы собираетесь удалить весь ваш", diff --git a/frontend/src/locales/zh/common.js b/frontend/src/locales/zh/common.js index 0f30c4f7..476533d1 100644 --- a/frontend/src/locales/zh/common.js +++ b/frontend/src/locales/zh/common.js @@ -84,6 +84,8 @@ const TRANSLATIONS = { remove: "移除工作区图像", }, delete: { + title: "删除工作区", + description: "删除此工作区及其所有数据。这将删除所有用户的工作区。", delete: "删除工作区", deleting: "正在删除工作区...", "confirm-start": "您即将删除整个", diff --git a/frontend/src/models/system.js b/frontend/src/models/system.js index b922457b..095244a4 100644 --- a/frontend/src/models/system.js +++ b/frontend/src/models/system.js @@ -420,22 +420,6 @@ const System = { return { success: false, error: e.message }; }); }, - getCanDeleteWorkspaces: async function () { - return await fetch(`${API_BASE}/system/can-delete-workspaces`, { - method: "GET", - cache: "no-cache", - headers: baseHeaders(), - }) - .then((res) => { - if (!res.ok) throw new Error("Could not fetch can delete workspaces."); - return res.json(); - }) - .then((res) => res?.canDelete) - .catch((e) => { - console.error(e); - return false; - }); - }, getWelcomeMessages: async function () { return await fetch(`${API_BASE}/system/welcome-messages`, { method: "GET", @@ -512,10 +496,23 @@ const System = { return false; }); }, - customModels: async function (provider, apiKey = null, basePath = null) { + customModels: async function ( + provider, + apiKey = null, + basePath = null, + timeout = null + ) { + const controller = new AbortController(); + if (!!timeout) { + setTimeout(() => { + controller.abort("Request timed out."); + }, timeout); + } + return fetch(`${API_BASE}/system/custom-models`, { method: "POST", headers: baseHeaders(), + signal: controller.signal, body: JSON.stringify({ provider, apiKey, diff --git a/frontend/src/pages/Admin/System/index.jsx b/frontend/src/pages/Admin/System/index.jsx index bdab765a..3924c6e8 100644 --- a/frontend/src/pages/Admin/System/index.jsx +++ b/frontend/src/pages/Admin/System/index.jsx @@ -8,7 +8,6 @@ import CTAButton from "@/components/lib/CTAButton"; export default function AdminSystem() { const [saving, setSaving] = useState(false); const [hasChanges, setHasChanges] = useState(false); - const [canDelete, setCanDelete] = useState(false); const [messageLimit, setMessageLimit] = useState({ enabled: false, limit: 10, @@ -18,7 +17,6 @@ export default function AdminSystem() { e.preventDefault(); setSaving(true); await Admin.updateSystemPreferences({ - users_can_delete_workspaces: canDelete, limit_user_messages: messageLimit.enabled, message_limit: messageLimit.limit, }); @@ -31,7 +29,6 @@ export default function AdminSystem() { async function fetchSettings() { const settings = (await Admin.systemPreferences())?.settings; if (!settings) return; - setCanDelete(settings?.users_can_delete_workspaces); setMessageLimit({ enabled: settings.limit_user_messages, limit: settings.message_limit, @@ -71,29 +68,6 @@ export default function AdminSystem() {
)}
-
-

- Users can delete workspaces -

-

- Allow non-admin users to delete workspaces that they are a part - of. This would delete the workspace for everyone. -

- -
-
- -

Limit messages per user per day diff --git a/frontend/src/pages/WorkspaceSettings/GeneralAppearance/DeleteWorkspace/index.jsx b/frontend/src/pages/WorkspaceSettings/GeneralAppearance/DeleteWorkspace/index.jsx index 32a3eaa4..44c7127a 100644 --- a/frontend/src/pages/WorkspaceSettings/GeneralAppearance/DeleteWorkspace/index.jsx +++ b/frontend/src/pages/WorkspaceSettings/GeneralAppearance/DeleteWorkspace/index.jsx @@ -1,22 +1,14 @@ -import { useEffect, useState } from "react"; +import { useState } from "react"; import { useParams } from "react-router-dom"; import Workspace from "@/models/workspace"; import paths from "@/utils/paths"; -import System from "@/models/system"; import { useTranslation } from "react-i18next"; +import showToast from "@/utils/toast"; export default function DeleteWorkspace({ workspace }) { const { slug } = useParams(); const [deleting, setDeleting] = useState(false); - const [canDelete, setCanDelete] = useState(false); const { t } = useTranslation(); - useEffect(() => { - async function fetchKeys() { - const canDelete = await System.getCanDeleteWorkspaces(); - setCanDelete(canDelete); - } - fetchKeys(); - }, [workspace?.slug]); const deleteWorkspace = async () => { if ( @@ -40,16 +32,20 @@ export default function DeleteWorkspace({ workspace }) { ? (window.location = paths.home()) : window.location.reload(); }; - - if (!canDelete) return null; return ( - +
+ +

+ {t("general.delete.description")} +

+ +
); } diff --git a/frontend/src/utils/constants.js b/frontend/src/utils/constants.js index 3f637617..a08439d0 100644 --- a/frontend/src/utils/constants.js +++ b/frontend/src/utils/constants.js @@ -10,6 +10,19 @@ export const SEEN_WATCH_ALERT = "anythingllm_watched_document_alert"; export const USER_BACKGROUND_COLOR = "bg-historical-msg-user"; export const AI_BACKGROUND_COLOR = "bg-historical-msg-system"; +export const OLLAMA_COMMON_URLS = [ + "http://127.0.0.1:11434", + "http://host.docker.internal:11434", + "http://172.17.0.1:11434", +]; + +export const LMSTUDIO_COMMON_URLS = [ + "http://localhost:1234/v1", + "http://127.0.0.1:1234/v1", + "http://host.docker.internal:1234/v1", + "http://172.17.0.1:1234/v1", +]; + export function fullApiUrl() { if (API_BASE !== "/api") return API_BASE; return `${window.location.origin}/api`; diff --git a/server/endpoints/admin.js b/server/endpoints/admin.js index 67d7210f..d7cab1f5 100644 --- a/server/endpoints/admin.js +++ b/server/endpoints/admin.js @@ -319,9 +319,6 @@ function adminEndpoints(app) { try { const embedder = getEmbeddingEngineSelection(); const settings = { - users_can_delete_workspaces: - (await SystemSettings.get({ label: "users_can_delete_workspaces" })) - ?.value === "true", limit_user_messages: (await SystemSettings.get({ label: "limit_user_messages" })) ?.value === "true", diff --git a/server/endpoints/api/admin/index.js b/server/endpoints/api/admin/index.js index 600d3636..dd47f374 100644 --- a/server/endpoints/api/admin/index.js +++ b/server/endpoints/api/admin/index.js @@ -616,7 +616,6 @@ function apiAdminEndpoints(app) { type: 'object', example: { settings: { - users_can_delete_workspaces: true, limit_user_messages: false, message_limit: 10, } @@ -641,9 +640,6 @@ function apiAdminEndpoints(app) { } const settings = { - users_can_delete_workspaces: - (await SystemSettings.get({ label: "users_can_delete_workspaces" })) - ?.value === "true", limit_user_messages: (await SystemSettings.get({ label: "limit_user_messages" })) ?.value === "true", @@ -673,7 +669,6 @@ function apiAdminEndpoints(app) { content: { "application/json": { example: { - users_can_delete_workspaces: false, limit_user_messages: true, message_limit: 5, } diff --git a/server/endpoints/system.js b/server/endpoints/system.js index 1849a2fc..05a24e5c 100644 --- a/server/endpoints/system.js +++ b/server/endpoints/system.js @@ -479,7 +479,6 @@ function systemEndpoints(app) { }); await SystemSettings._updateSettings({ multi_user_mode: true, - users_can_delete_workspaces: false, limit_user_messages: false, message_limit: 25, }); @@ -776,33 +775,6 @@ function systemEndpoints(app) { } ); - app.get( - "/system/can-delete-workspaces", - [validatedRequest], - async function (request, response) { - try { - if (!response.locals.multiUserMode) { - return response.status(200).json({ canDelete: true }); - } - - const user = await userFromSession(request, response); - if ([ROLES.admin, ROLES.manager].includes(user?.role)) { - return response.status(200).json({ canDelete: true }); - } - - const canDelete = await SystemSettings.canDeleteWorkspaces(); - response.status(200).json({ canDelete }); - } catch (error) { - console.error("Error fetching can delete workspaces:", error); - response.status(500).json({ - success: false, - message: "Internal server error", - canDelete: false, - }); - } - } - ); - app.get( "/system/welcome-messages", [validatedRequest, flexUserRoleValid([ROLES.all])], diff --git a/server/models/systemSettings.js b/server/models/systemSettings.js index 3f44f722..ea1dd01e 100644 --- a/server/models/systemSettings.js +++ b/server/models/systemSettings.js @@ -15,7 +15,6 @@ function isNullOrNaN(value) { const SystemSettings = { protectedFields: ["multi_user_mode"], supportedFields: [ - "users_can_delete_workspaces", "limit_user_messages", "message_limit", "logo_filename", @@ -302,16 +301,6 @@ const SystemSettings = { } }, - canDeleteWorkspaces: async function () { - try { - const setting = await this.get({ label: "users_can_delete_workspaces" }); - return setting?.value === "true"; - } catch (error) { - console.error(error.message); - return false; - } - }, - hasEmbeddings: async function () { try { const { Document } = require("./documents"); diff --git a/server/prisma/seed.js b/server/prisma/seed.js index 829b812a..c58e4556 100644 --- a/server/prisma/seed.js +++ b/server/prisma/seed.js @@ -4,7 +4,6 @@ const prisma = new PrismaClient(); async function main() { const settings = [ { label: "multi_user_mode", value: "false" }, - { label: "users_can_delete_workspaces", value: "false" }, { label: "limit_user_messages", value: "false" }, { label: "message_limit", value: "25" }, { label: "logo_filename", value: "anything-llm.png" }, diff --git a/server/swagger/openapi.json b/server/swagger/openapi.json index 2b5ee82e..571fef59 100644 --- a/server/swagger/openapi.json +++ b/server/swagger/openapi.json @@ -710,7 +710,6 @@ "type": "object", "example": { "settings": { - "users_can_delete_workspaces": true, "limit_user_messages": false, "message_limit": 10 } @@ -792,7 +791,6 @@ "content": { "application/json": { "example": { - "users_can_delete_workspaces": false, "limit_user_messages": true, "message_limit": 5 }