@@ -1352,14 +1352,11 @@ test.describe("background shortcut", () => {
13521352 / ^ E x p l o r e \s * B a c k g r o u n d t a s k \d + h \d { 2 } m $ / ,
13531353 / ^ s l e e p 1 2 0 \d + h \d { 2 } m $ / ,
13541354 ] )
1355+ // A shell opens its output in the menu rather than revealing its call in the timeline.
13551356 await list . getByRole ( "menuitem" , { name : / s l e e p 1 2 0 / } ) . click ( )
1356- await expect ( list ) . toHaveCount ( 0 )
1357- await expect ( used ) . toHaveAttribute ( "aria-expanded" , "true" )
1358- const shellCall = page . locator ( '[data-timeline-part-id="call_shell_backgrounded"]' )
1359- await expect ( shellCall . locator ( '[data-slot="collapsible-trigger"]' ) ) . toHaveAttribute ( "aria-expanded" , "true" )
1360- await expect ( shellCall ) . toBeInViewport ( )
1361-
1362- await activity . click ( )
1357+ await expect ( list ) . toHaveAttribute ( "data-view" , "shell" )
1358+ await expect ( used ) . toHaveAttribute ( "aria-expanded" , "false" )
1359+ await list . getByRole ( "menuitem" , { name : "Back to background work" , exact : true } ) . click ( )
13631360
13641361 const interrupt = page . waitForRequest (
13651362 ( request ) =>
@@ -1384,6 +1381,7 @@ test.describe("background shortcut", () => {
13841381 await expect ( list ) . toHaveCount ( 0 )
13851382 await expect ( backgroundCard ) . toContainText ( "Background task (background)" )
13861383 await expect ( backgroundCard . locator ( '[data-component="session-progress-indicator-v2"]' ) ) . toBeVisible ( )
1384+ await used . click ( )
13871385 await expect (
13881386 page . locator ( '[data-timeline-part-id="call_shell_backgrounded"] [data-component="text-shimmer"]' ) ,
13891387 ) . toHaveAttribute ( "data-active" , "true" )
@@ -1407,24 +1405,19 @@ test.describe("background shortcut", () => {
14071405 // Reaching the shell lands on the end of the timeline, which would otherwise follow new content again.
14081406 { name : "at the end of the timeline" , before : 40 , searches : 0 , after : 0 } ,
14091407 ] ) {
1410- test ( `holds a revealed shell ${ fixture . name } just under its stuck group header` , async ( { page } ) => {
1408+ // A starting subagent call is the pill's row that reveals its call; grouping subagents puts it inside the group.
1409+ test ( `holds a revealed call ${ fixture . name } just under its stuck group header` , async ( { page } ) => {
14111410 const timeline = await setupTimeline ( page , {
1412- settings : { timelineDetail : detailed } ,
1411+ settings : { timelineDetail : { ... detailed , subagents : { placement : "grouped" } } } ,
14131412 sessionStatus : { [ sessionID ] : { type : "busy" } } ,
14141413 messages : [
14151414 userMessage ( ) ,
14161415 assistantMessage (
14171416 [
14181417 ...( fixture . before ? [ textPart ( "prt_earlier" , notes ( "Earlier" , fixture . before ) ) ] : [ ] ) ,
14191418 ...searches ( 0 , 42 - fixture . searches ) ,
1420- toolPart (
1421- "prt_far_shell" ,
1422- "shell" ,
1423- "completed" ,
1424- { command : "sleep 120" } ,
1425- { output : "working" , metadata : { shellID : "shell_far" , status : "running" } } ,
1426- ) ,
1427- // The open group outgrows the viewport, so aligning the group instead of the shell misses it.
1419+ toolPart ( "prt_far_call" , "subagent" , "running" , { description : "Map the far code" , agent : "explore" } ) ,
1420+ // The open group outgrows the viewport, so aligning the group instead of the call misses it.
14281421 ...searches ( 42 - fixture . searches , fixture . searches ) ,
14291422 ...( fixture . after ? [ textPart ( "prt_follow_up" , notes ( "Follow-up" , fixture . after ) ) ] : [ ] ) ,
14301423 ] ,
@@ -1433,60 +1426,40 @@ test.describe("background shortcut", () => {
14331426 ] ,
14341427 } )
14351428
1436- await timeline . transport . send ( {
1437- id : "evt_far_shell_created" ,
1438- created : 3 ,
1439- type : "shell.created" ,
1440- location : { directory } ,
1441- data : {
1442- info : {
1443- id : "shell_far" ,
1444- status : "running" ,
1445- command : "sleep 120" ,
1446- cwd : directory ,
1447- shell : "bash" ,
1448- file : "/tmp/far.out" ,
1449- metadata : { sessionID } ,
1450- time : { started : 2 } ,
1451- } ,
1452- } ,
1453- } )
1454-
14551429 const group = page
14561430 . locator ( '[data-component="collapsed-tool-group"]' )
14571431 . locator ( ':scope > [data-component="collapsible"] > [data-slot="collapsible-trigger"]' )
14581432
1459- const shellTrigger = page . locator ( '[data-timeline-part-id="prt_far_shell"] [data-slot="collapsible-trigger "]' )
1433+ const call = page . locator ( '[data-timeline-part-id="prt_far_call "]' )
14601434
14611435 const aligned = ( ) =>
14621436 expect
14631437 . poll ( async ( ) => {
1464- const [ header , shell ] = await Promise . all ( [ group . boundingBox ( ) , shellTrigger . boundingBox ( ) ] )
1438+ const [ header , row ] = await Promise . all ( [ group . boundingBox ( ) , call . boundingBox ( ) ] )
14651439
1466- return header && shell ? Math . round ( shell . y - ( header . y + header . height ) ) : undefined
1440+ return header && row ? Math . round ( row . y - ( header . y + header . height ) ) : undefined
14671441 } )
14681442 . toBe ( 0 )
14691443
14701444 await expect (
14711445 fixture . after ? page . getByText ( `Follow-up note ${ fixture . after } .` , { exact : true } ) : group ,
14721446 ) . toBeInViewport ( )
1473- await expect ( shellTrigger ) . toHaveCount ( 0 )
1474- await page . getByRole ( "button" , { name : "1 shell " , exact : true } ) . click ( )
1447+ await expect ( call ) . toHaveCount ( 0 )
1448+ await page . getByRole ( "button" , { name : "1 subagent " , exact : true } ) . click ( )
14751449 await page
1476- . getByRole ( "menu" , { name : "1 shell " , exact : true } )
1477- . getByRole ( "menuitem" , { name : / s l e e p 1 2 0 / } )
1450+ . getByRole ( "menu" , { name : "1 subagent " , exact : true } )
1451+ . getByRole ( "menuitem" , { name : / M a p t h e f a r c o d e / } )
14781452 . click ( )
14791453
14801454 await expect ( group ) . toHaveAttribute ( "aria-expanded" , "true" )
1481- await expect ( shellTrigger ) . toHaveAttribute ( "aria-expanded" , "true" )
1482- await expect ( shellTrigger ) . toBeInViewport ( )
1455+ await expect ( call ) . toBeInViewport ( )
14831456
1484- // A shell at the very end cannot rise under the header until more content arrives below it.
1457+ // A call at the very end cannot rise under the header until more content arrives below it.
14851458 if ( fixture . searches ) await aligned ( )
14861459 // Nothing covers the row, so it takes the next click.
1487- await shellTrigger . click ( { trial : true } )
1460+ await call . click ( { trial : true } )
14881461
1489- // The agent keeps writing below the shell ; the shell stays where it was revealed.
1462+ // The agent keeps writing below the call ; the call stays where it was revealed.
14901463 await timeline . send ( partUpdated ( textPart ( "prt_late" , notes ( "Late" , 30 ) ) ) )
14911464 await expect ( page . getByText ( "Late note 30." , { exact : true } ) ) . toBeAttached ( )
14921465 await aligned ( )
@@ -2142,10 +2115,7 @@ test("highlights a quote's source only while its first comment is written", asyn
21422115 await expect
21432116 . poll ( ( ) =>
21442117 first . evaluate ( ( element ) =>
2145- [
2146- "::selection" ,
2147- "::highlight(timeline-quote-source)" ,
2148- ] . map ( ( pseudo ) => {
2118+ [ "::selection" , "::highlight(timeline-quote-source)" ] . map ( ( pseudo ) => {
21492119 const style = getComputedStyle ( element , pseudo )
21502120
21512121 return {
@@ -2245,11 +2215,13 @@ test("keeps the native selection height after quoting wrapped and formatted text
22452215 const height = await source . locator ( "p" ) . evaluate ( ( element ) => parseFloat ( getComputedStyle ( element ) . lineHeight ) )
22462216 await expect
22472217 . poll ( ( ) =>
2248- source . locator ( '[data-component="timeline-quote-background"] > span' ) . evaluateAll (
2249- ( lines , height ) =>
2250- lines . length > 0 && lines . every ( ( line ) => Math . abs ( line . getBoundingClientRect ( ) . height - height ) < 0.1 ) ,
2251- height ,
2252- ) ,
2218+ source
2219+ . locator ( '[data-component="timeline-quote-background"] > span' )
2220+ . evaluateAll (
2221+ ( lines , height ) =>
2222+ lines . length > 0 && lines . every ( ( line ) => Math . abs ( line . getBoundingClientRect ( ) . height - height ) < 0.1 ) ,
2223+ height ,
2224+ ) ,
22532225 )
22542226 . toBe ( true )
22552227} )
0 commit comments