From 6c0f886cdf4b4249dca29e9340b3b998a7262d61 Mon Sep 17 00:00:00 2001 From: Tim Baek Date: Fri, 6 Feb 2026 02:48:35 +0400 Subject: [PATCH 01/42] refac --- backend/open_webui/env.py | 6 ++++++ backend/open_webui/utils/headers.py | 15 +++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/backend/open_webui/env.py b/backend/open_webui/env.py index 3fc75c72bb..dea5d67870 100644 --- a/backend/open_webui/env.py +++ b/backend/open_webui/env.py @@ -194,6 +194,12 @@ ENABLE_FORWARD_USER_INFO_HEADERS = ( os.environ.get("ENABLE_FORWARD_USER_INFO_HEADERS", "False").lower() == "true" ) +# Header names for user info forwarding (customizable via environment variables) +FORWARD_USER_INFO_HEADER_NAME = os.environ.get("FORWARD_USER_INFO_HEADER_NAME", "X-OpenWebUI-User-Name") +FORWARD_USER_INFO_HEADER_ID = os.environ.get("FORWARD_USER_INFO_HEADER_ID", "X-OpenWebUI-User-Id") +FORWARD_USER_INFO_HEADER_EMAIL = os.environ.get("FORWARD_USER_INFO_HEADER_EMAIL", "X-OpenWebUI-User-Email") +FORWARD_USER_INFO_HEADER_ROLE = os.environ.get("FORWARD_USER_INFO_HEADER_ROLE", "X-OpenWebUI-User-Role") + # Experimental feature, may be removed in future ENABLE_STAR_SESSIONS_MIDDLEWARE = ( os.environ.get("ENABLE_STAR_SESSIONS_MIDDLEWARE", "False").lower() == "true" diff --git a/backend/open_webui/utils/headers.py b/backend/open_webui/utils/headers.py index 3caee50334..cdf5d2d85d 100644 --- a/backend/open_webui/utils/headers.py +++ b/backend/open_webui/utils/headers.py @@ -1,11 +1,18 @@ from urllib.parse import quote +from open_webui.env import ( + FORWARD_USER_INFO_HEADER_NAME, + FORWARD_USER_INFO_HEADER_ID, + FORWARD_USER_INFO_HEADER_EMAIL, + FORWARD_USER_INFO_HEADER_ROLE, +) + def include_user_info_headers(headers, user): return { **headers, - "X-OpenWebUI-User-Name": quote(user.name, safe=" "), - "X-OpenWebUI-User-Id": user.id, - "X-OpenWebUI-User-Email": user.email, - "X-OpenWebUI-User-Role": user.role, + FORWARD_USER_INFO_HEADER_NAME: quote(user.name, safe=" "), + FORWARD_USER_INFO_HEADER_ID: user.id, + FORWARD_USER_INFO_HEADER_EMAIL: user.email, + FORWARD_USER_INFO_HEADER_ROLE: user.role, } From 8e79b3d0bc4903f30e747b663ac818976618c83c Mon Sep 17 00:00:00 2001 From: Tim Baek Date: Fri, 6 Feb 2026 03:03:34 +0400 Subject: [PATCH 02/42] refac --- backend/open_webui/utils/tools.py | 11 +++++++---- src/lib/apis/index.ts | 7 ++++--- src/lib/utils/index.ts | 15 +++++++++------ 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/backend/open_webui/utils/tools.py b/backend/open_webui/utils/tools.py index b2f95a8297..6a55a9536b 100644 --- a/backend/open_webui/utils/tools.py +++ b/backend/open_webui/utils/tools.py @@ -697,9 +697,10 @@ def convert_openapi_to_tool_payload(openapi_spec): "parameters": {"type": "object", "properties": {}, "required": []}, } - # Extract path and query parameters for param in operation.get("parameters", []): - param_name = param["name"] + param_name = param.get("name") + if not param_name: + continue param_schema = param.get("schema", {}) description = param_schema.get("description", "") if not description: @@ -971,8 +972,10 @@ async def execute_tool_server( body_params = {} for param in operation.get("parameters", []): - param_name = param["name"] - param_in = param["in"] + param_name = param.get("name") + if not param_name: + continue + param_in = param.get("in") if param_name in params: if param_in == "path": path_params[param_name] = params[param_name] diff --git a/src/lib/apis/index.ts b/src/lib/apis/index.ts index 8f35fbf881..92c28e1d9d 100644 --- a/src/lib/apis/index.ts +++ b/src/lib/apis/index.ts @@ -449,8 +449,9 @@ export const executeToolServer = async ( if (operation.parameters) { operation.parameters.forEach((param: any) => { - const paramName = param.name; - const paramIn = param.in; + const paramName = param?.name; + if (!paramName) return; + const paramIn = param?.in; if (params.hasOwnProperty(paramName)) { if (paramIn === 'path') { pathParams[paramName] = params[paramName]; @@ -1674,7 +1675,7 @@ export interface ModelMeta { profile_image_url?: string; } -export interface ModelParams {} +export interface ModelParams { } export type GlobalModelConfig = ModelConfig[]; diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 3577eb0045..c4046f05d2 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -1277,17 +1277,20 @@ export const convertOpenApiToToolPayload = (openApiSpec) => { // Extract path and query parameters if (operation.parameters) { operation.parameters.forEach((param) => { - let description = param.schema.description || param.description || ''; - if (param.schema.enum && Array.isArray(param.schema.enum)) { - description += `. Possible values: ${param.schema.enum.join(', ')}`; + const paramName = param?.name; + if (!paramName) return; + const paramSchema = param?.schema ?? {}; + let description = paramSchema.description || param.description || ''; + if (paramSchema.enum && Array.isArray(paramSchema.enum)) { + description += `. Possible values: ${paramSchema.enum.join(', ')}`; } - tool.parameters.properties[param.name] = { - type: param.schema.type, + tool.parameters.properties[paramName] = { + type: paramSchema.type, description: description }; if (param.required) { - tool.parameters.required.push(param.name); + tool.parameters.required.push(paramName); } }); } From 2c37daef86a058e370151ecead17f10078102307 Mon Sep 17 00:00:00 2001 From: Tim Baek Date: Fri, 6 Feb 2026 03:23:37 +0400 Subject: [PATCH 03/42] refac --- backend/open_webui/env.py | 11 +++++++---- backend/open_webui/retrieval/web/external.py | 3 ++- backend/open_webui/retrieval/web/yandex.py | 3 ++- backend/open_webui/routers/ollama.py | 3 ++- backend/open_webui/routers/openai.py | 3 ++- backend/open_webui/utils/headers.py | 16 ++++++++-------- backend/open_webui/utils/middleware.py | 9 +++++++++ backend/open_webui/utils/tools.py | 10 ++++++++++ 8 files changed, 42 insertions(+), 16 deletions(-) diff --git a/backend/open_webui/env.py b/backend/open_webui/env.py index dea5d67870..4289475c04 100644 --- a/backend/open_webui/env.py +++ b/backend/open_webui/env.py @@ -195,10 +195,13 @@ ENABLE_FORWARD_USER_INFO_HEADERS = ( ) # Header names for user info forwarding (customizable via environment variables) -FORWARD_USER_INFO_HEADER_NAME = os.environ.get("FORWARD_USER_INFO_HEADER_NAME", "X-OpenWebUI-User-Name") -FORWARD_USER_INFO_HEADER_ID = os.environ.get("FORWARD_USER_INFO_HEADER_ID", "X-OpenWebUI-User-Id") -FORWARD_USER_INFO_HEADER_EMAIL = os.environ.get("FORWARD_USER_INFO_HEADER_EMAIL", "X-OpenWebUI-User-Email") -FORWARD_USER_INFO_HEADER_ROLE = os.environ.get("FORWARD_USER_INFO_HEADER_ROLE", "X-OpenWebUI-User-Role") +FORWARD_USER_INFO_HEADER_USER_NAME = os.environ.get("FORWARD_USER_INFO_HEADER_USER_NAME", "X-OpenWebUI-User-Name") +FORWARD_USER_INFO_HEADER_USER_ID = os.environ.get("FORWARD_USER_INFO_HEADER_USER_ID", "X-OpenWebUI-User-Id") +FORWARD_USER_INFO_HEADER_USER_EMAIL = os.environ.get("FORWARD_USER_INFO_HEADER_USER_EMAIL", "X-OpenWebUI-User-Email") +FORWARD_USER_INFO_HEADER_USER_ROLE = os.environ.get("FORWARD_USER_INFO_HEADER_USER_ROLE", "X-OpenWebUI-User-Role") + +# Header name for chat ID forwarding (customizable via environment variable) +FORWARD_SESSION_INFO_HEADER_CHAT_ID = os.environ.get("FORWARD_SESSION_INFO_HEADER_CHAT_ID", "X-OpenWebUI-Chat-Id") # Experimental feature, may be removed in future ENABLE_STAR_SESSIONS_MIDDLEWARE = ( diff --git a/backend/open_webui/retrieval/web/external.py b/backend/open_webui/retrieval/web/external.py index 527c918a47..1dd63273ae 100644 --- a/backend/open_webui/retrieval/web/external.py +++ b/backend/open_webui/retrieval/web/external.py @@ -8,6 +8,7 @@ from fastapi import Request from open_webui.retrieval.web.main import SearchResult, get_filtered_results from open_webui.utils.headers import include_user_info_headers +from open_webui.env import FORWARD_SESSION_INFO_HEADER_CHAT_ID log = logging.getLogger(__name__) @@ -31,7 +32,7 @@ def search_external( chat_id = getattr(request.state, "chat_id", None) if chat_id: - headers["X-OpenWebUI-Chat-Id"] = str(chat_id) + headers[FORWARD_SESSION_INFO_HEADER_CHAT_ID] = str(chat_id) response = requests.post( external_url, diff --git a/backend/open_webui/retrieval/web/yandex.py b/backend/open_webui/retrieval/web/yandex.py index def134d996..fd1bc7274a 100644 --- a/backend/open_webui/retrieval/web/yandex.py +++ b/backend/open_webui/retrieval/web/yandex.py @@ -11,6 +11,7 @@ from fastapi import Request from open_webui.retrieval.web.main import SearchResult, get_filtered_results from open_webui.utils.headers import include_user_info_headers +from open_webui.env import FORWARD_SESSION_INFO_HEADER_CHAT_ID from xml.etree import ElementTree as ET from xml.etree.ElementTree import Element @@ -50,7 +51,7 @@ def search_yandex( chat_id = getattr(request.state, "chat_id", None) if chat_id: - headers["X-OpenWebUI-Chat-Id"] = str(chat_id) + headers[FORWARD_SESSION_INFO_HEADER_CHAT_ID] = str(chat_id) payload = {} if yandex_search_config == "" else json.loads(yandex_search_config) diff --git a/backend/open_webui/routers/ollama.py b/backend/open_webui/routers/ollama.py index cfbdbcac08..ed231aabce 100644 --- a/backend/open_webui/routers/ollama.py +++ b/backend/open_webui/routers/ollama.py @@ -23,6 +23,7 @@ from open_webui.models.users import UserModel from open_webui.env import ( ENABLE_FORWARD_USER_INFO_HEADERS, + FORWARD_SESSION_INFO_HEADER_CHAT_ID, ) from fastapi import ( @@ -137,7 +138,7 @@ async def send_post_request( if ENABLE_FORWARD_USER_INFO_HEADERS and user: headers = include_user_info_headers(headers, user) if metadata and metadata.get("chat_id"): - headers["X-OpenWebUI-Chat-Id"] = metadata.get("chat_id") + headers[FORWARD_SESSION_INFO_HEADER_CHAT_ID] = metadata.get("chat_id") r = await session.post( url, diff --git a/backend/open_webui/routers/openai.py b/backend/open_webui/routers/openai.py index b1d31afb8f..0b5433314c 100644 --- a/backend/open_webui/routers/openai.py +++ b/backend/open_webui/routers/openai.py @@ -33,6 +33,7 @@ from open_webui.env import ( AIOHTTP_CLIENT_TIMEOUT, AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST, ENABLE_FORWARD_USER_INFO_HEADERS, + FORWARD_SESSION_INFO_HEADER_CHAT_ID, BYPASS_MODEL_ACCESS_CONTROL, ) from open_webui.models.users import UserModel @@ -142,7 +143,7 @@ async def get_headers_and_cookies( if ENABLE_FORWARD_USER_INFO_HEADERS and user: headers = include_user_info_headers(headers, user) if metadata and metadata.get("chat_id"): - headers["X-OpenWebUI-Chat-Id"] = metadata.get("chat_id") + headers[FORWARD_SESSION_INFO_HEADER_CHAT_ID] = metadata.get("chat_id") token = None auth_type = config.get("auth_type") diff --git a/backend/open_webui/utils/headers.py b/backend/open_webui/utils/headers.py index cdf5d2d85d..f0b13c00d3 100644 --- a/backend/open_webui/utils/headers.py +++ b/backend/open_webui/utils/headers.py @@ -1,18 +1,18 @@ from urllib.parse import quote from open_webui.env import ( - FORWARD_USER_INFO_HEADER_NAME, - FORWARD_USER_INFO_HEADER_ID, - FORWARD_USER_INFO_HEADER_EMAIL, - FORWARD_USER_INFO_HEADER_ROLE, + FORWARD_USER_INFO_HEADER_USER_NAME, + FORWARD_USER_INFO_HEADER_USER_ID, + FORWARD_USER_INFO_HEADER_USER_EMAIL, + FORWARD_USER_INFO_HEADER_USER_ROLE, ) def include_user_info_headers(headers, user): return { **headers, - FORWARD_USER_INFO_HEADER_NAME: quote(user.name, safe=" "), - FORWARD_USER_INFO_HEADER_ID: user.id, - FORWARD_USER_INFO_HEADER_EMAIL: user.email, - FORWARD_USER_INFO_HEADER_ROLE: user.role, + FORWARD_USER_INFO_HEADER_USER_NAME: quote(user.name, safe=" "), + FORWARD_USER_INFO_HEADER_USER_ID: user.id, + FORWARD_USER_INFO_HEADER_USER_EMAIL: user.email, + FORWARD_USER_INFO_HEADER_USER_ROLE: user.role, } diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 3fcaf0fe97..5db562725d 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -127,7 +127,10 @@ from open_webui.env import ( ENABLE_REALTIME_CHAT_SAVE, ENABLE_QUERIES_CACHE, RAG_SYSTEM_CONTEXT, + ENABLE_FORWARD_USER_INFO_HEADERS, + FORWARD_SESSION_INFO_HEADER_CHAT_ID, ) +from open_webui.utils.headers import include_user_info_headers from open_webui.constants import TASKS @@ -2207,6 +2210,12 @@ async def process_chat_payload(request, form_data, user, metadata, model): for key, value in connection_headers.items(): headers[key] = value + # Add user info headers if enabled + if ENABLE_FORWARD_USER_INFO_HEADERS and user: + headers = include_user_info_headers(headers, user) + if metadata and metadata.get("chat_id"): + headers[FORWARD_SESSION_INFO_HEADER_CHAT_ID] = metadata.get("chat_id") + mcp_clients[server_id] = MCPClient() await mcp_clients[server_id].connect( url=mcp_server_connection.get("url", ""), diff --git a/backend/open_webui/utils/tools.py b/backend/open_webui/utils/tools.py index 6a55a9536b..ec281b43a1 100644 --- a/backend/open_webui/utils/tools.py +++ b/backend/open_webui/utils/tools.py @@ -45,7 +45,10 @@ from open_webui.env import ( AIOHTTP_CLIENT_TIMEOUT, AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA, AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL, + ENABLE_FORWARD_USER_INFO_HEADERS, + FORWARD_SESSION_INFO_HEADER_CHAT_ID, ) +from open_webui.utils.headers import include_user_info_headers from open_webui.tools.builtin import ( search_web, fetch_url, @@ -335,6 +338,13 @@ async def get_tools( for key, value in connection_headers.items(): headers[key] = value + # Add user info headers if enabled + if ENABLE_FORWARD_USER_INFO_HEADERS and user: + headers = include_user_info_headers(headers, user) + metadata = extra_params.get("__metadata__", {}) + if metadata and metadata.get("chat_id"): + headers[FORWARD_SESSION_INFO_HEADER_CHAT_ID] = metadata.get("chat_id") + def make_tool_function( function_name, tool_server_data, headers ): From a214ec40ea00eebcba49570647ca6ab8f61765d5 Mon Sep 17 00:00:00 2001 From: Tim Baek Date: Fri, 6 Feb 2026 03:34:21 +0400 Subject: [PATCH 04/42] fix --- backend/open_webui/retrieval/web/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/open_webui/retrieval/web/utils.py b/backend/open_webui/retrieval/web/utils.py index 6c1ea4b1bf..45787cb4bd 100644 --- a/backend/open_webui/retrieval/web/utils.py +++ b/backend/open_webui/retrieval/web/utils.py @@ -174,7 +174,7 @@ class URLProcessingMixin: def _safe_process_url_sync(self, url: str) -> bool: """Synchronous version of safety checks.""" - if self.verify_ssl and not self._verify_ssl_cert(url): + if self.verify_ssl and not verify_ssl_cert(url): raise ValueError(f"SSL certificate verification failed for {url}") self._sync_wait_for_rate_limit() return True From 26286625f4f8207f690371c7bfab947d1d3a7f79 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 5 Feb 2026 23:40:58 -0600 Subject: [PATCH 05/42] refac --- src/lib/components/chat/MessageInput.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index 5914e7afce..d3b10d3caf 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -1746,7 +1746,7 @@