Commit graph

7042 commits

Author SHA1 Message Date
G30
6f55514c5c
fix: let validate_url accept dotless hosts when local web fetch is enabled (#29945) 2026-09-12 17:56:16 -04:00
Timothy Jaeryang Baek
0edd731c74 refac 2026-09-12 17:11:37 -04:00
Classic298
746caa7c78
fix: honor ENABLE_PROFILE_IMAGE_URL_FORWARDING for channel webhook profile images (#29889)
Setting ENABLE_PROFILE_IMAGE_URL_FORWARDING=false stops the user and model profile image endpoints from redirecting browsers to external avatar URLs, but channel webhook avatars kept redirecting regardless. An operator who turned the setting off precisely to stop clients leaking their IP, User-Agent and Referer to outside origins still leaked all three whenever anyone viewed a channel message posted by a webhook with an external profile image URL.

The webhook profile image endpoint now reads the same setting the user and model endpoints already read, and serves the bundled default image instead of the redirect when forwarding is off. Stored URLs are untouched, so turning the setting back on restores the previous behaviour.

Verified against the real handler with seeded webhook rows: with the setting unset or true the endpoint still returns the 302 with the original Location, with it false it returns the default favicon as image/png with no Location and no header carrying the external host, and the data URI, no image and unknown webhook responses are byte identical in both states.
2026-09-12 16:06:34 -05:00
G30
ee4834e299
fix: only log a reranking model change when the request carries one (#29922) 2026-09-12 16:04:14 -05:00
Timothy Jaeryang Baek
a910b0d8f6 refac 2026-09-12 17:02:44 -04:00
Classic298
75b1836322
fix: drop thinking blocks when converting Anthropic Messages requests to Chat Completions (#29849)
* fix: drop thinking blocks when converting Anthropic Messages requests to Chat Completions

Claude Code and other Anthropic SDK clients pointed at /api/v1/messages send the assistant's earlier thinking blocks back with every follow-up request. Since 0.11.0 those blocks were copied into the OpenAI assistant message as content parts of type thinking, a part type Chat Completions does not define. Strict OpenAI-compatible servers such as NVIDIA Dynamo reject the whole request with 400 "data did not match any variant of untagged enum ChatCompletionRequestAssistantMessageContent", so a conversation with a reasoning model died on its second turn. The error reports its position at the very end of the body, which made the request look cut off; it was complete.

Thinking and redacted_thinking blocks are now skipped in the conversion, which is what happened before 0.11.0. An assistant turn that held only thinking blocks is kept as an empty assistant message so the turn order survives. Native Anthropic and LiteLLM connections are unaffected because they receive the request untouched, and thinking blocks in responses are still produced.

Fixes #29799

* fix: keep signed thinking blocks when converting Anthropic Messages requests

Dropping every thinking block also removed the signed ones. Those are the blocks a gateway such as LiteLLM forwards to Anthropic, which needs the signed thinking block of the previous assistant turn when a tool-use turn continues with extended thinking. Only the unsigned blocks are the problem: Open WebUI creates them itself from reasoning_content, and strict Chat Completions backends reject them because thinking is not a content part type they know.

Unsigned thinking blocks are now dropped while signed thinking and redacted_thinking blocks are kept, the same rule LiteLLM applies before forwarding to Anthropic and the rule the native chat path already uses for Anthropic reasoning details. Backends that never emit a signature, such as NVIDIA Dynamo and vLLM, keep receiving requests without thinking parts, so the original failure stays fixed.
2026-09-12 15:56:59 -05:00
Timothy Jaeryang Baek
c78ad89934 refac 2026-09-12 16:56:26 -04:00
Timothy Jaeryang Baek
7a4a4b93dc refac 2026-09-12 15:41:57 -04:00
Timothy Jaeryang Baek
ffae4116a8 refac 2026-09-12 14:57:22 -04:00
Classic298
0313ea0238
fix: stop every task of a chat when stopping a response without Redis (#29844)
Pressing Stop on a chat that has more than one running task (a multi-model
response, or a follow-up sent from another tab or device while a response
is still streaming) reported success but only cancelled the first task.
The survivors kept streaming and kept executing tool calls until the
iteration limit, which is the runaway reported in the issue.

Without Redis the stop loop iterates the live task-id list of the chat.
Each awaited cancellation runs that task's cleanup, which removes its id
from the same list mid-iteration, so the loop runs out one element early
and the last task is never cancelled. Returning a snapshot of the list to
callers keeps the loop on the ids it started with. Redis deployments
already got a fresh list from the set and were not affected.

Verified against a mock upstream that calls a tool on every turn: with three
tasks on one chat, stop left one or two alive before the change and cancels
all of them after it.

Fixes #29816
2026-09-12 13:55:13 -05:00
G30
4ee53e051e
fix: sanitize user-typed notification target ids the same way generated ones are (#29947) 2026-09-12 13:50:19 -05:00
Timothy Jaeryang Baek
17dbc6f001 refac
Some checks failed
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args: free_disk:false name:main suffix:]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_CUDA=true USE_CUDA_VER=cu126 free_disk:true name:cuda126 suffix:-cuda126]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_CUDA=true free_disk:true name:cuda suffix:-cuda]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_OLLAMA=true free_disk:false name:ollama suffix:-ollama]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_SLIM=true free_disk:false name:slim suffix:-slim]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args: free_disk:false name:main suffix:]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_CUDA=true USE_CUDA_VER=cu126 free_disk:true name:cuda126 suffix:-cuda126]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_CUDA=true free_disk:true name:cuda suffix:-cuda]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_OLLAMA=true free_disk:false name:ollama suffix:-ollama]) (push) Waiting to run
Create and publish Docker images with specific build args / merge (map[name:cuda suffix:-cuda]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_SLIM=true free_disk:false name:slim suffix:-slim]) (push) Waiting to run
Create and publish Docker images with specific build args / merge (map[name:cuda126 suffix:-cuda126]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge (map[name:main suffix:]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge (map[name:ollama suffix:-ollama]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge (map[name:slim suffix:-slim]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / notify-helm-charts (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (, main) (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (-cuda, cuda) (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (-cuda126, cuda126) (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (-ollama, ollama) (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (-slim, slim) (push) Blocked by required conditions
Frontend Build / Unit Tests (push) Waiting to run
Frontend Build / Format & Build (push) Waiting to run
Python CI / Ruff Format (3.11) (push) Has been cancelled
Python CI / Ruff Format (3.12) (push) Has been cancelled
2026-09-09 17:09:53 -04:00
Timothy Jaeryang Baek
8a19e2f867 refac 2026-09-09 17:09:45 -04:00
Timothy Jaeryang Baek
e35b907f73 refac 2026-09-09 16:39:44 -04:00
Classic298
44f9a4f7f9
fix: stop forwarding upstream Server and Date headers from the OpenAI and Ollama proxies (#29843)
Streamed chat completions and the other proxied OpenAI and Ollama responses
went out with two Server and two Date headers: the upstream's copies, forwarded
verbatim, plus uvicorn's own. nginx in front of Open WebUI logs "upstream sent
duplicate header line" for both on every streamed request.

Server and Date belong to whoever terminates the connection, so both proxies now
drop the upstream's copies next to the encoding headers they already stripped.
The filter also compares header names case-insensitively. Before, it matched
title-case names only, so uvicorn-based upstreams such as vLLM and LiteLLM,
which send lowercase header names, had none of their headers stripped at all,
including the Content-Encoding entry the filter exists for.

Same fix as #29824 for the terminal proxy, applied to the other two proxy paths.
2026-09-09 16:35:48 -04:00
Timothy Jaeryang Baek
ee46e2664a refac 2026-09-09 12:51:59 -04:00
Classic298
c955cbd2c5
fix: stop forwarding upstream Server and Date headers from the terminal proxy (#29841)
Proxied terminal responses (GET /api/v1/terminals/{id}/ports and every other
proxied route) went out with two Server and two Date headers: the terminal
server's copies, forwarded verbatim, plus uvicorn's own. nginx in front of Open
WebUI logs "upstream sent duplicate header line" for both on every request, and
the ports route is polled often enough to fill gigabytes of error log per day.

Server and Date belong to whoever terminates the connection, so the proxy now
drops the upstream's copies next to the framing headers it already stripped.
uvicorn's own values still go out, once. Everything else, including custom
upstream headers and TERMINAL_PROXY_HEADERS, passes through unchanged.

The OpenAI and Ollama proxies forward upstream Server and Date the same way and
are left for a separate change.

Fixes #29824
2026-09-09 12:31:02 -04:00
Classic298
1b67da7004
feat: sort flags for kb_exec file listings (#29840)
kb_exec silently ignored ls -t. It accepted the flag, dropped it and
returned the same undefined database order as a plain ls, so the model
believed it had a newest-first list when it did not. With a few thousand
files in a knowledge base there was no way to ask what changed recently
without reading the whole listing and comparing dates by eye.

ls, tree and find now sort their file lines by name by default, so the
same knowledge base always lists the same way. -t sorts newest first,
-S largest first and -r reverses, combinable like -at or -tr, matching
the flags the model already knows from a shell. Directories keep their
existing name order and stay grouped first. No query changes: the
timestamps and sizes were already loaded for the date and size columns.
2026-09-09 12:30:47 -04:00
Timothy Jaeryang Baek
12b14124b9 refac 2026-09-08 23:18:48 -04:00
Timothy Jaeryang Baek
31b272d3c9 refac 2026-09-08 22:20:33 -04:00
Timothy Jaeryang Baek
ba34bee2d1 refac 2026-09-08 12:45:11 -04:00
Timothy Jaeryang Baek
aaaf26fb8e refac 2026-09-08 12:38:07 -04:00
Timothy Jaeryang Baek
98a920168e refac 2026-09-07 14:46:52 -04:00
G30
2f2f4c872f
fix(retrieval): drain playwright route handlers before the page closes (#29325) 2026-09-07 13:20:59 -04:00
Timothy Jaeryang Baek
f5fcf4c89f refac 2026-09-07 12:40:44 -04:00
Timothy Jaeryang Baek
f9f815c862 refac 2026-09-07 12:21:23 -04:00
Timothy Jaeryang Baek
b141fdc49e refac 2026-09-07 12:18:23 -04:00
Timothy Jaeryang Baek
3cda47cdb4 refac 2026-09-07 12:16:09 -04:00
Timothy Jaeryang Baek
b71744b178 refac 2026-09-07 12:15:20 -04:00
Timothy Jaeryang Baek
57acc2b68f refac
Some checks failed
Python CI / Ruff Format (3.11) (push) Has been cancelled
Python CI / Ruff Format (3.12) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args: free_disk:false name:main suffix:]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_CUDA=true USE_CUDA_VER=cu126 free_disk:true name:cuda126 suffix:-cuda126]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_CUDA=true free_disk:true name:cuda suffix:-cuda]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_OLLAMA=true free_disk:false name:ollama suffix:-ollama]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_SLIM=true free_disk:false name:slim suffix:-slim]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args: free_disk:false name:main suffix:]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_CUDA=true USE_CUDA_VER=cu126 free_disk:true name:cuda126 suffix:-cuda126]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_CUDA=true free_disk:true name:cuda suffix:-cuda]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_OLLAMA=true free_disk:false name:ollama suffix:-ollama]) (push) Has been cancelled
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_SLIM=true free_disk:false name:slim suffix:-slim]) (push) Has been cancelled
Frontend Build / Format & Build (push) Has been cancelled
Frontend Build / Unit Tests (push) Has been cancelled
Create and publish Docker images with specific build args / copy-to-dockerhub (-cuda126, cuda126) (push) Has been cancelled
Create and publish Docker images with specific build args / copy-to-dockerhub (-ollama, ollama) (push) Has been cancelled
Create and publish Docker images with specific build args / copy-to-dockerhub (-slim, slim) (push) Has been cancelled
Create and publish Docker images with specific build args / merge (map[name:cuda suffix:-cuda]) (push) Has been cancelled
Create and publish Docker images with specific build args / notify-helm-charts (push) Has been cancelled
Create and publish Docker images with specific build args / merge (map[name:cuda126 suffix:-cuda126]) (push) Has been cancelled
Create and publish Docker images with specific build args / merge (map[name:main suffix:]) (push) Has been cancelled
Create and publish Docker images with specific build args / merge (map[name:ollama suffix:-ollama]) (push) Has been cancelled
Create and publish Docker images with specific build args / merge (map[name:slim suffix:-slim]) (push) Has been cancelled
Create and publish Docker images with specific build args / copy-to-dockerhub (, main) (push) Has been cancelled
Create and publish Docker images with specific build args / copy-to-dockerhub (-cuda, cuda) (push) Has been cancelled
2026-09-06 23:23:59 -04:00
Timothy Jaeryang Baek
d418840aa9 refac 2026-09-06 19:36:17 -04:00
Timothy Jaeryang Baek
7eefeef4f1 refac 2026-09-06 19:32:31 -04:00
Timothy Jaeryang Baek
6c7aa3543d refac 2026-09-06 19:02:44 -04:00
Classic298
4b10190096
refac: move the connection index role check into the listing handlers (#29619)
The Ollama and OpenAI model listing handlers now check the caller's role themselves instead of declaring it as a route-level dependency.
2026-09-06 18:30:31 -04:00
Timothy Jaeryang Baek
77d2000eb7 refac 2026-09-06 18:29:46 -04:00
Classic298
ae01ef9c95
fix: skip image, media and font requests in the Playwright web loader (#29742)
Fetching a page with many media files through the Playwright web loader was extremely slow or timed out, while raw Playwright loaded the same page in a couple of seconds. The loader routes every request the page makes through the backend HTTP client and downloads the full body before the browser sees any of it, and the browser cancelling a media request once it has enough never reaches that download. On a page with a few dozen audio players every file was pulled in full for a text extraction that never reads it.

Image, media and font requests are now aborted in the interceptor before any fetch is made. None of them feed the text extraction. Measured on the page from the report with the default timeout on the same connection:

| | requests fetched | bytes downloaded | elapsed |
|---|---|---|---|
| before | 151 | 55.0 MB | 10.1 s |
| after | 45 | 3.9 MB | 2.6 s |

Fixes #29741
2026-09-06 17:01:00 -05:00
Timothy Jaeryang Baek
649c012ecf refac 2026-09-06 17:53:02 -04:00
Classic298
2e16a761ee
refactor: scope tool export to tools the caller can write (#29310)
The bulk tool export returned every tool the caller could read, while the per-tool export path returns only what the caller can write. This aligns the two, matching how model export already scopes its query.

Callers still export their own tools and any tool shared with them for writing; admins running with BYPASS_ADMIN_ACCESS_CONTROL are unaffected.
2026-09-06 17:44:45 -04:00
Timothy Jaeryang Baek
a1c02098aa refac 2026-09-06 17:35:49 -04:00
Timothy Jaeryang Baek
508de20779 refac 2026-09-06 17:27:30 -04:00
Timothy Jaeryang Baek
0fa4dea5ff refac 2026-09-06 17:21:57 -04:00
Timothy Jaeryang Baek
d27aa72ab4 refac 2026-09-06 17:13:32 -04:00
Timothy Jaeryang Baek
c4a349651e refac 2026-09-06 17:10:01 -04:00
Classic298
1932ca649e
fix: stop sending OpenAPI tool server path and query parameters in the request body (#29717)
Tool calls to an OpenAPI tool server put every argument the model returned into the JSON request body, including the parameters that were already substituted into the URL. Servers that validate their input strictly (additionalProperties: false) answered 422 "unexpected property", so reads worked and every write through an endpoint with a path or query parameter failed.

The body is now built from the model's arguments minus the operation's declared parameters, keeping any name the requestBody schema declares as a property of its own, so an endpoint that wants the resource id in the body as well as in the path still gets it.

The filter only runs when the resolved body schema lists its properties. A free-form, composed or non-JSON body offers nothing to check a name against, so those requests go out exactly as before.

src/lib/apis/index.ts carries the same request builder for direct tool server connections and had the same bug, so it gets the same fix.

Fixes #29716
2026-09-06 17:01:26 -04:00
Classic298
66e021a926
fix: normalize a tool call name sent as null (#29690)
Some endpoints stream a tool call whose function name is JSON null instead of a string. Nothing normalized it, so the null stayed on the tool call, was written into the stored message, and was sent back to the endpoint in the assistant message on the next turn, where a null is not a valid function name.

The delta accumulator now replaces a null name with an empty string, at the same point it already normalizes the arguments field. The call still fails as an unknown tool, which is the right outcome for a call that has no name, so the result is one failed tool call instead of a follow-up request the endpoint has to reject.

This is done where the delta enters the accumulator rather than at the consumers, because the name is emitted to the client and persisted while the response is still streaming, before anything downstream could clean it up.

Checked against 1261 streaming delta sequences: behaviour is unchanged except where the delta that creates the tool call carries a null name.

Seen in #29686 with a custom sglang build.
2026-09-06 17:00:03 -04:00
Classic298
cd68a66fba
Gate the channel webhook profile image endpoint on channel access (#29703)
Any authenticated user could fetch a channel webhook's avatar, or be redirected to its external profile image URL, without belonging to the channel or holding any read access to it. This was the only webhook route with neither a channel check nor the channels feature gate.

The route now applies the same read gate every other route in this router uses: active membership for group and direct message channels, admin or a channel read grant otherwise, answering with 403 on denial and 404 when the webhook's channel row no longer exists. It also runs the channels feature and permission gate, so with channels disabled, or the permission withdrawn from regular users, the endpoint now refuses where it previously served the image.

Avatars keep rendering for channel members, and a denied request shows the default logo rather than a broken image, because the avatar component already falls back on an image error.
2026-09-06 16:58:50 -04:00
Timothy Jaeryang Baek
cb942bb94c refac 2026-09-06 16:48:30 -04:00
Classic298
08ca3d859f
chore: drop the unused Noto Sans variable fonts (#29723)
The four Noto Sans variable fonts under open_webui/static/fonts have never been loaded. Removing them makes an installed package 40 MB smaller on disk, the wheel about 24 MB, and the Docker image about 80 MB, because the image currently stores the static directory twice.

The PDF generator registers only the static faces through add_font, and the stylesheet that names the variable fonts, pdf-style.css, is read into a variable that nothing ever uses, so no code path can reach them. The frontend never fetches these files either.

Only the four @font-face blocks that pointed at the deleted files are removed; the rest of the stylesheet, font stack included, is left exactly as it is.

The files were reachable under the public /static mount, so anything outside this repository that hotlinked them gets a 404 from now on.

Part of #29721.
2026-09-06 16:39:36 -04:00
Classic298
e07e8ed0d4
chore: drop the Google Drive client and other unimported dependency pins (#29726)
The Docker image and a fresh pip install get about 100 MB smaller uncompressed. The removed pins are ones nothing in the backend imports and that no installed package requires, with the one exception of async-timeout, which redis still requires below Python 3.11.3; the resolver installs it there as a transitive dependency, just no longer pinned to 5.0.1 for plain pip installs.

google-api-python-client, google-auth-httplib2 and google-auth-oauthlib were added for Google Drive in 2024, but the picker is frontend-only and loads gapi from apis.google.com; together they are about 95 MB on disk. pymongo, the langchain meta package, pymdown-extensions, pytube, APScheduler and RestrictedPython have no importer; the YouTube loader, the scheduler and the tool sandbox are all hand-written in this repository.

google-genai stays: nothing imports it either, but the tool-call path carries accommodations written for python-genai callers, so Gemini pipes are expected to find it in the shared environment.

uv.lock is regenerated, deletions only.

One user-visible consequence: a tool or function that imported one of the removed packages without declaring it in its frontmatter requirements has worked only because the package was preinstalled. Declaring it fixes that where frontmatter installs are enabled and the instance can reach PyPI; an offline instance needs the package installed into the image instead.

Part of #29721.
2026-09-06 16:39:24 -04:00
Classic298
ca9ec06c7e
chore: drop nltk, unused at the pinned versions (#29725)
The main and CUDA Docker images get about 21 MB smaller (the nltk package, the punkt_tab data and its zip); slim images, which never downloaded the data, about 6 MB.

nltk was in the image for unstructured, which used it to tokenize documents. The Dockerfile download was added for airgapped containers failing on the missing punkt_tab data (#21150; the same request in #16260), the same lookup failed on first use in other setups (#17594, #4642), and the download in start.sh and start_windows.bat came with the Playwright web loader mode and sits in that branch.

unstructured 0.22.31, the pinned version, has no nltk references at all and tokenizes with spaCy, nothing else installed requires nltk outside transformers' testing and dev extras, and nothing in the backend imports it, so the pin and both downloads go together.

One user-visible consequence: a tool or function that imports nltk inside the container stops working unless it declares nltk in its frontmatter requirements. On an offline instance the package, and any nltk data such as punkt_tab, have to be installed into the image instead.

Part of #29721.
2026-09-06 16:39:05 -04:00