Add TUI orchestration conversation tab bar#13832
Conversation
0039266 to
da1366d
Compare
061490a to
14791bf
Compare
da1366d to
9f29b02
Compare
14791bf to
00f818b
Compare
9f29b02 to
f58a51a
Compare
01fc847 to
e8ad459
Compare
26a62c0 to
f905aac
Compare
e8ad459 to
806dc7b
Compare
f905aac to
a80f9db
Compare
46372b9 to
cffd251
Compare
0adb153 to
0557ca7
Compare
6cef323 to
9f1e03d
Compare
9d24d1a to
de9dc08
Compare
61d7777 to
8b3e92d
Compare
6753de5 to
73aa9b3
Compare
|
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 Powered by Oz |
There was a problem hiding this comment.
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
| history: &BlocklistAIHistoryModel, | ||
| conversation_id: AIConversationId, | ||
| ) -> Option<TuiSessionId> { | ||
| let surface_id = history.terminal_surface_id_for_conversation(&conversation_id)?; |
There was a problem hiding this comment.
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 { .. } |
There was a problem hiding this comment.
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.
8b3e92d to
d0dd53d
Compare
26257d9 to
ed5ff02
Compare
d0dd53d to
e0c5b18
Compare
ed5ff02 to
31e0eab
Compare
e0c5b18 to
24c7de0
Compare
31e0eab to
8209665
Compare
24c7de0 to
9d27dc9
Compare
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
Co-Authored-By: Oz <oz-agent@warp.dev>
9d27dc9 to
de63143
Compare
| /// 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 { |
There was a problem hiding this comment.
Semantically is this an actual tab (a UI concept) or a child orchestrated session?
There was a problem hiding this comment.
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>, |
There was a problem hiding this comment.
What is page_anchor and explicitly_paged?
| } => true, | ||
| BlocklistAIHistoryEvent::CreatedSubtask { .. } | ||
| | BlocklistAIHistoryEvent::UpgradedTask { .. } | ||
| | BlocklistAIHistoryEvent::AppendedExchange { .. } |
| ) { | ||
| self.page_root_conversation_id = Some(root_conversation_id); | ||
| self.page_anchor = Some(page_anchor); | ||
| self.explicitly_paged = true; |
There was a problem hiding this comment.
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>, |
There was a problem hiding this comment.
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>>, |
There was a problem hiding this comment.
This state should also belong to the model imo

Description
Adds an orchestration conversation tab bar to the Warp TUI, built on the reusable
TuiTabBarViewfrom 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.TuiOrchestrationModelprojects 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+Upenters 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, andShift+Downreturns 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.rsandinput/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
./script/runScreenshots / Videos
https://www.loom.com/share/c53869fe8e3f49bc84a660beb70b6dfd
Agent Mode
CHANGELOG-NONE