Commit Graph
17899 Commits
Author SHA1 Message Date
Classic298 be9af1653e fix: anchor chat input expand button to the input row (#27676)
The "expand input" button was positioned with `fixed top-0 right-0`. That only kept it near the composer by accident: `#message-input-container` sets `backdrop-blur-sm`, and a backdrop-filter makes an element the containing block for fixed descendants, so the button resolved to the top-right corner of the entire composer instead of the text area it belongs to.

That corner is already taken. The `@`-tagged model chip renders as the first row of the same container with its dismiss button at the right end, so with a multi-line prompt and a tagged model the two controls are drawn on top of each other. The attached-files row has the same problem: the button paints over the first thumbnail and its remove button.

Anchor the button to the wrapper that holds the text area instead, using `relative`/`absolute`, so it always sits at the top-right of the input row and below whatever rows precede it. With no chip and no files the position is unchanged. As a side effect the button is no longer a child of the `overflow-auto` scroller, so it can no longer be clipped or scrolled out of view on long prompts.

Fixes #26736
2026-08-10 23:26:53 -06:00
G30andNameless-Monster-Nerd b91bb67b55 fix: hide chat fork actions when chat import permission is disabled (#27711)
Co-authored-by: Nameless-Monster-Nerd <Nameless-Monster-Nerd@users.noreply.github.com>
2026-08-10 23:24:59 -06:00
Classic298 5c79ccc9e5 refactor: walk chat message history by map key (#28034)
`get_message_list` moves through `messages_map` by key but tracked each message's own `id` field, which the message body does not have to carry. Track the key instead.
2026-08-10 23:24:41 -06:00
G30 80d2f4154a fix: align public_tools and public_notes sharing defaults with config (#27716)
The SharingPermissions model defaulted public_tools and public_notes to
True while the config defaults (USER_PERMISSIONS_WORKSPACE_TOOLS_ALLOW_PUBLIC_SHARING
and USER_PERMISSIONS_NOTES_ALLOW_PUBLIC_SHARING) are both False.

On an instance whose stored user.permissions config predates these keys,
GET /api/v1/users/default/permissions fills the gap from the model and
reports both as enabled, while has_permission fills it from
DEFAULT_USER_PERMISSIONS and denies. Saving any unrelated permission then
persists the model's True, granting public tool and note sharing the admin
never enabled.
2026-08-10 23:24:18 -06:00
G30 a3d33b4cf3 fix: hide chat delete actions when the chat delete permission is disabled (#27714)
The chat delete endpoints gate on chat.delete for non-admins, but none of
the UI affordances that reach them were conditioned on it, so a user
without the permission is offered controls that always fail with
"Access prohibited".

Gates every entry point on the same condition the backend enforces,
matching the existing chat.share / chat.export / chat.import gates in the
same components:

- Sidebar chat menu (ChatMenu) Delete item — also covers the Search
  modal's menu, which reuses ChatMenu
- Sidebar Shift+hover inline Delete button (ChatItem)
- Sidebar hidden #delete-chat-button keyboard-shortcut target (ChatItem)
- Chat navbar menu Delete item (Navbar/Menu)
- Search modal Shift-held inline Delete button (SearchModal)
- Settings -> Data Controls -> Delete All Chats
- Settings -> Archived Chats per-row Delete
2026-08-10 23:24:02 -06:00
G30 fe62934be7 fix: derive overview node spacing from rem so branches never overlap (#27995) 2026-08-10 23:23:31 -06:00
Classic298andClaude 2207876ae7 fix: generate valid WEBUI_SECRET_KEY in start_windows.bat (#28061)
The key generation loop redirected input from a non-existent file
(`SET /p WEBUI_SECRET_KEY=<!random!>>%KEY_FILE%`), printing "The system
cannot find the file specified." once per iteration and leaving the key
file empty, so startup failed with "WEBUI_SECRET_KEY is not set".

Build a fixed-length alphanumeric key by indexing into a charset with
%RANDOM% and write it once with `<nul set /p`. Also quote the key file
path and use delayed expansion so paths with spaces work.


Claude-Session: https://claude.ai/code/session_01CmgBivWjad68mX4yBVWMi2

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-10 23:22:43 -06:00
Timothy Jaeryang Baek bd8378f643 refac 2026-08-10 23:22:08 -06:00
Classic298 1f22cccd22 perf: stop formatting every exported log record twice under OTEL log export (#27840)
With ENABLE_OTEL and ENABLE_OTEL_LOGS set, InterceptHandler builds the message once for loguru and then hands the same LogRecord to the OpenTelemetry handler, whose _translate calls record.getMessage() a second time. That used to be free, because the message was already a finished f-string with nothing to substitute. Now that log calls pass lazy %-args, the second call re-runs the whole interpolation, so every exported record is formatted twice.

The two getMessage() calls on a 78 kB retrieval record:

    before  373.0 us
    after     0.1 us

Stamping the built message back onto the record makes the second call a plain string return. msg and args are both in OpenTelemetry's _RESERVED_ATTRS, so neither ever reaches the exported attributes. The isinstance guard matters: _translate exports a non-str msg such as the dicts routers/audio.py logs as a typed body rather than a string, so those records are left untouched, and they have no %-args to format twice anyway. Body, attributes and severity were compared against LoggingHandler._translate for str, dict, list, int, None, exception and exc_info records.
2026-08-10 23:13:52 -06:00
Timothy Jaeryang Baek ce3c175e26 refac 2026-08-10 23:13:10 -06:00
Timothy Jaeryang Baek de289eb1aa refac 2026-08-10 23:07:47 -06:00
Timothy Jaeryang Baek d8ae7ed405 refac 2026-08-10 23:01:41 -06:00
Cypandbglee bee1ded5ab i18n: update Korean translations (#27681)
Co-authored-by: bglee <bglee@hct.co.kr>
2026-08-10 23:01:24 -06:00
Timothy Jaeryang Baek 629cdcb530 refac 2026-08-10 22:57:21 -06:00
Timothy Jaeryang Baek 89922cc9d5 refac 2026-08-10 22:53:37 -06:00
Timothy Jaeryang Baek 2a6e671f54 refac 2026-08-10 22:47:39 -06:00
Timothy Jaeryang Baek c2107e5bb3 refac 2026-08-10 22:36:42 -06:00
Kylapaallikko b7de04da14 Update fi-FI translation.json (#27700)
Added missing translations and improved existing ones.
2026-08-10 22:27:44 -06:00
G30 38a03830c2 fix: show a placeholder when an image cannot be loaded (#27730)
A message referencing a file that no longer exists rendered a broken
image, because nothing anywhere noticed the failed load. What the user saw
depended on the caller's alt text: in a response the alt is the message
content, so the entire reply was rendered inside the image frame, and the
preview still opened full-screen on a dead image.

Image.svelte now tracks a failed load and renders an 'Image unavailable'
placeholder instead, suppressing the preview for a source that cannot be
shown. The failed state resets when the source changes, so a replaced or
corrected URL is retried. An onError callback lets a caller react without
changing behaviour for the eight existing call sites, which are untouched.

Responses now pass the file name (or 'Generated Image') as alt rather than
the message content, which was never a description of the image.
2026-08-10 22:27:13 -06:00
Timothy Jaeryang Baek 0b4b7ae5ff refac 2026-08-10 22:20:53 -06:00
G30 04c22f0c41 fix: use the local date for the event modal's default start and end (#27779) 2026-08-10 22:19:54 -06:00
Classic298 3dbb4078b3 fix: repair two broken logging calls, one of which makes VECTOR_DB=opengauss unusable (#27838)
SRC_LOG_LEVELS became an empty dict when per-module log levels were dropped, and env.py keeps it only as a legacy name. opengauss.py is the last thing in the tree that still indexes it, at module scope, so importing the module raises KeyError: 'RAG' and any deployment on VECTOR_DB=opengauss dies the first time it touches the vector store. The factory imports it lazily, which is why nothing else trips over it. Deleting the line is the whole fix: every other vector backend takes getLogger(__name__) and inherits the root level.

colbert.py passes an argument to a message with no placeholder to consume it:

    log.info('ColBERT: Loading model', name)

At INFO, which is the default, logging evaluates 'ColBERT: Loading model' % ('colbert-ir/colbertv2.0',) and raises TypeError: not all arguments converted during string formatting. The record is swallowed by handleError, so loading a ColBERT reranker prints '--- Logging error ---' plus a traceback to stderr instead of the model name. Adding %s prints the name and drops the traceback.
2026-08-10 22:19:41 -06:00
Timothy Jaeryang Baek 3793b0c886 refac 2026-08-10 22:15:54 -06:00
Timothy Jaeryang Baek 3e9b075954 refac 2026-08-10 22:11:05 -06:00
Timothy Jaeryang Baek 2a45fa04cb refac 2026-08-10 21:58:12 -06:00
Teitur BendtsenandT209211 b74c144c96 i18n: add Faroese translation (#28159)
Co-authored-by: T209211 <tbe@betri.fo>
2026-08-10 21:51:45 -06:00
Adam I. Horvath cbd47eaa67 i18n: improve hungarian translations (#28214)
adds missing hungarian translations and improves existing hungarian ui labels.
2026-08-10 21:44:40 -06:00
Classic298 38fcee7f21 Update pull_request_template.md (#28246) 2026-08-10 21:43:33 -06:00
developersorli f44647e251 feat(i18n): add complete Slovenian (sl-SI) translations (#28268) 2026-08-10 21:43:02 -06:00
Classic298andTim Baek a680f21e12 feat: make OAuth admin settings read-only when ENABLE_OAUTH_PERSISTENT_CONFIG is off (#28276)
When ENABLE_OAUTH_PERSISTENT_CONFIG is off (the default), oauth.* config is
never persisted and is read from environment variables, but the admin panel
still let admins edit the OAuth/OIDC fields and silently dropped every save on
restart, which kept confusing users who missed the docs warning
(open-webui/open-webui#28247).

The OAuth/OIDC section is now read-only in that case: the admin oauth config
endpoint reports the flag and the UI wraps the section in a disabled fieldset,
slightly dimmed with every control inert but all values still visible, plus a
note naming the env var. Saving skips the OAuth POST since nothing can change.
With the flag enabled the section behaves exactly as before.

Known limits: the guard is UI-side only (the POST endpoint keeps accepting
writes, unchanged), and disabled fields mean values cannot be selected and the
masked client secret cannot be revealed while read-only. Switch.svelte gains a
disabled:cursor-not-allowed style that applies to any disabled switch app-wide.

Co-authored-by: Tim Baek <tim@openwebui.com>
2026-08-10 21:41:07 -06:00
G30 a3e5d0b362 fix(chat): attribute shared chat messages to their author, not the viewer (#28274) 2026-08-10 21:40:54 -06:00
Timothy Jaeryang Baek 8edab5020e refac 2026-08-10 21:39:27 -06:00
Timothy Jaeryang Baek 3c010951db refac 2026-08-10 21:21:52 -06:00
Timothy Jaeryang Baek 48a5696042 refac 2026-08-10 21:06:40 -06:00
Timothy Jaeryang Baek d6679082e5 refac 2026-08-10 21:00:01 -06:00
Timothy Jaeryang Baek 943294df9a refac 2026-08-10 20:46:38 -06:00
G30 d661fb49b8 ci: relabel bug reports when the title is corrected after opening (#28333)
The labeler only listened for issues.opened, so it judged a title exactly
once. Reporters who omit the prefix are asked by the triage bot to add one,
and the title they then fix is never looked at again, leaving a genuine bug
report unlabelled until somebody notices it by hand.

It now also runs on issues.edited. Body only edits return immediately, so
the extra runs are limited to titles actually changing, and a bug label a
maintainer has already removed is not restored: on an edit the issue events
are checked for a previous removal first. The opened path is unchanged and
makes no additional API call.

The title pattern also required a delimiter after the bracket, so the
bracketed form the comment advertises, "[Bug] something is broken", never
matched unless it happened to be written "[Bug]: something is broken".
Both forms match now, while "[bug/perf]" keeps matching and titles that
merely mention the word, such as "[UI Bug]" or "fixed a typo", still do not.
2026-08-10 20:45:02 -06:00
G30 d10d552117 fix(chats): surface the error message instead of [object Object] (#28260) 2026-08-10 20:44:32 -06:00
Timothy Jaeryang Baek 178ccb30e1 refac 2026-08-10 20:37:53 -06:00
Timothy Jaeryang Baek 5cecb7dbfa refac 2026-08-10 20:30:56 -06:00
G30 148283f974 fix: release a queued message once an attached URL finishes (#28381)
A message sent while an attachment is still uploading is held in the chat
queue until the file settles. For files that release works, because the
message input calls onUpdate once the upload completes, which refreshes the
queued entry and asks the queue to run.

Attaching a URL takes a different path. uploadWeb sets the item to uploaded
but calls neither onUpdate nor processNextInQueue, and the queue is
otherwise only revisited when a generation finishes or when the chat is
mounted while idle. In a new chat with nothing generating, none of those
happen, so a message queued behind a URL waits with no event able to
release it until the chat is reloaded.

uploadWeb now asks the queue to run when it is done, the same way the file
path already does.
2026-08-10 20:24:35 -06:00
Timothy Jaeryang Baek b20bcdbba7 refac 2026-08-10 20:22:29 -06:00
Timothy Jaeryang Baek 5ec16e76e6 refac 2026-08-10 20:13:03 -06:00
Classic298 5462c02af0 fix: OIDC login fails when the provider adds a private JOSE header (#28065)
Logging in through CyberArk Identity dies at the callback with "Unsupported {'app_id'} in header" and the user sees "The email or password provided is incorrect". Any provider that puts a vendor-specific parameter in the ID token header hits this; CAS was already patched by name, CyberArk is the next one.

Authlib 1.7 verifies ID tokens with joserfc, which rejects header parameters it does not recognise. The old fix registered `client_id` so CAS would work, which only ever fixes one provider at a time. This turns off the unknown-header rejection instead, so any private header parameter is ignored rather than fatal. Signature verification, the algorithm allowlist, `crit` handling and value validation of registered headers all still run, so nothing that actually protects the token is relaxed.

Fixes #28062
2026-08-10 20:06:31 -06:00
Timothy Jaeryang Baek a41faa3c22 refac 2026-08-10 20:00:43 -06:00
Classic298 c5ec01b1f9 fix: make the aiodns resolver opt-in and pin aiodns to 3.6.1 (#28242)
Since v0.11.0 shipped aiodns, aiohttp silently switched every outbound request from the OS resolver to c-ares. On some Windows hosts the bundled c-ares 1.34.6 (pycares 5) discovers only 127.0.0.1:53 as nameserver, so every external provider lookup fails (#28013). In Docker the long-lived c-ares channel intermittently stops resolving container names while Docker's embedded DNS keeps answering, which wipes the Ollama model list and fails all in-flight chats with a misleading "Model not found" (#28215).

This restores the pre-0.11 ThreadedResolver (OS resolver) by default and gates the c-ares path behind a new env var, AIOHTTP_CLIENT_ASYNC_DNS_RESOLVER, off by default. The event-loop DNS perf improvement is now opt-in for deployments whose resolver setup is known to work with c-ares, instead of a process-wide side effect of the package being installed.

aiodns is also downgraded and pinned to 3.6.1 (pycares<5), the last release before the broken c-ares 1.34.6 build, so opting in does not hit the Windows regression. The hardcoded AsyncResolver in the Mistral OCR loader now follows the same switch. Simply removing aiodns instead was not an option because opting in would then be impossible, and #28215 showed the Docker failure is c-ares itself, not aiodns 4.x.
2026-08-10 19:52:29 -06:00
Timothy Jaeryang Baek 8d1c205d8e refac 2026-08-10 19:46:46 -06:00
Timothy Jaeryang Baek b606e13da3 refac 2026-08-10 19:44:56 -06:00
Classic298 eff5c4a2d9 feat: parse :::writing block metadata and use the subject as the block title (#28280)
Newer OpenAI chat models put metadata on the opening line of a colon fence block, like :::writing{variant="email" id="48173" subject="Short question" recipient="mail@example.com"}. The tokenizer matched that line and discarded it, so every block rendered under the same generic "Writing" heading no matter what it contained.

The opening line is now parsed into an attributes map on the token and the header uses it: the subject becomes the title, the recipient follows it and the full string is reachable on hover when the row is too narrow for it. Blocks without metadata render exactly as before, and the other fence types get the parsed attributes for free.

Attributes are read only from inside the {...} braces, not from the whole opening line. Scanning the whole line turned ordinary prose containing key="value" into metadata, and it backtracked quadratically: a 40k character opening line took 586ms to parse, and that runs again on every re-lex while the message streams. Anchored to the braces it is 0.0ms.

Nothing here turns the recipient into a link or a send action. That metadata is model output and can be steered by whatever is in the context, so a prefilled mail action is a separate decision rather than a side effect of parsing.
2026-08-10 19:44:06 -06:00
Timothy Jaeryang Baek 385d08bea5 refac 2026-08-10 19:42:05 -06:00