Skip to content

Close agent chat/terminal tabs when their agent is destroyed externally#148

Open
gnguralnick wants to merge 3 commits into
mainfrom
gabriel/destroyed-agent-tabs
Open

Close agent chat/terminal tabs when their agent is destroyed externally#148
gnguralnick wants to merge 3 commits into
mainfrom
gabriel/destroyed-agent-tabs

Conversation

@gnguralnick

Copy link
Copy Markdown
Contributor

What

In the system_interface dockview UI, destroying an agent from outside the UI (e.g. from a terminal) left that agent's chat and terminal tabs open. They now close automatically.

Why it happened

The backend already broadcasts an updated agent list on external destruction (_handle_agent_destroyed -> broadcast_agents_updated). The frontend's agents_updated handler in DockviewWorkspace.ts used that event only to open the initial chat tab; it never reconciled already-open tabs against the live agent set.

The change

  • computePanelsToCloseForRemovedAgents(...) (pure, exported): given the open panels plus the live and ever-seen agent id sets, returns which tabs to close.
  • The agents_updated listener now closes those tabs before its existing initial-tab logic.
  • A tab is closed only if its backing agent was seen alive earlier this session and has since disappeared. The ever-seen gate prevents tearing down tabs for agents that simply haven't loaded yet (empty list right after connect, or restored-layout tabs before the first update).
  • Only chat panels and agent-terminal iframe tabs count as agent-bound. Generic terminals, applications, and ad-hoc URL tabs carry the primary agent id as a placeholder owner and are deliberately excluded.

The in-UI destroy button path already removes the panel directly, so the reconciliation is a no-op there (no double-removal).

Tests

Added DockviewWorkspace.test.ts (6 cases): destroyed agents' chat and terminal tabs close; live agents, not-yet-seen agents, and non-agent tabs are untouched; mixed layouts close only the dead agent's tabs.

  • npm run lint -> clean
  • npm run test -> 89 passed, 0 failed

Gabriel Guralnick and others added 3 commits June 9, 2026 14:23
When an agent was destroyed outside the system_interface UI (e.g. from a
terminal), the backend broadcast an updated agent list but the frontend
only used that event to open the initial chat tab -- the destroyed
agent's chat and terminal tabs stayed open. Reconcile open agent-bound
tabs against each agents_updated event and close any whose backing agent
was seen alive earlier this session and has since disappeared. An
ever-seen gate prevents tearing down tabs for agents that simply haven't
loaded yet (empty list right after connect, or restored-layout tabs
before the first update).

Co-authored-by: Sculptor <sculptor@imbue.com>
Problem: The rule for recognizing an agent-terminal iframe URL
(url.startsWith(<terminal url>) && url.includes("arg=agent")) was
duplicated in DockviewWorkspace.ts -- the newly added getPanelBackingAgentId
carried one copy and createComponent's iframe case already had an identical
one. The two recognition sites could drift apart on any future change to the
terminal-URL shape.

Fix: Extract the predicate into a single exported pure helper,
isAgentTerminalUrl(url, terminalUrlPrefix), placed beside the existing
buildAgentTerminalUrl URL constructor, and use it at both sites. The prefix is
passed in so the helper stays pure and unit-testable, matching how
getPanelBackingAgentId already threads the prefix through.

Co-authored-by: Sculptor <sculptor@imbue.com>
@gnguralnick gnguralnick marked this pull request as ready for review June 11, 2026 22:36
@joshalbrecht

Copy link
Copy Markdown
Contributor

I'm a little skeptical of the UX here -- it would be very confusing to a user if their chat just disappeared

It seems better to keep the chat open (if it was already open), but simply have some sort of "this agent was destroyed" overlay, and then they can close it? That would properly communicate to them what happened

@gnguralnick

Copy link
Copy Markdown
Contributor Author

sounds good. i can switch it to that!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants