[PR #18357] [CLOSED] feat(websockets): Enable multi-tab support by isolating WebSocket connections #63619

Closed
opened 2026-05-06 08:30:54 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/open-webui/open-webui/pull/18357
Author: @MyoungHaSong
Created: 10/15/2025
Status: Closed

Base: devHead: feat/multi-tab-websocket-isolation


📝 Commits (1)

  • 3beab85 feat(websockets): Isolate WebSocket connections per browser tab

📊 Changes

14 files changed (+73 additions, -34 deletions)

View changed files

📝 backend/open_webui/functions.py (+1 -1)
📝 backend/open_webui/socket/main.py (+18 -9)
📝 backend/open_webui/utils/chat.py (+3 -2)
📝 src/lib/components/channel/Channel.svelte (+3 -2)
📝 src/lib/components/channel/MessageInput.svelte (+2 -1)
📝 src/lib/components/channel/Thread.svelte (+2 -1)
📝 src/lib/components/chat/Chat.svelte (+1 -1)
📝 src/lib/components/chat/ContentRenderer/FloatingButtons.svelte (+2 -1)
📝 src/lib/components/common/RichTextInput.svelte (+5 -0)
📝 src/lib/components/layout/Sidebar.svelte (+1 -1)
📝 src/lib/components/notes/NoteEditor.svelte (+1 -1)
📝 src/lib/stores/index.ts (+1 -1)
📝 src/routes/+layout.svelte (+30 -13)
📝 vite.config.ts (+3 -0)

📄 Description

This change introduces WebSocket connection isolation for each browser tab,
resolving interference issues when multiple Open WebUI tabs are open
simultaneously.

Previously, all tabs shared a single WebSocket event stream, causing messages and
UI updates intended for one tab to incorrectly appear in others. This also led to
connection drops and unresponsive chats.

Key changes:

  • Backend: The get_event_emitter function now accepts a broadcast: bool
    parameter. By setting broadcast=False for user-specific events (like chat
    streaming), messages are now directed only to the originating client's session ID
    (sid).

  • Frontend: Refactored the WebSocket handling to use Svelte's Context API. Each
    tab's component tree now maintains its own isolated socket instance, preventing
    cross-tab state pollution. This affects Chat, Channel, and other real-time
    components.

  • Bug Fix: A RangeError in RichTextInput (ProseMirror) is now guarded
    against, improving editor stability.

  • Build: Added y-protocols/awareness to vite.config.ts optimizeDeps to
    prevent potential pre-bundling issues.

Closes #16219

Pull Request Checklist

Before submitting, make sure you've checked the following:

  • Target branch: Verify that the pull request targets the dev branch.
  • Description: Provide a concise description of the changes made in this
    pull request.
  • Changelog: Ensure a changelog entry following the format of Keep a
    Changelog
    is added at the bottom of the PR
    description.
  • Documentation: If necessary, update relevant documentation.
  • Dependencies: No new dependencies added.
  • Testing: Manual testing performed across multiple tabs, direct
    connections, and pipeline requests.
  • Agentic AI Code: This PR has gone through human review and manual
    testing.
  • Code review: Self-review performed.
  • Title Prefix: feat prefix used to indicate new feature.

Changelog Entry

Description

Enables true multi-tab support by isolating WebSocket connections per browser tab.
Fixes issue where chat responses and UI updates from one tab would incorrectly
appear in other tabs, causing connection interference and unresponsive chats.

Added

  • Backend broadcast parameter to get_event_emitter function for targeted
    message delivery
  • Frontend Context API-based socket management for tab isolation
  • Guard clause in RichTextInput.svelte to prevent ProseMirror RangeError

Changed

  • Backend: Modified get_event_emitter in socket/main.py to accept broadcast: bool parameter
  • Backend: Updated utils/chat.py to use broadcast=False for chat streaming
    events (2 locations)
  • Backend: Updated functions.py to use broadcast=False for function execution
    events
  • Frontend: Refactored +layout.svelte to create tab-specific socket instances
    using Context API
  • Frontend: Updated 7 components to consume socket from context instead of global
    store:
    • Chat.svelte
    • ContentRenderer/FloatingButtons.svelte
    • Channel.svelte
    • Thread.svelte
    • MessageInput.svelte
    • Sidebar.svelte
    • NoteEditor.svelte
  • Build: Added y-protocols/awareness to vite.config.ts optimizeDeps

Fixed

  • WebSocket connection interference between multiple browser tabs
  • Chat responses appearing in wrong tabs
  • Connection drops when multiple tabs are active
  • Unresponsive pipeline and direct connection requests in multi-tab scenarios
  • ProseMirror RangeError when cursor is at position 0 in RichTextInput

Additional Information

Testing performed:

  1. Opened two separate browser tabs
  2. Started chat in Tab 1 with streaming response
  3. Started different chat in Tab 2 while Tab 1 was still streaming
  4. Verified responses were isolated to correct tabs
  5. Tested direct connections and pipeline requests in both tabs
  6. Confirmed no connection drops or interference

Technical approach:

  • Backend uses session ID (sid) targeting instead of broadcasting to all user
    connections
  • Frontend uses Svelte's getContext/setContext to provide tab-local socket
    instances
  • Each tab's component tree maintains independent WebSocket state

Contributor License Agreement

By submitting this pull request, I confirm that I have read and fully agree to the
Contributor License Agreement (CLA), and I am providing my contributions under its
terms.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/open-webui/open-webui/pull/18357 **Author:** [@MyoungHaSong](https://github.com/MyoungHaSong) **Created:** 10/15/2025 **Status:** ❌ Closed **Base:** `dev` ← **Head:** `feat/multi-tab-websocket-isolation` --- ### 📝 Commits (1) - [`3beab85`](https://github.com/open-webui/open-webui/commit/3beab8518d3ff1a88e8ec216af16699f7660f2e1) feat(websockets): Isolate WebSocket connections per browser tab ### 📊 Changes **14 files changed** (+73 additions, -34 deletions) <details> <summary>View changed files</summary> 📝 `backend/open_webui/functions.py` (+1 -1) 📝 `backend/open_webui/socket/main.py` (+18 -9) 📝 `backend/open_webui/utils/chat.py` (+3 -2) 📝 `src/lib/components/channel/Channel.svelte` (+3 -2) 📝 `src/lib/components/channel/MessageInput.svelte` (+2 -1) 📝 `src/lib/components/channel/Thread.svelte` (+2 -1) 📝 `src/lib/components/chat/Chat.svelte` (+1 -1) 📝 `src/lib/components/chat/ContentRenderer/FloatingButtons.svelte` (+2 -1) 📝 `src/lib/components/common/RichTextInput.svelte` (+5 -0) 📝 `src/lib/components/layout/Sidebar.svelte` (+1 -1) 📝 `src/lib/components/notes/NoteEditor.svelte` (+1 -1) 📝 `src/lib/stores/index.ts` (+1 -1) 📝 `src/routes/+layout.svelte` (+30 -13) 📝 `vite.config.ts` (+3 -0) </details> ### 📄 Description This change introduces WebSocket connection isolation for each browser tab, resolving interference issues when multiple Open WebUI tabs are open simultaneously. Previously, all tabs shared a single WebSocket event stream, causing messages and UI updates intended for one tab to incorrectly appear in others. This also led to connection drops and unresponsive chats. Key changes: - **Backend:** The `get_event_emitter` function now accepts a `broadcast: bool` parameter. By setting `broadcast=False` for user-specific events (like chat streaming), messages are now directed only to the originating client's session ID (sid). - **Frontend:** Refactored the WebSocket handling to use Svelte's Context API. Each tab's component tree now maintains its own isolated socket instance, preventing cross-tab state pollution. This affects Chat, Channel, and other real-time components. - **Bug Fix:** A `RangeError` in `RichTextInput` (ProseMirror) is now guarded against, improving editor stability. - **Build:** Added `y-protocols/awareness` to `vite.config.ts` optimizeDeps to prevent potential pre-bundling issues. Closes #16219 # Pull Request Checklist **Before submitting, make sure you've checked the following:** - [x] **Target branch:** Verify that the pull request targets the `dev` branch. - [x] **Description:** Provide a concise description of the changes made in this pull request. - [x] **Changelog:** Ensure a changelog entry following the format of [Keep a Changelog](https://keepachangelog.com/) is added at the bottom of the PR description. - [ ] **Documentation:** If necessary, update relevant documentation. - [ ] **Dependencies:** No new dependencies added. - [x] **Testing:** Manual testing performed across multiple tabs, direct connections, and pipeline requests. - [x] **Agentic AI Code:** This PR has gone through human review and manual testing. - [x] **Code review:** Self-review performed. - [x] **Title Prefix:** `feat` prefix used to indicate new feature. # Changelog Entry ### Description Enables true multi-tab support by isolating WebSocket connections per browser tab. Fixes issue where chat responses and UI updates from one tab would incorrectly appear in other tabs, causing connection interference and unresponsive chats. ### Added - Backend `broadcast` parameter to `get_event_emitter` function for targeted message delivery - Frontend Context API-based socket management for tab isolation - Guard clause in `RichTextInput.svelte` to prevent ProseMirror RangeError ### Changed - Backend: Modified `get_event_emitter` in `socket/main.py` to accept `broadcast: bool` parameter - Backend: Updated `utils/chat.py` to use `broadcast=False` for chat streaming events (2 locations) - Backend: Updated `functions.py` to use `broadcast=False` for function execution events - Frontend: Refactored `+layout.svelte` to create tab-specific socket instances using Context API - Frontend: Updated 7 components to consume socket from context instead of global store: - `Chat.svelte` - `ContentRenderer/FloatingButtons.svelte` - `Channel.svelte` - `Thread.svelte` - `MessageInput.svelte` - `Sidebar.svelte` - `NoteEditor.svelte` - Build: Added `y-protocols/awareness` to `vite.config.ts` optimizeDeps ### Fixed - WebSocket connection interference between multiple browser tabs - Chat responses appearing in wrong tabs - Connection drops when multiple tabs are active - Unresponsive pipeline and direct connection requests in multi-tab scenarios - ProseMirror RangeError when cursor is at position 0 in `RichTextInput` ### Additional Information **Testing performed:** 1. Opened two separate browser tabs 2. Started chat in Tab 1 with streaming response 3. Started different chat in Tab 2 while Tab 1 was still streaming 4. Verified responses were isolated to correct tabs 5. Tested direct connections and pipeline requests in both tabs 6. Confirmed no connection drops or interference **Technical approach:** - Backend uses session ID (sid) targeting instead of broadcasting to all user connections - Frontend uses Svelte's `getContext`/`setContext` to provide tab-local socket instances - Each tab's component tree maintains independent WebSocket state ### Contributor License Agreement By submitting this pull request, I confirm that I have read and fully agree to the Contributor License Agreement (CLA), and I am providing my contributions under its terms. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-05-06 08:30:54 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#63619