Skip to content

Commit f966935

Browse files
authored
Merge pull request open-webui#15448 from open-webui/dev
0.6.16
2 parents 5eca495 + 045984e commit f966935

File tree

311 files changed

+16954
-7362
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

311 files changed

+16954
-7362
lines changed

CHANGELOG.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,65 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.6.16] - 2025-07-14
9+
10+
### Added
11+
12+
- 🗂️ **Folders as Projects**: Organize your workflow with folder-based projects—set folder-level system prompts and associate custom knowledge, bringing seamless, context-rich management to teams and users handling multiple initiatives or clients.
13+
- 📁 **Instant Folder-Based Chat Creation**: Start a new chat directly from any folder; just click and your new conversation is automatically embedded in the right project context—no more manual dragging or setup, saving time and eliminating mistakes.
14+
- 🧩 **Prompt Variables with Automatic Input Modal**: Prompts containing variables now display a clean, auto-generated input modal that **autofocuses on the first field** for instant value entry—just select the prompt and fill in exactly what’s needed, reducing friction and guesswork.
15+
- 🔡 **Variable Input Typing in Prompts**: Define input types for prompt variables (e.g., text, textarea, number, select, color, date, map and more), giving everyone a clearer and more precise prompt-building experience for advanced automation or workflows.
16+
- 🚀 **Base Model List Caching**: Cache your base model list to speed up model selection and reduce repeated API calls; toggle this in Admin Settings > Connections for responsive model management even in large or multi-provider setups.
17+
- ⏱️ **Configurable Model List Cache TTL**: Take control over model list caching with the new MODEL_LIST_CACHE_TTL environment variable. Set a custom cache duration in seconds to balance performance and freshness, reducing API requests in stable environments or ensuring rapid updates when models change frequently.
18+
- 🔖 **Reference Notes as Knowledge or in Chats**: Use any note as knowledge for a model or folder, or reference it directly from chat—integrate living documentation into your Retrieval Augmented Generation workflows or discussions, bridging knowledge and action.
19+
- 📝 **Chat Directly with Notes (Experimental)**: Ask questions about any note, and directly edit or update notes from within a chat—unlock direct AI-powered brainstorming, summarization, and cleanup, like having your own collaborative AI canvas.
20+
- 🤝 **Collaborative Notes with Multi-User Editing**: Share notes with others and collaborate live—multiple users can edit a note in real-time, boosting cooperative knowledge building and workflow documentation.
21+
- 🛡️ **Collaborative Note Permissions**: Control who can view or edit each note with robust sharing permissions, ensuring privacy or collaboration per your organizational needs.
22+
- 🔗 **Copy Link to Notes**: Quickly copy and share direct links to notes for easier knowledge transfer within your team or external collaborators.
23+
- 📋 **Task List Support in Notes**: Add, organize, and manage checklists or tasks inside your notes—plan projects, track to-dos, and keep everything actionable in a single space.
24+
- 🧠 **AI-Generated Note Titles**: Instantly generate relevant and concise titles for your notes using AI—keep your knowledge library organized without tedious manual editing.
25+
- 🔄 **Full Undo/Redo Support in Notes**: Effortlessly undo or redo your latest note changes—never fear mistakes or accidental edits while collaborating or writing.
26+
- 📝 **Enhanced Note Word/Character Counter**: Always know the size of your notes with built-in counters, making it easier to adhere to length guidelines for shared or published content.
27+
- 🖊️ **Floating & Bubble Formatting Menus in Note Editor**: Access text formatting tools through both a floating menu and an intuitive bubble menu directly in the note editor—making rich text editing faster, more discoverable, and easier than ever.
28+
- ✍️ **Rich Text Prompt Insertion**: A new setting allows prompts to be inserted directly into the chat box as fully-formatted rich text, preserving Markdown elements like headings, lists, and bold text for a more intuitive and visually consistent editing experience.
29+
- 🌐 **Configurable Database URL**: WebUI now supports more flexible database configuration via new environment variables—making deployment and scaling simpler across various infrastructure setups.
30+
- 🎛️ **Completely Frontend-Handled File Upload in Temporary Chats**: When using temporary chats, file extraction now occurs fully in your browser with zero files sent to the backend, further strengthening privacy and giving you instant feedback.
31+
- 🔄 **Enhanced Banner and Chat Command Visibility**: Banner handling and command feedback in chat are now clearer and more contextually visible, making alerts, suggestions, and automation easier to spot and interact with for all users.
32+
- 📱 **Mobile Experience Polished**: The "new chat" button is back in mobile, plus core navigation and input controls have been smoothed out for better usability on phones and tablets.
33+
- 📄 **OpenDocument Text (.odt) Support**: Seamlessly upload and process .odt files from open-source office suites like LibreOffice and OpenOffice, expanding your ability to build knowledge from a wider range of document formats.
34+
- 📑 **Enhanced Markdown Document Splitting**: Improve knowledge retrieval from Markdown files with a new header-aware splitting strategy. This method intelligently chunks documents based on their header structure, preserving the original context and hierarchy for more accurate and relevant RAG results.
35+
- 📚 **Full Context Mode for Knowledge Bases**: When adding a knowledge base to a folder or custom model, you can now toggle full context mode for the entire knowledge base. This bypasses the usual chunking and retrieval process, making it perfect for leaner knowledge bases.
36+
- 🕰️ **Configurable OAuth Timeout**: Enhance login reliability by setting a custom timeout (OAUTH_TIMEOUT) for all OAuth providers (Google, Microsoft, GitHub, OIDC), preventing authentication failures on slow or restricted networks.
37+
- 🎨 **Accessibility & High-Contrast Theme Enhancements**: Major accessibility overhaul with significant updates to the high-contrast theme. Improved focus visibility, ARIA labels, and semantic HTML ensure core components like the chat interface and model selector are fully compliant and readable for visually impaired users.
38+
- ↕️ **Resizable System Prompt Fields**: Conveniently resize system prompt input fields to comfortably view and edit lengthy or complex instructions, improving the user experience for advanced model configuration.
39+
- 🔧 **Granular Update Check Control**: Gain finer control over outbound connections with the new ENABLE_VERSION_UPDATE_CHECK flag. This allows administrators to disable version update checks independently of the full OFFLINE_MODE, perfect for environments with restricted internet access that still need to download embedding models.
40+
- 🗃️ **Configurable Qdrant Collection Prefix**: Enhance scalability by setting a custom QDRANT_COLLECTION_PREFIX. This allows multiple Open WebUI instances to share a single Qdrant cluster safely, ensuring complete data isolation between separate deployments without conflicts.
41+
- ⚙️ **Improved Default Database Performance**: Enhanced out-of-the-box performance by setting smarter database connection pooling defaults, reducing API response times for users on non-SQLite databases without requiring manual configuration.
42+
- 🔧 **Configurable Redis Key Prefix**: Added support for the REDIS_KEY_PREFIX environment variable, allowing multiple Open WebUI instances to share a Redis cluster with isolated key namespaces for improved multi-tenancy.
43+
- ➡️ **Forward User Context to Reranker**: For advanced RAG integrations, user information (ID, name, email, role) can now be forwarded as HTTP headers to external reranking services, enabling personalized results or per-user access control.
44+
- ⚙️ **PGVector Connection Pooling**: Enhance performance and stability for PGVector-based RAG by enabling and configuring the database connection pool. New environment variables allow fine-tuning of pool size, timeout, and overflow settings to handle high-concurrency workloads efficiently.
45+
- ⚙️ **General Backend Refactoring**: Extensive refactoring delivers a faster, more reliable, and robust backend experience—improving chat speed, model management, and day-to-day reliability.
46+
- 🌍 **Expanded & Improved Translations**: Enjoy a more accessible and intuitive experience thanks to comprehensive updates and enhancements for Chinese (Simplified and Traditional), German, French, Catalan, Irish, and Spanish translations throughout the interface.
47+
48+
### Fixed
49+
50+
- 🛠️ **Rich Text Input Stability and Performance**: Multiple improvements ensure faster, cleaner text editing and rendering with reduced glitches—especially supporting links, color picking, checkbox controls, and code blocks in notes and chats.
51+
- 📷 **Seamless iPhone Image Uploads**: Effortlessly upload photos from iPhones and other devices using HEIC format—images are now correctly recognized and processed, eliminating compatibility issues.
52+
- 🔄 **Audio MIME Type Registration**: Issues with audio file content types have been resolved, guaranteeing smoother, error-free uploads and playback for transcription or note attachments.
53+
- 🖍️ **Input Commands Now Always Visible**: Input commands (like prompts or knowledge) dynamically adjust their height on small screens, ensuring nothing is cut off and every tool remains easily accessible.
54+
- 🛑 **Tool Result Rendering**: Fixed display problems with tool results, providing fast, clear feedback when using external or internal tools.
55+
- 🗂️ **Table Alignment in Markdown**: Markdown tables are now rendered and aligned as expected, keeping reports and documentation readable.
56+
- 🖼️ **Thread Image Handling**: Fixed an issue where messages containing only images in threads weren’t displayed correctly.
57+
- 🗝️ **Note Access Control Security**: Tightened access control logic for notes to guarantee that shared or collaborative notes respect all user permissions and privacy safeguards.
58+
- 🧾 **Ollama API Compatibility**: Fixed model parameter naming in the API to ensure uninterrupted compatibility for all Ollama endpoints.
59+
- 🛠️ **Detection for 'text/html' Files**: Files loaded with docling/tika are now reliably detected as the correct type, improving knowledge ingestion and document parsing.
60+
- 🔐 **OAuth Login Stability**: Resolved a critical OAuth bug that caused login failures on subsequent attempts after logging out. The user session is now completely cleared on logout, ensuring reliable and secure authentication across all supported providers (Google, Microsoft, GitHub, OIDC).
61+
- 🚪 **OAuth Logout and Redirect Reliability**: The OAuth logout process has been made more robust. Logout requests now correctly use proxy environment variables, ensuring they succeed in corporate networks. Additionally, the custom WEBUI_AUTH_SIGNOUT_REDIRECT_URL is now properly respected for all OAuth/OIDC configurations, ensuring a seamless sign-out experience.
62+
- 📜 **Banner Newline Rendering**: Banners now correctly render newline characters, ensuring that multi-line announcements and messages are displayed with their intended formatting.
63+
- ℹ️ **Consistent Model Description Rendering**: Model descriptions now render Markdown correctly in the main chat interface, matching the formatting seen in the model selection dropdown for a consistent user experience.
64+
- 🔄 **Offline Mode Update Check Display**: Corrected a UI bug where the "Checking for Updates..." message would display indefinitely when the application was set to offline mode.
65+
- 🛠️ **Tool Result Encoding**: Fixed a bug where tool calls returning non-ASCII characters would fail, ensuring robust handling of international text and special characters in tool outputs.
66+
867
## [0.6.15] - 2025-06-16
968

1069
### Added

backend/open_webui/config.py

Lines changed: 99 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@
1313
import requests
1414
from pydantic import BaseModel
1515
from sqlalchemy import JSON, Column, DateTime, Integer, func
16+
from authlib.integrations.starlette_client import OAuth
17+
1618

1719
from open_webui.env import (
1820
DATA_DIR,
1921
DATABASE_URL,
2022
ENV,
2123
REDIS_URL,
24+
REDIS_KEY_PREFIX,
2225
REDIS_SENTINEL_HOSTS,
2326
REDIS_SENTINEL_PORT,
2427
FRONTEND_BUILD_DIR,
@@ -211,11 +214,16 @@ def save(self):
211214
class AppConfig:
212215
_state: dict[str, PersistentConfig]
213216
_redis: Optional[redis.Redis] = None
217+
_redis_key_prefix: str
214218

215219
def __init__(
216-
self, redis_url: Optional[str] = None, redis_sentinels: Optional[list] = []
220+
self,
221+
redis_url: Optional[str] = None,
222+
redis_sentinels: Optional[list] = [],
223+
redis_key_prefix: str = "open-webui",
217224
):
218225
super().__setattr__("_state", {})
226+
super().__setattr__("_redis_key_prefix", redis_key_prefix)
219227
if redis_url:
220228
super().__setattr__(
221229
"_redis",
@@ -230,7 +238,7 @@ def __setattr__(self, key, value):
230238
self._state[key].save()
231239

232240
if self._redis:
233-
redis_key = f"open-webui:config:{key}"
241+
redis_key = f"{self._redis_key_prefix}:config:{key}"
234242
self._redis.set(redis_key, json.dumps(self._state[key].value))
235243

236244
def __getattr__(self, key):
@@ -239,7 +247,7 @@ def __getattr__(self, key):
239247

240248
# If Redis is available, check for an updated value
241249
if self._redis:
242-
redis_key = f"open-webui:config:{key}"
250+
redis_key = f"{self._redis_key_prefix}:config:{key}"
243251
redis_value = self._redis.get(redis_key)
244252

245253
if redis_value is not None:
@@ -431,6 +439,12 @@ def __getattr__(self, key):
431439
os.environ.get("OAUTH_SCOPES", "openid email profile"),
432440
)
433441

442+
OAUTH_TIMEOUT = PersistentConfig(
443+
"OAUTH_TIMEOUT",
444+
"oauth.oidc.oauth_timeout",
445+
os.environ.get("OAUTH_TIMEOUT", ""),
446+
)
447+
434448
OAUTH_CODE_CHALLENGE_METHOD = PersistentConfig(
435449
"OAUTH_CODE_CHALLENGE_METHOD",
436450
"oauth.oidc.code_challenge_method",
@@ -534,13 +548,20 @@ def load_oauth_providers():
534548
OAUTH_PROVIDERS.clear()
535549
if GOOGLE_CLIENT_ID.value and GOOGLE_CLIENT_SECRET.value:
536550

537-
def google_oauth_register(client):
551+
def google_oauth_register(client: OAuth):
538552
client.register(
539553
name="google",
540554
client_id=GOOGLE_CLIENT_ID.value,
541555
client_secret=GOOGLE_CLIENT_SECRET.value,
542556
server_metadata_url="https://accounts.google.com/.well-known/openid-configuration",
543-
client_kwargs={"scope": GOOGLE_OAUTH_SCOPE.value},
557+
client_kwargs={
558+
"scope": GOOGLE_OAUTH_SCOPE.value,
559+
**(
560+
{"timeout": int(OAUTH_TIMEOUT.value)}
561+
if OAUTH_TIMEOUT.value
562+
else {}
563+
),
564+
},
544565
redirect_uri=GOOGLE_REDIRECT_URI.value,
545566
)
546567

@@ -555,14 +576,19 @@ def google_oauth_register(client):
555576
and MICROSOFT_CLIENT_TENANT_ID.value
556577
):
557578

558-
def microsoft_oauth_register(client):
579+
def microsoft_oauth_register(client: OAuth):
559580
client.register(
560581
name="microsoft",
561582
client_id=MICROSOFT_CLIENT_ID.value,
562583
client_secret=MICROSOFT_CLIENT_SECRET.value,
563584
server_metadata_url=f"{MICROSOFT_CLIENT_LOGIN_BASE_URL.value}/{MICROSOFT_CLIENT_TENANT_ID.value}/v2.0/.well-known/openid-configuration?appid={MICROSOFT_CLIENT_ID.value}",
564585
client_kwargs={
565586
"scope": MICROSOFT_OAUTH_SCOPE.value,
587+
**(
588+
{"timeout": int(OAUTH_TIMEOUT.value)}
589+
if OAUTH_TIMEOUT.value
590+
else {}
591+
),
566592
},
567593
redirect_uri=MICROSOFT_REDIRECT_URI.value,
568594
)
@@ -575,7 +601,7 @@ def microsoft_oauth_register(client):
575601

576602
if GITHUB_CLIENT_ID.value and GITHUB_CLIENT_SECRET.value:
577603

578-
def github_oauth_register(client):
604+
def github_oauth_register(client: OAuth):
579605
client.register(
580606
name="github",
581607
client_id=GITHUB_CLIENT_ID.value,
@@ -584,7 +610,14 @@ def github_oauth_register(client):
584610
authorize_url="https://github.com/login/oauth/authorize",
585611
api_base_url="https://api.github.com",
586612
userinfo_endpoint="https://api.github.com/user",
587-
client_kwargs={"scope": GITHUB_CLIENT_SCOPE.value},
613+
client_kwargs={
614+
"scope": GITHUB_CLIENT_SCOPE.value,
615+
**(
616+
{"timeout": int(OAUTH_TIMEOUT.value)}
617+
if OAUTH_TIMEOUT.value
618+
else {}
619+
),
620+
},
588621
redirect_uri=GITHUB_CLIENT_REDIRECT_URI.value,
589622
)
590623

@@ -600,9 +633,12 @@ def github_oauth_register(client):
600633
and OPENID_PROVIDER_URL.value
601634
):
602635

603-
def oidc_oauth_register(client):
636+
def oidc_oauth_register(client: OAuth):
604637
client_kwargs = {
605638
"scope": OAUTH_SCOPES.value,
639+
**(
640+
{"timeout": int(OAUTH_TIMEOUT.value)} if OAUTH_TIMEOUT.value else {}
641+
),
606642
}
607643

608644
if (
@@ -895,6 +931,18 @@ def oidc_oauth_register(client):
895931
pass
896932
OPENAI_API_BASE_URL = "https://api.openai.com/v1"
897933

934+
935+
####################################
936+
# MODELS
937+
####################################
938+
939+
ENABLE_BASE_MODELS_CACHE = PersistentConfig(
940+
"ENABLE_BASE_MODELS_CACHE",
941+
"models.base_models_cache",
942+
os.environ.get("ENABLE_BASE_MODELS_CACHE", "False").lower() == "true",
943+
)
944+
945+
898946
####################################
899947
# TOOL_SERVERS
900948
####################################
@@ -1794,11 +1842,12 @@ class BannerModel(BaseModel):
17941842
QDRANT_URI = os.environ.get("QDRANT_URI", None)
17951843
QDRANT_API_KEY = os.environ.get("QDRANT_API_KEY", None)
17961844
QDRANT_ON_DISK = os.environ.get("QDRANT_ON_DISK", "false").lower() == "true"
1797-
QDRANT_PREFER_GRPC = os.environ.get("QDRANT_PREFER_GRPC", "False").lower() == "true"
1845+
QDRANT_PREFER_GRPC = os.environ.get("QDRANT_PREFER_GRPC", "false").lower() == "true"
17981846
QDRANT_GRPC_PORT = int(os.environ.get("QDRANT_GRPC_PORT", "6334"))
17991847
ENABLE_QDRANT_MULTITENANCY_MODE = (
1800-
os.environ.get("ENABLE_QDRANT_MULTITENANCY_MODE", "false").lower() == "true"
1848+
os.environ.get("ENABLE_QDRANT_MULTITENANCY_MODE", "true").lower() == "true"
18011849
)
1850+
QDRANT_COLLECTION_PREFIX = os.environ.get("QDRANT_COLLECTION_PREFIX", "open-webui")
18021851

18031852
# OpenSearch
18041853
OPENSEARCH_URI = os.environ.get("OPENSEARCH_URI", "https://localhost:9200")
@@ -1837,6 +1886,45 @@ class BannerModel(BaseModel):
18371886
"PGVECTOR_PGCRYPTO is enabled but PGVECTOR_PGCRYPTO_KEY is not set. Please provide a valid key."
18381887
)
18391888

1889+
1890+
PGVECTOR_POOL_SIZE = os.environ.get("PGVECTOR_POOL_SIZE", None)
1891+
1892+
if PGVECTOR_POOL_SIZE != None:
1893+
try:
1894+
PGVECTOR_POOL_SIZE = int(PGVECTOR_POOL_SIZE)
1895+
except Exception:
1896+
PGVECTOR_POOL_SIZE = None
1897+
1898+
PGVECTOR_POOL_MAX_OVERFLOW = os.environ.get("PGVECTOR_POOL_MAX_OVERFLOW", 0)
1899+
1900+
if PGVECTOR_POOL_MAX_OVERFLOW == "":
1901+
PGVECTOR_POOL_MAX_OVERFLOW = 0
1902+
else:
1903+
try:
1904+
PGVECTOR_POOL_MAX_OVERFLOW = int(PGVECTOR_POOL_MAX_OVERFLOW)
1905+
except Exception:
1906+
PGVECTOR_POOL_MAX_OVERFLOW = 0
1907+
1908+
PGVECTOR_POOL_TIMEOUT = os.environ.get("PGVECTOR_POOL_TIMEOUT", 30)
1909+
1910+
if PGVECTOR_POOL_TIMEOUT == "":
1911+
PGVECTOR_POOL_TIMEOUT = 30
1912+
else:
1913+
try:
1914+
PGVECTOR_POOL_TIMEOUT = int(PGVECTOR_POOL_TIMEOUT)
1915+
except Exception:
1916+
PGVECTOR_POOL_TIMEOUT = 30
1917+
1918+
PGVECTOR_POOL_RECYCLE = os.environ.get("PGVECTOR_POOL_RECYCLE", 3600)
1919+
1920+
if PGVECTOR_POOL_RECYCLE == "":
1921+
PGVECTOR_POOL_RECYCLE = 3600
1922+
else:
1923+
try:
1924+
PGVECTOR_POOL_RECYCLE = int(PGVECTOR_POOL_RECYCLE)
1925+
except Exception:
1926+
PGVECTOR_POOL_RECYCLE = 3600
1927+
18401928
# Pinecone
18411929
PINECONE_API_KEY = os.environ.get("PINECONE_API_KEY", None)
18421930
PINECONE_ENVIRONMENT = os.environ.get("PINECONE_ENVIRONMENT", None)

0 commit comments

Comments
 (0)