Skip to content

Commit b249809

Browse files
authored
Merge pull request open-webui#15738 from open-webui/dev
0.6.17
2 parents 2470da8 + a01e512 commit b249809

File tree

144 files changed

+6821
-3566
lines changed

Some content is hidden

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

144 files changed

+6821
-3566
lines changed

.github/workflows/format-build-frontend.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
node-version: '22'
3333

3434
- name: Install Dependencies
35-
run: npm install
35+
run: npm install --force
3636

3737
- name: Format Frontend
3838
run: npm run format
@@ -59,7 +59,7 @@ jobs:
5959
node-version: '22'
6060

6161
- name: Install Dependencies
62-
run: npm ci
62+
run: npm ci --force
6363

6464
- name: Run vitest
6565
run: npm run test:frontend

CHANGELOG.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,53 @@ 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.17] - 2025-07-19
9+
10+
### Added
11+
12+
- 📂 **Dedicated Folder View with Chat List**: Clicking a folder now reveals a brand-new landing page showcasing a list of all chats within that folder, making navigation simpler and giving teams immediate visibility into project-specific conversations.
13+
- 🆕 **Streamlined Folder Creation Modal**: Creating a new folder is now a seamless, unified experience with a dedicated modal that visually and functionally matches the edit folder flow, making workspace organization more intuitive and error-free for all users.
14+
- 🗃️ **Direct File Uploads to Folder Knowledge**: You can now upload files straight to a folder’s knowledge—empowering you to enrich project spaces by adding resources and documents directly, without the need to pre-create knowledge bases beforehand.
15+
- 🔎 **Chat Preview in Search**: When searching chats, instantly preview results in context without having to open them—making discovery, auditing, and recall dramatically quicker, especially in large, active teams.
16+
- 🖼️ **Image Upload and Inline Insertion in Notes**: Notes now support inserting images directly among your text, letting you create rich, visually structured documentation, brainstorms, or reports in a more natural and engaging way—no more images just as attachments.
17+
- 📱 **Enhanced Note Selection Editing and Q&A**: Select any portion of your notes to either edit just the highlighted part or ask focused questions about that content—streamlining workflows, boosting productivity, and making reviews or AI-powered enhancements more targeted.
18+
- 📝 **Copy Notes as Rich Text**: Copy entire notes—including all formatting, images, and structure—directly as rich text for seamless pasting into emails, reports, or other tools, maintaining clarity and consistency outside the WebUI.
19+
-**Fade-In Streaming Text Experience**: Live-generated responses now elegantly fade in as the AI streams them, creating a more natural and visually engaging reading experience; easily toggled off in Interface settings if you prefer static displays.
20+
- 🔄 **Settings for Follow-Up Prompts**: Fine-tune your follow-up prompt experience—with new controls, you can choose to keep them visible or have them inserted directly into the message input instead of auto-submitting, giving you more flexibility and control over your workflow.
21+
- 🔗 **Prompt Variable Documentation Quick Link**: Access documentation for prompt variables in one click from the prompt editor modal—shortening the learning curve and making advanced prompt-building more accessible.
22+
- 📈 **Active and Total User Metrics for Telemetry**: Gain valuable insights into usage patterns and platform engagement with new metrics tracking active and total users—enhancing auditability and planning for large organizations.
23+
- 🏷️ **Traceability with Log Trace and Span IDs**: Each log entry now carries detailed trace and span IDs, making it much easier for admins to pinpoint and resolve issues across distributed systems or in complex troubleshooting.
24+
- 👥 **User Group Add/Remove Endpoints**: Effortlessly add or remove users from groups with new, improved endpoints—giving admins and team leads faster, clearer control over collaboration and permissions.
25+
- ⚙️ **Note Settings and Controls Streamlined**: The main “Settings” for notes are now simply called “Controls”, and note files now reside in a dedicated controls section, decluttering navigation and making it easier to find and configure note-related options.
26+
- 🚀 **Faster Admin User Page Loads**: The user list endpoint for admins has been optimized to exclude heavy profile images, speeding up load times for large teams and reducing waiting during administrative tasks.
27+
- 📡 **Chat ID Header Forwarding**: Ollama and OpenAI router requests now include the chat ID in request headers, enabling better request correlation and debugging capabilities across AI model integrations.
28+
- 🧠 **Enhanced Reasoning Tag Processing**: Improved and expanded reasoning tag parsing to handle various tag formats more robustly, including standard XML-style tags and custom delimiters, ensuring better AI reasoning transparency and debugging capabilities.
29+
- 🔐 **OAuth Token Endpoint Authentication Method**: Added configurable OAuth token endpoint authentication method support, providing enhanced flexibility and security options for enterprise OAuth integrations and identity provider compatibility.
30+
- 🛡️ **Redis Sentinel High Availability Support**: Comprehensive Redis Sentinel failover implementation with automatic master discovery, intelligent retry logic for connection failures, and seamless operation during master node outages—eliminating single points of failure and ensuring continuous service availability in production deployments.
31+
- 🌐 **Localization & Internationalization Improvements**: Refined and expanded translations for Simplified Chinese, Traditional Chinese, French, German, Korean, and Polish, ensuring a more fluent and native experience for global users across all supported languages.
32+
33+
### Fixed
34+
35+
- 🏷️ **Hybrid Search Functionality Restored**: Hybrid search now works seamlessly again—enabling more accurate, relevant, and comprehensive knowledge discovery across all RAG-powered workflows.
36+
- 🚦 **Note Chat - Edit Button Disabled During AI Generation**: The edit button when chatting with a note is now disabled while the AI is responding—preventing accidental edits and ensuring workflow clarity during chat sessions.
37+
- 🧹 **Cleaner Database Credentials**: Database connection no longer duplicates ‘@’ in credentials, preventing potential connection issues and ensuring smoother, more reliable integrations.
38+
- 🧑‍💻 **File Deletion Now Removes Related Vector Data**: When files are deleted from storage, they are now purged from the vector database as well, ensuring clean data management and preventing clutter or stale search results.
39+
- 📁 **Files Modal Translation Issues Fixed**: All modal dialog strings—including “Using Entire Document” and “Using Focused Retrieval”—are now fully translated for a more consistent and localized UI experience.
40+
- 🚫 **Drag-and-Drop File Upload Disabled for Unsupported Models**: File upload by drag-and-drop is disabled when using models that do not support attachments—removing confusion and preventing workflow interruptions.
41+
- 🔑 **Ollama Tool Calls Now Reliable**: Fixed issues with Ollama-based tool calls, ensuring uninterrupted AI augmentation and tool use for every chat.
42+
- 📄 **MIME Type Help String Correction**: Cleaned up mimetype help text by removing extraneous characters, providing clearer guidance for file upload configurations.
43+
- 📝 **Note Editor Permission Fix**: Removed unnecessary admin-only restriction from note chat functionality, allowing all authorized users to access note editing features as intended.
44+
- 📋 **Chat Sources Handling Improved**: Fixed sources handling logic to prevent duplicate source assignments in chat messages, ensuring cleaner and more accurate source attribution during conversations.
45+
- 😀 **Emoji Generation Error Handling**: Improved error handling in audio router and fixed metadata structure for emoji generation tasks, preventing crashes and ensuring more reliable emoji generation functionality.
46+
- 🔒 **Folder System Prompt Permission Enforcement**: System prompt fields in folder edit modal are now properly hidden for users without system prompt permissions, ensuring consistent security policy enforcement across all folder management interfaces.
47+
- 🌐 **WebSocket Redis Lock Timeout Type Conversion**: Fixed proper integer type conversion for WebSocket Redis lock timeout configuration with robust error handling, preventing potential configuration errors and ensuring stable WebSocket connections.
48+
- 📦 **PostHog Dependency Added**: Added PostHog 5.4.0 library to resolve ChromaDB compatibility issues, ensuring stable vector database operations and preventing library version conflicts during deployment.
49+
50+
### Changed
51+
52+
- 👀 **Tiptap Editor Upgraded to v3**: The underlying rich text editor has been updated for future-proofing, though some supporting libraries remain on v2 for compatibility. For now, please install dependencies using 'npm install --force' to avoid installation errors.
53+
- 🚫 **Removed Redundant or Unused Strings and Elements**: Miscellaneous unused, duplicate, or obsolete code and translations have been cleaned up to maintain a streamlined and high-performance experience.
54+
855
## [0.6.16] - 2025-07-14
956

1057
### Added

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ WORKDIR /app
3030
RUN apk add --no-cache git
3131

3232
COPY package.json package-lock.json ./
33-
RUN npm ci
33+
RUN npm ci --force
3434

3535
COPY . .
3636
ENV APP_BUILD_HASH=${BUILD_HASH}

LICENSE_HISTORY

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
All code and materials created before commit `60d84a3aae9802339705826e9095e272e3c83623` are subject to the following copyright and license:
2+
3+
Copyright (c) 2023-2025 Timothy Jaeryang Baek
4+
All rights reserved.
5+
6+
Redistribution and use in source and binary forms, with or without
7+
modification, are permitted provided that the following conditions are met:
8+
9+
1. Redistributions of source code must retain the above copyright notice, this
10+
list of conditions and the following disclaimer.
11+
12+
2. Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
16+
3. Neither the name of the copyright holder nor the names of its
17+
contributors may be used to endorse or promote products derived from
18+
this software without specific prior written permission.
19+
20+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30+
31+
All code and materials created before commit `a76068d69cd59568b920dfab85dc573dbbb8f131` are subject to the following copyright and license:
32+
33+
MIT License
34+
35+
Copyright (c) 2023 Timothy Jaeryang Baek
36+
37+
Permission is hereby granted, free of charge, to any person obtaining a copy
38+
of this software and associated documentation files (the "Software"), to deal
39+
in the Software without restriction, including without limitation the rights
40+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
41+
copies of the Software, and to permit persons to whom the Software is
42+
furnished to do so, subject to the following conditions:
43+
44+
The above copyright notice and this permission notice shall be included in all
45+
copies or substantial portions of the Software.
46+
47+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
48+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
49+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
50+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
51+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
52+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
53+
SOFTWARE.

backend/open_webui/config.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,12 @@ def __getattr__(self, key):
445445
os.environ.get("OAUTH_TIMEOUT", ""),
446446
)
447447

448+
OAUTH_TOKEN_ENDPOINT_AUTH_METHOD = PersistentConfig(
449+
"OAUTH_TOKEN_ENDPOINT_AUTH_METHOD",
450+
"oauth.oidc.token_endpoint_auth_method",
451+
os.environ.get("OAUTH_TOKEN_ENDPOINT_AUTH_METHOD", None),
452+
)
453+
448454
OAUTH_CODE_CHALLENGE_METHOD = PersistentConfig(
449455
"OAUTH_CODE_CHALLENGE_METHOD",
450456
"oauth.oidc.code_challenge_method",
@@ -636,6 +642,13 @@ def github_oauth_register(client: OAuth):
636642
def oidc_oauth_register(client: OAuth):
637643
client_kwargs = {
638644
"scope": OAUTH_SCOPES.value,
645+
**(
646+
{
647+
"token_endpoint_auth_method": OAUTH_TOKEN_ENDPOINT_AUTH_METHOD.value
648+
}
649+
if OAUTH_TOKEN_ENDPOINT_AUTH_METHOD.value
650+
else {}
651+
),
639652
**(
640653
{"timeout": int(OAUTH_TIMEOUT.value)} if OAUTH_TIMEOUT.value else {}
641654
),
@@ -676,6 +689,17 @@ def oidc_oauth_register(client: OAuth):
676689

677690
STATIC_DIR = Path(os.getenv("STATIC_DIR", OPEN_WEBUI_DIR / "static")).resolve()
678691

692+
try:
693+
if STATIC_DIR.exists():
694+
for item in STATIC_DIR.iterdir():
695+
if item.is_file() or item.is_symlink():
696+
try:
697+
item.unlink()
698+
except Exception as e:
699+
pass
700+
except Exception as e:
701+
pass
702+
679703
for file_path in (FRONTEND_BUILD_DIR / "static").glob("**/*"):
680704
if file_path.is_file():
681705
target_path = STATIC_DIR / file_path.relative_to(

backend/open_webui/env.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -276,9 +276,6 @@ def parse_section(section):
276276
DATABASE_CRED += f"{DATABASE_USER}"
277277
if DATABASE_PASSWORD:
278278
DATABASE_CRED += f":{DATABASE_PASSWORD}"
279-
if DATABASE_CRED:
280-
DATABASE_CRED += "@"
281-
282279

283280
DB_VARS = {
284281
"db_type": DATABASE_TYPE,
@@ -352,6 +349,15 @@ def parse_section(section):
352349
REDIS_SENTINEL_HOSTS = os.environ.get("REDIS_SENTINEL_HOSTS", "")
353350
REDIS_SENTINEL_PORT = os.environ.get("REDIS_SENTINEL_PORT", "26379")
354351

352+
# Maximum number of retries for Redis operations when using Sentinel fail-over
353+
REDIS_SENTINEL_MAX_RETRY_COUNT = os.environ.get("REDIS_SENTINEL_MAX_RETRY_COUNT", "2")
354+
try:
355+
REDIS_SENTINEL_MAX_RETRY_COUNT = int(REDIS_SENTINEL_MAX_RETRY_COUNT)
356+
if REDIS_SENTINEL_MAX_RETRY_COUNT < 1:
357+
REDIS_SENTINEL_MAX_RETRY_COUNT = 2
358+
except ValueError:
359+
REDIS_SENTINEL_MAX_RETRY_COUNT = 2
360+
355361
####################################
356362
# UVICORN WORKERS
357363
####################################
@@ -450,7 +456,13 @@ def parse_section(section):
450456
WEBSOCKET_MANAGER = os.environ.get("WEBSOCKET_MANAGER", "")
451457

452458
WEBSOCKET_REDIS_URL = os.environ.get("WEBSOCKET_REDIS_URL", REDIS_URL)
453-
WEBSOCKET_REDIS_LOCK_TIMEOUT = os.environ.get("WEBSOCKET_REDIS_LOCK_TIMEOUT", 60)
459+
460+
websocket_redis_lock_timeout = os.environ.get("WEBSOCKET_REDIS_LOCK_TIMEOUT", "60")
461+
462+
try:
463+
WEBSOCKET_REDIS_LOCK_TIMEOUT = int(websocket_redis_lock_timeout)
464+
except ValueError:
465+
WEBSOCKET_REDIS_LOCK_TIMEOUT = 60
454466

455467
WEBSOCKET_SENTINEL_HOSTS = os.environ.get("WEBSOCKET_SENTINEL_HOSTS", "")
456468

backend/open_webui/models/folders.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,15 @@ class FolderForm(BaseModel):
6363

6464
class FolderTable:
6565
def insert_new_folder(
66-
self, user_id: str, name: str, parent_id: Optional[str] = None
66+
self, user_id: str, form_data: FolderForm, parent_id: Optional[str] = None
6767
) -> Optional[FolderModel]:
6868
with get_db() as db:
6969
id = str(uuid.uuid4())
7070
folder = FolderModel(
7171
**{
7272
"id": id,
7373
"user_id": user_id,
74-
"name": name,
74+
**(form_data.model_dump(exclude_unset=True) or {}),
7575
"parent_id": parent_id,
7676
"created_at": int(time.time()),
7777
"updated_at": int(time.time()),

backend/open_webui/models/groups.py

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,14 @@ class GroupForm(BaseModel):
8383
permissions: Optional[dict] = None
8484

8585

86-
class GroupUpdateForm(GroupForm):
86+
class UserIdsForm(BaseModel):
8787
user_ids: Optional[list[str]] = None
8888

8989

90+
class GroupUpdateForm(GroupForm, UserIdsForm):
91+
pass
92+
93+
9094
class GroupTable:
9195
def insert_new_group(
9296
self, user_id: str, form_data: GroupForm
@@ -275,5 +279,53 @@ def sync_groups_by_group_names(self, user_id: str, group_names: list[str]) -> bo
275279
log.exception(e)
276280
return False
277281

282+
def add_users_to_group(
283+
self, id: str, user_ids: Optional[list[str]] = None
284+
) -> Optional[GroupModel]:
285+
try:
286+
with get_db() as db:
287+
group = db.query(Group).filter_by(id=id).first()
288+
if not group:
289+
return None
290+
291+
if not group.user_ids:
292+
group.user_ids = []
293+
294+
for user_id in user_ids:
295+
if user_id not in group.user_ids:
296+
group.user_ids.append(user_id)
297+
298+
group.updated_at = int(time.time())
299+
db.commit()
300+
db.refresh(group)
301+
return GroupModel.model_validate(group)
302+
except Exception as e:
303+
log.exception(e)
304+
return None
305+
306+
def remove_users_from_group(
307+
self, id: str, user_ids: Optional[list[str]] = None
308+
) -> Optional[GroupModel]:
309+
try:
310+
with get_db() as db:
311+
group = db.query(Group).filter_by(id=id).first()
312+
if not group:
313+
return None
314+
315+
if not group.user_ids:
316+
return GroupModel.model_validate(group)
317+
318+
for user_id in user_ids:
319+
if user_id in group.user_ids:
320+
group.user_ids.remove(user_id)
321+
322+
group.updated_at = int(time.time())
323+
db.commit()
324+
db.refresh(group)
325+
return GroupModel.model_validate(group)
326+
except Exception as e:
327+
log.exception(e)
328+
return None
329+
278330

279331
Groups = GroupTable()

backend/open_webui/models/users.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,18 @@ class UserListResponse(BaseModel):
7474
total: int
7575

7676

77+
class UserInfoResponse(BaseModel):
78+
id: str
79+
name: str
80+
email: str
81+
role: str
82+
83+
84+
class UserInfoListResponse(BaseModel):
85+
users: list[UserInfoResponse]
86+
total: int
87+
88+
7789
class UserResponse(BaseModel):
7890
id: str
7991
name: str

backend/open_webui/retrieval/utils.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,9 @@ def get_sources_from_items(
611611
elif item.get("collection_name"):
612612
# Direct Collection Name
613613
collection_names.append(item["collection_name"])
614+
elif item.get("collection_names"):
615+
# Collection Names List
616+
collection_names.extend(item["collection_names"])
614617

615618
# If query_result is None
616619
# Fallback to collection names and vector search the collections

0 commit comments

Comments
 (0)