When an admin took someone out of a group, a chat shared with that group with "Allow replies" stayed open on that person's screen, message box included. Changing a group drops that person's live connection, and when it came back the chat was only checked again if the server let them back in, so a refused rejoin left the page as it was. Now the chat is checked again after every answer, so someone who lost access is sent to the home page.
Fixes#32527
Status messages above a reply, such as the ones functions and tools send, were always cut to one line, so a longer message like a token usage summary could never be read in full, especially when several models answer side by side. Clicking a single status line now shows its full text, and when there are several, clicking opens the status history with every entry in full. Status lines with their own view, like web search results, are unchanged.
Fixes#30056
Opening a chat from the sidebar while the home page was still setting up a new chat let that setup finish afterwards and clear the opened chat's id. The next message then failed with "Unexpected token 'd', "data: {"id"... is not valid JSON" and the chat's tags did not load. The new chat setup now stops once another chat has been opened. Signing in to an OAuth tool still turns it on together with the model's default tools.
Follow-up to #32488
With Redis, if every tool server was unreachable when Open WebUI loaded the tool server list, it cached an empty list and served it forever. The tools stayed missing from chats and the tool list after the servers came back, until a restart, a save in the tool server settings or a manual delete of the cached Redis key. An empty cached list is now only trusted while no OpenAPI tool server is enabled, so the next request that loads tools fetches the servers again, the same way terminal servers already behave. While an enabled server stays unreachable, each such request tries it again and can wait for its timeout.
Fixes#29573
Connecting Google Drive asked every user for the drive.readonly scope, read access to their whole Drive. Google classes that scope as restricted, so each self-hosted install needed Google's restricted-scope verification and security assessment, and until then users got the "Google hasn't verified this app" warning. The picker now only requests drive.file, access to the files the user picks, which Google classes as non-sensitive and which needs no such verification. With that scope Google requires the picker to name the Cloud project, so it sends the project number again, taken from the leading digits of the Google Drive client ID. It also opens in list view, as Google recommends for this scope, since the picker gets no thumbnail access with it.
Fixes#29537
Adding a custom parameter named tools to a model, for example to turn on a provider's native web search, made Open WebUI drop all of its own tools for that model: notes, knowledge, tasks and any tools attached to the model stopped working, and attached files lost their context. Those tools now stay, and the model's custom tools are sent alongside them. API calls that pass their own tools, or an empty list to turn tools off, behave as before.
Fixes#32528
On dev, opening a folder's page showed a spinner forever and never listed its chats, because the date next to each chat could not be formatted after the search dialog rewrite. The folder page now loads the date format it needs itself, so its chat list shows again.
Fixes#32525
Files read from a URL are sent to a document parser based on their file name. An arXiv link like arxiv.org/pdf/1706.03762 has a dot in the paper ID, so the name was read as having the extension ".03762", the PDF went to the plain text reader and the model got raw PDF bytes. When the part after the dot is not a known file type, the extension now comes from the file type the server reports, so these links are read as PDFs. Files the server only labels as generic binary keep their name as before.
Before Open WebUI reads a URL for the model, it checks whether the URL is a web page or a file. That check went out without the user agent, browser headers and SSL verification setting the web loader uses, so sites that block unknown clients (Wikimedia, for example) refused it. The URL was then treated as a web page and the model got the raw PDF bytes instead of the document text. The check now sends the same request as the web loader, so it gets the same answer and files go to document extraction again.
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 / 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/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 / 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
With Settings > Interface > Landing Page Mode set to Chat, the new chat
page renders the message list, so the block that reveals a message picked
from search ran there too. With no chat open, chat?.id and
$page.params.id are both undefined, the guard passed, and chat.id threw
"can't access property 'id'" on every refresh.
Require a chat before comparing its id with the page's.
The model editor dropped meta.defaultFeatureIds when the list was empty.
When Admin Settings > Models > Model Defaults turns a default feature on,
the backend fills in that default for any model without the key, so
switching the last feature off on a model saved nothing and the admin
default came back on reopen and in new chats.
Keep the empty list when the admin default is not empty, so the model's
choice is stored and overrides it.
The prompt and tool editors resend every stored grant on Save, and the
update routes ran that whole list through filter_allowed_access_grants.
A collaborator without the public sharing permission therefore had the
owner's Public grant stripped, and the stripped list replaced the stored
one, so one Save made the prompt or tool private for everyone else.
Keep grants that are already stored and filter only the ones the save
adds, as the model update route has done since 754c4b576.
When Admin Settings > Models > Model Defaults turns a built-in tool off,
a model that turns it back on lost that choice on Save. The editor seeds
the model's builtinTools with the admin defaults object itself, and
setBuiltinTool deleted the tool's key in place, so the admin defaults
changed too. The empty map was then dropped on save, and the backend
filled in the admin default again.
Update a copy of the map in setBuiltinTool, as the Default Features
toggles in Capabilities.svelte already build a new list, and keep the
empty map when the admin default is not empty, so the model's choice is
stored and overrides it.
Since cloned and forked chats keep each message's original author, a
copy of someone else's shared chat kept the sharer as the author of
every prompt and reply. Regenerate and Continue in the copy then failed
with "You can only regenerate your own messages.", and edits to those
messages were dropped on save, although the copy belongs to the person
who made it.
When a shared chat is cloned, or forked by someone other than its owner,
give the source owner's messages to the new owner, the same per-message
loop shared_chat_response uses to set authors. Messages written by other
participants of an Allow replies chat keep their authors.
The Interface tab's Save sent fontFamily and imageCompressionSize every
time, read from the settings store, which already carries the admin's
Default Interface Settings for anything the user has not set. One Save
with nothing changed therefore stored the admin's default as a personal
value: the row switched from "Default" to "Custom", and a later change
to the admin default never reached that account.
Leave a value out of that Save while the user only inherits it, as
isDefaultSetting already decides for the "Default" label. Values the
user set keep saving as before.
speak() synthesizes one sentence at a time and enqueues each clip as it
arrives. When a clip finishes before the next one is ready, the audio queue
reports 'empty-queue', and the onStopped handler set speaking to false. The
loop only enqueues while speaking is true, so every later clip was
synthesized and then dropped, and the speaker button went back to idle.
Ignore 'empty-queue' while the synthesis loop is still running; playback
resumes on the next enqueue, and the queue's 'empty-queue' after the last
clip still ends playback as before.
When Open WebUI authenticates to the OAuth provider with client_secret_basic, either because OAUTH_TOKEN_ENDPOINT_AUTH_METHOD is set to it or because an MCP tool server's OAuth provider only offers that method, sign-in sent the client ID and secret in an HTTP Basic header but the token refresh always put them in the request body. Providers that only accept Basic rejected every refresh with invalid_client, so once the access token expired Open WebUI deleted the user's saved OAuth tokens, and model connections and tool servers set to forward the user's OAuth token stopped working until the user signed in again. The refresh now authenticates the same way sign-in does for client_secret_basic, with the credentials only in the Basic header. Setups using client_secret_post, or leaving the setting unset, still send the credentials in the request body exactly as before.
Fixes#32506
With an Open Terminal orchestrator connection set to Terminal Contexts > Chat = "Per chat" (Admin > Integrations > Open Terminal), the preview of an HTML file shown inside an assistant reply looked for the file in the shared terminal workspace, so it showed "File not found" even though the file sits in the chat's own workspace. The sidebar file browser already opens the same file correctly since #32418. The preview inside the reply now uses the chat's own workspace as well.
Fixes#32477
On a wide window the thread side panel keeps one Thread instance while
you open another thread, and initHandler reset the messages and typing
state for the new thread but not replyToMessage. The "Replying to"
banner stayed, and sending saved the new thread's message quoting a
message from the previous thread.
Clear replyToMessage in initHandler, as #31376 does for switching
channels.
Enabling an OAuth MCP tool from the Integrations menu sends the user through the OAuth login and back to a new chat, where the tool should be on. When the selected model had tools of its own enabled by default, the tool came back switched off, so it had to be enabled a second time. Now it stays on, together with the model's own tools. For the same reason, a link like `/?tools=my_tool` opened with such a model ignored the listed tools, and now turns them on.
Fixes#32476
Opening a PDF without any text, such as a scan, in the knowledge base file viewer scrolled the whole page up. The workspace tabs, the knowledge base header and the viewer toolbar went off screen and a blank block appeared at the bottom. Scanned PDFs now open with the page in place, the same as PDFs with text.
Fixes#32481
* i18n: improve zh-TW terms and fill missing settings strings
Replace Mainland Chinese terms with Taiwan usage (創建 -> 建立, 菜單 -> 選單,
加載 -> 載入, 用戶 -> 使用者, 文檔 -> 文件) and translate the untranslated
Apps, tool search and realtime audio settings strings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* i18n: translate remaining zh-TW strings
Fill the 283 untranslated zh-TW strings, following the terms already used
in the file (工作區, 函式, 技能, 知識庫, 終端, 權限範圍, 目前使用版本,
虛擬形象, Token 數) and common Taiwan software terms (資訊清單 for
manifest, 提交訊息 for commit message, 並排/內嵌 for diff layouts).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>