Conversation streaming for the TUI#13057
Conversation
3cb8802 to
44f7640
Compare
44f7640 to
9f5a53d
Compare
863eeae to
5953228
Compare
5953228 to
d9b26c6
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 refactors the Blocklist AI conversation models around terminal-surface-scoped selection/history, adds a TUI conversation coordinator, and introduces one-shot warp_tui --prompt streaming with worker-dispatch support.
Concerns
- The TUI prompt stream treats every status other than
InProgressas terminal success, which can prematurely stop transient recovery, waiting, blocked, error, and cancellation states while returning a successful CLI exit. - This is a user-facing TUI behavior change, but the PR description does not include screenshots or a screen recording. For this user-facing change, please include screenshots or a screen recording demonstrating it working end to end.
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
| update: ConversationStatusUpdate::Changed { .. }, | ||
| } => { | ||
| self.print_stream_snapshot(*conversation_id, ctx); | ||
| if !status.is_in_progress() { |
There was a problem hiding this comment.
!status.is_in_progress() treats TransientError, WaitingForEvents, and Blocked as final and terminates with None, so retries/waits/tool-blocked/error states can be cut off while the CLI exits successfully; gate completion on terminal statuses and surface non-success statuses as errors.

Description
This PR changes it so that the main cluster of conversation models (i.e. the
BlocklistAIContextModel,BlocklistAIInputModel,BlocklistAIController, andBlocklistAIHistoryModel) necessary for conversation streaming and basic conversation management can be re-used by theTUIw/ noTUIorGUIspecific code within said models (i.e. the models are not concerned w/ whether they are associated with aTUIorGUIsurface).Luckily enough, there's actually not much that needs to be changed within these models to get them working for the TUI and GUI in a surface-agnostic way. The major things that change are:
terminal_view_id: EntityId, replaced withterminal_surface_id: EntityId. This is where the majority of the LOC changed come from in this PR, and it should be a behavior no-op. Just want to make sure we're clear on our naming here.AgentViewController, as this controller is GUI specific. What makes this a little tricky is that theAgentViewControllerwas doing several jobs: it was telling the models whether an agent view was open or not, telling the models what conversation was currently selected, and emitting presentation lifecycle events consumed by the shared models. To handle these jobs, this PR adds an object-safeConversationSelectionabstraction that each surface implements and passes to the shared models behind aConversationSelectionHandle. ForGUIsurfaces,AgentViewConversationSelectiondelegates presentation operations toAgentViewControllerand translates Agent View lifecycle events into events consumed by shared models. ForTUIsurfaces,TuiConversationSelectionowns the pending conversation selection directly.The history model also now distinguishes between transferring a conversation to a new terminal surface and simply marking an already-owned conversation as the active streaming target. This ensures automatic follow-ups don't accidentally transfer conversations between surfaces, while explicit transfers still clean up the previous renderer and selection.
Finally, this PR adds a one-shot
--promptruntime path towarp_tui, which streams a response directly back as output. I would just delete this as "testing code", but I actually think it's worthwhile to keep given our long-term plan of replacing the portion of the Oz CLI responsible for handling prompt submission with the TUI. The reusable conversation coordination lives inTuiConversationModel, while the one-shot stdout behavior lives inPromptStreamSurface.This PR also adds a
--conversation-idflag so that you can continue an existing conversation. This flag accepts a server conversation token, allowing the TUI to restore the corresponding conversation and test that follow-ups are WAI.The TUI now uses the normal backing terminal server. To prevent this from recursively starting more TUI frontends, worker invocations are dispatched before TUI frontend arguments are parsed.
Reviewing this PR
A lot of this PR is no-op field name changes or simple call structure changes that aren't worth reading. The files worth digging into are:
The tech spec for an over-arching tech implementation guide
◦
specs/conversation-streaming-for-tui/TECH.mdThe new
ConversationSelectionabstraction and its GUI/TUI implementations◦
app/src/ai/blocklist/conversation_selection.rs◦
app/src/ai/blocklist/agent_view/conversation_selection.rs◦
crates/warp_tui/src/conversation_selection.rsThe existing models migrated onto that abstraction. These are skim-able IMO but worth looking at just to see how the abstractions introduced in this PR are used in action.
◦
app/src/ai/blocklist/context_model.rs◦
app/src/ai/blocklist/input_model.rs◦
app/src/ai/blocklist/controller.rsThe history-model behavioral portions (again, skim-able)
◦
app/src/ai/blocklist/history_model.rs◦ Do not read all of the changed lines sequentially; most are renames. Focus on:
▪
set_active_conversation_id▪
mark_active_conversation_id▪
restore_conversations▪ clear/remove/delete behavior
▪
terminal_surface_id_for_conversation▪
ConversationTransferredBetweenTerminalSurfaces▪
BlocklistAIHistoryEvent::terminal_surface_id◦ The important behavior is conversation transfer between surfaces and ensuring the previous renderer/selection is cleaned up.
The TUI conversation model
◦
crates/warp_tui/src/conversation_model.rsThe TUI presentation streaming adapter
◦
crates/warp_tui/src/prompt_stream.rs◦ Focus on:
▪ model cluster construction
▪ retained surface/manager lifetimes
▪ stdout snapshot behavior
▪ tool-action failure behavior
▪ final-status and error termination
The bug fix around preventing a fork bomb while allowing us to spin up a backing terminal server
◦
app/src/lib.rs◦
app/src/tui.rs◦
crates/warp_tui/src/lib.rs◦
crates/warp_cli/src/lib.rs—is_worker_invocation◦
crates/warp_tui/tests/worker_dispatch.rsTesting
./script/runScreenshots / Videos
https://www.loom.com/share/2ecdc7fa6ee54bcab0b4183a237d12af
Agent Mode