Add a custom MIME type (application/x-open-webui-drag) to intentional
chat and folder drag sources. The onDragOver handler in MessageInput
now checks for this type instead of the generic text/plain, which
SortableJS also sets during reorder operations for pinned menu items
(Notes, Workspace) and pinned Models.
* feat(ui): add drag-to-reorder for pinned notes in sidebar
* feat(chat): support folder, note, and model drag-and-drop from sidebar as context references
---------
Co-authored-by: Tim Baek <tim@openwebui.com>
The base model selector in the model creation workspace listed every
model from the global store, ignoring the per-model visibility (hidden)
flag. Models marked as not visible were correctly hidden from the chat
model selector but still appeared in the workspace 'Base Model (From)'
dropdown.
Filter out hidden models (info.meta.hidden) to match the chat selector
behavior, while still keeping a model visible if it is the currently
selected base, so editing a preset built on a now-hidden base does not
show a blank dropdown.
Fixes#25665https://claude.ai/code/session_01CUvzYN9DjvwTpNCT5QL33B
Co-authored-by: Claude <noreply@anthropic.com>
A trailing space in the Open Terminal bearer token broke only the
interactive terminal: HTTP calls put the token in the Authorization
header, where the spec strips trailing whitespace, so the connection
test, file listing and tool calls all worked. The terminal WebSocket
can't set headers from the browser, so it sends the token inside a JSON
auth message that preserves the space verbatim, failing auth with
[Connection closed]. Normalize the key on save so whitespace never
enters storage, and trim it in the WebSocket auth message so existing
saved configs work without re-saving.
Fixes#25613
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Sign Out button on the Account Pending overlay only cleared the
local token and redirected to /auth, skipping the backend signout. This
left the OAuth/OIDC session alive at the IdP, so re-login bounced the
user straight back into pending and never re-fetched updated role/group
claims. Call userSignOut() and honor the returned redirect_url, matching
the sidebar logout flow.
Fixes#25644
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The file picker and Files modal only render filenames and metadata, but
searchFiles()/getFiles() never passed content=false, so the backend
serialized data.content (full extracted text) of every file into each
response. On instances with many large documents this turns a metadata
list into tens of MB per request, re-issued on every picker keystroke.
The backend already supports content=false on GET /files/ and
GET /files/search; this just makes the list/search callers opt out of the
payload by default. The param stays overridable for callers that need it.
Fixes#25741
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A chat created in place (new chat -> first message) keeps chatIdProp
undefined because the URL is swapped via history.replaceState without a
remount, so none of the chatIdProp-gated updateLastReadAt paths fire and
the chat is never persisted with a last_read_at. Starting another new
chat via initNewChat reset $chatId without marking the outgoing chat
read, so on refresh updated_at > last_read_at (NULL) and the chat shows
as unread in the sidebar.
Mark the outgoing chat read in initNewChat, mirroring navigateHandler.
Fixes#25108
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(calendar): add repeat/recurrence dropdown to event modal
* fix(calendar): anchor recurring event expansion to event start date
The expand_recurring_event() utility used the view range start as dtstart,
causing FREQ=WEEKLY events to land on the wrong day of the week. Use the
event's original start date instead so recurrence patterns stay correct.