Browse Source

Merge branch 'websearch' into feat/backend-web-search

Timothy Jaeryang Baek 11 months ago
parent
commit
bced90734b
77 changed files with 1336 additions and 343 deletions
  1. 8 2
      .github/workflows/docker-build.yaml
  2. 6 0
      Dockerfile
  3. 3 3
      backend/apps/openai/main.py
  4. 48 0
      backend/apps/webui/internal/migrations/011_add_user_settings.py
  5. 5 1
      backend/apps/webui/main.py
  6. 10 2
      backend/apps/webui/models/users.py
  7. 30 0
      backend/apps/webui/routers/configs.py
  8. 45 1
      backend/apps/webui/routers/users.py
  9. 25 2
      backend/config.py
  10. 25 7
      backend/main.py
  11. 2 0
      hatch_build.py
  12. 2 2
      package-lock.json
  13. 1 1
      package.json
  14. 58 0
      src/lib/apis/configs/index.ts
  15. 55 1
      src/lib/apis/index.ts
  16. 56 0
      src/lib/apis/users/index.ts
  17. 137 0
      src/lib/components/admin/Settings/Banners.svelte
  18. 1 1
      src/lib/components/admin/Settings/Database.svelte
  19. 69 5
      src/lib/components/admin/Settings/General.svelte
  20. 36 14
      src/lib/components/admin/Settings/Users.svelte
  21. 42 0
      src/lib/components/admin/SettingsModal.svelte
  22. 54 10
      src/lib/components/chat/Chat.svelte
  23. 1 1
      src/lib/components/chat/Messages/ResponseMessage.svelte
  24. 4 8
      src/lib/components/chat/ModelSelector.svelte
  25. 2 2
      src/lib/components/chat/Settings/About.svelte
  26. 9 11
      src/lib/components/chat/Settings/Audio.svelte
  27. 2 4
      src/lib/components/chat/Settings/Chats.svelte
  28. 198 180
      src/lib/components/chat/Settings/Connections.svelte
  29. 13 14
      src/lib/components/chat/Settings/General.svelte
  30. 11 16
      src/lib/components/chat/Settings/Interface.svelte
  31. 1 2
      src/lib/components/chat/Settings/Personalization.svelte
  32. 2 1
      src/lib/components/chat/SettingsModal.svelte
  33. 13 11
      src/lib/components/chat/ShareChatModal.svelte
  34. 125 0
      src/lib/components/common/Banner.svelte
  35. 2 1
      src/lib/components/layout/Sidebar.svelte
  36. 1 1
      src/lib/components/layout/Sidebar/ArchivedChatsModal.svelte
  37. 1 0
      src/lib/constants.ts
  38. 5 0
      src/lib/i18n/locales/ar-BH/translation.json
  39. 5 0
      src/lib/i18n/locales/bg-BG/translation.json
  40. 5 0
      src/lib/i18n/locales/bn-BD/translation.json
  41. 5 0
      src/lib/i18n/locales/ca-ES/translation.json
  42. 5 0
      src/lib/i18n/locales/ceb-PH/translation.json
  43. 5 0
      src/lib/i18n/locales/de-DE/translation.json
  44. 5 0
      src/lib/i18n/locales/dg-DG/translation.json
  45. 5 0
      src/lib/i18n/locales/en-GB/translation.json
  46. 5 0
      src/lib/i18n/locales/en-US/translation.json
  47. 5 0
      src/lib/i18n/locales/es-ES/translation.json
  48. 5 0
      src/lib/i18n/locales/fa-IR/translation.json
  49. 5 0
      src/lib/i18n/locales/fi-FI/translation.json
  50. 5 0
      src/lib/i18n/locales/fr-CA/translation.json
  51. 5 0
      src/lib/i18n/locales/fr-FR/translation.json
  52. 5 0
      src/lib/i18n/locales/he-IL/translation.json
  53. 5 0
      src/lib/i18n/locales/hi-IN/translation.json
  54. 5 0
      src/lib/i18n/locales/hr-HR/translation.json
  55. 5 0
      src/lib/i18n/locales/it-IT/translation.json
  56. 5 0
      src/lib/i18n/locales/ja-JP/translation.json
  57. 5 0
      src/lib/i18n/locales/ka-GE/translation.json
  58. 5 0
      src/lib/i18n/locales/ko-KR/translation.json
  59. 5 0
      src/lib/i18n/locales/nl-NL/translation.json
  60. 5 0
      src/lib/i18n/locales/pa-IN/translation.json
  61. 5 0
      src/lib/i18n/locales/pl-PL/translation.json
  62. 5 0
      src/lib/i18n/locales/pt-BR/translation.json
  63. 5 0
      src/lib/i18n/locales/pt-PT/translation.json
  64. 5 0
      src/lib/i18n/locales/ru-RU/translation.json
  65. 5 0
      src/lib/i18n/locales/sr-RS/translation.json
  66. 5 0
      src/lib/i18n/locales/sv-SE/translation.json
  67. 5 0
      src/lib/i18n/locales/tr-TR/translation.json
  68. 5 0
      src/lib/i18n/locales/uk-UA/translation.json
  69. 23 18
      src/lib/i18n/locales/vi-VN/translation.json
  70. 5 0
      src/lib/i18n/locales/zh-CN/translation.json
  71. 5 0
      src/lib/i18n/locales/zh-TW/translation.json
  72. 18 10
      src/lib/stores/index.ts
  73. 9 0
      src/lib/types/index.ts
  74. 13 1
      src/routes/(app)/+layout.svelte
  75. 3 3
      src/routes/auth/+page.svelte
  76. 0 6
      src/routes/s/[id]/+page.svelte
  77. 2 1
      vite.config.ts

+ 8 - 2
.github/workflows/docker-build.yaml

@@ -84,6 +84,8 @@ jobs:
           outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
           cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
           cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
+          build-args: |
+            BUILD_HASH=${{ github.sha }}
 
       - name: Export digest
         run: |
@@ -170,7 +172,9 @@ jobs:
           outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
           cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
           cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
-          build-args: USE_CUDA=true
+          build-args: |
+            BUILD_HASH=${{ github.sha }}
+            USE_CUDA=true
 
       - name: Export digest
         run: |
@@ -257,7 +261,9 @@ jobs:
           outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
           cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
           cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
-          build-args: USE_OLLAMA=true
+          build-args: |
+            BUILD_HASH=${{ github.sha }}
+            USE_OLLAMA=true
 
       - name: Export digest
         run: |

+ 6 - 0
Dockerfile

@@ -11,12 +11,14 @@ ARG USE_CUDA_VER=cu121
 # IMPORTANT: If you change the embedding model (sentence-transformers/all-MiniLM-L6-v2) and vice versa, you aren't able to use RAG Chat with your previous documents loaded in the WebUI! You need to re-embed them.
 ARG USE_EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
 ARG USE_RERANKING_MODEL=""
+ARG BUILD_HASH=dev-build
 # Override at your own risk - non-root configurations are untested
 ARG UID=0
 ARG GID=0
 
 ######## WebUI frontend ########
 FROM --platform=$BUILDPLATFORM node:21-alpine3.19 as build
+ARG BUILD_HASH
 
 WORKDIR /app
 
@@ -24,6 +26,7 @@ COPY package.json package-lock.json ./
 RUN npm ci
 
 COPY . .
+ENV APP_BUILD_HASH=${BUILD_HASH}
 RUN npm run build
 
 ######## WebUI backend ########
@@ -35,6 +38,7 @@ ARG USE_OLLAMA
 ARG USE_CUDA_VER
 ARG USE_EMBEDDING_MODEL
 ARG USE_RERANKING_MODEL
+ARG BUILD_HASH
 ARG UID
 ARG GID
 
@@ -150,4 +154,6 @@ HEALTHCHECK CMD curl --silent --fail http://localhost:8080/health | jq -e '.stat
 
 USER $UID:$GID
 
+ENV WEBUI_BUILD_VERSION=${BUILD_HASH}
+
 CMD [ "bash", "start.sh"]

+ 3 - 3
backend/apps/openai/main.py

@@ -198,7 +198,7 @@ async def fetch_url(url, key):
 
 
 def merge_models_lists(model_lists):
-    log.info(f"merge_models_lists {model_lists}")
+    log.debug(f"merge_models_lists {model_lists}")
     merged_list = []
 
     for idx, models in enumerate(model_lists):
@@ -237,7 +237,7 @@ async def get_all_models():
         ]
 
         responses = await asyncio.gather(*tasks)
-        log.info(f"get_all_models:responses() {responses}")
+        log.debug(f"get_all_models:responses() {responses}")
 
         models = {
             "data": merge_models_lists(
@@ -254,7 +254,7 @@ async def get_all_models():
             )
         }
 
-        log.info(f"models: {models}")
+        log.debug(f"models: {models}")
         app.state.MODELS = {model["id"]: model for model in models["data"]}
 
     return models

+ 48 - 0
backend/apps/webui/internal/migrations/011_add_user_settings.py

@@ -0,0 +1,48 @@
+"""Peewee migrations -- 002_add_local_sharing.py.
+
+Some examples (model - class or model name)::
+
+    > Model = migrator.orm['table_name']            # Return model in current state by name
+    > Model = migrator.ModelClass                   # Return model in current state by name
+
+    > migrator.sql(sql)                             # Run custom SQL
+    > migrator.run(func, *args, **kwargs)           # Run python function with the given args
+    > migrator.create_model(Model)                  # Create a model (could be used as decorator)
+    > migrator.remove_model(model, cascade=True)    # Remove a model
+    > migrator.add_fields(model, **fields)          # Add fields to a model
+    > migrator.change_fields(model, **fields)       # Change fields
+    > migrator.remove_fields(model, *field_names, cascade=True)
+    > migrator.rename_field(model, old_field_name, new_field_name)
+    > migrator.rename_table(model, new_table_name)
+    > migrator.add_index(model, *col_names, unique=False)
+    > migrator.add_not_null(model, *field_names)
+    > migrator.add_default(model, field_name, default)
+    > migrator.add_constraint(model, name, sql)
+    > migrator.drop_index(model, *col_names)
+    > migrator.drop_not_null(model, *field_names)
+    > migrator.drop_constraints(model, *constraints)
+
+"""
+
+from contextlib import suppress
+
+import peewee as pw
+from peewee_migrate import Migrator
+
+
+with suppress(ImportError):
+    import playhouse.postgres_ext as pw_pext
+
+
+def migrate(migrator: Migrator, database: pw.Database, *, fake=False):
+    """Write your migrations here."""
+
+    # Adding fields settings to the 'user' table
+    migrator.add_fields("user", settings=pw.TextField(null=True))
+
+
+def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
+    """Write your rollback migrations here."""
+
+    # Remove the settings field
+    migrator.remove_fields("user", "settings")

+ 5 - 1
backend/apps/webui/main.py

@@ -13,7 +13,7 @@ from apps.webui.routers import (
     utils,
 )
 from config import (
-    WEBUI_VERSION,
+    WEBUI_BUILD_HASH,
     WEBUI_AUTH,
     DEFAULT_MODELS,
     DEFAULT_PROMPT_SUGGESTIONS,
@@ -23,7 +23,9 @@ from config import (
     WEBHOOK_URL,
     WEBUI_AUTH_TRUSTED_EMAIL_HEADER,
     JWT_EXPIRES_IN,
+    WEBUI_BANNERS,
     AppConfig,
+    ENABLE_COMMUNITY_SHARING,
 )
 
 app = FastAPI()
@@ -40,7 +42,9 @@ app.state.config.DEFAULT_PROMPT_SUGGESTIONS = DEFAULT_PROMPT_SUGGESTIONS
 app.state.config.DEFAULT_USER_ROLE = DEFAULT_USER_ROLE
 app.state.config.USER_PERMISSIONS = USER_PERMISSIONS
 app.state.config.WEBHOOK_URL = WEBHOOK_URL
+app.state.config.BANNERS = WEBUI_BANNERS
 
+app.state.config.ENABLE_COMMUNITY_SHARING = ENABLE_COMMUNITY_SHARING
 
 app.state.MODELS = {}
 app.state.AUTH_TRUSTED_EMAIL_HEADER = WEBUI_AUTH_TRUSTED_EMAIL_HEADER

+ 10 - 2
backend/apps/webui/models/users.py

@@ -1,11 +1,11 @@
-from pydantic import BaseModel
+from pydantic import BaseModel, ConfigDict
 from peewee import *
 from playhouse.shortcuts import model_to_dict
 from typing import List, Union, Optional
 import time
 from utils.misc import get_gravatar_url
 
-from apps.webui.internal.db import DB
+from apps.webui.internal.db import DB, JSONField
 from apps.webui.models.chats import Chats
 
 ####################
@@ -25,11 +25,18 @@ class User(Model):
     created_at = BigIntegerField()
 
     api_key = CharField(null=True, unique=True)
+    settings = JSONField(null=True)
 
     class Meta:
         database = DB
 
 
+class UserSettings(BaseModel):
+    ui: Optional[dict] = {}
+    model_config = ConfigDict(extra="allow")
+    pass
+
+
 class UserModel(BaseModel):
     id: str
     name: str
@@ -42,6 +49,7 @@ class UserModel(BaseModel):
     created_at: int  # timestamp in epoch
 
     api_key: Optional[str] = None
+    settings: Optional[UserSettings] = None
 
 
 ####################

+ 30 - 0
backend/apps/webui/routers/configs.py

@@ -8,6 +8,8 @@ from pydantic import BaseModel
 import time
 import uuid
 
+from config import BannerModel
+
 from apps.webui.models.users import Users
 
 from utils.utils import (
@@ -57,3 +59,31 @@ async def set_global_default_suggestions(
     data = form_data.model_dump()
     request.app.state.config.DEFAULT_PROMPT_SUGGESTIONS = data["suggestions"]
     return request.app.state.config.DEFAULT_PROMPT_SUGGESTIONS
+
+
+############################
+# SetBanners
+############################
+
+
+class SetBannersForm(BaseModel):
+    banners: List[BannerModel]
+
+
+@router.post("/banners", response_model=List[BannerModel])
+async def set_banners(
+    request: Request,
+    form_data: SetBannersForm,
+    user=Depends(get_admin_user),
+):
+    data = form_data.model_dump()
+    request.app.state.config.BANNERS = data["banners"]
+    return request.app.state.config.BANNERS
+
+
+@router.get("/banners", response_model=List[BannerModel])
+async def get_banners(
+    request: Request,
+    user=Depends(get_current_user),
+):
+    return request.app.state.config.BANNERS

+ 45 - 1
backend/apps/webui/routers/users.py

@@ -9,7 +9,13 @@ import time
 import uuid
 import logging
 
-from apps.webui.models.users import UserModel, UserUpdateForm, UserRoleUpdateForm, Users
+from apps.webui.models.users import (
+    UserModel,
+    UserUpdateForm,
+    UserRoleUpdateForm,
+    UserSettings,
+    Users,
+)
 from apps.webui.models.auths import Auths
 from apps.webui.models.chats import Chats
 
@@ -68,6 +74,42 @@ async def update_user_role(form_data: UserRoleUpdateForm, user=Depends(get_admin
     )
 
 
+############################
+# GetUserSettingsBySessionUser
+############################
+
+
+@router.get("/user/settings", response_model=Optional[UserSettings])
+async def get_user_settings_by_session_user(user=Depends(get_verified_user)):
+    user = Users.get_user_by_id(user.id)
+    if user:
+        return user.settings
+    else:
+        raise HTTPException(
+            status_code=status.HTTP_400_BAD_REQUEST,
+            detail=ERROR_MESSAGES.USER_NOT_FOUND,
+        )
+
+
+############################
+# UpdateUserSettingsBySessionUser
+############################
+
+
+@router.post("/user/settings/update", response_model=UserSettings)
+async def update_user_settings_by_session_user(
+    form_data: UserSettings, user=Depends(get_verified_user)
+):
+    user = Users.update_user_by_id(user.id, {"settings": form_data.model_dump()})
+    if user:
+        return user.settings
+    else:
+        raise HTTPException(
+            status_code=status.HTTP_400_BAD_REQUEST,
+            detail=ERROR_MESSAGES.USER_NOT_FOUND,
+        )
+
+
 ############################
 # GetUserById
 ############################
@@ -81,6 +123,8 @@ class UserResponse(BaseModel):
 @router.get("/{user_id}", response_model=UserResponse)
 async def get_user_by_id(user_id: str, user=Depends(get_verified_user)):
 
+    # Check if user_id is a shared chat
+    # If it is, get the user_id from the chat
     if user_id.startswith("shared-"):
         chat_id = user_id.replace("shared-", "")
         chat = Chats.get_chat_by_id(chat_id)

+ 25 - 2
backend/config.py

@@ -8,6 +8,8 @@ from chromadb import Settings
 from base64 import b64encode
 from bs4 import BeautifulSoup
 from typing import TypeVar, Generic, Union
+from pydantic import BaseModel
+from typing import Optional
 
 from pathlib import Path
 import json
@@ -166,10 +168,10 @@ CHANGELOG = changelog_json
 
 
 ####################################
-# WEBUI_VERSION
+# WEBUI_BUILD_HASH
 ####################################
 
-WEBUI_VERSION = os.environ.get("WEBUI_VERSION", "v1.0.0-alpha.100")
+WEBUI_BUILD_HASH = os.environ.get("WEBUI_BUILD_HASH", "dev-build")
 
 ####################################
 # DATA/FRONTEND BUILD DIR
@@ -566,6 +568,27 @@ WEBHOOK_URL = PersistentConfig(
 
 ENABLE_ADMIN_EXPORT = os.environ.get("ENABLE_ADMIN_EXPORT", "True").lower() == "true"
 
+ENABLE_COMMUNITY_SHARING = PersistentConfig(
+    "ENABLE_COMMUNITY_SHARING",
+    "ui.enable_community_sharing",
+    os.environ.get("ENABLE_COMMUNITY_SHARING", "True").lower() == "true",
+)
+
+class BannerModel(BaseModel):
+    id: str
+    type: str
+    title: Optional[str] = None
+    content: str
+    dismissible: bool
+    timestamp: int
+
+
+WEBUI_BANNERS = PersistentConfig(
+    "WEBUI_BANNERS",
+    "ui.banners",
+    [BannerModel(**banner) for banner in json.loads("[]")],
+)
+
 ####################################
 # WEBUI_SECRET_KEY
 ####################################

+ 25 - 7
backend/main.py

@@ -56,6 +56,7 @@ from config import (
     ENABLE_ADMIN_EXPORT,
     RAG_WEB_SEARCH_ENABLED,
     AppConfig,
+    WEBUI_BUILD_HASH,
 )
 from constants import ERROR_MESSAGES
 
@@ -85,7 +86,8 @@ print(
       |_|                                               
 
       
-v{VERSION} - building the best open-source AI user interface.      
+v{VERSION} - building the best open-source AI user interface.
+{f"Commit: {WEBUI_BUILD_HASH}" if WEBUI_BUILD_HASH != "dev-build" else ""}
 https://github.com/open-webui/open-webui
 """
 )
@@ -357,15 +359,18 @@ async def get_app_config():
         "status": True,
         "name": WEBUI_NAME,
         "version": VERSION,
-        "auth": WEBUI_AUTH,
-        "auth_trusted_header": bool(webui_app.state.AUTH_TRUSTED_EMAIL_HEADER),
-        "enable_signup": webui_app.state.config.ENABLE_SIGNUP,
-        "enable_image_generation": images_app.state.config.ENABLED,
-        "enable_admin_export": ENABLE_ADMIN_EXPORT,
         "default_locale": default_locale,
         "default_models": webui_app.state.config.DEFAULT_MODELS,
         "default_prompt_suggestions": webui_app.state.config.DEFAULT_PROMPT_SUGGESTIONS,
-        "enable_websearch": RAG_WEB_SEARCH_ENABLED,
+        "features": {
+            "auth": WEBUI_AUTH,
+            "auth_trusted_header": bool(webui_app.state.AUTH_TRUSTED_EMAIL_HEADER),
+            "enable_signup": webui_app.state.config.ENABLE_SIGNUP,
+            "enable_websearch": RAG_WEB_SEARCH_ENABLED,
+            "enable_image_generation": images_app.state.config.ENABLED,
+            "enable_community_sharing": webui_app.state.config.ENABLE_COMMUNITY_SHARING,
+            "enable_admin_export": ENABLE_ADMIN_EXPORT,
+        },
     }
 
 
@@ -416,6 +421,19 @@ async def update_webhook_url(form_data: UrlForm, user=Depends(get_admin_user)):
     }
 
 
+@app.get("/api/community_sharing", response_model=bool)
+async def get_community_sharing_status(request: Request, user=Depends(get_admin_user)):
+    return webui_app.state.config.ENABLE_COMMUNITY_SHARING
+
+
+@app.get("/api/community_sharing/toggle", response_model=bool)
+async def toggle_community_sharing(request: Request, user=Depends(get_admin_user)):
+    webui_app.state.config.ENABLE_COMMUNITY_SHARING = (
+        not webui_app.state.config.ENABLE_COMMUNITY_SHARING
+    )
+    return webui_app.state.config.ENABLE_COMMUNITY_SHARING
+
+
 @app.get("/api/version")
 async def get_app_config():
     return {

+ 2 - 0
hatch_build.py

@@ -1,4 +1,5 @@
 # noqa: INP001
+import os
 import shutil
 import subprocess
 from sys import stderr
@@ -18,4 +19,5 @@ class CustomBuildHook(BuildHookInterface):
         stderr.write("### npm install\n")
         subprocess.run([npm, "install"], check=True)  # noqa: S603
         stderr.write("\n### npm run build\n")
+        os.environ["APP_BUILD_HASH"] = version
         subprocess.run([npm, "run", "build"], check=True)  # noqa: S603

+ 2 - 2
package-lock.json

@@ -1,12 +1,12 @@
 {
 	"name": "open-webui",
-	"version": "0.2.0.dev1",
+	"version": "0.2.0.dev2",
 	"lockfileVersion": 3,
 	"requires": true,
 	"packages": {
 		"": {
 			"name": "open-webui",
-			"version": "0.2.0.dev1",
+			"version": "0.2.0.dev2",
 			"dependencies": {
 				"@pyscript/core": "^0.4.32",
 				"@sveltejs/adapter-node": "^1.3.1",

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
 	"name": "open-webui",
-	"version": "0.2.0.dev1",
+	"version": "0.2.0.dev2",
 	"private": true,
 	"scripts": {
 		"dev": "npm run pyodide:fetch && vite dev --host",

+ 58 - 0
src/lib/apis/configs/index.ts

@@ -1,4 +1,5 @@
 import { WEBUI_API_BASE_URL } from '$lib/constants';
+import type { Banner } from '$lib/types';
 
 export const setDefaultModels = async (token: string, models: string) => {
 	let error = null;
@@ -59,3 +60,60 @@ export const setDefaultPromptSuggestions = async (token: string, promptSuggestio
 
 	return res;
 };
+
+export const getBanners = async (token: string): Promise<Banner[]> => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/configs/banners`, {
+		method: 'GET',
+		headers: {
+			'Content-Type': 'application/json',
+			Authorization: `Bearer ${token}`
+		}
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			console.log(err);
+			error = err.detail;
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
+export const setBanners = async (token: string, banners: Banner[]) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/configs/banners`, {
+		method: 'POST',
+		headers: {
+			'Content-Type': 'application/json',
+			Authorization: `Bearer ${token}`
+		},
+		body: JSON.stringify({
+			banners: banners
+		})
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			console.log(err);
+			error = err.detail;
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};

+ 55 - 1
src/lib/apis/index.ts

@@ -1,4 +1,4 @@
-import { WEBUI_BASE_URL } from '$lib/constants';
+import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
 
 export const getModels = async (token: string = '') => {
 	let error = null;
@@ -246,6 +246,60 @@ export const updateWebhookUrl = async (token: string, url: string) => {
 	return res.url;
 };
 
+export const getCommunitySharingEnabledStatus = async (token: string) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_BASE_URL}/api/community_sharing`, {
+		method: 'GET',
+		headers: {
+			'Content-Type': 'application/json',
+			Authorization: `Bearer ${token}`
+		}
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			console.log(err);
+			error = err;
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
+export const toggleCommunitySharingEnabledStatus = async (token: string) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_BASE_URL}/api/community_sharing/toggle`, {
+		method: 'GET',
+		headers: {
+			'Content-Type': 'application/json',
+			Authorization: `Bearer ${token}`
+		}
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			console.log(err);
+			error = err.detail;
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
 export const getModelConfig = async (token: string): Promise<GlobalModelConfig> => {
 	let error = null;
 

+ 56 - 0
src/lib/apis/users/index.ts

@@ -115,6 +115,62 @@ export const getUsers = async (token: string) => {
 	return res ? res : [];
 };
 
+export const getUserSettings = async (token: string) => {
+	let error = null;
+	const res = await fetch(`${WEBUI_API_BASE_URL}/users/user/settings`, {
+		method: 'GET',
+		headers: {
+			'Content-Type': 'application/json',
+			Authorization: `Bearer ${token}`
+		}
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			console.log(err);
+			error = err.detail;
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
+export const updateUserSettings = async (token: string, settings: object) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/users/user/settings/update`, {
+		method: 'POST',
+		headers: {
+			'Content-Type': 'application/json',
+			Authorization: `Bearer ${token}`
+		},
+		body: JSON.stringify({
+			...settings
+		})
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			console.log(err);
+			error = err.detail;
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
 export const getUserById = async (token: string, userId: string) => {
 	let error = null;
 

+ 137 - 0
src/lib/components/admin/Settings/Banners.svelte

@@ -0,0 +1,137 @@
+<script lang="ts">
+	import { v4 as uuidv4 } from 'uuid';
+
+	import { getContext, onMount } from 'svelte';
+	import { banners as _banners } from '$lib/stores';
+	import type { Banner } from '$lib/types';
+
+	import { getBanners, setBanners } from '$lib/apis/configs';
+
+	import type { Writable } from 'svelte/store';
+	import type { i18n as i18nType } from 'i18next';
+	import Tooltip from '$lib/components/common/Tooltip.svelte';
+	import Switch from '$lib/components/common/Switch.svelte';
+	const i18n: Writable<i18nType> = getContext('i18n');
+
+	export let saveHandler: Function;
+
+	let banners: Banner[] = [];
+
+	onMount(async () => {
+		banners = await getBanners(localStorage.token);
+	});
+
+	const updateBanners = async () => {
+		_banners.set(await setBanners(localStorage.token, banners));
+	};
+</script>
+
+<form
+	class="flex flex-col h-full justify-between space-y-3 text-sm"
+	on:submit|preventDefault={async () => {
+		updateBanners();
+		saveHandler();
+	}}
+>
+	<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-80 h-full">
+		<div class=" space-y-3 pr-1.5">
+			<div class="flex w-full justify-between mb-2">
+				<div class=" self-center text-sm font-semibold">
+					{$i18n.t('Banners')}
+				</div>
+
+				<button
+					class="p-1 px-3 text-xs flex rounded transition"
+					type="button"
+					on:click={() => {
+						if (banners.length === 0 || banners.at(-1).content !== '') {
+							banners = [
+								...banners,
+								{
+									id: uuidv4(),
+									type: '',
+									title: '',
+									content: '',
+									dismissible: true,
+									timestamp: Math.floor(Date.now() / 1000)
+								}
+							];
+						}
+					}}
+				>
+					<svg
+						xmlns="http://www.w3.org/2000/svg"
+						viewBox="0 0 20 20"
+						fill="currentColor"
+						class="w-4 h-4"
+					>
+						<path
+							d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"
+						/>
+					</svg>
+				</button>
+			</div>
+			<div class="flex flex-col space-y-1">
+				{#each banners as banner, bannerIdx}
+					<div class=" flex justify-between">
+						<div class="flex flex-row flex-1 border rounded-xl dark:border-gray-800">
+							<select
+								class="w-fit capitalize rounded-xl py-2 px-4 text-xs bg-transparent outline-none"
+								bind:value={banner.type}
+							>
+								{#if banner.type == ''}
+									<option value="" selected disabled class="text-gray-900">{$i18n.t('Type')}</option
+									>
+								{/if}
+								<option value="info" class="text-gray-900">{$i18n.t('Info')}</option>
+								<option value="warning" class="text-gray-900">{$i18n.t('Warning')}</option>
+								<option value="error" class="text-gray-900">{$i18n.t('Error')}</option>
+								<option value="success" class="text-gray-900">{$i18n.t('Success')}</option>
+							</select>
+
+							<input
+								class="pr-5 py-1.5 text-xs w-full bg-transparent outline-none"
+								placeholder={$i18n.t('Content')}
+								bind:value={banner.content}
+							/>
+
+							<div class="relative top-1.5 -left-2">
+								<Tooltip content="Dismissible" className="flex h-fit items-center">
+									<Switch bind:state={banner.dismissible} />
+								</Tooltip>
+							</div>
+						</div>
+
+						<button
+							class="px-2"
+							type="button"
+							on:click={() => {
+								banners.splice(bannerIdx, 1);
+								banners = banners;
+							}}
+						>
+							<svg
+								xmlns="http://www.w3.org/2000/svg"
+								viewBox="0 0 20 20"
+								fill="currentColor"
+								class="w-4 h-4"
+							>
+								<path
+									d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
+								/>
+							</svg>
+						</button>
+					</div>
+				{/each}
+			</div>
+		</div>
+	</div>
+	<div class="flex justify-end pt-3 text-sm font-medium">
+		<button
+			class=" px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
+			type="submit"
+		>
+			Save
+		</button>
+	</div>
+</form>

+ 1 - 1
src/lib/components/admin/Settings/Database.svelte

@@ -34,7 +34,7 @@
 		<div>
 			<div class=" mb-2 text-sm font-medium">{$i18n.t('Database')}</div>
 
-			{#if $config?.enable_admin_export ?? true}
+			{#if $config?.features.enable_admin_export ?? true}
 				<div class="  flex w-full justify-between">
 					<!-- <div class=" self-center text-xs font-medium">{$i18n.t('Allow Chat Deletion')}</div> -->
 

+ 69 - 5
src/lib/components/admin/Settings/General.svelte

@@ -1,5 +1,10 @@
 <script lang="ts">
-	import { getWebhookUrl, updateWebhookUrl } from '$lib/apis';
+	import {
+		getCommunitySharingEnabledStatus,
+		getWebhookUrl,
+		toggleCommunitySharingEnabledStatus,
+		updateWebhookUrl
+	} from '$lib/apis';
 	import {
 		getDefaultUserRole,
 		getJWTExpiresDuration,
@@ -18,6 +23,7 @@
 	let JWTExpiresIn = '';
 
 	let webhookUrl = '';
+	let communitySharingEnabled = true;
 
 	const toggleSignUpEnabled = async () => {
 		signUpEnabled = await toggleSignUpEnabledStatus(localStorage.token);
@@ -35,11 +41,28 @@
 		webhookUrl = await updateWebhookUrl(localStorage.token, webhookUrl);
 	};
 
+	const toggleCommunitySharingEnabled = async () => {
+		communitySharingEnabled = await toggleCommunitySharingEnabledStatus(localStorage.token);
+	};
+
 	onMount(async () => {
-		signUpEnabled = await getSignUpEnabledStatus(localStorage.token);
-		defaultUserRole = await getDefaultUserRole(localStorage.token);
-		JWTExpiresIn = await getJWTExpiresDuration(localStorage.token);
-		webhookUrl = await getWebhookUrl(localStorage.token);
+		await Promise.all([
+			(async () => {
+				signUpEnabled = await getSignUpEnabledStatus(localStorage.token);
+			})(),
+			(async () => {
+				defaultUserRole = await getDefaultUserRole(localStorage.token);
+			})(),
+			(async () => {
+				JWTExpiresIn = await getJWTExpiresDuration(localStorage.token);
+			})(),
+			(async () => {
+				webhookUrl = await getWebhookUrl(localStorage.token);
+			})(),
+			(async () => {
+				communitySharingEnabled = await getCommunitySharingEnabledStatus(localStorage.token);
+			})()
+		]);
 	});
 </script>
 
@@ -114,6 +137,47 @@
 				</div>
 			</div>
 
+			<div class="  flex w-full justify-between">
+				<div class=" self-center text-xs font-medium">{$i18n.t('Enable Community Sharing')}</div>
+
+				<button
+					class="p-1 px-3 text-xs flex rounded transition"
+					on:click={() => {
+						toggleCommunitySharingEnabled();
+					}}
+					type="button"
+				>
+					{#if communitySharingEnabled}
+						<svg
+							xmlns="http://www.w3.org/2000/svg"
+							viewBox="0 0 16 16"
+							fill="currentColor"
+							class="w-4 h-4"
+						>
+							<path
+								d="M11.5 1A3.5 3.5 0 0 0 8 4.5V7H2.5A1.5 1.5 0 0 0 1 8.5v5A1.5 1.5 0 0 0 2.5 15h7a1.5 1.5 0 0 0 1.5-1.5v-5A1.5 1.5 0 0 0 9.5 7V4.5a2 2 0 1 1 4 0v1.75a.75.75 0 0 0 1.5 0V4.5A3.5 3.5 0 0 0 11.5 1Z"
+							/>
+						</svg>
+						<span class="ml-2 self-center">{$i18n.t('Enabled')}</span>
+					{:else}
+						<svg
+							xmlns="http://www.w3.org/2000/svg"
+							viewBox="0 0 16 16"
+							fill="currentColor"
+							class="w-4 h-4"
+						>
+							<path
+								fill-rule="evenodd"
+								d="M8 1a3.5 3.5 0 0 0-3.5 3.5V7A1.5 1.5 0 0 0 3 8.5v5A1.5 1.5 0 0 0 4.5 15h7a1.5 1.5 0 0 0 1.5-1.5v-5A1.5 1.5 0 0 0 11.5 7V4.5A3.5 3.5 0 0 0 8 1Zm2 6V4.5a2 2 0 1 0-4 0V7h4Z"
+								clip-rule="evenodd"
+							/>
+						</svg>
+
+						<span class="ml-2 self-center">{$i18n.t('Disabled')}</span>
+					{/if}
+				</button>
+			</div>
+
 			<hr class=" dark:border-gray-700 my-3" />
 
 			<div class=" w-full justify-between">

+ 36 - 14
src/lib/components/admin/Settings/Users.svelte

@@ -1,15 +1,19 @@
 <script lang="ts">
-	import { getModelFilterConfig, updateModelFilterConfig } from '$lib/apis';
+	import { getBackendConfig, getModelFilterConfig, updateModelFilterConfig } from '$lib/apis';
 	import { getSignUpEnabledStatus, toggleSignUpEnabledStatus } from '$lib/apis/auths';
 	import { getUserPermissions, updateUserPermissions } from '$lib/apis/users';
 
 	import { onMount, getContext } from 'svelte';
-	import { models } from '$lib/stores';
+	import { models, config } from '$lib/stores';
+	import Switch from '$lib/components/common/Switch.svelte';
+	import { setDefaultModels } from '$lib/apis/configs';
 
 	const i18n = getContext('i18n');
 
 	export let saveHandler: Function;
 
+	let defaultModelId = '';
+
 	let whitelistEnabled = false;
 	let whitelistModels = [''];
 	let permissions = {
@@ -24,9 +28,10 @@
 		const res = await getModelFilterConfig(localStorage.token);
 		if (res) {
 			whitelistEnabled = res.enabled;
-
 			whitelistModels = res.models.length > 0 ? res.models : [''];
 		}
+
+		defaultModelId = $config.default_models ? $config?.default_models.split(',')[0] : '';
 	});
 </script>
 
@@ -34,10 +39,13 @@
 	class="flex flex-col h-full justify-between space-y-3 text-sm"
 	on:submit|preventDefault={async () => {
 		// console.log('submit');
-		await updateUserPermissions(localStorage.token, permissions);
 
+		await setDefaultModels(localStorage.token, defaultModelId);
+		await updateUserPermissions(localStorage.token, permissions);
 		await updateModelFilterConfig(localStorage.token, whitelistEnabled, whitelistModels);
 		saveHandler();
+
+		await config.set(await getBackendConfig());
 	}}
 >
 	<div class=" space-y-3 pr-1.5 overflow-y-scroll max-h-80">
@@ -88,26 +96,40 @@
 
 		<hr class=" dark:border-gray-700 my-2" />
 
-		<div class="mt-2 space-y-3 pr-1.5">
+		<div class="mt-2 space-y-3">
 			<div>
 				<div class="mb-2">
 					<div class="flex justify-between items-center text-xs">
 						<div class=" text-sm font-medium">{$i18n.t('Manage Models')}</div>
 					</div>
 				</div>
+				<div class=" space-y-1 mb-3">
+					<div class="mb-2">
+						<div class="flex justify-between items-center text-xs">
+							<div class=" text-xs font-medium">{$i18n.t('Default Model')}</div>
+						</div>
+					</div>
+
+					<div class="flex-1 mr-2">
+						<select
+							class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
+							bind:value={defaultModelId}
+							placeholder="Select a model"
+						>
+							<option value="" disabled selected>{$i18n.t('Select a model')}</option>
+							{#each $models.filter((model) => model.id) as model}
+								<option value={model.id} class="bg-gray-100 dark:bg-gray-700">{model.name}</option>
+							{/each}
+						</select>
+					</div>
+				</div>
 
-				<div class=" space-y-3">
-					<div>
+				<div class=" space-y-1">
+					<div class="mb-2">
 						<div class="flex justify-between items-center text-xs">
 							<div class=" text-xs font-medium">{$i18n.t('Model Whitelisting')}</div>
 
-							<button
-								class=" text-xs font-medium text-gray-500"
-								type="button"
-								on:click={() => {
-									whitelistEnabled = !whitelistEnabled;
-								}}>{whitelistEnabled ? $i18n.t('On') : $i18n.t('Off')}</button
-							>
+							<Switch bind:state={whitelistEnabled} />
 						</div>
 					</div>
 

+ 42 - 0
src/lib/components/admin/SettingsModal.svelte

@@ -6,6 +6,9 @@
 	import General from './Settings/General.svelte';
 	import Users from './Settings/Users.svelte';
 
+	import Banners from '$lib/components/admin/Settings/Banners.svelte';
+	import { toast } from 'svelte-sonner';
+
 	const i18n = getContext('i18n');
 
 	export let show = false;
@@ -117,24 +120,63 @@
 					</div>
 					<div class=" self-center">{$i18n.t('Database')}</div>
 				</button>
+
+				<button
+					class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
+					'banners'
+						? 'bg-gray-200 dark:bg-gray-700'
+						: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
+					on:click={() => {
+						selectedTab = 'banners';
+					}}
+				>
+					<div class=" self-center mr-2">
+						<svg
+							xmlns="http://www.w3.org/2000/svg"
+							viewBox="0 0 24 24"
+							fill="currentColor"
+							class="size-4"
+						>
+							<path
+								d="M5.85 3.5a.75.75 0 0 0-1.117-1 9.719 9.719 0 0 0-2.348 4.876.75.75 0 0 0 1.479.248A8.219 8.219 0 0 1 5.85 3.5ZM19.267 2.5a.75.75 0 1 0-1.118 1 8.22 8.22 0 0 1 1.987 4.124.75.75 0 0 0 1.48-.248A9.72 9.72 0 0 0 19.266 2.5Z"
+							/>
+							<path
+								fill-rule="evenodd"
+								d="M12 2.25A6.75 6.75 0 0 0 5.25 9v.75a8.217 8.217 0 0 1-2.119 5.52.75.75 0 0 0 .298 1.206c1.544.57 3.16.99 4.831 1.243a3.75 3.75 0 1 0 7.48 0 24.583 24.583 0 0 0 4.83-1.244.75.75 0 0 0 .298-1.205 8.217 8.217 0 0 1-2.118-5.52V9A6.75 6.75 0 0 0 12 2.25ZM9.75 18c0-.034 0-.067.002-.1a25.05 25.05 0 0 0 4.496 0l.002.1a2.25 2.25 0 1 1-4.5 0Z"
+								clip-rule="evenodd"
+							/>
+						</svg>
+					</div>
+					<div class=" self-center">{$i18n.t('Banners')}</div>
+				</button>
 			</div>
 			<div class="flex-1 md:min-h-[380px]">
 				{#if selectedTab === 'general'}
 					<General
 						saveHandler={() => {
 							show = false;
+							toast.success($i18n.t('Settings saved successfully!'));
 						}}
 					/>
 				{:else if selectedTab === 'users'}
 					<Users
 						saveHandler={() => {
 							show = false;
+							toast.success($i18n.t('Settings saved successfully!'));
 						}}
 					/>
 				{:else if selectedTab === 'db'}
 					<Database
 						saveHandler={() => {
 							show = false;
+							toast.success($i18n.t('Settings saved successfully!'));
+						}}
+					/>
+				{:else if selectedTab === 'banners'}
+					<Banners
+						saveHandler={() => {
+							show = false;
+							toast.success($i18n.t('Settings saved successfully!'));
 						}}
 					/>
 				{/if}

+ 54 - 10
src/lib/components/chat/Chat.svelte

@@ -15,7 +15,8 @@
 		settings,
 		showSidebar,
 		tags as _tags,
-		WEBUI_NAME
+		WEBUI_NAME,
+		banners
 	} from '$lib/stores';
 	import { convertMessagesToHistory, copyToClipboard, splitStream } from '$lib/utils';
 
@@ -45,7 +46,10 @@
 	import type { Writable } from 'svelte/store';
 	import type { i18n as i18nType } from 'i18next';
 	import { runWebSearch } from '$lib/apis/rag';
-
+	import Banner from '../common/Banner.svelte';
+	import { getUserSettings } from '$lib/apis/users';
+  
+  
 	const i18n: Writable<i18nType> = getContext('i18n');
 
 	export let chatIdProp = '';
@@ -141,6 +145,7 @@
 		} else if ($settings?.models) {
 			selectedModels = $settings?.models;
 		} else if ($config?.default_models) {
+			console.log($config?.default_models.split(',') ?? '');
 			selectedModels = $config?.default_models.split(',');
 		} else {
 			selectedModels = [''];
@@ -159,10 +164,13 @@
 			$models.map((m) => m.id).includes(modelId) ? modelId : ''
 		);
 
-		let _settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
-		settings.set({
-			..._settings
-		});
+		const userSettings = await getUserSettings(localStorage.token);
+
+		if (userSettings) {
+			settings.set(userSettings.ui);
+		} else {
+			settings.set(JSON.parse(localStorage.getItem('settings') ?? '{}'));
+		}
 
 		const chatInput = document.getElementById('chat-textarea');
 		setTimeout(() => chatInput?.focus(), 0);
@@ -192,12 +200,20 @@
 						: convertMessagesToHistory(chatContent.messages);
 				title = chatContent.title;
 
-				let _settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
+				const userSettings = await getUserSettings(localStorage.token);
+
+				if (userSettings) {
+					await settings.set(userSettings.ui);
+				} else {
+					await settings.set(JSON.parse(localStorage.getItem('settings') ?? '{}'));
+				}
+
 				await settings.set({
-					..._settings,
-					system: chatContent.system ?? _settings.system,
-					params: chatContent.options ?? _settings.params
+					...$settings,
+					system: chatContent.system ?? $settings.system,
+					params: chatContent.options ?? $settings.params
 				});
+
 				autoScroll = true;
 				await tick();
 
@@ -1073,6 +1089,34 @@
 			{chat}
 			{initNewChat}
 		/>
+
+		{#if $banners.length > 0 && !$chatId && selectedModels.length <= 1}
+			<div
+				class="absolute top-[4.25rem] w-full {$showSidebar ? 'md:max-w-[calc(100%-260px)]' : ''}"
+			>
+				<div class=" flex flex-col gap-1 w-full">
+					{#each $banners.filter( (b) => (b.dismissible ? !JSON.parse(localStorage.getItem('dismissedBannerIds') ?? '[]').includes(b.id) : true) ) as banner}
+						<Banner
+							{banner}
+							on:dismiss={(e) => {
+								const bannerId = e.detail;
+
+								localStorage.setItem(
+									'dismissedBannerIds',
+									JSON.stringify(
+										[
+											bannerId,
+											...JSON.parse(localStorage.getItem('dismissedBannerIds') ?? '[]')
+										].filter((id) => $banners.find((b) => b.id === id))
+									)
+								);
+							}}
+						/>
+					{/each}
+				</div>
+			</div>
+		{/if}
+
 		<div class="flex flex-col flex-auto">
 			<div
 				class=" pb-2.5 flex flex-col justify-between w-full flex-auto overflow-auto h-0 max-w-full"

+ 1 - 1
src/lib/components/chat/Messages/ResponseMessage.svelte

@@ -797,7 +797,7 @@
 											</button>
 										</Tooltip>
 
-										{#if $config.enable_image_generation && !readOnly}
+										{#if $config?.features.enable_image_generation && !readOnly}
 											<Tooltip content="Generate Image" placement="bottom">
 												<button
 													class="{isLastMessage

+ 4 - 8
src/lib/components/chat/ModelSelector.svelte

@@ -1,13 +1,13 @@
 <script lang="ts">
-	import { Collapsible } from 'bits-ui';
-
-	import { setDefaultModels } from '$lib/apis/configs';
 	import { models, showSettings, settings, user, mobile } from '$lib/stores';
 	import { onMount, tick, getContext } from 'svelte';
 	import { toast } from 'svelte-sonner';
 	import Selector from './ModelSelector/Selector.svelte';
 	import Tooltip from '../common/Tooltip.svelte';
 
+	import { setDefaultModels } from '$lib/apis/configs';
+	import { updateUserSettings } from '$lib/apis/users';
+
 	const i18n = getContext('i18n');
 
 	export let selectedModels = [''];
@@ -22,12 +22,8 @@
 			return;
 		}
 		settings.set({ ...$settings, models: selectedModels });
-		localStorage.setItem('settings', JSON.stringify($settings));
+		await updateUserSettings(localStorage.token, { ui: $settings });
 
-		if ($user.role === 'admin') {
-			console.log('setting default models globally');
-			await setDefaultModels(localStorage.token, selectedModels.join(','));
-		}
 		toast.success($i18n.t('Default model updated'));
 	};
 

+ 2 - 2
src/lib/components/chat/Settings/About.svelte

@@ -1,7 +1,7 @@
 <script lang="ts">
 	import { getVersionUpdates } from '$lib/apis';
 	import { getOllamaVersion } from '$lib/apis/ollama';
-	import { WEBUI_VERSION } from '$lib/constants';
+	import { WEBUI_BUILD_HASH, WEBUI_VERSION } from '$lib/constants';
 	import { WEBUI_NAME, config, showChangelog } from '$lib/stores';
 	import { compareVersion } from '$lib/utils';
 	import { onMount, getContext } from 'svelte';
@@ -54,7 +54,7 @@
 			<div class="flex w-full justify-between items-center">
 				<div class="flex flex-col text-xs text-gray-700 dark:text-gray-200">
 					<div class="flex gap-1">
-						<Tooltip content={WEBUI_VERSION === '0.1.117' ? "🪖 We're just getting started." : ''}>
+						<Tooltip content={WEBUI_BUILD_HASH}>
 							v{WEBUI_VERSION}
 						</Tooltip>
 

+ 9 - 11
src/lib/components/chat/Settings/Audio.svelte

@@ -1,6 +1,6 @@
 <script lang="ts">
 	import { getAudioConfig, updateAudioConfig } from '$lib/apis/audio';
-	import { user } from '$lib/stores';
+	import { user, settings } from '$lib/stores';
 	import { createEventDispatcher, onMount, getContext } from 'svelte';
 	import { toast } from 'svelte-sonner';
 	const dispatch = createEventDispatcher();
@@ -99,16 +99,14 @@
 	};
 
 	onMount(async () => {
-		let settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
-
-		conversationMode = settings.conversationMode ?? false;
-		speechAutoSend = settings.speechAutoSend ?? false;
-		responseAutoPlayback = settings.responseAutoPlayback ?? false;
-
-		STTEngine = settings?.audio?.STTEngine ?? '';
-		TTSEngine = settings?.audio?.TTSEngine ?? '';
-		speaker = settings?.audio?.speaker ?? '';
-		model = settings?.audio?.model ?? '';
+		conversationMode = $settings.conversationMode ?? false;
+		speechAutoSend = $settings.speechAutoSend ?? false;
+		responseAutoPlayback = $settings.responseAutoPlayback ?? false;
+
+		STTEngine = $settings?.audio?.STTEngine ?? '';
+		TTSEngine = $settings?.audio?.TTSEngine ?? '';
+		speaker = $settings?.audio?.speaker ?? '';
+		model = $settings?.audio?.model ?? '';
 
 		if (TTSEngine === 'openai') {
 			getOpenAIVoices();

+ 2 - 4
src/lib/components/chat/Settings/Chats.svelte

@@ -2,7 +2,7 @@
 	import fileSaver from 'file-saver';
 	const { saveAs } = fileSaver;
 
-	import { chats, user, config } from '$lib/stores';
+	import { chats, user, settings } from '$lib/stores';
 
 	import {
 		archiveAllChats,
@@ -99,9 +99,7 @@
 	};
 
 	onMount(async () => {
-		let settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
-
-		saveChatHistory = settings.saveChatHistory ?? true;
+		saveChatHistory = $settings.saveChatHistory ?? true;
 	});
 </script>
 

+ 198 - 180
src/lib/components/chat/Settings/Connections.svelte

@@ -20,6 +20,7 @@
 	} from '$lib/apis/openai';
 	import { toast } from 'svelte-sonner';
 	import Switch from '$lib/components/common/Switch.svelte';
+	import Spinner from '$lib/components/common/Spinner.svelte';
 
 	const i18n = getContext('i18n');
 
@@ -31,8 +32,8 @@
 	let OPENAI_API_KEYS = [''];
 	let OPENAI_API_BASE_URLS = [''];
 
-	let ENABLE_OPENAI_API = false;
-	let ENABLE_OLLAMA_API = false;
+	let ENABLE_OPENAI_API = null;
+	let ENABLE_OLLAMA_API = null;
 
 	const updateOpenAIHandler = async () => {
 		OPENAI_API_BASE_URLS = await updateOpenAIUrls(localStorage.token, OPENAI_API_BASE_URLS);
@@ -57,16 +58,23 @@
 
 	onMount(async () => {
 		if ($user.role === 'admin') {
+			await Promise.all([
+				(async () => {
+					OLLAMA_BASE_URLS = await getOllamaUrls(localStorage.token);
+				})(),
+				(async () => {
+					OPENAI_API_BASE_URLS = await getOpenAIUrls(localStorage.token);
+				})(),
+				(async () => {
+					OPENAI_API_KEYS = await getOpenAIKeys(localStorage.token);
+				})()
+			]);
+
 			const ollamaConfig = await getOllamaConfig(localStorage.token);
 			const openaiConfig = await getOpenAIConfig(localStorage.token);
 
 			ENABLE_OPENAI_API = openaiConfig.ENABLE_OPENAI_API;
 			ENABLE_OLLAMA_API = ollamaConfig.ENABLE_OLLAMA_API;
-
-			OLLAMA_BASE_URLS = await getOllamaUrls(localStorage.token);
-
-			OPENAI_API_BASE_URLS = await getOpenAIUrls(localStorage.token);
-			OPENAI_API_KEYS = await getOpenAIKeys(localStorage.token);
 		}
 	});
 </script>
@@ -78,202 +86,212 @@
 		dispatch('save');
 	}}
 >
-	<div class="  pr-1.5 overflow-y-scroll max-h-[25rem] space-y-3">
-		<div class=" space-y-3">
-			<div class="mt-2 space-y-2 pr-1.5">
+	<div class="space-y-3 pr-1.5 overflow-y-scroll h-[24rem] max-h-[25rem]">
+		{#if ENABLE_OPENAI_API !== null && ENABLE_OLLAMA_API !== null}
+			<div class=" space-y-3">
+				<div class="mt-2 space-y-2 pr-1.5">
+					<div class="flex justify-between items-center text-sm">
+						<div class="  font-medium">{$i18n.t('OpenAI API')}</div>
+
+						<div class="mt-1">
+							<Switch
+								bind:state={ENABLE_OPENAI_API}
+								on:change={async () => {
+									updateOpenAIConfig(localStorage.token, ENABLE_OPENAI_API);
+								}}
+							/>
+						</div>
+					</div>
+
+					{#if ENABLE_OPENAI_API}
+						<div class="flex flex-col gap-1">
+							{#each OPENAI_API_BASE_URLS as url, idx}
+								<div class="flex w-full gap-2">
+									<div class="flex-1">
+										<input
+											class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
+											placeholder={$i18n.t('API Base URL')}
+											bind:value={url}
+											autocomplete="off"
+										/>
+									</div>
+
+									<div class="flex-1">
+										<input
+											class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
+											placeholder={$i18n.t('API Key')}
+											bind:value={OPENAI_API_KEYS[idx]}
+											autocomplete="off"
+										/>
+									</div>
+									<div class="self-center flex items-center">
+										{#if idx === 0}
+											<button
+												class="px-1"
+												on:click={() => {
+													OPENAI_API_BASE_URLS = [...OPENAI_API_BASE_URLS, ''];
+													OPENAI_API_KEYS = [...OPENAI_API_KEYS, ''];
+												}}
+												type="button"
+											>
+												<svg
+													xmlns="http://www.w3.org/2000/svg"
+													viewBox="0 0 16 16"
+													fill="currentColor"
+													class="w-4 h-4"
+												>
+													<path
+														d="M8.75 3.75a.75.75 0 0 0-1.5 0v3.5h-3.5a.75.75 0 0 0 0 1.5h3.5v3.5a.75.75 0 0 0 1.5 0v-3.5h3.5a.75.75 0 0 0 0-1.5h-3.5v-3.5Z"
+													/>
+												</svg>
+											</button>
+										{:else}
+											<button
+												class="px-1"
+												on:click={() => {
+													OPENAI_API_BASE_URLS = OPENAI_API_BASE_URLS.filter(
+														(url, urlIdx) => idx !== urlIdx
+													);
+													OPENAI_API_KEYS = OPENAI_API_KEYS.filter((key, keyIdx) => idx !== keyIdx);
+												}}
+												type="button"
+											>
+												<svg
+													xmlns="http://www.w3.org/2000/svg"
+													viewBox="0 0 16 16"
+													fill="currentColor"
+													class="w-4 h-4"
+												>
+													<path d="M3.75 7.25a.75.75 0 0 0 0 1.5h8.5a.75.75 0 0 0 0-1.5h-8.5Z" />
+												</svg>
+											</button>
+										{/if}
+									</div>
+								</div>
+								<div class=" mb-1 text-xs text-gray-400 dark:text-gray-500">
+									{$i18n.t('WebUI will make requests to')}
+									<span class=" text-gray-200">'{url}/models'</span>
+								</div>
+							{/each}
+						</div>
+					{/if}
+				</div>
+			</div>
+
+			<hr class=" dark:border-gray-700" />
+
+			<div class="pr-1.5 space-y-2">
 				<div class="flex justify-between items-center text-sm">
-					<div class="  font-medium">{$i18n.t('OpenAI API')}</div>
+					<div class="  font-medium">{$i18n.t('Ollama API')}</div>
 
 					<div class="mt-1">
 						<Switch
-							bind:state={ENABLE_OPENAI_API}
+							bind:state={ENABLE_OLLAMA_API}
 							on:change={async () => {
-								updateOpenAIConfig(localStorage.token, ENABLE_OPENAI_API);
+								updateOllamaConfig(localStorage.token, ENABLE_OLLAMA_API);
 							}}
 						/>
 					</div>
 				</div>
-
-				{#if ENABLE_OPENAI_API}
-					<div class="flex flex-col gap-1">
-						{#each OPENAI_API_BASE_URLS as url, idx}
-							<div class="flex w-full gap-2">
-								<div class="flex-1">
+				{#if ENABLE_OLLAMA_API}
+					<div class="flex w-full gap-1.5">
+						<div class="flex-1 flex flex-col gap-2">
+							{#each OLLAMA_BASE_URLS as url, idx}
+								<div class="flex gap-1.5">
 									<input
 										class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
-										placeholder={$i18n.t('API Base URL')}
+										placeholder={$i18n.t('Enter URL (e.g. http://localhost:11434)')}
 										bind:value={url}
-										autocomplete="off"
 									/>
-								</div>
 
-								<div class="flex-1">
-									<input
-										class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
-										placeholder={$i18n.t('API Key')}
-										bind:value={OPENAI_API_KEYS[idx]}
-										autocomplete="off"
-									/>
-								</div>
-								<div class="self-center flex items-center">
-									{#if idx === 0}
-										<button
-											class="px-1"
-											on:click={() => {
-												OPENAI_API_BASE_URLS = [...OPENAI_API_BASE_URLS, ''];
-												OPENAI_API_KEYS = [...OPENAI_API_KEYS, ''];
-											}}
-											type="button"
-										>
-											<svg
-												xmlns="http://www.w3.org/2000/svg"
-												viewBox="0 0 16 16"
-												fill="currentColor"
-												class="w-4 h-4"
+									<div class="self-center flex items-center">
+										{#if idx === 0}
+											<button
+												class="px-1"
+												on:click={() => {
+													OLLAMA_BASE_URLS = [...OLLAMA_BASE_URLS, ''];
+												}}
+												type="button"
 											>
-												<path
-													d="M8.75 3.75a.75.75 0 0 0-1.5 0v3.5h-3.5a.75.75 0 0 0 0 1.5h3.5v3.5a.75.75 0 0 0 1.5 0v-3.5h3.5a.75.75 0 0 0 0-1.5h-3.5v-3.5Z"
-												/>
-											</svg>
-										</button>
-									{:else}
-										<button
-											class="px-1"
-											on:click={() => {
-												OPENAI_API_BASE_URLS = OPENAI_API_BASE_URLS.filter(
-													(url, urlIdx) => idx !== urlIdx
-												);
-												OPENAI_API_KEYS = OPENAI_API_KEYS.filter((key, keyIdx) => idx !== keyIdx);
-											}}
-											type="button"
-										>
-											<svg
-												xmlns="http://www.w3.org/2000/svg"
-												viewBox="0 0 16 16"
-												fill="currentColor"
-												class="w-4 h-4"
+												<svg
+													xmlns="http://www.w3.org/2000/svg"
+													viewBox="0 0 16 16"
+													fill="currentColor"
+													class="w-4 h-4"
+												>
+													<path
+														d="M8.75 3.75a.75.75 0 0 0-1.5 0v3.5h-3.5a.75.75 0 0 0 0 1.5h3.5v3.5a.75.75 0 0 0 1.5 0v-3.5h3.5a.75.75 0 0 0 0-1.5h-3.5v-3.5Z"
+													/>
+												</svg>
+											</button>
+										{:else}
+											<button
+												class="px-1"
+												on:click={() => {
+													OLLAMA_BASE_URLS = OLLAMA_BASE_URLS.filter(
+														(url, urlIdx) => idx !== urlIdx
+													);
+												}}
+												type="button"
 											>
-												<path d="M3.75 7.25a.75.75 0 0 0 0 1.5h8.5a.75.75 0 0 0 0-1.5h-8.5Z" />
-											</svg>
-										</button>
-									{/if}
+												<svg
+													xmlns="http://www.w3.org/2000/svg"
+													viewBox="0 0 16 16"
+													fill="currentColor"
+													class="w-4 h-4"
+												>
+													<path d="M3.75 7.25a.75.75 0 0 0 0 1.5h8.5a.75.75 0 0 0 0-1.5h-8.5Z" />
+												</svg>
+											</button>
+										{/if}
+									</div>
 								</div>
-							</div>
-							<div class=" mb-1 text-xs text-gray-400 dark:text-gray-500">
-								{$i18n.t('WebUI will make requests to')}
-								<span class=" text-gray-200">'{url}/models'</span>
-							</div>
-						{/each}
-					</div>
-				{/if}
-			</div>
-		</div>
-
-		<hr class=" dark:border-gray-700" />
-
-		<div class="pr-1.5 space-y-2">
-			<div class="flex justify-between items-center text-sm">
-				<div class="  font-medium">{$i18n.t('Ollama API')}</div>
+							{/each}
+						</div>
 
-				<div class="mt-1">
-					<Switch
-						bind:state={ENABLE_OLLAMA_API}
-						on:change={async () => {
-							updateOllamaConfig(localStorage.token, ENABLE_OLLAMA_API);
-						}}
-					/>
-				</div>
-			</div>
-			{#if ENABLE_OLLAMA_API}
-				<div class="flex w-full gap-1.5">
-					<div class="flex-1 flex flex-col gap-2">
-						{#each OLLAMA_BASE_URLS as url, idx}
-							<div class="flex gap-1.5">
-								<input
-									class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
-									placeholder={$i18n.t('Enter URL (e.g. http://localhost:11434)')}
-									bind:value={url}
-								/>
-
-								<div class="self-center flex items-center">
-									{#if idx === 0}
-										<button
-											class="px-1"
-											on:click={() => {
-												OLLAMA_BASE_URLS = [...OLLAMA_BASE_URLS, ''];
-											}}
-											type="button"
-										>
-											<svg
-												xmlns="http://www.w3.org/2000/svg"
-												viewBox="0 0 16 16"
-												fill="currentColor"
-												class="w-4 h-4"
-											>
-												<path
-													d="M8.75 3.75a.75.75 0 0 0-1.5 0v3.5h-3.5a.75.75 0 0 0 0 1.5h3.5v3.5a.75.75 0 0 0 1.5 0v-3.5h3.5a.75.75 0 0 0 0-1.5h-3.5v-3.5Z"
-												/>
-											</svg>
-										</button>
-									{:else}
-										<button
-											class="px-1"
-											on:click={() => {
-												OLLAMA_BASE_URLS = OLLAMA_BASE_URLS.filter((url, urlIdx) => idx !== urlIdx);
-											}}
-											type="button"
-										>
-											<svg
-												xmlns="http://www.w3.org/2000/svg"
-												viewBox="0 0 16 16"
-												fill="currentColor"
-												class="w-4 h-4"
-											>
-												<path d="M3.75 7.25a.75.75 0 0 0 0 1.5h8.5a.75.75 0 0 0 0-1.5h-8.5Z" />
-											</svg>
-										</button>
-									{/if}
-								</div>
-							</div>
-						{/each}
+						<div class="flex">
+							<button
+								class="self-center p-2 bg-gray-200 hover:bg-gray-300 dark:bg-gray-900 dark:hover:bg-gray-850 rounded-lg transition"
+								on:click={() => {
+									updateOllamaUrlsHandler();
+								}}
+								type="button"
+							>
+								<svg
+									xmlns="http://www.w3.org/2000/svg"
+									viewBox="0 0 20 20"
+									fill="currentColor"
+									class="w-4 h-4"
+								>
+									<path
+										fill-rule="evenodd"
+										d="M15.312 11.424a5.5 5.5 0 01-9.201 2.466l-.312-.311h2.433a.75.75 0 000-1.5H3.989a.75.75 0 00-.75.75v4.242a.75.75 0 001.5 0v-2.43l.31.31a7 7 0 0011.712-3.138.75.75 0 00-1.449-.39zm1.23-3.723a.75.75 0 00.219-.53V2.929a.75.75 0 00-1.5 0V5.36l-.31-.31A7 7 0 003.239 8.188a.75.75 0 101.448.389A5.5 5.5 0 0113.89 6.11l.311.31h-2.432a.75.75 0 000 1.5h4.243a.75.75 0 00.53-.219z"
+										clip-rule="evenodd"
+									/>
+								</svg>
+							</button>
+						</div>
 					</div>
 
-					<div class="flex">
-						<button
-							class="self-center p-2 bg-gray-200 hover:bg-gray-300 dark:bg-gray-900 dark:hover:bg-gray-850 rounded-lg transition"
-							on:click={() => {
-								updateOllamaUrlsHandler();
-							}}
-							type="button"
+					<div class="mt-2 text-xs text-gray-400 dark:text-gray-500">
+						{$i18n.t('Trouble accessing Ollama?')}
+						<a
+							class=" text-gray-300 font-medium underline"
+							href="https://github.com/open-webui/open-webui#troubleshooting"
+							target="_blank"
 						>
-							<svg
-								xmlns="http://www.w3.org/2000/svg"
-								viewBox="0 0 20 20"
-								fill="currentColor"
-								class="w-4 h-4"
-							>
-								<path
-									fill-rule="evenodd"
-									d="M15.312 11.424a5.5 5.5 0 01-9.201 2.466l-.312-.311h2.433a.75.75 0 000-1.5H3.989a.75.75 0 00-.75.75v4.242a.75.75 0 001.5 0v-2.43l.31.31a7 7 0 0011.712-3.138.75.75 0 00-1.449-.39zm1.23-3.723a.75.75 0 00.219-.53V2.929a.75.75 0 00-1.5 0V5.36l-.31-.31A7 7 0 003.239 8.188a.75.75 0 101.448.389A5.5 5.5 0 0113.89 6.11l.311.31h-2.432a.75.75 0 000 1.5h4.243a.75.75 0 00.53-.219z"
-									clip-rule="evenodd"
-								/>
-							</svg>
-						</button>
+							{$i18n.t('Click here for help.')}
+						</a>
 					</div>
+				{/if}
+			</div>
+		{:else}
+			<div class="flex h-full justify-center">
+				<div class="my-auto">
+					<Spinner className="size-6" />
 				</div>
-
-				<div class="mt-2 text-xs text-gray-400 dark:text-gray-500">
-					{$i18n.t('Trouble accessing Ollama?')}
-					<a
-						class=" text-gray-300 font-medium underline"
-						href="https://github.com/open-webui/open-webui#troubleshooting"
-						target="_blank"
-					>
-						{$i18n.t('Click here for help.')}
-					</a>
-				</div>
-			{/if}
-		</div>
+			</div>
+		{/if}
 	</div>
 
 	<div class="flex justify-end pt-3 text-sm font-medium">

+ 13 - 14
src/lib/components/chat/Settings/General.svelte

@@ -4,7 +4,7 @@
 	import { getLanguages } from '$lib/i18n';
 	const dispatch = createEventDispatcher();
 
-	import { models, user, theme } from '$lib/stores';
+	import { models, settings, theme } from '$lib/stores';
 
 	const i18n = getContext('i18n');
 
@@ -71,23 +71,22 @@
 	onMount(async () => {
 		selectedTheme = localStorage.theme ?? 'system';
 
-		let settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
 		languages = await getLanguages();
 
-		notificationEnabled = settings.notificationEnabled ?? false;
-		system = settings.system ?? '';
+		notificationEnabled = $settings.notificationEnabled ?? false;
+		system = $settings.system ?? '';
 
-		requestFormat = settings.requestFormat ?? '';
-		keepAlive = settings.keepAlive ?? null;
+		requestFormat = $settings.requestFormat ?? '';
+		keepAlive = $settings.keepAlive ?? null;
 
-		params.seed = settings.seed ?? 0;
-		params.temperature = settings.temperature ?? '';
-		params.frequency_penalty = settings.frequency_penalty ?? '';
-		params.top_k = settings.top_k ?? '';
-		params.top_p = settings.top_p ?? '';
-		params.num_ctx = settings.num_ctx ?? '';
-		params = { ...params, ...settings.params };
-		params.stop = settings?.params?.stop ? (settings?.params?.stop ?? []).join(',') : null;
+		params.seed = $settings.seed ?? 0;
+		params.temperature = $settings.temperature ?? '';
+		params.frequency_penalty = $settings.frequency_penalty ?? '';
+		params.top_k = $settings.top_k ?? '';
+		params.top_p = $settings.top_p ?? '';
+		params.num_ctx = $settings.num_ctx ?? '';
+		params = { ...params, ...$settings.params };
+		params.stop = $settings?.params?.stop ? ($settings?.params?.stop ?? []).join(',') : null;
 	});
 
 	const applyTheme = (_theme: string) => {

+ 11 - 16
src/lib/components/chat/Settings/Interface.svelte

@@ -105,23 +105,18 @@
 			promptSuggestions = $config?.default_prompt_suggestions;
 		}
 
-		let settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
-
-		titleAutoGenerate = settings?.title?.auto ?? true;
-		titleAutoGenerateModel = settings?.title?.model ?? '';
-		titleAutoGenerateModelExternal = settings?.title?.modelExternal ?? '';
+		titleAutoGenerate = $settings?.title?.auto ?? true;
+		titleAutoGenerateModel = $settings?.title?.model ?? '';
+		titleAutoGenerateModelExternal = $settings?.title?.modelExternal ?? '';
 		titleGenerationPrompt =
-			settings?.title?.prompt ??
-			$i18n.t(
-				"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':"
-			) + ' {{prompt}}';
-
-		responseAutoCopy = settings.responseAutoCopy ?? false;
-		showUsername = settings.showUsername ?? false;
-		chatBubble = settings.chatBubble ?? true;
-		fullScreenMode = settings.fullScreenMode ?? false;
-		splitLargeChunks = settings.splitLargeChunks ?? false;
-		chatDirection = settings.chatDirection ?? 'LTR';
+			$settings?.title?.prompt ??
+			`Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title': {{prompt}}`;
+		responseAutoCopy = $settings.responseAutoCopy ?? false;
+		showUsername = $settings.showUsername ?? false;
+		chatBubble = $settings.chatBubble ?? true;
+		fullScreenMode = $settings.fullScreenMode ?? false;
+		splitLargeChunks = $settings.splitLargeChunks ?? false;
+		chatDirection = $settings.chatDirection ?? 'LTR';
 	});
 </script>
 

+ 1 - 2
src/lib/components/chat/Settings/Personalization.svelte

@@ -19,8 +19,7 @@
 	let enableMemory = false;
 
 	onMount(async () => {
-		let settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
-		enableMemory = settings?.memory ?? false;
+		enableMemory = $settings?.memory ?? false;
 	});
 </script>
 

+ 2 - 1
src/lib/components/chat/SettingsModal.svelte

@@ -17,6 +17,7 @@
 	import Images from './Settings/Images.svelte';
 	import User from '../icons/User.svelte';
 	import Personalization from './Settings/Personalization.svelte';
+	import { updateUserSettings } from '$lib/apis/users';
 
 	const i18n = getContext('i18n');
 
@@ -26,7 +27,7 @@
 		console.log(updated);
 		await settings.set({ ...$settings, ...updated });
 		await models.set(await getModels());
-		localStorage.setItem('settings', JSON.stringify($settings));
+		await updateUserSettings(localStorage.token, { ui: $settings });
 	};
 
 	const getModels = async () => {

+ 13 - 11
src/lib/components/chat/ShareChatModal.svelte

@@ -1,6 +1,6 @@
 <script lang="ts">
 	import { getContext, onMount } from 'svelte';
-	import { models } from '$lib/stores';
+	import { models, config } from '$lib/stores';
 
 	import { toast } from 'svelte-sonner';
 	import { deleteSharedChatById, getChatById, shareChatById } from '$lib/apis/chats';
@@ -134,16 +134,18 @@
 				<div class="flex justify-end">
 					<div class="flex flex-col items-end space-x-1 mt-1.5">
 						<div class="flex gap-1">
-							<button
-								class=" self-center px-3.5 py-2 rounded-xl text-sm font-medium bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-white"
-								type="button"
-								on:click={() => {
-									shareChat();
-									show = false;
-								}}
-							>
-								{$i18n.t('Share to OpenWebUI Community')}
-							</button>
+							{#if $config?.features.enable_community_sharing}
+								<button
+									class=" self-center px-3.5 py-2 rounded-xl text-sm font-medium bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-white"
+									type="button"
+									on:click={() => {
+										shareChat();
+										show = false;
+									}}
+								>
+									{$i18n.t('Share to OpenWebUI Community')}
+								</button>
+							{/if}
 
 							<button
 								class=" self-center flex items-center gap-1 px-3.5 py-2 rounded-xl text-sm font-medium bg-emerald-600 hover:bg-emerald-500 text-white"

+ 125 - 0
src/lib/components/common/Banner.svelte

@@ -0,0 +1,125 @@
+<script lang="ts">
+	import type { Banner } from '$lib/types';
+	import { onMount, createEventDispatcher } from 'svelte';
+	import { fade } from 'svelte/transition';
+
+	const dispatch = createEventDispatcher();
+
+	export let banner: Banner = {
+		id: '',
+		type: 'info',
+		title: '',
+		content: '',
+		url: '',
+		dismissable: true,
+		timestamp: Math.floor(Date.now() / 1000)
+	};
+
+	export let dismissed = false;
+
+	let mounted = false;
+
+	const classNames: Record<string, string> = {
+		info: 'bg-blue-500/20 text-blue-700 dark:text-blue-200 ',
+		success: 'bg-green-500/20 text-green-700 dark:text-green-200',
+		warning: 'bg-yellow-500/20 text-yellow-700 dark:text-yellow-200',
+		error: 'bg-red-500/20 text-red-700 dark:text-red-200'
+	};
+
+	const dismiss = (id) => {
+		dismissed = true;
+		dispatch('dismiss', id);
+	};
+
+	onMount(() => {
+		mounted = true;
+	});
+</script>
+
+{#if !dismissed}
+	{#if mounted}
+		<div
+			class=" top-0 left-0 right-0 p-2 mx-4 px-3 flex justify-center items-center relative rounded-xl border border-gray-100 dark:border-gray-850 text-gray-800 dark:text-gary-100 bg-white dark:bg-gray-900 backdrop-blur-xl z-40"
+			transition:fade={{ delay: 100, duration: 300 }}
+		>
+			<div class=" flex flex-col md:flex-row md:items-center flex-1 text-sm w-fit gap-1.5">
+				<div class="flex justify-between self-start">
+					<div
+						class=" text-xs font-black {classNames[banner.type] ??
+							classNames['info']}  w-fit px-2 rounded uppercase line-clamp-1 mr-0.5"
+					>
+						{banner.type}
+					</div>
+
+					{#if banner.url}
+						<div class="flex md:hidden group w-fit md:items-center">
+							<a
+								class="text-gray-700 dark:text-white text-xs font-bold underline"
+								href="/assets/files/whitepaper.pdf"
+								target="_blank">Learn More</a
+							>
+
+							<div
+								class=" ml-1 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-white"
+							>
+								<!--  -->
+								<svg
+									xmlns="http://www.w3.org/2000/svg"
+									viewBox="0 0 16 16"
+									fill="currentColor"
+									class="w-4 h-4"
+								>
+									<path
+										fill-rule="evenodd"
+										d="M4.22 11.78a.75.75 0 0 1 0-1.06L9.44 5.5H5.75a.75.75 0 0 1 0-1.5h5.5a.75.75 0 0 1 .75.75v5.5a.75.75 0 0 1-1.5 0V6.56l-5.22 5.22a.75.75 0 0 1-1.06 0Z"
+										clip-rule="evenodd"
+									/>
+								</svg>
+							</div>
+						</div>
+					{/if}
+				</div>
+
+				<div class="flex-1 text-xs text-gray-700 dark:text-white">
+					{banner.content}
+				</div>
+			</div>
+
+			{#if banner.url}
+				<div class="hidden md:flex group w-fit md:items-center">
+					<a
+						class="text-gray-700 dark:text-white text-xs font-bold underline"
+						href="/"
+						target="_blank">Learn More</a
+					>
+
+					<div class=" ml-1 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-white">
+						<!--  -->
+						<svg
+							xmlns="http://www.w3.org/2000/svg"
+							viewBox="0 0 16 16"
+							fill="currentColor"
+							class="size-4"
+						>
+							<path
+								fill-rule="evenodd"
+								d="M4.22 11.78a.75.75 0 0 1 0-1.06L9.44 5.5H5.75a.75.75 0 0 1 0-1.5h5.5a.75.75 0 0 1 .75.75v5.5a.75.75 0 0 1-1.5 0V6.56l-5.22 5.22a.75.75 0 0 1-1.06 0Z"
+								clip-rule="evenodd"
+							/>
+						</svg>
+					</div>
+				</div>
+			{/if}
+			<div class="flex self-start">
+				{#if banner.dismissible}
+					<button
+						on:click={() => {
+							dismiss(banner.id);
+						}}
+						class=" -mt-[3px] ml-1.5 mr-1 text-gray-400 dark:hover:text-white h-1">&times;</button
+					>
+				{/if}
+			</div>
+		</div>
+	{/if}
+{/if}

+ 2 - 1
src/lib/components/layout/Sidebar.svelte

@@ -33,6 +33,7 @@
 	import ArchiveBox from '../icons/ArchiveBox.svelte';
 	import ArchivedChatsModal from './Sidebar/ArchivedChatsModal.svelte';
 	import UserMenu from './Sidebar/UserMenu.svelte';
+	import { updateUserSettings } from '$lib/apis/users';
 
 	const BREAKPOINT = 768;
 
@@ -183,7 +184,7 @@
 
 	const saveSettings = async (updated) => {
 		await settings.set({ ...$settings, ...updated });
-		localStorage.setItem('settings', JSON.stringify($settings));
+		await updateUserSettings(localStorage.token, { ui: $settings });
 		location.href = '/';
 	};
 

+ 1 - 1
src/lib/components/layout/Sidebar/ArchivedChatsModal.svelte

@@ -101,7 +101,7 @@
 			<hr class=" dark:border-gray-850 my-2" />
 			<div class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6">
 				{#if chats.length > 0}
-					<div>
+					<div class="w-full">
 						<div class="text-left text-sm w-full mb-3 max-h-[22rem] overflow-y-scroll">
 							<div class="relative overflow-x-auto">
 								<table class="w-full text-sm text-left text-gray-600 dark:text-gray-400 table-auto">

+ 1 - 0
src/lib/constants.ts

@@ -13,6 +13,7 @@ export const IMAGES_API_BASE_URL = `${WEBUI_BASE_URL}/images/api/v1`;
 export const RAG_API_BASE_URL = `${WEBUI_BASE_URL}/rag/api/v1`;
 
 export const WEBUI_VERSION = APP_VERSION;
+export const WEBUI_BUILD_HASH = APP_BUILD_HASH;
 export const REQUIRED_OLLAMA_VERSION = '0.1.16';
 
 export const SUPPORTED_FILE_TYPE = [

+ 5 - 0
src/lib/i18n/locales/ar-BH/translation.json

@@ -63,6 +63,7 @@
 	"available!": "متاح",
 	"Back": "خلف",
 	"Bad Response": "استجابة خطاء",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "قبل",
 	"Being lazy": "كون كسول",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "أدخل الاسم كامل",
 	"Enter Your Password": "ادخل كلمة المرور",
 	"Enter Your Role": "أدخل الصلاحيات",
+	"Error": "",
 	"Experimental": "تجريبي",
 	"Export All Chats (All Users)": "تصدير جميع الدردشات (جميع المستخدمين)",
 	"Export Chats": "تصدير جميع الدردشات",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "مطالبات الاستيراد",
 	"Include `--api` flag when running stable-diffusion-webui": "قم بتضمين علامة `-api` عند تشغيل Stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "إدخال الأوامر",
 	"Interface": "واجهه المستخدم",
 	"Invalid Tag": "تاق غير صالحة",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "هل تواجه مشكلة في الوصول",
 	"TTS Settings": "TTS اعدادات",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "اكتب عنوان URL لحل مشكلة الوجه (تنزيل).",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "{{provider}}خطاء أوه! حدثت مشكلة في الاتصال بـ ",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "نوع ملف غير معروف '{{file_type}}', ولكن القبول والتعامل كنص عادي ",
@@ -470,6 +474,7 @@
 	"variable": "المتغير",
 	"variable to have them replaced with clipboard content.": "متغير لاستبدالها بمحتوى الحافظة.",
 	"Version": "إصدار",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "تحذير: إذا قمت بتحديث أو تغيير نموذج التضمين الخاص بك، فستحتاج إلى إعادة استيراد كافة المستندات.",
 	"Web": "Web",
 	"Web Loader Settings": "Web تحميل اعدادات",

+ 5 - 0
src/lib/i18n/locales/bg-BG/translation.json

@@ -63,6 +63,7 @@
 	"available!": "наличен!",
 	"Back": "Назад",
 	"Bad Response": "Невалиден отговор от API",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "преди",
 	"Being lazy": "Да бъдеш мързелив",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Въведете вашето пълно име",
 	"Enter Your Password": "Въведете вашата парола",
 	"Enter Your Role": "Въведете вашата роля",
+	"Error": "",
 	"Experimental": "Експериментално",
 	"Export All Chats (All Users)": "Експортване на всички чатове (За всички потребители)",
 	"Export Chats": "Експортване на чатове",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Импортване на промптове",
 	"Include `--api` flag when running stable-diffusion-webui": "Включете флага `--api`, когато стартирате stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "Въведете команди",
 	"Interface": "Интерфейс",
 	"Invalid Tag": "Невалиден тег",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Проблеми с достъпът до Ollama?",
 	"TTS Settings": "TTS Настройки",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Въведете Hugging Face Resolve (Download) URL",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "О, не! Възникна проблем при свързването с {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Непознат файлов тип '{{file_type}}', но се приема и обработва като текст",
@@ -470,6 +474,7 @@
 	"variable": "променлива",
 	"variable to have them replaced with clipboard content.": "променливи да се заменят съдържанието от клипборд.",
 	"Version": "Версия",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Предупреждение: Ако актуализирате или промените вашия модел за вграждане, трябва да повторите импортирането на всички документи.",
 	"Web": "Уеб",
 	"Web Loader Settings": "Настройки за зареждане на уеб",

+ 5 - 0
src/lib/i18n/locales/bn-BD/translation.json

@@ -63,6 +63,7 @@
 	"available!": "উপলব্ধ!",
 	"Back": "পেছনে",
 	"Bad Response": "খারাপ প্রতিক্রিয়া",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "পূর্ববর্তী",
 	"Being lazy": "অলস হওয়া",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "আপনার পূর্ণ নাম লিখুন",
 	"Enter Your Password": "আপনার পাসওয়ার্ড লিখুন",
 	"Enter Your Role": "আপনার রোল লিখুন",
+	"Error": "",
 	"Experimental": "পরিক্ষামূলক",
 	"Export All Chats (All Users)": "সব চ্যাট এক্সপোর্ট করুন (সব ইউজারের)",
 	"Export Chats": "চ্যাটগুলো এক্সপোর্ট করুন",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "প্রম্পটগুলো ইমপোর্ট করুন",
 	"Include `--api` flag when running stable-diffusion-webui": "stable-diffusion-webui চালু করার সময় `--api` ফ্ল্যাগ সংযুক্ত করুন",
+	"Info": "",
 	"Input commands": "ইনপুট কমান্ডস",
 	"Interface": "ইন্টারফেস",
 	"Invalid Tag": "অবৈধ ট্যাগ",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Ollama এক্সেস করতে সমস্যা হচ্ছে?",
 	"TTS Settings": "TTS সেটিংসমূহ",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Hugging Face থেকে ডাউনলোড করার ইউআরএল টাইপ করুন",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "ওহ-হো! {{provider}} এর সাথে কানেকশনে সমস্যা হয়েছে।",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "অপরিচিত ফাইল ফরম্যাট '{{file_type}}', তবে প্লেইন টেক্সট হিসেবে গ্রহণ করা হলো",
@@ -470,6 +474,7 @@
 	"variable": "ভেরিয়েবল",
 	"variable to have them replaced with clipboard content.": "ক্লিপবোর্ডের কন্টেন্ট দিয়ে যেই ভেরিয়েবল রিপ্লেস করা যাবে।",
 	"Version": "ভার্সন",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "সতর্কীকরণ: আপনি যদি আপনার এম্বেডিং মডেল আপডেট বা পরিবর্তন করেন, তাহলে আপনাকে সমস্ত নথি পুনরায় আমদানি করতে হবে।.",
 	"Web": "ওয়েব",
 	"Web Loader Settings": "ওয়েব লোডার সেটিংস",

+ 5 - 0
src/lib/i18n/locales/ca-ES/translation.json

@@ -63,6 +63,7 @@
 	"available!": "disponible!",
 	"Back": "Enrere",
 	"Bad Response": "Resposta Erroni",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "abans",
 	"Being lazy": "Ser l'estupidez",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Introdueix el Teu Nom Complet",
 	"Enter Your Password": "Introdueix la Teva Contrasenya",
 	"Enter Your Role": "Introdueix el Teu Ròl",
+	"Error": "",
 	"Experimental": "Experimental",
 	"Export All Chats (All Users)": "Exporta Tots els Xats (Tots els Usuaris)",
 	"Export Chats": "Exporta Xats",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Importa Prompts",
 	"Include `--api` flag when running stable-diffusion-webui": "Inclou la bandera `--api` quan executis stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "Entra ordres",
 	"Interface": "Interfície",
 	"Invalid Tag": "Etiqueta Inválida",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Problemes accedint a Ollama?",
 	"TTS Settings": "Configuracions TTS",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Escriu URL de Resolució (Descàrrega) de Hugging Face",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Uf! Hi va haver un problema connectant-se a {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Tipus d'Arxiu Desconegut '{{file_type}}', però acceptant i tractant com a text pla",
@@ -470,6 +474,7 @@
 	"variable": "variable",
 	"variable to have them replaced with clipboard content.": "variable per tenir-les reemplaçades amb el contingut del porta-retalls.",
 	"Version": "Versió",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Avís: Si actualitzeu o canvieu el model d'incrustació, haureu de tornar a importar tots els documents.",
 	"Web": "Web",
 	"Web Loader Settings": "Configuració del carregador web",

+ 5 - 0
src/lib/i18n/locales/ceb-PH/translation.json

@@ -63,6 +63,7 @@
 	"available!": "magamit!",
 	"Back": "Balik",
 	"Bad Response": "",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "",
 	"Being lazy": "",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Ibutang ang imong tibuok nga ngalan",
 	"Enter Your Password": "Ibutang ang imong password",
 	"Enter Your Role": "",
+	"Error": "",
 	"Experimental": "Eksperimento",
 	"Export All Chats (All Users)": "I-export ang tanan nga mga chat (Tanan nga tiggamit)",
 	"Export Chats": "I-export ang mga chat",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Import prompt",
 	"Include `--api` flag when running stable-diffusion-webui": "Iapil ang `--api` nga bandila kung nagdagan nga stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "Pagsulod sa input commands",
 	"Interface": "Interface",
 	"Invalid Tag": "",
@@ -450,6 +453,7 @@
 	"Top P": "Ibabaw nga P",
 	"Trouble accessing Ollama?": "Adunay mga problema sa pag-access sa Ollama?",
 	"TTS Settings": "Mga Setting sa TTS",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Pagsulod sa resolusyon (pag-download) URL Hugging Face",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh!  {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Wala mailhi nga tipo sa file '{{file_type}}', apan gidawat ug gitratar ingon yano nga teksto",
@@ -470,6 +474,7 @@
 	"variable": "variable",
 	"variable to have them replaced with clipboard content.": "variable aron pulihan kini sa mga sulud sa clipboard.",
 	"Version": "Bersyon",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "",
 	"Web": "Web",
 	"Web Loader Settings": "",

+ 5 - 0
src/lib/i18n/locales/de-DE/translation.json

@@ -63,6 +63,7 @@
 	"available!": "verfügbar!",
 	"Back": "Zurück",
 	"Bad Response": "Schlechte Antwort",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "bereits geteilt",
 	"Being lazy": "Faul sein",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Gib deinen vollständigen Namen ein",
 	"Enter Your Password": "Gib dein Passwort ein",
 	"Enter Your Role": "Gebe deine Rolle ein",
+	"Error": "",
 	"Experimental": "Experimentell",
 	"Export All Chats (All Users)": "Alle Chats exportieren (alle Benutzer)",
 	"Export Chats": "Chats exportieren",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Prompts importieren",
 	"Include `--api` flag when running stable-diffusion-webui": "Füge das `--api`-Flag hinzu, wenn du stable-diffusion-webui nutzt",
+	"Info": "",
 	"Input commands": "Eingabebefehle",
 	"Interface": "Benutzeroberfläche",
 	"Invalid Tag": "Ungültiger Tag",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Probleme beim Zugriff auf Ollama?",
 	"TTS Settings": "TTS-Einstellungen",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Gib die Hugging Face Resolve (Download) URL ein",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Ups! Es gab ein Problem bei der Verbindung mit {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Unbekannter Dateityp '{{file_type}}', wird jedoch akzeptiert und als einfacher Text behandelt.",
@@ -470,6 +474,7 @@
 	"variable": "Variable",
 	"variable to have them replaced with clipboard content.": "Variable, um den Inhalt der Zwischenablage beim Nutzen des Prompts zu ersetzen.",
 	"Version": "Version",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Warnung: Wenn du dein Einbettungsmodell aktualisierst oder änderst, musst du alle Dokumente erneut importieren.",
 	"Web": "Web",
 	"Web Loader Settings": "Web Loader Einstellungen",

+ 5 - 0
src/lib/i18n/locales/dg-DG/translation.json

@@ -63,6 +63,7 @@
 	"available!": "available! So excite!",
 	"Back": "Back",
 	"Bad Response": "",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "",
 	"Being lazy": "",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Enter Your Full Wow",
 	"Enter Your Password": "Enter Your Barkword",
 	"Enter Your Role": "",
+	"Error": "",
 	"Experimental": "Much Experiment",
 	"Export All Chats (All Users)": "Export All Chats (All Doggos)",
 	"Export Chats": "Export Barks",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Import Promptos",
 	"Include `--api` flag when running stable-diffusion-webui": "Include `--api` flag when running stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "Input commands",
 	"Interface": "Interface",
 	"Invalid Tag": "",
@@ -450,6 +453,7 @@
 	"Top P": "Top P very top",
 	"Trouble accessing Ollama?": "Trouble accessing Ollama? Much trouble?",
 	"TTS Settings": "TTS Settings much settings",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Type Hugging Face Resolve (Download) URL much download",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! There was an issue connecting to {{provider}}. Much uh-oh!",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Unknown File Type '{{file_type}}', but accepting and treating as plain text very unknown",
@@ -470,6 +474,7 @@
 	"variable": "variable very variable",
 	"variable to have them replaced with clipboard content.": "variable to have them replaced with clipboard content. Very replace.",
 	"Version": "Version much version",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "",
 	"Web": "Web very web",
 	"Web Loader Settings": "",

+ 5 - 0
src/lib/i18n/locales/en-GB/translation.json

@@ -63,6 +63,7 @@
 	"available!": "",
 	"Back": "",
 	"Bad Response": "",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "",
 	"Being lazy": "",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "",
 	"Enter Your Password": "",
 	"Enter Your Role": "",
+	"Error": "",
 	"Experimental": "",
 	"Export All Chats (All Users)": "",
 	"Export Chats": "",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "",
 	"Include `--api` flag when running stable-diffusion-webui": "",
+	"Info": "",
 	"Input commands": "",
 	"Interface": "",
 	"Invalid Tag": "",
@@ -450,6 +453,7 @@
 	"Top P": "",
 	"Trouble accessing Ollama?": "",
 	"TTS Settings": "",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "",
@@ -470,6 +474,7 @@
 	"variable": "",
 	"variable to have them replaced with clipboard content.": "",
 	"Version": "",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "",
 	"Web": "",
 	"Web Loader Settings": "",

+ 5 - 0
src/lib/i18n/locales/en-US/translation.json

@@ -63,6 +63,7 @@
 	"available!": "",
 	"Back": "",
 	"Bad Response": "",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "",
 	"Being lazy": "",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "",
 	"Enter Your Password": "",
 	"Enter Your Role": "",
+	"Error": "",
 	"Experimental": "",
 	"Export All Chats (All Users)": "",
 	"Export Chats": "",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "",
 	"Include `--api` flag when running stable-diffusion-webui": "",
+	"Info": "",
 	"Input commands": "",
 	"Interface": "",
 	"Invalid Tag": "",
@@ -450,6 +453,7 @@
 	"Top P": "",
 	"Trouble accessing Ollama?": "",
 	"TTS Settings": "",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "",
@@ -470,6 +474,7 @@
 	"variable": "",
 	"variable to have them replaced with clipboard content.": "",
 	"Version": "",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "",
 	"Web": "",
 	"Web Loader Settings": "",

+ 5 - 0
src/lib/i18n/locales/es-ES/translation.json

@@ -63,6 +63,7 @@
 	"available!": "¡disponible!",
 	"Back": "Volver",
 	"Bad Response": "Respuesta incorrecta",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "antes",
 	"Being lazy": "Ser perezoso",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Ingrese su nombre completo",
 	"Enter Your Password": "Ingrese su contraseña",
 	"Enter Your Role": "Ingrese su rol",
+	"Error": "",
 	"Experimental": "Experimental",
 	"Export All Chats (All Users)": "Exportar todos los chats (Todos los usuarios)",
 	"Export Chats": "Exportar Chats",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Importar Prompts",
 	"Include `--api` flag when running stable-diffusion-webui": "Incluir el indicador `--api` al ejecutar stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "Ingresar comandos",
 	"Interface": "Interfaz",
 	"Invalid Tag": "Etiqueta Inválida",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "¿Problemas para acceder a Ollama?",
 	"TTS Settings": "Configuración de TTS",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Escriba la URL (Descarga) de Hugging Face Resolve",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "¡Uh oh! Hubo un problema al conectarse a {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Tipo de archivo desconocido '{{file_type}}', pero se acepta y se trata como texto sin formato",
@@ -470,6 +474,7 @@
 	"variable": "variable",
 	"variable to have them replaced with clipboard content.": "variable para reemplazarlos con el contenido del portapapeles.",
 	"Version": "Versión",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Advertencia: Si actualiza o cambia su modelo de inserción, necesitará volver a importar todos los documentos.",
 	"Web": "Web",
 	"Web Loader Settings": "Web Loader Settings",

+ 5 - 0
src/lib/i18n/locales/fa-IR/translation.json

@@ -63,6 +63,7 @@
 	"available!": "در دسترس!",
 	"Back": "بازگشت",
 	"Bad Response": "پاسخ خوب نیست",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "قبل",
 	"Being lazy": "حالت سازنده",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "نام کامل خود را وارد کنید",
 	"Enter Your Password": "رمز عبور خود را وارد کنید",
 	"Enter Your Role": "نقش خود را وارد کنید",
+	"Error": "",
 	"Experimental": "آزمایشی",
 	"Export All Chats (All Users)": "اکسپورت از همه گپ\u200cها(همه کاربران)",
 	"Export Chats": "اکسپورت از گپ\u200cها",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "ایمپورت پرامپت\u200cها",
 	"Include `--api` flag when running stable-diffusion-webui": "فلگ `--api` را هنکام اجرای stable-diffusion-webui استفاده کنید.",
+	"Info": "",
 	"Input commands": "ورودی دستورات",
 	"Interface": "رابط",
 	"Invalid Tag": "تگ نامعتبر",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "در دسترسی به اولاما مشکل دارید؟",
 	"TTS Settings": "تنظیمات TTS",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "مقدار URL دانلود (Resolve) Hugging Face را وارد کنید",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "اوه اوه! مشکلی در اتصال به {{provider}} وجود داشت.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "نوع فایل '{{file_type}}' ناشناخته است، به عنوان یک فایل متنی ساده با آن برخورد می شود.",
@@ -470,6 +474,7 @@
 	"variable": "متغیر",
 	"variable to have them replaced with clipboard content.": "متغیر برای جایگزینی آنها با محتوای کلیپ بورد.",
 	"Version": "نسخه",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "هشدار: اگر شما به روز کنید یا تغییر دهید مدل شما، باید تمام سند ها را مجددا وارد کنید.",
 	"Web": "وب",
 	"Web Loader Settings": "تنظیمات لودر وب",

+ 5 - 0
src/lib/i18n/locales/fi-FI/translation.json

@@ -63,6 +63,7 @@
 	"available!": "saatavilla!",
 	"Back": "Takaisin",
 	"Bad Response": "Epäkelpo vastaus",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "ennen",
 	"Being lazy": "Oli laiska",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Syötä koko nimesi",
 	"Enter Your Password": "Syötä salasanasi",
 	"Enter Your Role": "Syötä roolisi",
+	"Error": "",
 	"Experimental": "Kokeellinen",
 	"Export All Chats (All Users)": "Vie kaikki keskustelut (kaikki käyttäjät)",
 	"Export Chats": "Vie keskustelut",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Tuo kehotteita",
 	"Include `--api` flag when running stable-diffusion-webui": "Sisällytä `--api`-parametri suorittaessasi stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "Syötä komennot",
 	"Interface": "Käyttöliittymä",
 	"Invalid Tag": "Virheellinen tagi",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Ongelmia Ollama-yhteydessä?",
 	"TTS Settings": "Puheentuottamisasetukset",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Kirjoita Hugging Face -resolve-osoite",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Voi ei! Yhteysongelma {{provider}}:n kanssa.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Tuntematon tiedostotyyppi '{{file_type}}', mutta hyväksytään ja käsitellään pelkkänä tekstinä",
@@ -470,6 +474,7 @@
 	"variable": "muuttuja",
 	"variable to have them replaced with clipboard content.": "muuttuja korvataan leikepöydän sisällöllä.",
 	"Version": "Versio",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Varoitus: Jos päivität tai vaihdat upotusmallia, sinun on tuotava kaikki asiakirjat uudelleen.",
 	"Web": "Web",
 	"Web Loader Settings": "Web Loader asetukset",

+ 5 - 0
src/lib/i18n/locales/fr-CA/translation.json

@@ -63,6 +63,7 @@
 	"available!": "disponible !",
 	"Back": "Retour",
 	"Bad Response": "Mauvaise réponse",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "avant",
 	"Being lazy": "En manque de temps",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Entrez votre nom complet",
 	"Enter Your Password": "Entrez votre mot de passe",
 	"Enter Your Role": "Entrez votre rôle",
+	"Error": "",
 	"Experimental": "Expérimental",
 	"Export All Chats (All Users)": "Exporter toutes les discussions (Tous les utilisateurs)",
 	"Export Chats": "Exporter les discussions",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Importer les prompts",
 	"Include `--api` flag when running stable-diffusion-webui": "Inclure l'indicateur `--api` lors de l'exécution de stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "Entrez des commandes d'entrée",
 	"Interface": "Interface",
 	"Invalid Tag": "Tag invalide",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Des problèmes pour accéder à Ollama ?",
 	"TTS Settings": "Paramètres TTS",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Entrez l'URL de résolution (téléchargement) Hugging Face",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh ! Il y a eu un problème de connexion à {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Type de fichier inconnu '{{file_type}}', mais accepté et traité comme du texte brut",
@@ -470,6 +474,7 @@
 	"variable": "variable",
 	"variable to have them replaced with clipboard content.": "variable pour les remplacer par le contenu du presse-papiers.",
 	"Version": "Version",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Attention : Si vous mettez à jour ou changez votre modèle d'intégration, vous devrez réimporter tous les documents.",
 	"Web": "Web",
 	"Web Loader Settings": "Paramètres du chargeur Web",

+ 5 - 0
src/lib/i18n/locales/fr-FR/translation.json

@@ -63,6 +63,7 @@
 	"available!": "disponible !",
 	"Back": "Retour",
 	"Bad Response": "Mauvaise Réponse",
+	"Banners": "",
 	"Base Model (From)": "Modèle de Base (De)",
 	"before": "avant",
 	"Being lazy": "Est paresseux",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Entrez Votre Nom Complet",
 	"Enter Your Password": "Entrez Votre Mot De Passe",
 	"Enter Your Role": "Entrez Votre Rôle",
+	"Error": "",
 	"Experimental": "Expérimental",
 	"Export All Chats (All Users)": "Exporter Tous les Chats (Tous les Utilisateurs)",
 	"Export Chats": "Exporter les Chats",
@@ -228,6 +230,7 @@
 	"Import Models": "Importer des Modèles",
 	"Import Prompts": "Importer des Prompts",
 	"Include `--api` flag when running stable-diffusion-webui": "Inclure le drapeau `--api` lors de l'exécution de stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "Entrez les commandes d'entrée",
 	"Interface": "Interface",
 	"Invalid Tag": "Tag Invalide",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Problèmes d'accès à Ollama ?",
 	"TTS Settings": "Paramètres TTS",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Entrez l'URL de Résolution (Téléchargement) Hugging Face",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh ! Il y a eu un problème de connexion à {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Type de Fichier Inconnu '{{file_type}}', mais accepté et traité comme du texte brut",
@@ -470,6 +474,7 @@
 	"variable": "variable",
 	"variable to have them replaced with clipboard content.": "variable pour les remplacer par le contenu du presse-papiers.",
 	"Version": "Version",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Avertissement : Si vous mettez à jour ou modifier votre modèle d'embedding, vous devrez réimporter tous les documents.",
 	"Web": "Web",
 	"Web Loader Settings": "Paramètres du Chargeur Web",

+ 5 - 0
src/lib/i18n/locales/he-IL/translation.json

@@ -63,6 +63,7 @@
 	"available!": "זמין!",
 	"Back": "חזור",
 	"Bad Response": "תגובה שגויה",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "לפני",
 	"Being lazy": "להיות עצלן",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "הזן את שמך המלא",
 	"Enter Your Password": "הזן את הסיסמה שלך",
 	"Enter Your Role": "הזן את התפקיד שלך",
+	"Error": "",
 	"Experimental": "ניסיוני",
 	"Export All Chats (All Users)": "ייצוא כל הצ'אטים (כל המשתמשים)",
 	"Export Chats": "ייצוא צ'אטים",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "יבוא פקודות",
 	"Include `--api` flag when running stable-diffusion-webui": "כלול את הדגל `--api` בעת הרצת stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "פקודות קלט",
 	"Interface": "ממשק",
 	"Invalid Tag": "תג לא חוקי",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "קשה לגשת לOllama?",
 	"TTS Settings": "הגדרות TTS",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "הקלד כתובת URL של פתרון פנים מחבק (הורד)",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "או-הו! אירעה בעיה בהתחברות ל- {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "סוג קובץ לא ידוע '{{file_type}}', אך מקבל ומתייחס אליו כטקסט רגיל",
@@ -470,6 +474,7 @@
 	"variable": "משתנה",
 	"variable to have them replaced with clipboard content.": "משתנה להחליפו ב- clipboard תוכן.",
 	"Version": "גרסה",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "אזהרה: אם תעדכן או תשנה את מודל ההטבעה שלך, יהיה עליך לייבא מחדש את כל המסמכים.",
 	"Web": "רשת",
 	"Web Loader Settings": "הגדרות טעינת אתר",

+ 5 - 0
src/lib/i18n/locales/hi-IN/translation.json

@@ -63,6 +63,7 @@
 	"available!": "उपलब्ध!",
 	"Back": "पीछे",
 	"Bad Response": "ख़राब प्रतिक्रिया",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "पहले",
 	"Being lazy": "आलसी होना",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "अपना पूरा नाम भरें",
 	"Enter Your Password": "अपना पासवर्ड भरें",
 	"Enter Your Role": "अपनी भूमिका दर्ज करें",
+	"Error": "",
 	"Experimental": "प्रयोगात्मक",
 	"Export All Chats (All Users)": "सभी चैट निर्यात करें (सभी उपयोगकर्ताओं की)",
 	"Export Chats": "चैट निर्यात करें",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "प्रॉम्प्ट आयात करें",
 	"Include `--api` flag when running stable-diffusion-webui": "stable-diffusion-webui चलाते समय `--api` ध्वज शामिल करें",
+	"Info": "",
 	"Input commands": "इनपुट क命",
 	"Interface": "इंटरफेस",
 	"Invalid Tag": "अवैध टैग",
@@ -450,6 +453,7 @@
 	"Top P": "शीर्ष  P",
 	"Trouble accessing Ollama?": "Ollama तक पहुँचने में परेशानी हो रही है?",
 	"TTS Settings": "TTS सेटिंग्स",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "हगिंग फेस रिज़ॉल्व (डाउनलोड) यूआरएल टाइप करें",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "उह ओह! {{provider}} से कनेक्ट करने में एक समस्या थी।",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "अज्ञात फ़ाइल प्रकार '{{file_type}}', लेकिन स्वीकार करना और सादे पाठ के रूप में व्यवहार करना",
@@ -470,6 +474,7 @@
 	"variable": "वेरिएबल",
 	"variable to have them replaced with clipboard content.": "उन्हें क्लिपबोर्ड सामग्री से बदलने के लिए वेरिएबल।",
 	"Version": "संस्करण",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "चेतावनी: यदि आप अपने एम्बेडिंग मॉडल को अपडेट या बदलते हैं, तो आपको सभी दस्तावेज़ों को फिर से आयात करने की आवश्यकता होगी।",
 	"Web": "वेब",
 	"Web Loader Settings": "वेब लोडर सेटिंग्स",

+ 5 - 0
src/lib/i18n/locales/hr-HR/translation.json

@@ -63,6 +63,7 @@
 	"available!": "dostupno!",
 	"Back": "Natrag",
 	"Bad Response": "Loš odgovor",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "prije",
 	"Being lazy": "Biti lijen",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Unesite svoje puno ime",
 	"Enter Your Password": "Unesite svoju lozinku",
 	"Enter Your Role": "Unesite svoju ulogu",
+	"Error": "",
 	"Experimental": "Eksperimentalno",
 	"Export All Chats (All Users)": "Izvoz svih razgovora (svi korisnici)",
 	"Export Chats": "Izvoz razgovora",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Uvoz prompta",
 	"Include `--api` flag when running stable-diffusion-webui": "Uključite zastavicu `--api` prilikom pokretanja stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "Unos naredbi",
 	"Interface": "Sučelje",
 	"Invalid Tag": "Nevažeća oznaka",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Problemi s pristupom Ollama?",
 	"TTS Settings": "TTS postavke",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Upišite Hugging Face Resolve (Download) URL",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! Pojavio se problem s povezivanjem na {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Nepoznata vrsta datoteke '{{file_type}}', ali prihvaćena i obrađuje se kao običan tekst",
@@ -470,6 +474,7 @@
 	"variable": "varijabla",
 	"variable to have them replaced with clipboard content.": "varijabla za zamjenu sadržajem međuspremnika.",
 	"Version": "Verzija",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Upozorenje: Ako ažurirate ili promijenite svoj model za umetanje, morat ćete ponovno uvesti sve dokumente.",
 	"Web": "Web",
 	"Web Loader Settings": "Postavke web učitavanja",

+ 5 - 0
src/lib/i18n/locales/it-IT/translation.json

@@ -63,6 +63,7 @@
 	"available!": "disponibile!",
 	"Back": "Indietro",
 	"Bad Response": "Risposta non valida",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "prima",
 	"Being lazy": "Essere pigri",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Inserisci il tuo nome completo",
 	"Enter Your Password": "Inserisci la tua password",
 	"Enter Your Role": "Inserisci il tuo ruolo",
+	"Error": "",
 	"Experimental": "Sperimentale",
 	"Export All Chats (All Users)": "Esporta tutte le chat (tutti gli utenti)",
 	"Export Chats": "Esporta chat",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Importa prompt",
 	"Include `--api` flag when running stable-diffusion-webui": "Includi il flag `--api` quando esegui stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "Comandi di input",
 	"Interface": "Interfaccia",
 	"Invalid Tag": "Tag non valido",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Problemi di accesso a Ollama?",
 	"TTS Settings": "Impostazioni TTS",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Digita l'URL di Hugging Face Resolve (Download)",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! Si è verificato un problema durante la connessione a {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Tipo di file sconosciuto '{{file_type}}', ma accettato e trattato come testo normale",
@@ -470,6 +474,7 @@
 	"variable": "variabile",
 	"variable to have them replaced with clipboard content.": "variabile per farli sostituire con il contenuto degli appunti.",
 	"Version": "Versione",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Attenzione: se aggiorni o cambi il tuo modello di embedding, dovrai reimportare tutti i documenti.",
 	"Web": "Web",
 	"Web Loader Settings": "Impostazioni del caricatore Web",

+ 5 - 0
src/lib/i18n/locales/ja-JP/translation.json

@@ -63,6 +63,7 @@
 	"available!": "利用可能!",
 	"Back": "戻る",
 	"Bad Response": "応答が悪い",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "より前",
 	"Being lazy": "怠惰な",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "フルネームを入力してください",
 	"Enter Your Password": "パスワードを入力してください",
 	"Enter Your Role": "ロールを入力してください",
+	"Error": "",
 	"Experimental": "実験的",
 	"Export All Chats (All Users)": "すべてのチャットをエクスポート (すべてのユーザー)",
 	"Export Chats": "チャットをエクスポート",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "プロンプトをインポート",
 	"Include `--api` flag when running stable-diffusion-webui": "stable-diffusion-webuiを実行する際に`--api`フラグを含める",
+	"Info": "",
 	"Input commands": "入力コマンド",
 	"Interface": "インターフェース",
 	"Invalid Tag": "無効なタグ",
@@ -450,6 +453,7 @@
 	"Top P": "トップ P",
 	"Trouble accessing Ollama?": "Ollama へのアクセスに問題がありますか?",
 	"TTS Settings": "TTS 設定",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Hugging Face Resolve (ダウンロード) URL を入力してください",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "おっと! {{provider}} への接続に問題が発生しました。",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "不明なファイルタイプ '{{file_type}}' ですが、プレーンテキストとして受け入れて処理します",
@@ -470,6 +474,7 @@
 	"variable": "変数",
 	"variable to have them replaced with clipboard content.": "クリップボードの内容に置き換える変数。",
 	"Version": "バージョン",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "警告: 埋め込みモデルを更新または変更した場合は、すべてのドキュメントを再インポートする必要があります。",
 	"Web": "ウェブ",
 	"Web Loader Settings": "Web 読み込み設定",

+ 5 - 0
src/lib/i18n/locales/ka-GE/translation.json

@@ -63,6 +63,7 @@
 	"available!": "ხელმისაწვდომია!",
 	"Back": "უკან",
 	"Bad Response": "ხარვეზი",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "ადგილზე",
 	"Being lazy": "ჩაიტყვევა",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "შეიყვანეთ თქვენი სრული სახელი",
 	"Enter Your Password": "შეიყვანეთ თქვენი პაროლი",
 	"Enter Your Role": "შეიყვანეთ თქვენი როლი",
+	"Error": "",
 	"Experimental": "ექსპერიმენტალური",
 	"Export All Chats (All Users)": "ექსპორტი ყველა ჩათი (ყველა მომხმარებელი)",
 	"Export Chats": "მიმოწერის ექსპორტირება",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "მოთხოვნების იმპორტი",
 	"Include `--api` flag when running stable-diffusion-webui": "ჩართეთ `--api` დროშა stable-diffusion-webui-ის გაშვებისას",
+	"Info": "",
 	"Input commands": "შეყვანით ბრძანებებს",
 	"Interface": "ინტერფეისი",
 	"Invalid Tag": "არასწორი ტეგი",
@@ -450,6 +453,7 @@
 	"Top P": "ტოპ P",
 	"Trouble accessing Ollama?": "Ollama-ს ვერ უკავშირდები?",
 	"TTS Settings": "TTS პარამეტრები",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "სცადე გადმოწერო Hugging Face Resolve URL",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "{{provider}}-თან დაკავშირების პრობლემა წარმოიშვა.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "უცნობი ფაილის ტიპი „{{file_type}}“, მაგრამ მიიღება და განიხილება როგორც მარტივი ტექსტი",
@@ -470,6 +474,7 @@
 	"variable": "ცვლადი",
 	"variable to have them replaced with clipboard content.": "ცვლადი, რომ შეცვალოს ისინი ბუფერში შიგთავსით.",
 	"Version": "ვერსია",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "გაფრთხილება: თუ განაახლებთ ან შეცვლით ჩანერგვის მოდელს, მოგიწევთ ყველა დოკუმენტის ხელახლა იმპორტი.",
 	"Web": "ვები",
 	"Web Loader Settings": "ვების ჩატარების პარამეტრები",

+ 5 - 0
src/lib/i18n/locales/ko-KR/translation.json

@@ -63,6 +63,7 @@
 	"available!": "사용 가능!",
 	"Back": "뒤로가기",
 	"Bad Response": "응답이 좋지 않습니다.",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "이전",
 	"Being lazy": "게으름 피우기",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "전체 이름 입력",
 	"Enter Your Password": "비밀번호 입력",
 	"Enter Your Role": "역할 입력",
+	"Error": "",
 	"Experimental": "실험적",
 	"Export All Chats (All Users)": "모든 채팅 내보내기 (모든 사용자)",
 	"Export Chats": "채팅 내보내기",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "프롬프트 가져오기",
 	"Include `--api` flag when running stable-diffusion-webui": "stable-diffusion-webui를 실행할 때 '--api' 플래그 포함",
+	"Info": "",
 	"Input commands": "입력 명령",
 	"Interface": "인터페이스",
 	"Invalid Tag": "잘못된 태그",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Ollama에 접근하는 데 문제가 있나요?",
 	"TTS Settings": "TTS 설정",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Hugging Face Resolve (다운로드) URL 입력",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "앗! {{provider}}에 연결하는 데 문제가 있었습니다.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "알 수 없는 파일 유형 '{{file_type}}', 하지만 일반 텍스트로 허용하고 처리합니다.",
@@ -470,6 +474,7 @@
 	"variable": "변수",
 	"variable to have them replaced with clipboard content.": "변수를 사용하여 클립보드 내용으로 바꾸세요.",
 	"Version": "버전",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "웹 로더를 업데이트하거나 변경할 경우 모든 문서를 다시 가져와야 합니다.",
 	"Web": "웹",
 	"Web Loader Settings": "웹 로더 설정",

+ 5 - 0
src/lib/i18n/locales/nl-NL/translation.json

@@ -63,6 +63,7 @@
 	"available!": "beschikbaar!",
 	"Back": "Terug",
 	"Bad Response": "Ongeldig antwoord",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "voor",
 	"Being lazy": "Lustig zijn",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Voer je Volledige Naam in",
 	"Enter Your Password": "Voer je Wachtwoord in",
 	"Enter Your Role": "Voer je Rol in",
+	"Error": "",
 	"Experimental": "Experimenteel",
 	"Export All Chats (All Users)": "Exporteer Alle Chats (Alle Gebruikers)",
 	"Export Chats": "Exporteer Chats",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Importeer Prompts",
 	"Include `--api` flag when running stable-diffusion-webui": "Voeg `--api` vlag toe bij het uitvoeren van stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "Voer commando's in",
 	"Interface": "Interface",
 	"Invalid Tag": "Ongeldige Tag",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Problemen met toegang tot Ollama?",
 	"TTS Settings": "TTS instellingen",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Type Hugging Face Resolve (Download) URL",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! Er was een probleem met verbinden met {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Onbekend Bestandstype '{{file_type}}', maar accepteren en behandelen als platte tekst",
@@ -470,6 +474,7 @@
 	"variable": "variabele",
 	"variable to have them replaced with clipboard content.": "variabele om ze te laten vervangen door klembord inhoud.",
 	"Version": "Versie",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Warning: Als je de embedding model bijwerkt of wijzigt, moet je alle documenten opnieuw importeren.",
 	"Web": "Web",
 	"Web Loader Settings": "Web Loader instellingen",

+ 5 - 0
src/lib/i18n/locales/pa-IN/translation.json

@@ -63,6 +63,7 @@
 	"available!": "ਉਪਲਬਧ ਹੈ!",
 	"Back": "ਵਾਪਸ",
 	"Bad Response": "ਖਰਾਬ ਜਵਾਬ",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "ਪਹਿਲਾਂ",
 	"Being lazy": "ਆਲਸੀ ਹੋਣਾ",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "ਆਪਣਾ ਪੂਰਾ ਨਾਮ ਦਰਜ ਕਰੋ",
 	"Enter Your Password": "ਆਪਣਾ ਪਾਸਵਰਡ ਦਰਜ ਕਰੋ",
 	"Enter Your Role": "ਆਪਣੀ ਭੂਮਿਕਾ ਦਰਜ ਕਰੋ",
+	"Error": "",
 	"Experimental": "ਪਰਮਾਣੂਕ੍ਰਿਤ",
 	"Export All Chats (All Users)": "ਸਾਰੀਆਂ ਗੱਲਾਂ ਨਿਰਯਾਤ ਕਰੋ (ਸਾਰੇ ਉਪਭੋਗਤਾ)",
 	"Export Chats": "ਗੱਲਾਂ ਨਿਰਯਾਤ ਕਰੋ",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "ਪ੍ਰੰਪਟ ਆਯਾਤ ਕਰੋ",
 	"Include `--api` flag when running stable-diffusion-webui": "ਸਟੇਬਲ-ਡਿਫਿਊਸ਼ਨ-ਵੈਬਯੂਆਈ ਚਲਾਉਣ ਸਮੇਂ `--api` ਝੰਡਾ ਸ਼ਾਮਲ ਕਰੋ",
+	"Info": "",
 	"Input commands": "ਇਨਪੁਟ ਕਮਾਂਡਾਂ",
 	"Interface": "ਇੰਟਰਫੇਸ",
 	"Invalid Tag": "ਗਲਤ ਟੈਗ",
@@ -450,6 +453,7 @@
 	"Top P": "ਸਿਖਰ P",
 	"Trouble accessing Ollama?": "ਓਲਾਮਾ ਤੱਕ ਪਹੁੰਚਣ ਵਿੱਚ ਮੁਸ਼ਕਲ?",
 	"TTS Settings": "TTS ਸੈਟਿੰਗਾਂ",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Hugging Face Resolve (ਡਾਊਨਲੋਡ) URL ਟਾਈਪ ਕਰੋ",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "ਓਹੋ! {{provider}} ਨਾਲ ਕਨੈਕਟ ਕਰਨ ਵਿੱਚ ਸਮੱਸਿਆ ਆਈ।",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "ਅਣਜਾਣ ਫਾਈਲ ਕਿਸਮ '{{file_type}}', ਪਰ ਸਧਾਰਨ ਪਾਠ ਵਜੋਂ ਸਵੀਕਾਰ ਕਰਦੇ ਹੋਏ",
@@ -470,6 +474,7 @@
 	"variable": "ਵੈਰੀਏਬਲ",
 	"variable to have them replaced with clipboard content.": "ਕਲਿੱਪਬੋਰਡ ਸਮੱਗਰੀ ਨਾਲ ਬਦਲਣ ਲਈ ਵੈਰੀਏਬਲ।",
 	"Version": "ਵਰਜਨ",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "ਚੇਤਾਵਨੀ: ਜੇ ਤੁਸੀਂ ਆਪਣਾ ਐਮਬੈੱਡਿੰਗ ਮਾਡਲ ਅੱਪਡੇਟ ਜਾਂ ਬਦਲਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਨੂੰ ਸਾਰੇ ਡਾਕੂਮੈਂਟ ਮੁੜ ਆਯਾਤ ਕਰਨ ਦੀ ਲੋੜ ਹੋਵੇਗੀ।",
 	"Web": "ਵੈਬ",
 	"Web Loader Settings": "ਵੈਬ ਲੋਡਰ ਸੈਟਿੰਗਾਂ",

+ 5 - 0
src/lib/i18n/locales/pl-PL/translation.json

@@ -63,6 +63,7 @@
 	"available!": "dostępny!",
 	"Back": "Wstecz",
 	"Bad Response": "Zła odpowiedź",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "przed",
 	"Being lazy": "Jest leniwy",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Wprowadź swoje imię i nazwisko",
 	"Enter Your Password": "Wprowadź swoje hasło",
 	"Enter Your Role": "Wprowadź swoją rolę",
+	"Error": "",
 	"Experimental": "Eksperymentalne",
 	"Export All Chats (All Users)": "Eksportuj wszystkie czaty (wszyscy użytkownicy)",
 	"Export Chats": "Eksportuj czaty",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Importuj prompty",
 	"Include `--api` flag when running stable-diffusion-webui": "Dołącz flagę `--api` podczas uruchamiania stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "Wprowadź komendy",
 	"Interface": "Interfejs",
 	"Invalid Tag": "Nieprawidłowy tag",
@@ -450,6 +453,7 @@
 	"Top P": "Najlepsze P",
 	"Trouble accessing Ollama?": "Problemy z dostępem do Ollama?",
 	"TTS Settings": "Ustawienia TTS",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Wprowadź adres URL do pobrania z Hugging Face",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "O nie! Wystąpił problem z połączeniem z {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Nieznany typ pliku '{{file_type}}', ale akceptowany i traktowany jako zwykły tekst",
@@ -470,6 +474,7 @@
 	"variable": "zmienna",
 	"variable to have them replaced with clipboard content.": "zmienna która zostanie zastąpiona zawartością schowka.",
 	"Version": "Wersja",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Uwaga: Jeśli uaktualnisz lub zmienisz model osadzania, będziesz musiał ponownie zaimportować wszystkie dokumenty.",
 	"Web": "Sieć",
 	"Web Loader Settings": "Ustawienia pobierania z sieci",

+ 5 - 0
src/lib/i18n/locales/pt-BR/translation.json

@@ -63,6 +63,7 @@
 	"available!": "disponível!",
 	"Back": "Voltar",
 	"Bad Response": "Resposta ruim",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "antes",
 	"Being lazy": "Ser preguiçoso",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Digite seu Nome Completo",
 	"Enter Your Password": "Digite sua Senha",
 	"Enter Your Role": "Digite sua Função",
+	"Error": "",
 	"Experimental": "Experimental",
 	"Export All Chats (All Users)": "Exportar Todos os Bate-papos (Todos os Usuários)",
 	"Export Chats": "Exportar Bate-papos",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Importar Prompts",
 	"Include `--api` flag when running stable-diffusion-webui": "Inclua a flag `--api` ao executar stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "Comandos de entrada",
 	"Interface": "Interface",
 	"Invalid Tag": "Etiqueta Inválida",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Problemas para acessar o Ollama?",
 	"TTS Settings": "Configurações TTS",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Digite a URL do Hugging Face Resolve (Download)",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Opa! Houve um problema ao conectar-se a {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Tipo de arquivo desconhecido '{{file_type}}', mas aceitando e tratando como texto simples",
@@ -470,6 +474,7 @@
 	"variable": "variável",
 	"variable to have them replaced with clipboard content.": "variável para que sejam substituídos pelo conteúdo da área de transferência.",
 	"Version": "Versão",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Aviso: Se você atualizar ou alterar seu modelo de incorporação, você precisará reimportar todos os documentos.",
 	"Web": "Web",
 	"Web Loader Settings": "Configurações do Carregador da Web",

+ 5 - 0
src/lib/i18n/locales/pt-PT/translation.json

@@ -63,6 +63,7 @@
 	"available!": "disponível!",
 	"Back": "Voltar",
 	"Bad Response": "Resposta ruim",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "antes",
 	"Being lazy": "Ser preguiçoso",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Digite seu Nome Completo",
 	"Enter Your Password": "Digite sua Senha",
 	"Enter Your Role": "Digite sua Função",
+	"Error": "",
 	"Experimental": "Experimental",
 	"Export All Chats (All Users)": "Exportar Todos os Bate-papos (Todos os Usuários)",
 	"Export Chats": "Exportar Bate-papos",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Importar Prompts",
 	"Include `--api` flag when running stable-diffusion-webui": "Inclua a flag `--api` ao executar stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "Comandos de entrada",
 	"Interface": "Interface",
 	"Invalid Tag": "Etiqueta Inválida",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Problemas para acessar o Ollama?",
 	"TTS Settings": "Configurações TTS",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Digite a URL do Hugging Face Resolve (Download)",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Opa! Houve um problema ao conectar-se a {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Tipo de arquivo desconhecido '{{file_type}}', mas aceitando e tratando como texto simples",
@@ -470,6 +474,7 @@
 	"variable": "variável",
 	"variable to have them replaced with clipboard content.": "variável para que sejam substituídos pelo conteúdo da área de transferência.",
 	"Version": "Versão",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Aviso: Se você atualizar ou alterar seu modelo de vetorização, você precisará reimportar todos os documentos.",
 	"Web": "Web",
 	"Web Loader Settings": "Configurações do Carregador da Web",

+ 5 - 0
src/lib/i18n/locales/ru-RU/translation.json

@@ -63,6 +63,7 @@
 	"available!": "доступный!",
 	"Back": "Назад",
 	"Bad Response": "Недопустимый ответ",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "до",
 	"Being lazy": "ленивый",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Введите ваше полное имя",
 	"Enter Your Password": "Введите ваш пароль",
 	"Enter Your Role": "Введите вашу роль",
+	"Error": "",
 	"Experimental": "Экспериментальное",
 	"Export All Chats (All Users)": "Экспортировать все чаты (все пользователи)",
 	"Export Chats": "Экспортировать чаты",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Импорт подсказок",
 	"Include `--api` flag when running stable-diffusion-webui": "Добавьте флаг `--api` при запуске stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "Введите команды",
 	"Interface": "Интерфейс",
 	"Invalid Tag": "Недопустимый тег",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Проблемы с доступом к Ollama?",
 	"TTS Settings": "Настройки TTS",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Введите URL-адрес Hugging Face Resolve (загрузки)",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Упс! Возникла проблема подключения к {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Неизвестный тип файла '{{file_type}}', но принимается и обрабатывается как обычный текст",
@@ -470,6 +474,7 @@
 	"variable": "переменная",
 	"variable to have them replaced with clipboard content.": "переменная, чтобы их заменить содержимым буфера обмена.",
 	"Version": "Версия",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Предупреждение: Если вы обновите или измените модель эмбеддинга, вам нужно будет повторно импортировать все документы.",
 	"Web": "Веб",
 	"Web Loader Settings": "Настройки загрузчика Web",

+ 5 - 0
src/lib/i18n/locales/sr-RS/translation.json

@@ -63,6 +63,7 @@
 	"available!": "доступно!",
 	"Back": "Назад",
 	"Bad Response": "Лош одговор",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "пре",
 	"Being lazy": "Бити лењ",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Унесите ваше име и презиме",
 	"Enter Your Password": "Унесите вашу лозинку",
 	"Enter Your Role": "Унесите вашу улогу",
+	"Error": "",
 	"Experimental": "Експериментално",
 	"Export All Chats (All Users)": "Извези сва ћаскања (сви корисници)",
 	"Export Chats": "Извези ћаскања",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Увези упите",
 	"Include `--api` flag when running stable-diffusion-webui": "Укључи `--api` заставицу при покретању stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "Унеси наредбе",
 	"Interface": "Изглед",
 	"Invalid Tag": "Неисправна ознака",
@@ -450,6 +453,7 @@
 	"Top P": "Топ П",
 	"Trouble accessing Ollama?": "Проблеми са приступом Ollama-и?",
 	"TTS Settings": "TTS подешавања",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Унесите Hugging Face Resolve (Download) адресу",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Упс! Дошло је до проблема при повезивању са {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Непознат тип датотеке '{{file_type}}', али прихваћен и третиран као обичан текст",
@@ -470,6 +474,7 @@
 	"variable": "променљива",
 	"variable to have them replaced with clipboard content.": "променљива за замену са садржајем оставе.",
 	"Version": "Издање",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Упозорење: ако ажурирате или промените ваш модел уградње, мораћете поново да увезете све документе.",
 	"Web": "Веб",
 	"Web Loader Settings": "Подешавања веб учитавача",

+ 5 - 0
src/lib/i18n/locales/sv-SE/translation.json

@@ -63,6 +63,7 @@
 	"available!": "tillgänglig!",
 	"Back": "Tillbaka",
 	"Bad Response": "Felaktig respons",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "før",
 	"Being lazy": "Lägg till",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Ange ditt fullständiga namn",
 	"Enter Your Password": "Ange ditt lösenord",
 	"Enter Your Role": "Ange din roll",
+	"Error": "",
 	"Experimental": "Experimentell",
 	"Export All Chats (All Users)": "Exportera alla chattar (alla användare)",
 	"Export Chats": "Exportera chattar",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Importera prompts",
 	"Include `--api` flag when running stable-diffusion-webui": "Inkludera `--api`-flagga när du kör stabil-diffusion-webui",
+	"Info": "",
 	"Input commands": "Indatakommandon",
 	"Interface": "Gränssnitt",
 	"Invalid Tag": "Ogiltig tagg",
@@ -450,6 +453,7 @@
 	"Top P": "Topp P",
 	"Trouble accessing Ollama?": "Problem med att komma åt Ollama?",
 	"TTS Settings": "TTS-inställningar",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Skriv Hugging Face Resolve (nedladdning) URL",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Oj då! Det uppstod ett problem med att ansluta till {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Okänd filtyp '{{file_type}}', men accepterar och behandlar som vanlig text",
@@ -470,6 +474,7 @@
 	"variable": "variabel",
 	"variable to have them replaced with clipboard content.": "variabel för att få dem ersatta med urklippsinnehåll.",
 	"Version": "Version",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Varning: Om du uppdaterar eller ändrar din embedding modell måste du importera alla dokument igen.",
 	"Web": "Webb",
 	"Web Loader Settings": "Web Loader-inställningar",

+ 5 - 0
src/lib/i18n/locales/tr-TR/translation.json

@@ -63,6 +63,7 @@
 	"available!": "mevcut!",
 	"Back": "Geri",
 	"Bad Response": "Kötü Yanıt",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "önce",
 	"Being lazy": "Tembelleşiyor",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Tam Adınızı Girin",
 	"Enter Your Password": "Parolanızı Girin",
 	"Enter Your Role": "Rolünüzü Girin",
+	"Error": "",
 	"Experimental": "Deneysel",
 	"Export All Chats (All Users)": "Tüm Sohbetleri Dışa Aktar (Tüm Kullanıcılar)",
 	"Export Chats": "Sohbetleri Dışa Aktar",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Promptları İçe Aktar",
 	"Include `--api` flag when running stable-diffusion-webui": "stable-diffusion-webui çalıştırılırken `--api` bayrağını dahil edin",
+	"Info": "",
 	"Input commands": "Giriş komutları",
 	"Interface": "Arayüz",
 	"Invalid Tag": "Geçersiz etiket",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Ollama'ya erişmede sorun mu yaşıyorsunuz?",
 	"TTS Settings": "TTS Ayarları",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Hugging Face Resolve (Download) URL'sini Yazın",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Ah! {{provider}}'a bağlanırken bir sorun oluştu.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Bilinmeyen Dosya Türü '{{file_type}}', ancak düz metin olarak kabul ediliyor ve işleniyor",
@@ -470,6 +474,7 @@
 	"variable": "değişken",
 	"variable to have them replaced with clipboard content.": "panodaki içerikle değiştirilmesi için değişken.",
 	"Version": "Sürüm",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Uyarı: Gömme modelinizi günceller veya değiştirirseniz, tüm belgeleri yeniden içe aktarmanız gerekecektir.",
 	"Web": "Web",
 	"Web Loader Settings": "Web Yükleyici Ayarları",

+ 5 - 0
src/lib/i18n/locales/uk-UA/translation.json

@@ -63,6 +63,7 @@
 	"available!": "доступно!",
 	"Back": "Назад",
 	"Bad Response": "Неправильна відповідь",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "до того, як",
 	"Being lazy": "Не поспішати",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Введіть ваше ім'я",
 	"Enter Your Password": "Введіть ваш пароль",
 	"Enter Your Role": "Введіть вашу роль",
+	"Error": "",
 	"Experimental": "Експериментальне",
 	"Export All Chats (All Users)": "Експортувати всі чати (всі користувачі)",
 	"Export Chats": "Експортувати чати",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "Імпортувати промти",
 	"Include `--api` flag when running stable-diffusion-webui": "Включіть прапор `--api` при запуску stable-diffusion-webui",
+	"Info": "",
 	"Input commands": "Команди вводу",
 	"Interface": "Інтерфейс",
 	"Invalid Tag": "Недійсний тег",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Проблеми з доступом до Ollama?",
 	"TTS Settings": "Налаштування TTS",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "Введіть URL ресурсу Hugging Face Resolve (завантаження)",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Ой! Виникла проблема при підключенні до {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Невідомий тип файлу '{{file_type}}', але приймається та обробляється як звичайний текст",
@@ -470,6 +474,7 @@
 	"variable": "змінна",
 	"variable to have them replaced with clipboard content.": "змінна, щоб замінити їх вмістом буфера обміну.",
 	"Version": "Версія",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Попередження: Якщо ви оновлюєте або змінюєте модель вбудовування, вам потрібно буде повторно імпортувати всі документи.",
 	"Web": "Веб",
 	"Web Loader Settings": "Налаштування веб-завантажувача",

+ 23 - 18
src/lib/i18n/locales/vi-VN/translation.json

@@ -4,7 +4,7 @@
 	"(e.g. `sh webui.sh --api`)": "(vd: `sh webui.sh --api`)",
 	"(latest)": "(mới nhất)",
 	"{{ models }}": "",
-	"{{ owner }}: You cannot delete a base model": "",
+	"{{ owner }}: You cannot delete a base model": "{{ owner }}: Bạn không thể xóa base model",
 	"{{modelName}} is thinking...": "{{modelName}} đang suy nghĩ...",
 	"{{user}}'s Chats": "{{user}}'s Chats",
 	"{{webUIName}} Backend Required": "{{webUIName}} Yêu cầu Backend",
@@ -15,7 +15,7 @@
 	"Accurate information": "Thông tin chính xác",
 	"Add": "Thêm",
 	"Add a model id": "",
-	"Add a short description about what this model does": "",
+	"Add a short description about what this model does": "Thêm mô tả ngắn về những khả năng của model",
 	"Add a short title for this prompt": "Thêm tiêu đề ngắn cho prompt này",
 	"Add a tag": "Thêm thẻ (tag)",
 	"Add custom prompt": "Thêm prompt tùy chỉnh",
@@ -48,7 +48,7 @@
 	"API keys": "API Keys",
 	"April": "Tháng 4",
 	"Archive": "Lưu trữ",
-	"Archive All Chats": "",
+	"Archive All Chats": "Lưu tất cả các cuộc Chat",
 	"Archived Chats": "bản ghi trò chuyện",
 	"are allowed - Activate this command by typing": "được phép - Kích hoạt lệnh này bằng cách gõ",
 	"Are you sure?": "Bạn có chắc chắn không?",
@@ -63,12 +63,13 @@
 	"available!": "có sẵn!",
 	"Back": "Quay lại",
 	"Bad Response": "Trả lời KHÔNG tốt",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "trước",
 	"Being lazy": "Lười biếng",
 	"Bypass SSL verification for Websites": "Bỏ qua xác thực SSL cho các trang web",
 	"Cancel": "Hủy bỏ",
-	"Capabilities": "",
+	"Capabilities": "Năng lực",
 	"Change Password": "Đổi Mật khẩu",
 	"Chat": "Trò chuyện",
 	"Chat Bubble UI": "Bảng chat",
@@ -110,7 +111,7 @@
 	"Copy Link": "Sao chép link",
 	"Copying to clipboard was successful!": "Sao chép vào clipboard thành công!",
 	"Create a concise, 3-5 word phrase as a header for the following query, strictly adhering to the 3-5 word limit and avoiding the use of the word 'title':": "Tạo một cụm từ súc tích, 3-5 từ làm tiêu đề cho truy vấn sau, tuân thủ nghiêm ngặt giới hạn 3-5 từ và tránh sử dụng từ 'tiêu đề':",
-	"Create a model": "",
+	"Create a model": "Tạo model",
 	"Create Account": "Tạo Tài khoản",
 	"Create new key": "Tạo key mới",
 	"Create new secret key": "Tạo key bí mật mới",
@@ -119,7 +120,7 @@
 	"Current Model": "Mô hình hiện tại",
 	"Current Password": "Mật khẩu hiện tại",
 	"Custom": "Tùy chỉnh",
-	"Customize models for a specific purpose": "",
+	"Customize models for a specific purpose": "Tùy chỉnh model cho những mục đích riêng",
 	"Dark": "Tối",
 	"Database": "Cơ sở dữ liệu",
 	"December": "Tháng 12",
@@ -133,17 +134,17 @@
 	"delete": "xóa",
 	"Delete": "Xóa",
 	"Delete a model": "Xóa mô hình",
-	"Delete All Chats": "",
+	"Delete All Chats": "Xóa mọi cuộc Chat",
 	"Delete chat": "Xóa nội dung chat",
 	"Delete Chat": "Xóa chat",
 	"delete this link": "Xóa link này",
 	"Delete User": "Xóa người dùng",
 	"Deleted {{deleteModelTag}}": "Đã xóa {{deleteModelTag}}",
-	"Deleted {{name}}": "",
+	"Deleted {{name}}": "Đã xóa {{name}}",
 	"Description": "Mô tả",
 	"Didn't fully follow instructions": "Không tuân theo chỉ dẫn một cách đầy đủ",
 	"Disabled": "Đã vô hiệu hóa",
-	"Discover a model": "",
+	"Discover a model": "Khám phá model",
 	"Discover a prompt": "Khám phá thêm prompt mới",
 	"Discover, download, and explore custom prompts": "Tìm kiếm, tải về và khám phá thêm các prompt tùy chỉnh",
 	"Discover, download, and explore model presets": "Tìm kiếm, tải về và khám phá thêm các thiết lập mô hình sẵn",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "Nhập Họ và Tên của bạn",
 	"Enter Your Password": "Nhập Mật khẩu của bạn",
 	"Enter Your Role": "Nhập vai trò của bạn",
+	"Error": "Lỗi",
 	"Experimental": "Thử nghiệm",
 	"Export All Chats (All Users)": "Tải về tất cả nội dung chat (tất cả mọi người)",
 	"Export Chats": "Tải nội dung chat về máy",
@@ -214,7 +216,7 @@
 	"Good Response": "Trả lời tốt",
 	"h:mm a": "h:mm a",
 	"has no conversations.": "không có hội thoại",
-	"Hello, {{name}}": "Xin chào, {{name}}",
+	"Hello, {{name}}": "Xin chào {{name}}",
 	"Help": "Trợ giúp",
 	"Hide": "Ẩn",
 	"How can I help you today?": "Tôi có thể giúp gì cho bạn hôm nay?",
@@ -225,9 +227,10 @@
 	"Images": "Hình ảnh",
 	"Import Chats": "Nạp lại nội dung chat",
 	"Import Documents Mapping": "Nạp cấu trúc tài liệu",
-	"Import Models": "",
+	"Import Models": "Nạp model",
 	"Import Prompts": "Nạp các prompt lên hệ thống",
 	"Include `--api` flag when running stable-diffusion-webui": "Bao gồm flag `--api` khi chạy stable-diffusion-webui",
+	"Info": "Thông tin",
 	"Input commands": "Nhập các câu lệnh",
 	"Interface": "Giao diện",
 	"Invalid Tag": "Tag không hợp lệ",
@@ -279,8 +282,8 @@
 	"More": "Thêm",
 	"Name": "Tên",
 	"Name Tag": "Tên Thẻ",
-	"Name your model": "",
-	"New Chat": "Tạo cuộc trò chuyện mới",
+	"Name your model": "Tên model",
+	"New Chat": "Tạo chat mới",
 	"New Password": "Mật khẩu mới",
 	"No results found": "Không tìm thấy kết quả",
 	"No search query generated": "",
@@ -364,16 +367,16 @@
 	"Scan for documents from {{path}}": "Quét tài liệu từ đường dẫn: {{path}}",
 	"Search": "Tìm kiếm",
 	"Search a model": "Tìm model",
-	"Search Chats": "",
+	"Search Chats": "Tìm kiếm các cuộc Chat",
 	"Search Documents": "Tìm tài liệu",
-	"Search Models": "",
+	"Search Models": "Tìm model",
 	"Search Prompts": "Tìm prompt",
 	"Search Results": "",
 	"Searching the web for '{{searchQuery}}'": "",
 	"See readme.md for instructions": "Xem readme.md để biết hướng dẫn",
 	"See what's new": "Xem những cập nhật mới",
 	"Seed": "Seed",
-	"Select a base model": "",
+	"Select a base model": "Chọn một base model",
 	"Select a mode": "Chọn một chế độ",
 	"Select a model": "Chọn mô hình",
 	"Select an Ollama instance": "Chọn một thực thể Ollama",
@@ -422,7 +425,7 @@
 	"System Prompt": "Prompt Hệ thống (System Prompt)",
 	"Tags": "Thẻ",
 	"Tell us more:": "Hãy cho chúng tôi hiểu thêm về chất lượng của câu trả lời:",
-	"Temperature": "Temperature",
+	"Temperature": "Mức độ sáng tạo",
 	"Template": "Mẫu",
 	"Text Completion": "Hoàn tất Văn bản",
 	"Text-to-Speech Engine": "Công cụ Chuyển Văn bản thành Giọng nói",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Gặp vấn đề khi truy cập Ollama?",
 	"TTS Settings": "Cài đặt Chuyển văn bản thành Giọng nói",
+	"Type": "Kiểu",
 	"Type Hugging Face Resolve (Download) URL": "Nhập URL Hugging Face Resolve (Tải xuống)",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Ồ! Đã xảy ra sự cố khi kết nối với {{provider}}.",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Loại Tệp Không xác định '{{file_type}}', nhưng đang chấp nhận và xử lý như văn bản thô",
@@ -470,6 +474,7 @@
 	"variable": "biến",
 	"variable to have them replaced with clipboard content.": "biến để có chúng được thay thế bằng nội dung clipboard.",
 	"Version": "Version",
+	"Warning": "Cảnh báo",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Cảnh báo: Nếu cập nhật hoặc thay đổi embedding model, bạn sẽ cần cập nhật lại tất cả tài liệu.",
 	"Web": "Web",
 	"Web Loader Settings": "Cài đặt Web Loader",
@@ -488,7 +493,7 @@
 	"Write a summary in 50 words that summarizes [topic or keyword].": "Viết một tóm tắt trong vòng 50 từ cho [chủ đề hoặc từ khóa].",
 	"Yesterday": "Hôm qua",
 	"You": "Bạn",
-	"You cannot clone a base model": "",
+	"You cannot clone a base model": "Bạn không thể nhân bản base model",
 	"You have no archived conversations.": "Bạn chưa lưu trữ một nội dung chat nào",
 	"You have shared this chat": "Bạn vừa chia sẻ chat này",
 	"You're a helpful assistant.": "Bạn là một trợ lý hữu ích.",

+ 5 - 0
src/lib/i18n/locales/zh-CN/translation.json

@@ -63,6 +63,7 @@
 	"available!": "可用!",
 	"Back": "返回",
 	"Bad Response": "不良响应",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "之前",
 	"Being lazy": "懒惰",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "输入您的全名",
 	"Enter Your Password": "输入您的密码",
 	"Enter Your Role": "输入您的角色",
+	"Error": "",
 	"Experimental": "实验性",
 	"Export All Chats (All Users)": "导出所有聊天(所有用户)",
 	"Export Chats": "导出聊天",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "导入提示",
 	"Include `--api` flag when running stable-diffusion-webui": "运行 stable-diffusion-webui 时包含 `--api` 标志",
+	"Info": "",
 	"Input commands": "输入命令",
 	"Interface": "界面",
 	"Invalid Tag": "无效标签",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "访问 Ollama 时遇到问题?",
 	"TTS Settings": "文本转语音设置",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "输入 Hugging Face 解析(下载)URL",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "哎呀!连接到{{provider}}时出现问题。",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "未知文件类型'{{file_type}}',将视为纯文本进行处理",
@@ -470,6 +474,7 @@
 	"variable": "变量",
 	"variable to have them replaced with clipboard content.": "变量将被剪贴板内容替换。",
 	"Version": "版本",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "警告: 如果更新或更改 embedding 模型,则需要重新导入所有文档。",
 	"Web": "网页",
 	"Web Loader Settings": "Web 加载器设置",

+ 5 - 0
src/lib/i18n/locales/zh-TW/translation.json

@@ -63,6 +63,7 @@
 	"available!": "可以使用!",
 	"Back": "返回",
 	"Bad Response": "錯誤回應",
+	"Banners": "",
 	"Base Model (From)": "",
 	"before": "前",
 	"Being lazy": "懶人模式",
@@ -188,6 +189,7 @@
 	"Enter Your Full Name": "輸入你的全名",
 	"Enter Your Password": "輸入你的密碼",
 	"Enter Your Role": "輸入你的角色",
+	"Error": "",
 	"Experimental": "實驗功能",
 	"Export All Chats (All Users)": "匯出所有聊天紀錄(所有使用者)",
 	"Export Chats": "匯出聊天紀錄",
@@ -228,6 +230,7 @@
 	"Import Models": "",
 	"Import Prompts": "匯入提示詞",
 	"Include `--api` flag when running stable-diffusion-webui": "在運行 stable-diffusion-webui 時加上 `--api` 標誌",
+	"Info": "",
 	"Input commands": "輸入命令",
 	"Interface": "介面",
 	"Invalid Tag": "無效標籤",
@@ -450,6 +453,7 @@
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "存取 Ollama 時遇到問題?",
 	"TTS Settings": "文字轉語音設定",
+	"Type": "",
 	"Type Hugging Face Resolve (Download) URL": "輸入 Hugging Face 解析後的(下載)URL",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "哎呀!連線到 {{provider}} 時出現問題。",
 	"Unknown File Type '{{file_type}}', but accepting and treating as plain text": "未知的文件類型 '{{file_type}}',但接受並視為純文字",
@@ -470,6 +474,7 @@
 	"variable": "變數",
 	"variable to have them replaced with clipboard content.": "變數將替換為剪貼簿內容",
 	"Version": "版本",
+	"Warning": "",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "警告:如果更新或更改你的嵌入模型,則需要重新導入所有文件",
 	"Web": "網頁",
 	"Web Loader Settings": "Web 載入器設定",

+ 18 - 10
src/lib/stores/index.ts

@@ -1,6 +1,7 @@
 import { APP_NAME } from '$lib/constants';
 import { type Writable, writable } from 'svelte/store';
 import type { GlobalModelConfig, ModelConfig } from '$lib/apis';
+import type { Banner } from '$lib/types';
 
 // Backend
 export const WEBUI_NAME = writable(APP_NAME);
@@ -36,6 +37,8 @@ export const documents = writable([
 	}
 ]);
 
+export const banners: Writable<Banner[]> = writable([]);
+
 export const settings: Writable<Settings> = writable({});
 
 export const showSidebar = writable(false);
@@ -126,16 +129,21 @@ type Prompt = {
 };
 
 type Config = {
-	status?: boolean;
-	name?: string;
-	version?: string;
-	default_locale?: string;
-	images?: boolean;
-	default_models?: string[];
-	default_prompt_suggestions?: PromptSuggestion[];
-	auth_trusted_header?: boolean;
-	model_config?: GlobalModelConfig;
-	enable_websearch?: boolean;
+	status: boolean;
+	name: string;
+	version: string;
+	default_locale: string;
+	default_models: string[];
+	default_prompt_suggestions: PromptSuggestion[];
+	features: {
+		auth: boolean;
+		auth_trusted_header: boolean;
+    enable_signup: boolean;
+    enable_websearch?: boolean;
+		enable_image_generation: boolean;
+		enable_admin_export: boolean;
+		enable_community_sharing: boolean;
+	};
 };
 
 type PromptSuggestion = {

+ 9 - 0
src/lib/types/index.ts

@@ -0,0 +1,9 @@
+export type Banner = {
+	id: string;
+	type: string;
+	title?: string;
+	content: string;
+	url?: string;
+	dismissible?: boolean;
+	timestamp: number;
+};

+ 13 - 1
src/routes/(app)/+layout.svelte

@@ -22,6 +22,7 @@
 		prompts,
 		documents,
 		tags,
+		banners,
 		showChangelog,
 		config
 	} from '$lib/stores';
@@ -33,6 +34,8 @@
 	import ShortcutsModal from '$lib/components/chat/ShortcutsModal.svelte';
 	import ChangelogModal from '$lib/components/ChangelogModal.svelte';
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
+	import { getBanners } from '$lib/apis/configs';
+	import { getUserSettings } from '$lib/apis/users';
 
 	const i18n = getContext('i18n');
 
@@ -70,7 +73,13 @@
 				// IndexedDB Not Found
 			}
 
-			settings.set(JSON.parse(localStorage.getItem('settings') ?? '{}'));
+			const userSettings = await getUserSettings(localStorage.token);
+
+			if (userSettings) {
+				await settings.set(userSettings.ui);
+			} else {
+				await settings.set(JSON.parse(localStorage.getItem('settings') ?? '{}'));
+			}
 
 			await Promise.all([
 				(async () => {
@@ -82,6 +91,9 @@
 				(async () => {
 					documents.set(await getDocs(localStorage.token));
 				})(),
+				(async () => {
+					banners.set(await getBanners(localStorage.token));
+				})(),
 				(async () => {
 					tags.set(await getAllChatTags(localStorage.token));
 				})()

+ 3 - 3
src/routes/auth/+page.svelte

@@ -60,7 +60,7 @@
 			await goto('/');
 		}
 		loaded = true;
-		if (($config?.auth_trusted_header ?? false) || $config?.auth === false) {
+		if (($config?.features.auth_trusted_header ?? false) || $config?.features.auth === false) {
 			await signInHandler();
 		}
 	});
@@ -102,7 +102,7 @@
 		</div> -->
 
 		<div class="w-full sm:max-w-md px-10 min-h-screen flex flex-col text-center">
-			{#if ($config?.auth_trusted_header ?? false) || $config?.auth === false}
+			{#if ($config?.features.auth_trusted_header ?? false) || $config?.features.auth === false}
 				<div class=" my-auto pb-10 w-full">
 					<div
 						class="flex items-center justify-center gap-3 text-xl sm:text-2xl text-center font-bold dark:text-gray-200"
@@ -194,7 +194,7 @@
 								{mode === 'signin' ? $i18n.t('Sign in') : $i18n.t('Create Account')}
 							</button>
 
-							{#if $config.enable_signup}
+							{#if $config?.features.enable_signup}
 								<div class=" mt-4 text-sm text-center">
 									{mode === 'signin'
 										? $i18n.t("Don't have an account?")

+ 0 - 6
src/routes/s/[id]/+page.svelte

@@ -98,12 +98,6 @@
 						: convertMessagesToHistory(chatContent.messages);
 				title = chatContent.title;
 
-				let _settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
-				await settings.set({
-					..._settings,
-					system: chatContent.system ?? _settings.system,
-					options: chatContent.options ?? _settings.options
-				});
 				autoScroll = true;
 				await tick();
 

+ 2 - 1
vite.config.ts

@@ -18,7 +18,8 @@ import { defineConfig } from 'vite';
 export default defineConfig({
 	plugins: [sveltekit()],
 	define: {
-		APP_VERSION: JSON.stringify(process.env.npm_package_version)
+		APP_VERSION: JSON.stringify(process.env.npm_package_version),
+		APP_BUILD_HASH: JSON.stringify(process.env.APP_BUILD_HASH || 'dev-build')
 	},
 	build: {
 		sourcemap: true