#30426 stopped concurrent requests from refreshing the same OAuth session twice, but its lock only lives inside one process. With several uvicorn workers or replicas, two requests on different workers still send the same refresh token, a rotating provider rejects the second with invalid_grant, and the session gets deleted, so the user's OAuth session is logged out again.
When Redis is configured, which multi-worker and multi-replica deployments require, the refresh now takes a Redis lock per session instead of the in-process one. Single-process deployments without Redis keep the in-process lock. The waiter re-reads the session inside the lock as before and uses the token that was just stored.
It uses redis-py's own async lock because the existing RedisLock is synchronous and never waits. The Sentinel proxy now passes `lock` through unwrapped like `pipeline` and `pubsub`; otherwise it returned a coroutine and every refresh behind Sentinel would fail.
Tested with separate OS processes on one sqlite DB, a real Redis and a rotating mock provider: 2 and 5 processes (and 5 processes x 3 requests) now cause 1 refresh, every caller gets the new token and the session is kept (before: one refresh per process, session deleted every run). Single refresh, failed refresh, valid token and the single-process path without Redis are unchanged.
Follow-up to #30426, refs #30416
With S3 storage, a file whose stored name is close to the 255-byte filename limit and contains non-ASCII characters (for example a Cyrillic name of about 210-218 bytes) uploads fine, but every later read fails with "File name too long". Processing never gets the content, so the file shows as attached while the model receives no text.
The read path used boto3's download_file, which first writes to a temporary name with 9 extra characters. boto3 caps that temporary name by characters, not bytes, so multibyte names end up over the limit even though the final name fits.
The download now streams straight into the local path with download_fileobj, the same way the Azure provider already writes its local copy. That path is the one the upload just wrote successfully, so it always fits. ASCII names, key prefixes and multipart downloads behave as before.
Fixes#30409
Leaving the chat with voice mode active (Admin Panel, Workspace, Notes) left a hidden recorder running in the tab. The voice mode flag stays on when the chat page unmounts, so the overlay's teardown restarted recording on the destroyed component, which kept transcribing speech and sending prompts from other pages. Returning to the chat also opened an extra microphone stream that was never closed.
The overlay now marks itself destroyed on teardown and never starts or restarts recording after that, so leaving the chat shuts the microphone down fully.
Resetting the voice mode flag in the chat page cleanup was considered, but it changes behaviour for the controls panel on return and still runs after the overlay's own teardown.
Verified in Chromium with a fake microphone (14s per phase, transcription requests / live mic tracks):
| Phase | before | after |
|---|---|---|
| Call on chat | 3 / 1 | 3 / 1 |
| After moving to Workspace | 3 / 1 | 0 / 0 |
| Voice mode reopened | 3 / 3 | 3 / 1 |
Fixes#30405
The ydoc document update handler now schedules the debounced save only for note documents, since notes are the only ydoc documents with a save handler.
Since 0.11.4, creating or editing an automation on Windows with PostgreSQL fails with a 400, and the scheduler logs NotImplementedError on every tick, so automations do not work at all on that setup.
Schedules are now evaluated in a worker subprocess so a pathological rule can be killed after the 2s budget. On Windows with PostgreSQL, Open WebUI switches to the selector event loop that psycopg needs, and that loop cannot spawn subprocesses.
When spawning fails there, the evaluation now reruns on a Proactor event loop in a worker thread. The subprocess, the 2s budget and the kill on timeout all stay the same, and the global loop policy psycopg depends on is untouched. Falling back to a plain thread was considered and rejected: a thread cannot be stopped, so a costly rule would keep burning CPU after the timeout.
Verified with a loop that refuses subprocesses: base raises NotImplementedError, the fix returns the same results as base, still times out a pathological rule at 2s with the worker killed, and leaves no processes or loops behind under repeated and concurrent calls. Other platforms take the unchanged path.
Fixes#30400
With an OIDC provider that rotates refresh tokens, sending a chat to a system_oauth connection often logged the user's OAuth session out. Two requests reached the refresh at the same time and both sent the same refresh token. The provider rejected the second one with invalid_grant, and Open WebUI deleted the session, so every following request lost its token until the user logged in again.
Refreshes now take a per-session lock. A request that waited for another one re-reads the session and uses the token that was just stored, so the provider sees one refresh per rotation.
Tested with real sqlite sessions and a rotating mock provider: 2 and 5 concurrent callers now cause 1 refresh, all callers get the new token and the session is kept (before: one refresh per caller, all callers got nothing, session deleted). Single refresh, failed refresh and valid-token paths are unchanged.
The lock is per process, so deployments with several workers or replicas can still race across processes.
Fixes#30416
The analytics dashboard renders inside the settings modal, whose tab area clips overflowing content. Unlike the other tabs, analytics had no scroll area of its own, so on any instance with more than a handful of models or users the bottom of the model and user ranking tables was cut off and could not be reached.
The analytics wrapper now scrolls vertically, using the same scroll classes as the other settings tabs. Verified in a browser with 30 models and 45 users at 1400x900, 1280x720 and 700x900: before, wheel scrolling moved nothing; after, both tables scroll to their last row with a single scrollbar and no horizontal overflow.
Fixes#30428
When the configured TTS provider fails during a voice call, the text answer arrives but the overlay stays in "speaking" with no audio and no error until the user taps to interrupt. The sentence that failed never reaches the audio cache, so the playback loop re-queues it every 200 ms forever.
A failed sentence now marks its message as failed. The playback loop drops that message's unplayed sentences, the rest of the turn requests no more TTS, and the overlay returns to listening once the text finishes. The OpenAI-compatible path now shows the provider error once per turn, the same way Read Aloud and the Kokoro path already do. The next turn tries TTS again.
Failure is tracked per message so an outage (the report shows 16 parallel requests all failing) costs one toast and no further requests. The trade-off is that a one-off failure mutes the rest of that reply.
Verified with the real fetch/playback code in a harness: base loops forever with no toast; with the fix, one toast, the loop ends, later sentences are not requested, a new turn plays normally, and a late failure from a previous turn does not affect the next one.
Fixes#30052
With native function calling on an Ollama model, every request sent after a tool result was missing the model's system prompt, so the final answer ignored the model's instructions. Only other system content, such as the attached knowledge tag, was left. OpenAI connections were not affected.
Tool-call follow-ups are rebuilt from the chat's message list and skip the router's system prompt step, because the first request is expected to have already added it to that list. The OpenAI path does add it there, but the Ollama path converts the messages into a copy first and adds the prompt only to the copy, so the follow-ups never see it.
The model system prompt is now applied to the messages before the Ollama conversion, and the Ollama router is told to skip it for that request so it is not added twice. Ollama now behaves the same as the OpenAI path. Direct calls to /ollama/api/chat still get the prompt from the router as before.
Checked baseline against patched: first request and follow-up for plain, custom and arena Ollama models, with and without a chat system prompt, with template variables and on the OpenAI path. The prompt is now present exactly once on every Ollama follow-up, and nothing else changed.
Fixes#30161
Clicking a folder name in the sidebar while a chat was open switched that chat to the folder's default model for a moment before the page changed. That reset its tools and skills to the folder model's set and saved them as the chat's draft, so on returning to the chat the folder model's tools were shown and sent with the next message. The same happened to a chat just started from the home page.
The folder's default model is now only applied while the chat has no messages yet, the same rule new chats already follow when a folder page opens. Folder pages, new chats in a folder and editing a folder's default model behave as before.
Verified in a browser against a mock upstream: on dev the next request after the folder click carried the folder model's tool_ids and skill_ids; with the fix it carries the chat's own model's set, for both an existing chat and one started from the home page.
Fixes#30226
* fix: keep en-US as the last i18n fallback when a stored locale has no bundle
Settings labels rendered as raw keys such as settings.admin.connections.title
instead of "Connections" from the second page load on, while every other
label looked fine.
On the first visit the language detector saves whatever the browser reports
into localStorage, including bare codes like "en" that have no locale bundle.
The same value is saved by ?lang=en or DEFAULT_LOCALE=en. On the next load
that stored value became the only fallback language, so the missing bundle
left nothing to fall back to. Plain keys still looked right because the key
is the English text; only the settings.* keys have a distinct value.
en-US now stays at the end of the fallback list whenever a stored locale is
passed in. The stored locale keeps precedence, real locales are unaffected,
and the en-US bundle was already loaded for every language for the settings
merge, so there is no extra request.
Fixes#30348
* fix: match browser language codes to a locale bundle
Firefox reports German, Dutch and Polish as bare codes (de, nl, pl), both Chrome and Firefox report Japanese as ja, and Chrome in Latin America reports es-419. No bundle is keyed by any of these. The page layout used to match them on the first visit, but since 67ac1a4e9 (0.11.4) awaits the i18n init, the detector has already cached the raw code by the time that check runs, so it never does. Those users get an English interface, a language dropdown with nothing selected and English date formats, and the cached code keeps them there.
The detector now maps a reported code onto a bundle before anything else sees it. A code we ship stays as it is, matched case-insensitively. Otherwise the language's xx-XX bundle is used when there is one, so de and de-AT become de-DE, es-419 becomes es-ES, and fr becomes fr-FR even though fr-CA comes first in the list. A bare code with no xx-XX bundle takes the first one for its language, so ja becomes ja-JP. Any other regional code passes through untouched, so zh-HK is not sent to Simplified zh-CN, and no locale that works today changes.
Restoring the layout check would leave every browser that cached a raw code under 0.11.4 stuck. Matching in the detector migrates them on their next load, because the matched code is what gets cached. {{USER_LANGUAGE}} reports that matched code too, so es-419 users now send es-ES.
Verified against the real bundles on first and repeat loads, including the untouched cases fr-CA, pt-BR, zh-TW, zh-HK, ar-BH, en-GB and uz-Latn-UZ.
Reworked from the ground up after the feedback that the registry implementation did not land. The Redis room registry and its whole recovery protocol (heartbeats, liveness keys, pruning, distrust windows, cache invalidation) are gone; the change is now ~105 lines with no state kept outside the process.
With WEBSOCKET_MANAGER=redis every emit is published on one shared channel and every instance JSON-decodes every message: a 16 instance fleet decodes each streamed token delta 16 times and 15 discard it. py-spy across a loaded fleet (16 instances, ~4000 users) puts ~31% of all active CPU samples in the pubsub listener parse chain, the largest bucket.
Room-targeted emits are now published on a per-room channel instead; every instance keeps one static pattern subscription covering all room channels and drops messages for rooms without local members by channel name, paying a set lookup instead of a JSON parse. No state leaves the process, so recovery paths and loss windows are identical to the stock manager; acks and control messages stay on the shared channel and sio.call works across instances unchanged. This is the delivery scheme the official socket.io Redis adapter for Node.js ships by default.
Enabled by default; WEBSOCKET_REDIS_ROOM_CHANNELS=false restores shared-channel-only delivery. All instances must run the same mode, so the switch rides the full-stop upgrade this release already requires for its migration; in a mixed fleet, room emits from updated instances would not reach not-yet-updated ones. Verified end to end with two instances on a real Redis: cross-instance token streams delivered with the shared channel completely silent. Ref #28173.
<!--
🚨 DO NOT DELETE THE TEXT BELOW 🚨
Keep the "Contributor License Agreement" confirmation text intact.
Deleting it will trigger the CLA-Bot to INVALIDATE your PR.
Your PR will NOT be reviewed or merged until you check the box below confirming that you have read and agree to the terms of the CLA.
-->
- [x] By submitting this pull request, I confirm that I have read and fully agree to the [Contributor License Agreement (CLA)](https://github.com/open-webui/open-webui/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT), and I am providing my contributions under its terms.
> [!NOTE]
> Deleting the CLA section will lead to immediate closure of your PR and it will not be merged in.
With Chroma as the vector DB, hybrid search on a knowledge base with more than 32766 chunks fails with HTTP 400 "Error querying knowledge base". The legacy hybrid path fetches the whole collection to build the BM25 index, and Chroma's unbounded collection.get() binds one SQLite variable per row, so any collection above SQLite's 32766 variable limit raises "too many SQL variables" (reproduced on chromadb 1.5.9 with both PersistentClient and HttpClient). Vector-only search on the same collection works, which makes it look like a hybrid-search bug.
The Chroma adapter now reads the collection in pages of 10000 rows via limit/offset and concatenates them into the same GetResult shape as before.
Verified on a 90000-row collection: every row returned exactly once with documents and metadata aligned to ids, page order stable across page sizes, empty and exactly-one-page collections unchanged, and query_doc_with_hybrid_search returns results where it previously raised. The tests repo unit suite is identical before and after.
Fixes#30351
Generated images that come back as bare base64 (OpenAI b64_json, Gemini
bytesBase64Encoded and inlineData, Automatic1111) were always stored as
generated-image.png with content type image/png, even when the provider
returned JPEG or WebP, for example with {"output_format": "jpeg"} in the
OpenAI extra params. The image still rendered because browsers read the
bytes, but the download name, the served Content-Type and the type sent
along on a later image edit were wrong.
Bare base64 carries no format, so the type is now read from the bytes with
Pillow, the same way the file already inspects images elsewhere. A response
that is not an image at all now fails the generation instead of storing a
broken png. The file extension comes from the module's own extension map
first, because the Python 3.11 Docker image has no mime database entry for
WebP and would otherwise name the file generated-imageNone.
Fixes#29948
Every new saved chat logged "Error generating initial chat title" with a
KeyError: 'model' traceback. The title itself was already generated and
saved by then, so the log was misleading, and the memory settings played no
part in it. The error was silently logged at debug level since v0.10.0 and
became visible in v0.11.4 when the title path switched to log.exception.
The initial title task runs the shared background handler with a context
that has no resolved model, which the memory review step read
unconditionally. It now reads it with a default of None, which the memory
review already accepts. The title path never carries an assistant message,
so the review stops before doing any work there, and the main completion
path keeps reviewing memory exactly once per turn with the real model.
Fixes#30339
With the Docling content extraction engine, every conversion request
carried the server's full internal upload path (for example
/app/backend/data/uploads/<id>_report.pdf) as the multipart file name.
Docling only needs a bare file name, and a hosted Docling instance has
no business learning where Open WebUI keeps its files on disk.
The loader now sends the base name of the stored file, which is what
the MinerU, Datalab and Mistral loaders already do. Nothing else in
the request or the parsed result changes, verified against a capturing
mock server before and after.
Fixes#30352
When an MCP tool returns an image (e.g. a Home Assistant camera snapshot), the
snapshot shows up in the tool call section but the model never sees it: it
answers that there is no image. Only images arriving as inline data URIs were
attached to the model request; MCP images are uploaded to Files first and their
file URL was treated as display-only.
Now an image file item with a file URL is attached to the model request as an
input_image part in addition to staying in the tool call's displayed files. The
existing URL-to-base64 step already resolves file URLs, so the model receives
the image bytes; verified on a running instance with a mock MCP server and a
mock upstream (the second upstream request carries the byte-identical JPEG).
Inline data-URI images keep their existing model-only handling.
Fixes#30327
* chore: open the 0.11.4 changelog
Starts the section for the commits landed on dev after the 0.11.3 entry was
merged. Fixed records the direct connection listener left behind on every
request that ended badly, the metadata attached to an uploaded file that never
reached the retrieved sources, the slash command menu showing white text on
white in the light theme, and image editing refusing an image the instance
already held. Added carries the general improvements placeholder and the
Traditional Chinese, Korean and Finnish catalogues.
The tailwind reflow and the raw string escapes are omitted, the first being
whitespace and the second changing nothing that is visible today, though it
keeps the knowledge filesystem tools importable on a later Python.
* chore: extend the metadata and translation entries in 0.11.4
The metadata entry gains the follow-up that trims what travels with each piece
of a file, keeping the oversized and internal fields out of every chunk and
picking up metadata nested a level down, and is recorded there rather than as a
second entry because it continues the same story. The translation entry gains
the Russian and Ukrainian catalogues.
The settings group headings and the keys added for them are omitted: the new
keys carry no translation in any catalogue yet, so every heading still reads as
it did, and the change only makes them translatable later.
* chore: add the security advisory notice to 0.11.4
Adds the standard notice as the first item in the Fixed section. The release
touches the guard that keeps image editing from reaching private addresses, and
carries a listener leak a caller could drive without limit, so it meets the
trigger the format sets for the notice. The notice is the fixed wording and
takes no reference links of its own; the individual entries keep theirs.
* chore: record the file metadata entry as an addition in 0.11.4
Metadata attached to an upload reaching the retrieved sources is a capability
that was not there before rather than a correction, so the entry moves to Added
and leads that section, ahead of the general improvements placeholder and the
translation entry in their reserved places. The wording drops the framing that
described it as something no longer going missing; its pull request, issue and
follow-up commit travel with it unchanged.
* chore: give the file metadata entry a noun phrase label
The label read as an outcome, which suits a correction rather than an addition
and left the entry sounding like something that had stopped going wrong. It is
now the plain noun phrase the format asks of a label, with the sentence beneath
carrying what the metadata now does.
* chore: add the settings group heading entry to 0.11.4
The groundwork that made these headings translatable was held back last time,
the keys having landed empty in every catalogue so nothing read differently.
Russian and Ukrainian now carry the wording, so the change shows and the entry
joins Fixed at the foot of the section, below the corrections that reach
further. The two commits that made the headings translatable are referenced;
the catalogues that filled them sit in the translation entry, which names both
languages and carries no links.
* chore: add the code formatter entry and widen the translation coverage entry in 0.11.4
Fixed leads with the built-in code formatter, which pulled in the formatter but
none of the packages it depends on, so saving any tool or function ended in a
missing module error however plain the code was. It sits directly below the
advisory, being the correction that stops the most people getting their work
saved.
The settings heading entry widens into one covering every string that was fixed
in English, the headings among them, now that labels and messages across the
admin pages, the workspace and notifications have been opened up the same way
and Spanish, Russian and Ukrainian have filled them in. Its five commits travel
together. German and Spanish join the translation entry.
* chore: add the notes shortcut and web citation entries to 0.11.4
Added records the shortcut that turns a note's menu button into a delete button
while Shift is held, ahead of the placeholder and translation entries in their
reserved places.
Fixed records the pages a web search only listed no longer being offered as
things to cite, which had produced citations pointing at the wrong result under
a title that read as correct. It sits directly below the code formatter, a
citation that is wrong being worse to a reader than one that is missing.
* chore: add the version check, ligature and search entries to 0.11.4
Fixed gains the version check that reported whatever it was running as the
newest release whenever it could not reach the listing, and logged nothing
about it, which is placed high because an administrator reads it as an answer
rather than a failure. It also gains the arrow sequences drawn as glyphs, which
had text look altered although every character was stored and sent as typed;
that one sits with the other reading corrections.
Added gains the text search moved off the path the server answers on, so a long
search no longer keeps other requests waiting.
The metadata entry gains the four vector stores that never applied the shared
size cap, coercion and sanitising, bringing them in line with the other eleven
rather than standing as an entry of its own.
* chore: extend the quick delete entry to automations in 0.11.4
The shortcut that turns a note's trailing controls into a delete button now does
the same for a row on the automations page, so the entry names both places and
carries both pull requests with the issues they close, rather than repeating
itself for the second surface.
The pass blanking redundant English values in the en-US catalogue is omitted:
the key stands in for the value there, so nothing reads differently.
* chore: add the note from search entry to 0.11.4
Fixed records the three ways starting a note from the search box went wrong, as
one entry because they are one action: the browser back button making a further
note on every press, the action doing nothing at all when the notes page was
already open, and the typed text losing everything from the first ampersand or
hash onwards. It sits below the listener leak, unwanted notes being a nuisance
rather than something that grows on the server.
* chore: add the arena, relevance and dialog entries to 0.11.4
Fixed gains the arena model that failed on something unrelated whenever its
provider answered with an error, so the reason never reached the chat and
titles and tags broke alongside it; it is placed high, a message that fails
outright costing more than one that reads oddly. It also gains the relevance
figure that a reply drawing on a single source never showed, appearing only
once a second source joined it, and the grey band the attach webpage dialog
carried between its address box and its button.
* chore: add the per-language model wording entries to 0.11.4
Added leads with a model carrying its name, description and starter prompts in
each language, written in the workspace editor or the admin defaults and chosen
by the language the interface is set to, falling back to the plain wording where
that language has none. Every part of it arrived together, so it is one entry.
Changed opens the section for the saving call that now answers with the
suggestions and their per-language wording together where it returned the bare
list, which anything reading that response directly has to account for. No
schema change travels with it, so the section carries no migration warning.
* chore: widen the per-language wording entry in 0.11.4
The mechanism that gave a model its name, description and starter prompts in
each language now covers tools, skills, functions, banners and arena entries
too, each written in the editor that owns it, so the entry names them rather
than standing as a second one beside it. Both commits travel with it.
The response shape entry is unchanged: it is the saving call for the admin
defaults, which this second commit does not touch.
* chore: carry the valve labels and translation table into the wording entry
The entry named only what a resource is called and says about itself, leaving
out the labels on its valves, which are translatable down to the options in a
dropdown, and the table each editor now offers in place of the code when a
language is picked, with the JSON file it reads and writes. An import that
drops a placeholder the original fills in is refused, which is worth the words
it takes to say.
It stays one entry: every part of this arrived together and none of it existed
in another form before.
* chore: add the interface wording and sketch upload entries to 0.11.4
Added records an administrator being able to replace the interface's own
wording language by language, which is a separate thing from a model or a tool
carrying wording of its own and so stands beside that entry rather than joining
it. A replacement that drops a placeholder the original fills in is refused, as
it is for the resources.
Fixed records the Arduino sketch that failed to upload to a knowledge base
because its extension was missing from the list of files read as plain text, so
it went to a document extraction server that answered with something the loader
could not read.
* chore: carry the wording editor follow-ups into the 0.11.4 entry
Two follow-ups tidy the editor the per-language wording is written in, dropping
the line that said whether a field was translated or using the default and
holding back the controls beside a skill or tool name. Neither changes what the
entry describes, so they join its links rather than standing on their own.
The terminal work is left out: the dock it adds is not rendered anywhere yet,
and the rest of that commit rewrites the existing terminal in place and sends
two identifying headers upstream, none of which shows to anyone using it.
* chore: add the document escape sequence entry to 0.11.4
Fixed records the escape sequences in an uploaded file being rewritten before
the text was stored, so what was indexed and what the model read differed from
the file as written, and inconsistently at that, since the rewriting stopped at
the first line holding an angle bracket. It sits beside the sketch upload, both
being corrections to what a file turns into on its way into knowledge.
* chore: add the Apple Silicon and WebKit entries to 0.11.4
Fixed gains the question against a knowledge base that killed the server
outright on a Mac when a reranking model ran locally, placed high, an answer
lost with the connection costing more than one that reads oddly.
It also gains the two separate things the WebKit pull request corrects, kept
apart because a reader meets them as different problems: an assistant reply
coming up blank on Apple devices whose browser never says Safari, and the
sidebar hover preview laid out at the width of a full conversation there since
0.11.0.
* chore: add the terminal dock entry to 0.11.4
Added leads with the terminal pane carrying a tab for every command a model is
running beside the shell, which is the most visible thing in the release for
anyone who watches an agent work.
It was held back earlier on the reading that the dock was built but never
rendered. That reading came from searching a checkout that predated the commit;
the commit swaps the single terminal for the dock in the files pane, so it has
been in front of people since it landed.
* chore: add the note date entry to 0.11.4
Fixed records the date beneath a note title, which was wrapped in a button left
over from an earlier styling pass, so it took a pointing hand and announced
itself as something to press while doing nothing at all. It sits at the foot of
the section beside the dialog banding, both being small corrections to how
something looks rather than what it does.
* chore: add the token logging, model picture and image size entries to 0.11.4
Fixed leads, below the advisory, with the credentials an identity provider
handed over being written into the application log when a sign-in failed part
way through, and with the model picture that any signed-in person could fetch
whatever their access, which also told them whether a model id existed at all.
Both sit above the rest of the section, a credential in a log file and a way to
enumerate what a server holds costing more than anything below them.
Changed records the consequence a viewer will notice: a model picture falling
back to the standard logo wherever no grant is held, which is a change to what
people see rather than a correction, so it is kept apart from the entry above.
Added records the container image losing the second Python it never used.
* chore: gather the image size work and add the docx preview entries to 0.11.4
The image size entry now carries the fonts nothing loaded and the packages
nothing imports alongside the second Python it already named, with all four
pull requests, and states the running total rather than the one measurement it
started from. They are one entry because a reader meets them as one thing: less
to pull.
Changed records what that costs anyone whose tool or function imported a
package it never declared, which worked only while the package happened to be
in the image.
Fixed records the Word document preview no longer rendering an HTML
sub-document embedded in the file, and refusing a link that points anywhere
but a web address, a mail address or a telephone number.
* chore: write the image size figure in digits
The file gives every measurement in digits and spells out only counts of
things, so the size the image loses is written the same way as the ones
recorded before it.
* chore: add the slim image entry to 0.11.4
Changed records the slim image giving up the local models and converters it
carried, so an instance built that way now needs a service configured for
embeddings, vector storage, document extraction past plain text, and speech,
and refuses to build alongside the graphics card or Ollama options. The admin
pages mark what is unavailable and the server answers with what to configure,
both part of the same change.
It is kept out of the image size entry above, which gathers what was carried
and never used; this one removes things that were used and asks for them from
somewhere else.
* chore: correct the slim entry and add the citation link entry to 0.11.4
The slim entry read as though a service had to be configured before the image
would run. It does not: the vector client is built on first use behind a lock,
the speech engine raises only when one is asked for, and extraction raises per
file, so an instance starts and holds a conversation with none of it in place
and each feature asks for what it needs when it is reached. The entry now says
that.
The image size entry gains the slim build leaving behind the tool that
installed its packages and the source maps built beside the interface.
Fixed gains the source attached to a reply opening only where it points at a
web address, which sits with the document preview correction, both being about
where a link in something the model handed back is allowed to go. Portuguese
(Brazil) joins the translation entry.
* chore: add the BuildKit entry and fold the install tool into the size entry
The install tool now leaves every image rather than only the slim one, since it
is mounted for the install step instead of being installed and removed, so the
size entry names it among what the image no longer carries and the slim clause
keeps only the source maps.
Changed records what building the image yourself now takes: the BuildKit
builder, which the syntax line alone did not require before, and reach to the
registry that tool is fetched from.
* chore: add the webhook picture and nameless tool call entries to 0.11.4
Fixed gains the channel webhook picture that anyone signed in could fetch, or
be sent onward to, without belonging to the channel, which sits directly below
the model picture entry, the two being the same gap on two routes.
It also gains the tool call arriving with no name at all, which was kept as it
came, written into the stored message and handed back on the next turn for the
endpoint to refuse, and now fails once where it starts.
The line uninstalling the install tool is not recorded: it went in the same
breath as the mount that made it unnecessary, and the size entry already says
the tool no longer ships.
* chore: add the tool server request entry to 0.11.4
Fixed records a tool call to an OpenAPI tool server repeating in the body the
arguments already placed in the address, which a server checking its input
strictly refused, so reading worked and writing through any such address did
not. It is placed high, a whole class of tool call failing outright costing
more than the corrections below it.
* chore: bring the 0.11.4 date up to the newest change it records
The date was set when the section was opened and left there while entries kept
arriving, so it sat three days behind the last commit it covers.
* chore: add the sign-in form setting entry to 0.11.4
Added records the sign-in form becoming something an administrator can switch
off from the authentication settings. The setting itself is not new, having
been available since before this release as a value read at startup; what is
new is reaching it without restarting the server, so it is recorded as an
addition rather than a change to how signing in works.
The date on the section already stands at the day of this change.
* chore: add the slim backend narrowing entry to 0.11.4
Changed gains the set of things slim will work with at all, which is a separate
matter from the entry above it: that one says the local models are gone and a
service is asked for when a feature reaches for one, this one says which
databases, vector stores and file stores remain, and that being pointed at
anything else stops the server before it starts rather than at first use.
The browser-driven page reader goes with them.
It sits directly below the entry it qualifies.
* chore: say which slim limits stop the server and which do not
The entry put refusing to start against all three limits. Only two behave that
way: the database check raises while the module is read, and the storage
provider is chosen by a call made as the module is read. The vector store is
built on first use, so pointing slim at anything but PostgreSQL for it fails
when something searches, not at startup. The sentence now separates them.
* chore: soften the slim backend entry and cover the browser speech runtime
* chore: lead the 0.11.4 sections with the slimming entries
* chore: cover the slim web search and code interpreter changes
* chore: split the slim limits into their own entries and cover the PDF removal
* chore: fold the dropped Gemini SDK into the tool imports entry
* chore: rewrite the changed entries and cover git leaving the slim image
* chore: drop the entry for the unused PDF endpoint
* chore: cover the tool export scoping and the terminal command echo
* chore: lead with the slim image download size
* chore: cover the model registry rewrite fix
* chore: cover the playwright media skip and lead the registry entry with the cost
* chore: lead the playwright entry with the speed gain
* chore: drop the build and picture entries and retitle the tool imports one
* chore: write the measured image sizes and retitle the page loader entry
* chore: state only how much smaller the images are
* chore: retitle the per-language wording entry
* chore: retitle the terminal tabs entry
* chore: fold the translation coverage entry into translation updates
* chore: date the 0.11.4 section 2026-09-07
* chore: cover continuing a reply in a temporary chat
* chore: write the connection listing role check as a security fix
* chore: keep the connection listing fix brief
* chore: fold the continue reply refinements into its entry
* chore: note the llama.cpp continuation flags
* chore: cover cookie forwarding and the note save on navigation
* chore: cover the model access denial logging
* chore: cover the tool step merge and the model list filters
* chore: cover three fixes from 29494, 29493 and 29325
* chore: note the terminal pane open and collapse behaviour
* chore: cover the settings save rework
* chore: write the settings clobbering fix and trim the api note
* chore: name what the interface permission was blocking
* chore: cover the account menu row highlight
* chore: cover diff blocks, note formatting, tika 4 and the oauth session expiry
* chore: cover folder upload and the file browser selection fixes
* chore: cover file comparison and the query link submit
* chore: cover the task list height cap
* chore: add the server side of the tool call match fix
* chore: cover the exa result length cap
* chore: cover the modal shortcut, build stamp and sticky code headings
* chore: cover knowledge listing order, terminal proxy headers and stale tool links
* chore: cover the forwarded auth type header and terminal attachment name clashes
* chore: cover the misleading model editor permission error
* chore: cover the thread notification and overlapping select chevrons
* chore: cover the OpenAI and Ollama proxy header stripping
* chore: cover stopping every task attached to a chat
* chore: cover code blocks in channel structured output replies
* chore: cover whitespace in model ids and knowledge folder deletion
* chore: cover automation schedule times and mention IDs
* chore: cover the latest translation fills
* chore: note the further pt-BR translation pass
* chore: cover the follow-up suggestion in the message box
* chore: cover notification target names, MCP tool paging and the stop follow-up
* chore: cover thinking blocks, channel terminals and custom header encoding
* chore: cover link schemes, spellcheck, dotless hosts and webhook pictures
* chore: cover tool images, stopped replies, sync errors and terminal proxy limits
* chore: cover malformed tool calls and the direct connection note
* chore: cover the langchain community removal and broken streams
* chore: cover the empty page upload message
* chore: cover embed rendering and two memory leaks
* chore: cover the sign-in limiter, socket cleanup and stored tool images
* docs: changelog entries for terminal skills
* docs: cover the skills:create command and the streaming append option
* docs: cover the model editor save button fix
* docs: fold the skill save location refinements into the skills:create entry
* docs: cover model backgrounds, note range edits and the playwright websocket fix
* docs: link the autoscroll follow-up commit
* docs: cover the responses tool strictness and attachment-only fixes
* docs: widen the non-blocking search entry to the knowledge grep tool
* docs: cover branch descent, checkbox defaults, fork folders, search logging and file access
* docs: cover the direct connection guidance note
* docs: cover tag text leaking into streamed replies
* docs: SVG attachments, Docling conversion failures, title generation logging
* docs: chat unblocked after a failed reply
* docs: directory provisioning patch handling
* docs: settings search matches individual settings
* docs: Staan search, Excel in the code interpreter, pgvector index training, terminal tool gating
* docs: Responses API tool calling
* docs: vector search recall and connections, forking, bundled packages, chat import, image connection checks
* docs: message pair shortcut no longer sends the input
* docs: shortcut recording, note sharing, unarchiving from search, skill saves, recommended badge
* docs: workspace exports cover every prompt and model
* docs: terminal instructions file, sign-in roles, folders, feedback, admin forms
* docs: session revocation, sidebar bulk actions, speech file types, source metadata keys
* docs: model fallback, shared note traffic, recurrence counts, RE2 search, Redis task expiry, direct connection events
Add the entries for the commits since the last pass: the chat model fallback
(#29757) and the shared-note co-editing traffic drop (#28185) in Added, with the
Staan count fix (#30303) folded into the Staan entry and Italian added to the
translation entry. Fixed covers the schedule recurrence and count parsing
(#29262), the RE2-backed file searches, the Redis task expiry and stalled
recurrence guards, the direct-connection events travelling between workers,
the IME guard while renaming a chat, the S3 content-encoding image handling
(#29623) and the sixteen interface and workspace fixes.
* docs: issue references on the fix entries, general improvements without links
Append the issue or discussion each fix PR carries in its body to its
changelog entry, and drop every link from the general improvements entry, which
never carries any.
* docs: model pool cache, message round trips, folder backgrounds, delete shortcut, chat variables
Cover the eight newest dev commits: the per-worker model pool cache (#28176)
and the single-message chat read and write (#28184) in Added, and in Fixed
the knowledge directory scoping, model sharing surviving a save, the folder
background on creation (#30218), the Delete Chat shortcut working wherever
the chat was opened from (#30165) and chat variables a prompt no longer
declares (#30173).
* docs: searchapi results and errors, blocked groups saving, timer owner checks, terminal access rechecks
Cover the four commits still missing from the last pass: the searchapi.io fix
(#30308, with its issue), the OAuth blocked groups save round trip (3fc1146c1,
typed comma lists never took effect), the due-timer owner role check (#30220)
and the terminal session access recheck, which folds its in-cycle introduction
(a1189a2d7) and the cross-worker rework (e8bd0661d) into one entry.
* docs: issue and pull references on the knowledge directory and model sharing entries
The knowledge directory scoping is the landed form of #29887 and the model
sharing fix traces to #30093, which closes#30087; both entries carried only
their commit links.
* docs: memory review gating, channel message quotes, knowledge filter, tool result flushing, localized suggestions
Cover the last dev batch: the background memory review now stops when memory
is switched off or the account is barred (#30309), a deleted channel message
clears the quotes pointing at it (#30314, #30313), the knowledge File content
filter applies on the first click (#30211, #30210), tool results are published
when the round finishes instead of waiting on the stream throttle, with channel
and continuation replies no longer carrying picture data a tool handed the
model, and a fresh install now suggests starter prompts in the interface
language, with a way back to the defaults from the model defaults panel.
* docs: playground image edit request shape
The Images playground edit call wrapped its fields under a heading the
endpoint never read, so every edit came back rejected; the request now carries
them flat (c07fa08b9).
* docs: same-origin diagrams and SVG, read-only folders on the empty-chat page, placeholder translations
Cover the latest dev batch: diagrams and SVG previews only follow same-origin
and data references and a diagram reaching outside is refused (#30271), the
empty-chat page no longer shows folder edit controls for a folder shared
read-only (ee3ece1e2), and translated strings that had their placeholder
names localized or their braces lost are restored across the thirteen locales
(#30326).
{{ models }} -> {{ modelli }} etc. in 10 locales, {{name}} -> {{nombre}} in
gl-ES, {{file}} -> {{arxiu}} in ca-ES, and single/unbalanced braces in kab-DZ,
nb-NO and ca-ES. 22 strings in 13 locales, tokens only.
Mermaid diagrams and the shared SVG sanitizer now accept only same-origin and data: references. Image URLs, class styles and directive config are checked on the parsed diagram before it renders, and the sanitizer drops attribute values and stylesheet rules that point at another origin. use elements keep local #id references only.
SVGPanZoom and the SVG file preview call the shared sanitizer instead of keeping their own configs, so SVG artifacts and uploaded SVG files follow the same rule. Uploaded SVGs that reference external sprites now render those parts blank, which is the point of the change.
A diagram that references an external resource now reports an error instead of rendering, and an SVG artifact keeps everything except the rules that reference one.
With memories disabled instance-wide, or for a user barred from the feature,
the background review still ran every interval turn: it spent a task-model
call drafting memory operations and only then failed at the write, because
the router's permission check rejected it. The review now checks the
'memories.enable' switch and re-checks the 'features.memories' permission
the same way the context-injection path already does, so a model whose memory
capability is on no longer triggers memory work that can never land.
The permission lookup costs a groups query, so it runs last, after the free
config and interval gates; those stay on every turn's hot path.
The due-timer executor rehydrates the owner from the database and now
verifies that the owner is still a user or an admin before entering the
chat completion pipeline, mirroring the check the scheduled-automation
executor already performs. A timer whose owner no longer qualifies is
recorded as an error instead of being run.
Web search via searchapi.io could come back empty or near-empty with no
hint of why: an invalid or expired API key turned into an empty result
set instead of an error, the google_news engine splits its results
between organic_results and top_stories and only the first block was
read, and google links came back as google.com/goto redirects the web
loader cannot fetch, so citations pointed at a redirect blob.
The search now reads both result blocks, asks google engines for
resolved destination links, raises on HTTP errors, carries a 30s request
timeout, skips result rows without a link, and logs the response body at
debug instead of dumping every search at info.
Fixes#30305