@@ -60,6 +60,18 @@ const INDENT_WIDTH = 2;
6060const MAX_ELEMENT_LINES = 1000 ;
6161const MAX_TABLE_ROWS = 12 ;
6262const MIN_TABLE_CELL_WIDTH = 3 ;
63+ const STARTUP_BANNER_ART = [
64+ ' ____ _ _ _ ' ,
65+ '| _ \\ __ _| |_ __ _| | __ _ ___ _ __ | |_ ' ,
66+ '| | | |/ _` | __/ _` | | / _` |/ _ \\ `_ \\| __|' ,
67+ '| |_| | (_| | || (_| | |__| (_| | __/ | | | |_ ' ,
68+ '|____/ \\__,_|\\__\\__,_|_____\\__, |\\___|_| |_|\\__|' ,
69+ ' |___/ ' ,
70+ ] ;
71+ const STARTUP_BANNER_ART_WIDTH = Math . max (
72+ ...STARTUP_BANNER_ART . map ( ( line ) => textWidth ( line ) ) ,
73+ ) ;
74+ const STARTUP_BANNER_MAX_WIDTH = 72 ;
6375
6476/** Total display-column budget for a single chat row (mirrors the old estimate). */
6577export function chatContentWidth ( columns : number ) : number {
@@ -661,40 +673,71 @@ function pushStartupLines(
661673) : void {
662674 const conn = connectionDisplay ( startup . connectionStatus ) ;
663675 const run = runDisplay ( startup . runStatus ) ;
664- const session = startup . threadId ? ` session: ${ startup . threadId . slice ( 0 , 8 ) } ` : '' ;
676+ const bannerWidth = Math . max ( 20 , Math . min ( contentWidth , STARTUP_BANNER_MAX_WIDTH ) ) ;
677+ const border = `+${ '-' . repeat ( Math . max ( 0 , bannerWidth - 2 ) ) } +` ;
678+ const session = startup . threadId ? startup . threadId . slice ( 0 , 8 ) : 'new' ;
679+ const statusText = `${ conn . icon } ${ conn . text } | ${ run . icon } ${ run . text } ` ;
680+ const showArt = bannerWidth >= STARTUP_BANNER_ART_WIDTH + 4 ;
681+
682+ push ( 'startup:border:top' , < Text key = "startup:border:top" color = "cyan" > { border } </ Text > ) ;
683+ push ( 'startup:title' , (
684+ < Text key = "startup:title" bold color = "cyan" >
685+ { bannerContent ( 'DataAgent' , bannerWidth ) }
686+ </ Text >
687+ ) ) ;
688+
689+ if ( showArt ) {
690+ STARTUP_BANNER_ART . forEach ( ( line , index ) => {
691+ const key = `startup:art:${ index } ` ;
692+ push (
693+ key ,
694+ < Text key = { key } color = "cyan" >
695+ { bannerContent ( padToWidth ( line . trimEnd ( ) , STARTUP_BANNER_ART_WIDTH ) , bannerWidth ) }
696+ </ Text > ,
697+ ) ;
698+ } ) ;
699+ }
665700
666701 push (
667- 'startup:title' ,
668- < Text key = "startup:title" >
669- < Text bold color = "cyan" > DataAgent TUI</ Text >
670- { session ? < Text dimColor > { truncateToWidth ( session , Math . max ( 0 , contentWidth - 13 ) ) } </ Text > : null }
671- </ Text > ,
672- ) ;
673- push (
674- 'startup:model' ,
675- < Text key = "startup:model" >
676- < Text dimColor > model: </ Text >
677- < Text > { truncateToWidth ( startup . modelName , Math . max ( 0 , contentWidth - 11 ) ) } </ Text >
702+ 'startup:session' ,
703+ < Text key = "startup:session" dimColor >
704+ { bannerContent ( `session ${ session } | model ${ startup . modelName } ` , bannerWidth ) }
678705 </ Text > ,
679706 ) ;
680707 push (
681708 'startup:dir' ,
682- < Text key = "startup:dir" >
683- < Text dimColor > directory: </ Text >
684- < Text > { truncateToWidth ( startup . directory , Math . max ( 0 , contentWidth - 11 ) ) } </ Text >
709+ < Text key = "startup:dir" dimColor >
710+ { bannerContent ( `cwd ${ startup . directory } ` , bannerWidth ) }
685711 </ Text > ,
686712 ) ;
687713 push (
688714 'startup:status' ,
689715 < Text key = "startup:status" >
690- < Text color = { conn . color } > { conn . icon } { conn . text } </ Text >
691- < Text dimColor > | </ Text >
692- < Text color = { run . color } > { run . icon } { run . text } </ Text >
716+ { bannerContent ( statusText , bannerWidth ) }
693717 </ Text > ,
694718 ) ;
719+ push ( 'startup:border:bottom' , < Text key = "startup:border:bottom" color = "cyan" > { border } </ Text > ) ;
695720 push ( 'startup:after' , blankNode ( 'startup:after' ) ) ;
696721}
697722
723+ function bannerContent ( text : string , width : number ) : string {
724+ const innerWidth = Math . max ( 0 , width - 4 ) ;
725+ return `| ${ centerToWidth ( text , innerWidth ) } |` ;
726+ }
727+
728+ function centerToWidth ( text : string , width : number ) : string {
729+ const fitted = truncateToWidth ( text , width ) ;
730+ const remaining = Math . max ( 0 , width - textWidth ( fitted ) ) ;
731+ const left = Math . floor ( remaining / 2 ) ;
732+ const right = remaining - left ;
733+ return `${ ' ' . repeat ( left ) } ${ fitted } ${ ' ' . repeat ( right ) } ` ;
734+ }
735+
736+ function padToWidth ( text : string , width : number ) : string {
737+ const fitted = truncateToWidth ( text , width ) ;
738+ return `${ fitted } ${ ' ' . repeat ( Math . max ( 0 , width - textWidth ( fitted ) ) ) } ` ;
739+ }
740+
698741function blankNode ( key : string ) : React . ReactNode {
699742 return < Text key = { key } > </ Text > ;
700743}
0 commit comments