@@ -310,7 +310,7 @@ describe('AgentGroup inline main activity', () => {
310310 } )
311311
312312 it . each ( [ 'sim_cli' , 'run_code' ] ) (
313- 'shows %s argument preparation before its concrete call ' ,
313+ 'names a first %s call by its activity intent, else its own title, while its arguments stream ' ,
314314 ( toolName ) => {
315315 vi . useFakeTimers ( )
316316 const render = (
@@ -342,16 +342,107 @@ describe('AgentGroup inline main activity', () => {
342342 )
343343 )
344344 act ( ( ) => vi . advanceTimersByTime ( 1000 ) )
345+ expect ( container . textContent ) . not . toContain ( 'Working' )
345346 return container . textContent
346347 }
347- expect ( render ( { } , 'executing' ) ) . toBe ( 'Working…' )
348- const params = { code : '1' , activity : { id : 'check' , completedTitle : 'Checked inputs' } }
348+ expect ( render ( { } , 'executing' ) ) . toBe ( 'Running checks' )
349+ expect ( render ( { activity : { id : 'check' , title : 'Checking inputs' } } , 'executing' ) ) . toBe (
350+ 'Checking inputs'
351+ )
352+ const params = { code : '1' , activity : { id : 'check' , title : 'Checking inputs' } }
349353 expect ( render ( params , 'executing' ) ) . toBe ( 'Running checks' )
350354 expect ( render ( params , 'success' ) ) . toBe ( 'Running checks' )
351355 expect ( render ( params , 'success' , false ) ) . toBe ( 'Ran checks' )
352356 }
353357 )
354358
359+ it . each ( [
360+ [
361+ 'sim_cli' ,
362+ { toolName : 'sim_cli' , displayTitle : 'Running CLI command' , params : { } } ,
363+ {
364+ toolName : 'cli_workflows_list' ,
365+ displayTitle : 'Listing workflows' ,
366+ params : { args : [ 'workflows' , 'list' ] } ,
367+ } ,
368+ ] ,
369+ [
370+ 'run_code' ,
371+ { toolName : 'run_code' , displayTitle : 'Running code' , params : { activity : { id : 'a' } } } ,
372+ {
373+ toolName : 'run_code' ,
374+ displayTitle : 'Summing invoices' ,
375+ params : { activity : { id : 'a' } , title : 'Summing invoices' , code : '1' } ,
376+ } ,
377+ ] ,
378+ [
379+ 'call_integration_tool' ,
380+ { toolName : 'call_integration_tool' , displayTitle : 'Calling integration' , params : { } } ,
381+ {
382+ toolName : 'call_integration_tool' ,
383+ displayTitle : 'Sending the report' ,
384+ params : { } ,
385+ streamingArgs : '{"description":"Sending the report",' ,
386+ } ,
387+ ] ,
388+ ] ) (
389+ 'keeps the previous call in the live header while a %s call has no title' ,
390+ ( _name , pending , titled ) => {
391+ vi . useFakeTimers ( )
392+ const read = {
393+ id : 'read' ,
394+ toolName : 'read' ,
395+ displayTitle : 'Reading notes.md' ,
396+ status : 'success' as const ,
397+ }
398+ const render = ( next : Partial < ToolCallData > ) => {
399+ act ( ( ) =>
400+ root . render (
401+ createElement ( AgentGroup , {
402+ agentName : 'mothership' ,
403+ agentLabel : 'Sim' ,
404+ activity : { id : 'a' , title : 'Reconciling accounts' } ,
405+ isStreaming : true ,
406+ isLaneOpen : true ,
407+ items : [
408+ { type : 'tool' , data : read } ,
409+ {
410+ type : 'tool' ,
411+ data : { id : 'next' , status : 'executing' , ...next } as ToolCallData ,
412+ } ,
413+ ] ,
414+ } )
415+ )
416+ )
417+ act ( ( ) => vi . advanceTimersByTime ( 1000 ) )
418+ const header = container . querySelector ( '[role="status"]' ) !
419+ expect ( header . querySelector ( '[class*="shimmer"]' ) ) . not . toBeNull ( )
420+ expect ( container . textContent ) . not . toContain ( 'Working' )
421+ return { text : header . textContent , icon : header . querySelector ( 'svg' ) ?. outerHTML }
422+ }
423+ const iconOf = ( data : Partial < ToolCallData > ) => {
424+ act ( ( ) =>
425+ root . render (
426+ createElement ( AgentGroup , {
427+ agentName : 'mothership' ,
428+ agentLabel : 'Sim' ,
429+ items : [
430+ { type : 'tool' , data : { id : 'solo' , status : 'success' , ...data } as ToolCallData } ,
431+ ] ,
432+ } )
433+ )
434+ )
435+ return container . querySelector ( 'svg' ) ?. outerHTML
436+ }
437+ const readIcon = iconOf ( read )
438+ const titledIcon = iconOf ( titled )
439+ expect ( readIcon ) . not . toBe ( titledIcon )
440+
441+ expect ( render ( pending ) ) . toEqual ( { text : 'Reading notes.md' , icon : readIcon } )
442+ expect ( render ( titled ) ) . toEqual ( { text : titled . displayTitle , icon : titledIcon } )
443+ }
444+ )
445+
355446 it ( 'keeps an activity unfinished while a standalone approval is pending' , ( ) => {
356447 act ( ( ) =>
357448 root . render (
@@ -1175,6 +1266,48 @@ describe('AgentGroup nested status line', () => {
11751266 expect ( header ) . toContain ( 'Deploying Invoice Sync as API' )
11761267 } )
11771268
1269+ it ( 'keeps the previous call in a subagent header while the next call has no title' , ( ) => {
1270+ vi . useFakeTimers ( )
1271+ const header = ( items : AgentGroupItem [ ] ) => {
1272+ render ( items )
1273+ act ( ( ) => vi . advanceTimersByTime ( 1000 ) )
1274+ const status = container . querySelector ( '[role="status"]' ) !
1275+ expect ( status . querySelector ( '[class*="shimmer"]' ) ) . not . toBeNull ( )
1276+ expect ( container . textContent ) . not . toContain ( 'Working' )
1277+ return status . textContent
1278+ }
1279+ const cli = ( data : Partial < ToolCallData > ) : AgentGroupItem => ( {
1280+ type : 'tool' ,
1281+ data : { id : 'cli' , status : 'executing' , startedAt : 2 , ...data } as ToolCallData ,
1282+ } )
1283+ const pending = cli ( { toolName : 'sim_cli' , displayTitle : 'Running CLI command' , params : { } } )
1284+ const titled = cli ( {
1285+ toolName : 'cli_workflows_list' ,
1286+ displayTitle : 'Listing workflows' ,
1287+ params : { args : [ 'workflows' , 'list' ] } ,
1288+ } )
1289+ try {
1290+ expect ( header ( [ namedTool ( 'Reading workflow' , 'success' as ToolCallStatus , 1 ) , pending ] ) ) . toBe (
1291+ 'Reading workflow'
1292+ )
1293+ expect ( header ( [ namedTool ( 'Reading workflow' , 'success' as ToolCallStatus , 1 ) , titled ] ) ) . toBe (
1294+ 'Listing workflows'
1295+ )
1296+ expect ( header ( [ pending ] ) ) . toBe ( 'Running CLI command' )
1297+ expect (
1298+ header ( [
1299+ cli ( {
1300+ toolName : 'sim_cli' ,
1301+ displayTitle : 'Running CLI command' ,
1302+ params : { activity : { id : 'a' , title : 'Checking inputs' } } ,
1303+ } ) ,
1304+ ] )
1305+ ) . toBe ( 'Checking inputs' )
1306+ } finally {
1307+ vi . useRealTimers ( )
1308+ }
1309+ } )
1310+
11781311 it ( 'falls back to the last tool at any depth when nothing is running' , ( ) => {
11791312 const header = render ( [
11801313 namedTool ( 'Reading workflow' , 'success' as ToolCallStatus , 1 ) ,
0 commit comments