Implement client-session routing for Agent Web Socket Server#2175
Implement client-session routing for Agent Web Socket Server#2175GeorgeNgMsft merged 24 commits intomainfrom
Conversation
Set exit code instead of calling exit directly. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…be a critical exception
…icrosoft/TypeAgent into dev/georgeng/fix_as_easddr_use
…, rather than naive incremental retries
…icrosoft/TypeAgent into dev/georgeng/fix_as_easddr_use
…, IPC bridge) Implements /session slash commands (list, new, switch, rename, delete) in the renderer, a dropdown session selector in the chat header, and the main-process IPC bridge with a local backend stub for in-process dispatcher mode. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…om/microsoft/TypeAgent into dev/georgeng/websocket_session_map
|
This is a bigger change, we'll want to review this when working on the shell/browser extension clients |
Actually, since the session operations aren't implemented on the clients yet, I think this is okay to merge in for now and iterate upon further after review. |
There was a problem hiding this comment.
Pull request overview
This PR updates the browser agent’s process-wide AgentWebSocketServer to support multiple concurrent TypeAgent sessions by routing each WebSocket connection to per-session handler sets using a sessionId query parameter, and adds initial shell-side UI/API scaffolding for session management.
Changes:
- Add
sessionIdto the browser WebSocket connection URL and route connections via per-session handler registration onAgentWebSocketServer. - Update browser-agent components to use session-scoped active-client selection (
getActiveClient(sessionId, ...), etc.). - Add shell renderer UI (/session slash commands + session selector) and main/preload IPC plumbing for session management (local backend stub for now).
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| ts/packages/utils/webSocketUtils/src/webSockets.ts | Adds optional sessionId query parameter to generic WebSocket creation helper. |
| ts/packages/shell/src/renderer/src/webSocketAPI.ts | Adds session-management methods to the mobile/web fallback ClientAPI (mostly unsupported stubs). |
| ts/packages/shell/src/renderer/src/main.ts | Installs a session selector UI and wires sessionChanged callback into the renderer client. |
| ts/packages/shell/src/renderer/src/chat/sessionSelector.ts | New session selector dropdown UI that calls session APIs. |
| ts/packages/shell/src/renderer/src/chat/sessionCommands.ts | New /session command handler executing session actions via ClientAPI and posting results to chat. |
| ts/packages/shell/src/renderer/src/chat/chatView.ts | Intercepts /session commands before forwarding input to the dispatcher. |
| ts/packages/shell/src/renderer/assets/styles.less | Adds styling for the session selector/dropdown (light + dark mode). |
| ts/packages/shell/src/preload/electronTypes.ts | Extends ClientAPI and Client with session-management methods/types and sessionChanged callback. |
| ts/packages/shell/src/preload/chatView.ts | Adds IPC wiring for session management invokes and a session-changed push event to renderer. |
| ts/packages/shell/src/main/sessionManager.ts | New main-process IPC handler registration + local-mode backend stub for session APIs. |
| ts/packages/shell/src/main/instance.ts | Registers/unregisters the session IPC handlers for the shell instance lifecycle. |
| ts/packages/shell/src/main/browserIpc.ts | Supplies a sessionId when creating the inline-browser WebSocket connection. |
| ts/packages/agents/browser/src/extension/serviceWorker/websocket.ts | Appends sessionId (from extension settings) to the extension’s WS connection URL. |
| ts/packages/agents/browser/src/agent/webTypeAgent.mts | Routes web agent traffic to the session’s active client via getActiveClient(sessionId). |
| ts/packages/agents/browser/src/agent/rpc/externalBrowserControlClient.mts | Makes external browser control client session-aware when choosing the active extension client. |
| ts/packages/agents/browser/src/agent/knowledge/progress/knowledgeWebSocketBridge.mts | Sends knowledge progress events to the active client for the current session. |
| ts/packages/agents/browser/src/agent/import/importWebSocketHandler.mts | Sends import progress events to the active client for the current session. |
| ts/packages/agents/browser/src/agent/browserActions.mts | Adds sessionId to browser action context and adjusts request-to-client routing logic. |
| ts/packages/agents/browser/src/agent/browserActionHandler.mts | Registers/unregisters per-session handlers on the WS server and assigns a sessionId during context init. |
| ts/packages/agents/browser/src/agent/agentWebSocketServer.mts | Implements per-session handler registration and session-scoped active-client selection/routing. |
| ts/packages/agents/browser/README.md | Documents the updated WebSocket server architecture, routing, and URL format. |
Comments suppressed due to low confidence (1)
ts/packages/agents/browser/src/agent/browserActionHandler.mts:317
sessionIdis generated as a random UUID whenclientBrowserControlis undefined (extension-only mode), but the extension WebSocket client defaults tosessionId = "default"unless the user configures it. This makes the out-of-box extension-only flow unable to connect to the session handlers (client connects underdefault, handlers register under a random UUID). Consider defaulting to a stable session id (e.g.,"default") and/or plumbing an explicit sessionId throughAppAgentInitSettings.optionsso the agent and clients can agree on the same value.
return {
sessionId: clientBrowserControl ? "default" : crypto.randomUUID(),
clientBrowserControl,
useExternalBrowserControl: clientBrowserControl === undefined,
preferredClientType:
clientBrowserControl === undefined ? "extension" : "electron",
index: undefined,
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Problem
AgentWebSocketServer is a process-level singleton, but updateBrowserContext() was assigning its invoke handlers and connection/message callbacks as direct fields — overwriting them on every call. With multiple concurrent TypeAgent sessions, each new enable call would silently reroute all client traffic to the most recently activated session context, causing the wrong session to handle browser actions, web agent messages, and client connect/disconnect events.
Solution
Replace the shared callback fields with a Map<sessionId, SessionHandlers> so each session owns its own isolated handler set. Client connections are routed to the correct session by embedding sessionId in the WebSocket connection URL as a query parameter.
Notes
Added Architecture section documenting the WebSocket server, connection URL format, session routing, client type detection, and channel multiplexing