88 createFooterState ,
99 reduceFooterState ,
1010 selectFooterViewModel ,
11+ selectStatusBarExtras ,
1112 type FooterEvent ,
1213} from '#/tui/runtime/footer/footer-model' ;
1314import { SessionEventHandler } from '#/tui/controllers/session-event-handler' ;
@@ -174,11 +175,12 @@ function makeTokenSpeedHost() {
174175 ) ,
175176 ) ;
176177 } ) ;
177- return { host, footer } ;
178- }
179-
180- function renderFooter ( footer : FooterComponent ) : string {
181- return footer . render ( 160 ) [ 0 ] ?. replaceAll ( / \u001B \[ [ 0 - 9 ; ] * m / g, '' ) ?? '' ;
178+ return {
179+ host,
180+ footer,
181+ renderStatusBarExtras : ( ) =>
182+ selectStatusBarExtras ( footerState , Date . now ( ) , DEFAULT_STATUS_LINE_CONFIG ) . join ( ' ' ) ,
183+ } ;
182184}
183185
184186function sendQueuedViaHost ( host : ReturnType < typeof makeHost > [ 'host' ] , session : unknown ) {
@@ -368,7 +370,7 @@ describe('SessionEventHandler Dynamic Workflow routing', () => {
368370
369371describe ( 'SessionEventHandler token speed' , ( ) => {
370372 it ( 'projects spend into the footer and retains pricing for /cost' , ( ) => {
371- const { host, footer } = makeTokenSpeedHost ( ) ;
373+ const { host, footer, renderStatusBarExtras } = makeTokenSpeedHost ( ) ;
372374 const handler = new SessionEventHandler ( host ) ;
373375 try {
374376 handler . handleEvent (
@@ -382,9 +384,9 @@ describe('SessionEventHandler token speed', () => {
382384 vi . fn ( ) ,
383385 ) ;
384386
385- expect ( renderFooter ( footer ) ) . not . toContain ( 'in $3/M out $15/M' ) ;
386- expect ( renderFooter ( footer ) ) . toContain ( '$0.13' ) ;
387- expect ( renderFooter ( footer ) ) . not . toContain ( 'spent' ) ;
387+ expect ( renderStatusBarExtras ( ) ) . not . toContain ( 'in $3/M out $15/M' ) ;
388+ expect ( renderStatusBarExtras ( ) ) . toContain ( '$0.13' ) ;
389+ expect ( renderStatusBarExtras ( ) ) . not . toContain ( 'spent' ) ;
388390 expect ( host . state . appState . modelCostRates ) . toEqual ( { input : 3 , output : 15 } ) ;
389391 expect ( host . state . appState . totalCostUsd ) . toBe ( 0.125 ) ;
390392
@@ -445,7 +447,7 @@ describe('SessionEventHandler token speed', () => {
445447 ] ) ( 'updates a live estimate from $name and replaces it with exact usage' , ( { event } ) => {
446448 vi . useFakeTimers ( ) ;
447449 vi . setSystemTime ( 0 ) ;
448- const { host, footer } = makeTokenSpeedHost ( ) ;
450+ const { host, footer, renderStatusBarExtras } = makeTokenSpeedHost ( ) ;
449451 const handler = new SessionEventHandler ( host ) ;
450452 try {
451453 handler . handleEvent (
@@ -464,7 +466,7 @@ describe('SessionEventHandler token speed', () => {
464466 vi . setSystemTime ( 3_000 ) ;
465467 handler . handleEvent ( event ( 'x' . repeat ( 400 ) ) , vi . fn ( ) ) ;
466468
467- expect ( renderFooter ( footer ) ) . toContain ( '~100.0 t/s' ) ;
469+ expect ( renderStatusBarExtras ( ) ) . toContain ( '~100.0 t/s' ) ;
468470
469471 handler . handleEvent (
470472 {
@@ -483,8 +485,8 @@ describe('SessionEventHandler token speed', () => {
483485 } ,
484486 vi . fn ( ) ,
485487 ) ;
486- expect ( renderFooter ( footer ) ) . toContain ( '42.0 t/s' ) ;
487- expect ( renderFooter ( footer ) ) . not . toContain ( '~42.0 t/s' ) ;
488+ expect ( renderStatusBarExtras ( ) ) . toContain ( '42.0 t/s' ) ;
489+ expect ( renderStatusBarExtras ( ) ) . not . toContain ( '~42.0 t/s' ) ;
488490 } finally {
489491 footer . dispose ( ) ;
490492 }
@@ -493,7 +495,7 @@ describe('SessionEventHandler token speed', () => {
493495 it ( 'keeps concurrent agent stream estimates separate' , ( ) => {
494496 vi . useFakeTimers ( ) ;
495497 vi . setSystemTime ( 0 ) ;
496- const { host, footer } = makeTokenSpeedHost ( ) ;
498+ const { host, footer, renderStatusBarExtras } = makeTokenSpeedHost ( ) ;
497499 const handler = new SessionEventHandler ( host ) ;
498500 const event = ( agentId : string , delta : string ) => ( {
499501 type : 'assistant.delta' as const ,
@@ -508,18 +510,18 @@ describe('SessionEventHandler token speed', () => {
508510 handler . handleEvent ( event ( 'agent-b' , 'abcd' ) , vi . fn ( ) ) ;
509511 vi . setSystemTime ( 1_000 ) ;
510512 handler . handleEvent ( event ( 'agent-a' , 'x' . repeat ( 400 ) ) , vi . fn ( ) ) ;
511- expect ( renderFooter ( footer ) ) . toContain ( '~100.0 t/s' ) ;
513+ expect ( renderStatusBarExtras ( ) ) . toContain ( '~100.0 t/s' ) ;
512514
513515 vi . setSystemTime ( 1_500 ) ;
514516 handler . handleEvent ( event ( 'agent-b' , 'x' . repeat ( 200 ) ) , vi . fn ( ) ) ;
515- expect ( renderFooter ( footer ) ) . toContain ( '~50.0 t/s' ) ;
517+ expect ( renderStatusBarExtras ( ) ) . toContain ( '~50.0 t/s' ) ;
516518 } finally {
517519 footer . dispose ( ) ;
518520 }
519521 } ) ;
520522
521523 it ( 'uses the latest valid main or child completed stream' , ( ) => {
522- const { host, footer } = makeTokenSpeedHost ( ) ;
524+ const { host, footer, renderStatusBarExtras } = makeTokenSpeedHost ( ) ;
523525 const handler = new SessionEventHandler ( host ) ;
524526 try {
525527 handler . handleEvent (
@@ -539,7 +541,7 @@ describe('SessionEventHandler token speed', () => {
539541 } ,
540542 vi . fn ( ) ,
541543 ) ;
542- expect ( renderFooter ( footer ) ) . toContain ( '42.0 t/s' ) ;
544+ expect ( renderStatusBarExtras ( ) ) . toContain ( '42.0 t/s' ) ;
543545
544546 handler . handleEvent (
545547 {
@@ -558,7 +560,7 @@ describe('SessionEventHandler token speed', () => {
558560 } ,
559561 vi . fn ( ) ,
560562 ) ;
561- expect ( renderFooter ( footer ) ) . toContain ( '50.0 t/s' ) ;
563+ expect ( renderStatusBarExtras ( ) ) . toContain ( '50.0 t/s' ) ;
562564 } finally {
563565 footer . dispose ( ) ;
564566 }
@@ -591,7 +593,7 @@ describe('SessionEventHandler token speed', () => {
591593 output : 10 ,
592594 } , Number . NaN ] ,
593595 ] as const ) ( 'ignores %s' , ( _label , usage , llmStreamDurationMs ) => {
594- const { host, footer } = makeTokenSpeedHost ( ) ;
596+ const { host, footer, renderStatusBarExtras } = makeTokenSpeedHost ( ) ;
595597 const handler = new SessionEventHandler ( host ) ;
596598 try {
597599 handler . handleEvent (
@@ -611,7 +613,7 @@ describe('SessionEventHandler token speed', () => {
611613 } ,
612614 vi . fn ( ) ,
613615 ) ;
614- expect ( renderFooter ( footer ) ) . toContain ( '42.0 t/s' ) ;
616+ expect ( renderStatusBarExtras ( ) ) . toContain ( '42.0 t/s' ) ;
615617
616618 handler . handleEvent (
617619 {
@@ -625,14 +627,14 @@ describe('SessionEventHandler token speed', () => {
625627 } ,
626628 vi . fn ( ) ,
627629 ) ;
628- expect ( renderFooter ( footer ) ) . toContain ( '42.0 t/s' ) ;
630+ expect ( renderStatusBarExtras ( ) ) . toContain ( '42.0 t/s' ) ;
629631 } finally {
630632 footer . dispose ( ) ;
631633 }
632634 } ) ;
633635
634636 it ( 'clears completed throughput when the turn ends' , ( ) => {
635- const { host, footer } = makeTokenSpeedHost ( ) ;
637+ const { host, footer, renderStatusBarExtras } = makeTokenSpeedHost ( ) ;
636638 const handler = new SessionEventHandler ( host ) ;
637639 try {
638640 handler . handleEvent (
@@ -652,18 +654,18 @@ describe('SessionEventHandler token speed', () => {
652654 } ,
653655 vi . fn ( ) ,
654656 ) ;
655- expect ( renderFooter ( footer ) ) . toContain ( '42.0 t/s' ) ;
657+ expect ( renderStatusBarExtras ( ) ) . toContain ( '42.0 t/s' ) ;
656658
657659 handler . handleEvent ( turnEndedEvent ( ) , vi . fn ( ) ) ;
658660
659- expect ( renderFooter ( footer ) ) . not . toContain ( 't/s' ) ;
661+ expect ( renderStatusBarExtras ( ) ) . not . toContain ( 't/s' ) ;
660662 } finally {
661663 footer . dispose ( ) ;
662664 }
663665 } ) ;
664666
665667 it ( 'ignores replayed completion metrics and clears on runtime reset' , ( ) => {
666- const { host, footer } = makeTokenSpeedHost ( ) ;
668+ const { host, footer, renderStatusBarExtras } = makeTokenSpeedHost ( ) ;
667669 const handler = new SessionEventHandler ( host ) ;
668670 try {
669671 handler . handleEvent (
@@ -683,7 +685,7 @@ describe('SessionEventHandler token speed', () => {
683685 } ,
684686 vi . fn ( ) ,
685687 ) ;
686- expect ( renderFooter ( footer ) ) . toContain ( '10.0 t/s' ) ;
688+ expect ( renderStatusBarExtras ( ) ) . toContain ( '10.0 t/s' ) ;
687689
688690 host . state . appState . isReplaying = true ;
689691 handler . handleEvent (
@@ -703,10 +705,10 @@ describe('SessionEventHandler token speed', () => {
703705 } ,
704706 vi . fn ( ) ,
705707 ) ;
706- expect ( renderFooter ( footer ) ) . toContain ( '10.0 t/s' ) ;
708+ expect ( renderStatusBarExtras ( ) ) . toContain ( '10.0 t/s' ) ;
707709
708710 handler . resetRuntimeState ( ) ;
709- expect ( renderFooter ( footer ) ) . not . toContain ( 't/s' ) ;
711+ expect ( renderStatusBarExtras ( ) ) . not . toContain ( 't/s' ) ;
710712 } finally {
711713 footer . dispose ( ) ;
712714 }
0 commit comments