Skip to content

Add TUI orchestration conversation tab bar#13832

Open
harryalbert wants to merge 10 commits into
masterfrom
harry/code-1822-orchestration-tab-bar
Open

Add TUI orchestration conversation tab bar#13832
harryalbert wants to merge 10 commits into
masterfrom
harry/code-1822-orchestration-tab-bar

Conversation

@harryalbert

@harryalbert harryalbert commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Description

Adds an orchestration conversation tab bar to the Warp TUI, built on the reusable TuiTabBarView from the PR below. The bar is shown across the orchestrator and its retained child-agent sessions, highlights the active conversation, and switches directly between the existing full session views without rebuilding or moving conversation state.

TuiOrchestrationModel projects the live history topology into a semantic tab snapshot. It resolves the top-level orchestrator, reuses the GUI orchestration pill ordering, filters out conversations without navigable TUI sessions, and owns the shared page anchor and explicit-paging state. Model notifications refresh every retained session view, while lifecycle events remain reserved for materializing and removing child sessions.

The session view maps the snapshot into theme-aware tab styles and stable agent identities, retains the tab child view and its mouse state, and coordinates focus across full-session switches. Shift+Up enters the bar only from the first visual input row with no selection; Tab, arrow keys, and first/last-child bindings switch conversations while preserving tab focus, and Shift+Down returns to the session's normal interaction target. Mouse selection preserves whether the bar or input owned keyboard focus, while overflow controls change only the shared visible page.

The normal session layout now renders the full-width orchestration row above the existing padded transcript/input column. Alternate-screen applications still replace the complete surface, while normal blocking interactions remain below the tab bar. Dynamic child additions, removals, status changes, recency changes, and pin changes recompute the snapshot without stealing responder focus.

Linked Issue

CODE-1822 — Orchestration

Review guide

  • crates/warp_tui/src/orchestration_model.rs — topology snapshots, canonical ordering, shared page state, session navigation, and model invalidation.
  • crates/warp_tui/src/terminal_session_view.rs and input/view.rs — retained tab integration, focus handoff, keyboard/mouse navigation, and session rendering.
  • crates/warp_tui/src/session_registry.rs — authoritative conversation-to-retained-session resolution.

Testing

  • I have manually tested my changes locally with ./script/run

Screenshots / Videos

https://www.loom.com/share/c53869fe8e3f49bc84a660beb70b6dfd

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

CHANGELOG-NONE

@harryalbert
harryalbert changed the base branch from harry/code-1822-tui-tab-bar-component to graphite-base/13832 July 16, 2026 20:42
@harryalbert
harryalbert force-pushed the harry/code-1822-orchestration-tab-bar branch from 0039266 to da1366d Compare July 16, 2026 22:12
@harryalbert
harryalbert force-pushed the graphite-base/13832 branch from 061490a to 14791bf Compare July 16, 2026 22:12
@harryalbert
harryalbert changed the base branch from graphite-base/13832 to harry/code-1822-tui-tab-bar-component July 16, 2026 22:13
@harryalbert
harryalbert changed the base branch from harry/code-1822-tui-tab-bar-component to graphite-base/13832 July 16, 2026 23:09
@harryalbert
harryalbert force-pushed the harry/code-1822-orchestration-tab-bar branch from da1366d to 9f29b02 Compare July 17, 2026 02:57
@harryalbert
harryalbert force-pushed the graphite-base/13832 branch from 14791bf to 00f818b Compare July 17, 2026 02:57
@harryalbert
harryalbert changed the base branch from graphite-base/13832 to harry/code-1822-tui-tab-bar-component July 17, 2026 02:57
@harryalbert
harryalbert force-pushed the harry/code-1822-orchestration-tab-bar branch from 9f29b02 to f58a51a Compare July 17, 2026 12:40
@harryalbert
harryalbert force-pushed the harry/code-1822-tui-tab-bar-component branch 2 times, most recently from 01fc847 to e8ad459 Compare July 17, 2026 13:02
@harryalbert
harryalbert force-pushed the harry/code-1822-orchestration-tab-bar branch 2 times, most recently from 26a62c0 to f905aac Compare July 17, 2026 13:26
@harryalbert
harryalbert force-pushed the harry/code-1822-tui-tab-bar-component branch from e8ad459 to 806dc7b Compare July 17, 2026 13:26
@harryalbert
harryalbert force-pushed the harry/code-1822-orchestration-tab-bar branch from f905aac to a80f9db Compare July 17, 2026 13:48
@harryalbert
harryalbert force-pushed the harry/code-1822-tui-tab-bar-component branch 2 times, most recently from 46372b9 to cffd251 Compare July 17, 2026 15:02
@harryalbert
harryalbert force-pushed the harry/code-1822-orchestration-tab-bar branch 2 times, most recently from 0adb153 to 0557ca7 Compare July 17, 2026 15:17
@harryalbert
harryalbert force-pushed the harry/code-1822-tui-tab-bar-component branch from 6cef323 to 9f1e03d Compare July 17, 2026 15:20
@harryalbert
harryalbert force-pushed the harry/code-1822-orchestration-tab-bar branch 2 times, most recently from 9d24d1a to de9dc08 Compare July 17, 2026 15:51
@harryalbert
harryalbert force-pushed the harry/code-1822-orchestration-tab-bar branch from 61d7777 to 8b3e92d Compare July 17, 2026 17:51
@harryalbert
harryalbert force-pushed the harry/code-1822-tui-tab-bar-component branch from 6753de5 to 73aa9b3 Compare July 17, 2026 17:51
@harryalbert harryalbert changed the title Add TUI orchestration tab bar specs Add TUI orchestration conversation tab bar Jul 17, 2026
@harryalbert
harryalbert marked this pull request as ready for review July 17, 2026 19:38
@harryalbert
harryalbert requested a review from kevinyang372 July 17, 2026 19:38
@oz-for-oss

oz-for-oss Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

@harryalbert

I'm starting a first review of this pull request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

@oz-for-oss oz-for-oss Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This PR adds the TUI orchestration conversation tab bar, including topology snapshots, retained tab state, input focus handoff, session switching, rendering, and tests/specs.

Concerns

  • Conversation-to-session lookup currently treats any conversation present in a terminal surface history as immediately navigable, but focusing the session does not select that historical conversation. This can leave stale child tabs that focus the wrong session content after a child session selects/restores another conversation.
  • The TUI tab snapshot invalidation ignores exchange append/recency events even though the shared GUI ordering policy sorts completed children by last_modified_at(), so retained tab ordering and keyboard navigation can diverge from the GUI pill order until another event happens to refresh it.

Verdict

Found: 0 critical, 2 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment thread crates/warp_tui/src/session_registry.rs Outdated
history: &BlocklistAIHistoryModel,
conversation_id: AIConversationId,
) -> Option<TuiSessionId> {
let surface_id = history.terminal_surface_id_for_conversation(&conversation_id)?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] This only proves the conversation is present somewhere in the terminal surface history; focus_session does not select that historical conversation. If a child session has since selected/restored another conversation, the tab remains visible and clicking it focuses the wrong content. Filter against the retained view's selected conversation, or select/restore the target before treating it as navigable.

} => true,
BlocklistAIHistoryEvent::CreatedSubtask { .. }
| BlocklistAIHistoryEvent::UpgradedTask { .. }
| BlocklistAIHistoryEvent::AppendedExchange { .. }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] descendant_conversation_ids_in_pill_order uses last_modified_at() for completed-child ordering, and appending an exchange changes that source of truth. Ignoring AppendedExchange here can leave the retained TUI tab order and keyboard navigation stale until an unrelated status/metadata event, diverging from the GUI pill bar. Treat exchange events that affect recency as topology changes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this true?

@harryalbert
harryalbert force-pushed the harry/code-1822-orchestration-tab-bar branch from 8b3e92d to d0dd53d Compare July 17, 2026 19:48
@harryalbert
harryalbert force-pushed the harry/code-1822-tui-tab-bar-component branch 2 times, most recently from 26257d9 to ed5ff02 Compare July 17, 2026 19:49
@harryalbert
harryalbert force-pushed the harry/code-1822-orchestration-tab-bar branch from d0dd53d to e0c5b18 Compare July 17, 2026 19:49
@harryalbert
harryalbert changed the base branch from harry/code-1822-tui-tab-bar-component to graphite-base/13832 July 17, 2026 20:31
@harryalbert
harryalbert force-pushed the graphite-base/13832 branch from ed5ff02 to 31e0eab Compare July 17, 2026 20:45
@harryalbert
harryalbert force-pushed the harry/code-1822-orchestration-tab-bar branch from e0c5b18 to 24c7de0 Compare July 17, 2026 20:45
@harryalbert
harryalbert changed the base branch from graphite-base/13832 to harry/code-1822-tui-tab-bar-component July 17, 2026 20:45
@harryalbert
harryalbert force-pushed the harry/code-1822-tui-tab-bar-component branch from 31e0eab to 8209665 Compare July 17, 2026 20:46
@harryalbert
harryalbert force-pushed the harry/code-1822-orchestration-tab-bar branch from 24c7de0 to 9d27dc9 Compare July 17, 2026 20:46
Base automatically changed from harry/code-1822-tui-tab-bar-component to master July 17, 2026 21:23
@harryalbert
harryalbert force-pushed the harry/code-1822-orchestration-tab-bar branch from 9d27dc9 to de63143 Compare July 17, 2026 21:24

@kevinyang372 kevinyang372 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving to unblock

/// The TUI's child-agent coordinator singleton. See the module docs.
/// One navigable child tab in an orchestration snapshot.
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct TuiOrchestrationTab {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semantically is this an actual tab (a UI concept) or a child orchestrated session?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is the latter I am not sure we want to couple it with the front-end tab naming

event_consumers_by_session: HashMap<TuiSessionId, HashSet<AIConversationId>>,
/// Page state for the single orchestration tab bar visible at a time.
page_root_conversation_id: Option<AIConversationId>,
page_anchor: Option<AIConversationId>,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is page_anchor and explicitly_paged?

} => true,
BlocklistAIHistoryEvent::CreatedSubtask { .. }
| BlocklistAIHistoryEvent::UpgradedTask { .. }
| BlocklistAIHistoryEvent::AppendedExchange { .. }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this true?

) {
self.page_root_conversation_id = Some(root_conversation_id);
self.page_anchor = Some(page_anchor);
self.explicitly_paged = true;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm seems like explicitly_paged is just page_anchor.is_some()?

/// visibility itself is derived at render time, never stored.
active_blocker_view_id: Option<EntityId>,
orchestration_tab_bar: ViewHandle<TuiTabBarView>,
orchestration_snapshot: Option<TuiOrchestrationSnapshot>,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm shouldn't this be derived from the orchestration model? Why are we keeping a separate snapshot here

active_blocker_view_id: Option<EntityId>,
orchestration_tab_bar: ViewHandle<TuiTabBarView>,
orchestration_snapshot: Option<TuiOrchestrationSnapshot>,
orchestration_tabs_available: Rc<Cell<bool>>,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This state should also belong to the model imo

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants