@@ -7,10 +7,11 @@ use std::sync::Arc;
77
88use parking_lot:: FairMutex ;
99use warp:: tui_export:: {
10- AIAgentExchangeId , AIAgentInput , AIAgentOutput , AIAgentOutputMessage , AIAgentOutputMessageType ,
11- AIAgentText , AIAgentTextSection , AIBlockModel , AIBlockOutputStatus , AIConversationId ,
12- AIRequestType , Appearance , BlockId , LLMId , MessageId , OutputStatusUpdateCallback ,
13- RichContentItem , RichContentType , ServerOutputId , Shared , TerminalModel ,
10+ AIAgentAction , AIAgentActionId , AIAgentActionType , AIAgentExchangeId , AIAgentInput ,
11+ AIAgentOutput , AIAgentOutputMessage , AIAgentOutputMessageType , AIAgentText , AIAgentTextSection ,
12+ AIBlockModel , AIBlockOutputStatus , AIConversationId , AIRequestType , Appearance , BlockId , LLMId ,
13+ MessageId , OutputStatusUpdateCallback , RichContentItem , RichContentType , ServerOutputId ,
14+ Shared , TaskId , TerminalModel ,
1415} ;
1516use warpui:: platform:: WindowStyle ;
1617use warpui:: {
@@ -30,6 +31,7 @@ use crate::tui_block_list_viewport_source::{
3031 AgentBlockRegistry , CLISubagentBlockRegistry , HandoffBlockRegistry , TuiBlockListViewportSource ,
3132} ;
3233use crate :: tui_builder:: TuiUiBuilder ;
34+ use crate :: tui_shell_command_view:: TuiShellCommandViewAction ;
3335
3436/// Shape of the retained transcript fixture.
3537#[ derive( Clone , Copy , Debug ) ]
@@ -38,6 +40,8 @@ pub enum TranscriptDataset {
3840 ManySmallBlocks { blocks : usize } ,
3941 /// One rich agent response containing `rows` hard lines.
4042 LongAgentResponse { rows : usize } ,
43+ /// One expanded agent-requested command that remains active at `rows` output rows.
44+ RunningAgentCommand { rows : usize } ,
4145 /// A streaming rich response below `preceding_rows` of fixed history.
4246 OffscreenStreamingTail {
4347 preceding_rows : usize ,
@@ -130,6 +134,24 @@ impl TranscriptBenchmark {
130134 . lock ( )
131135 . simulate_block ( "history" , output. as_str ( ) ) ;
132136 }
137+ let running_command_action =
138+ if let TranscriptDataset :: RunningAgentCommand { rows } = dataset {
139+ let action = benchmark_command_action ( ) ;
140+ let output = "running command output\r \n " . repeat ( rows) ;
141+ let mut model = terminal_model. lock ( ) ;
142+ model. simulate_long_running_block ( "printf benchmark" , output. as_str ( ) ) ;
143+ model
144+ . block_list_mut ( )
145+ . active_block_mut ( )
146+ . set_agent_interaction_mode_for_requested_command (
147+ action. id . clone ( ) ,
148+ None ,
149+ AIConversationId :: new ( ) ,
150+ ) ;
151+ Some ( action)
152+ } else {
153+ None
154+ } ;
133155
134156 let agent_blocks = AgentBlockRegistry :: new ( RefCell :: new ( HashMap :: new ( ) ) ) ;
135157 let cli_subagent_blocks = CLISubagentBlockRegistry :: new ( RefCell :: new ( HashMap :: new ( ) ) ) ;
@@ -167,7 +189,8 @@ impl TranscriptBenchmark {
167189 TranscriptDataset :: OffscreenStreamingTail { .. } => {
168190 streaming_text_status ( text)
169191 }
170- TranscriptDataset :: ManySmallBlocks { .. } => unreachable ! ( ) ,
192+ TranscriptDataset :: ManySmallBlocks { .. }
193+ | TranscriptDataset :: RunningAgentCommand { .. } => unreachable ! ( ) ,
171194 } ;
172195 let terminal_model_for_block = terminal_model. clone ( ) ;
173196 let agent_block = app. update ( |ctx| {
@@ -191,6 +214,48 @@ impl TranscriptBenchmark {
191214 ) ;
192215 Some ( view_id)
193216 }
217+ TranscriptDataset :: RunningAgentCommand { .. } => {
218+ let ( action_model, model_events) = add_test_action_model_and_events ( & mut app) ;
219+ let action =
220+ running_command_action. expect ( "running command dataset has an action" ) ;
221+ let status = running_command_status ( action) ;
222+ let terminal_model_for_block = terminal_model. clone ( ) ;
223+ let agent_block = app. update ( |ctx| {
224+ ctx. add_typed_action_tui_view ( window_id, move |ctx| {
225+ TuiAIBlock :: new (
226+ ( AIConversationId :: new ( ) , AIAgentExchangeId :: new ( ) ) ,
227+ Rc :: new ( BenchmarkAgentBlockModel { status } ) ,
228+ action_model,
229+ & model_events,
230+ terminal_model_for_block,
231+ false ,
232+ ctx,
233+ )
234+ } )
235+ } ) ;
236+ let view_id = agent_block. id ( ) ;
237+ agent_blocks
238+ . borrow_mut ( )
239+ . insert ( view_id, agent_block. clone ( ) ) ;
240+ terminal_model. lock ( ) . block_list_mut ( ) . append_rich_content (
241+ RichContentItem :: new ( Some ( RichContentType :: AIBlock ) , view_id, None , false ) ,
242+ false ,
243+ ) ;
244+ app. update ( |ctx| {
245+ let shell_view_id = agent_block
246+ . as_ref ( ctx)
247+ . child_view_ids ( ctx)
248+ . into_iter ( )
249+ . next ( )
250+ . expect ( "running command agent block has a shell child" ) ;
251+ ctx. dispatch_typed_action_for_view (
252+ window_id,
253+ shell_view_id,
254+ & TuiShellCommandViewAction :: ToggleExpanded ,
255+ ) ;
256+ } ) ;
257+ Some ( view_id)
258+ }
194259 } ;
195260
196261 let mut benchmark = Self {
@@ -346,6 +411,36 @@ impl AIBlockModel for BenchmarkAgentBlockModel {
346411 }
347412}
348413
414+ fn benchmark_command_action ( ) -> AIAgentAction {
415+ AIAgentAction {
416+ id : AIAgentActionId :: from ( "benchmark-command" . to_owned ( ) ) ,
417+ task_id : TaskId :: new ( "benchmark-task" . to_owned ( ) ) ,
418+ action : AIAgentActionType :: RequestCommandOutput {
419+ command : "printf benchmark" . to_owned ( ) ,
420+ is_read_only : Some ( true ) ,
421+ is_risky : Some ( false ) ,
422+ wait_until_completion : true ,
423+ uses_pager : Some ( false ) ,
424+ rationale : None ,
425+ citations : Vec :: new ( ) ,
426+ } ,
427+ requires_result : true ,
428+ }
429+ }
430+
431+ fn running_command_status ( action : AIAgentAction ) -> AIBlockOutputStatus {
432+ AIBlockOutputStatus :: Complete {
433+ output : Shared :: new ( AIAgentOutput {
434+ messages : vec ! [ AIAgentOutputMessage {
435+ id: MessageId :: new( "benchmark-command-message" . to_owned( ) ) ,
436+ message: AIAgentOutputMessageType :: Action ( action) ,
437+ citations: Vec :: new( ) ,
438+ } ] ,
439+ ..Default :: default ( )
440+ } ) ,
441+ }
442+ }
443+
349444fn completed_text_status ( text : String ) -> AIBlockOutputStatus {
350445 AIBlockOutputStatus :: Complete {
351446 output : Shared :: new ( AIAgentOutput {
0 commit comments