MemberJunction / MemberJunction/MJ

Realtime surface tabs: no way to close a single live channel — only ending the call removes it

Open
#3,498 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
TSQL
Stars
29
Forks
6
Avg merge
1d 8h
Merged PRs (30d)
308

Description

Observed on MJ 5.51.0, client-direct realtime session with two channels active (Whiteboard + Remote Browser).

## What happens

Once two channel surfaces are open there is no way to close just one. The user who is done with the browser but still wants the whiteboard has only one option: end the call — which tears down both, plus the voice session.

## Why

`RealtimeSurfaceTabsComponent.RemoveTab(key)` exists and does the right thing (Activity is irremovable, focus falls back). But its only callers are review-mode cleanup in `RealtimeSessionOverlayComponent` — `cleanupStaleReviewBoardTab()` and `exitReview()`. No live channel tab renders a close affordance, and there is no corresponding teardown on the session side: `RealtimeSessionService` exposes no `CloseChannel` / `StopChannel` / `RemoveChannel`, so even calling `RemoveTab` on a live channel would hide the surface while leaving the plugin initialized, its tools advertised to the model, and (for Remote Browser) a server-side headless Chrome still running.

## Impact

Two costs. The obvious one is UX. The less obvious one is cost and correctness: a Remote Browser channel nobody wants keeps a browser alive server-side, and its `browser_*` tools stay in the model's vocabulary — so the agent can still act on a surface the user believes they dismissed.

This gets sharper as channel counts grow; the channel registry is deployment-wide (`MJ: AI Agent Channels.IsActive`, no per-agent scoping), so every session opens every active channel whether or not that session has any use for it.

## Sketch of a fix

A per-channel close on the session service that disposes the plugin, withdraws its tools, releases its server-side resources, and removes the tab — with `RemoveTab` becoming a consequence of that rather than the whole action. A closable flag per tab would let a host mark channels the user may dismiss (Activity stays irremovable).

Closing a channel is a mutation of the same live roster that #3497 says the agent cannot read. One concept, two symptoms.

Filing as a report only, per our process — no PR attached.

Contributor guide

Open the contributing guide

Research direction

Start with RealtimeSurfaceTabsComponent.RemoveTab(key), RealtimeSessionOverlayComponent.cleanupStaleReviewBoardTab() and exitReview(), and the RealtimeSessionService entry points. Trace how live channels initialize plugins, advertise tools, and release server-side resources. Done means a closable live channel removes its tab, withdraws its tools, disposes its plugin, and releases resources while Activity remains irremovable.

Written by the indexing model from the issue text.

Assessment

Domain
backend, frontend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.