1- import chalk from "chalk " ;
1+ import { stripVTControlCharacters , styleText } from "node:util " ;
22import { terminalLink } from "termi-link" ;
3- import boxen from "boxen" ;
43import Table from "cli-table3" ;
54import pluralize from "pluralize" ;
65
@@ -9,10 +8,45 @@ import type { ReporterDef } from "../../reporters/types";
98import { EvaluatorDef , EvalResultWithSummary } from "../../framework" ;
109import { isEmpty } from "../../util" ;
1110
11+ function visibleLength ( text : string ) {
12+ return stripVTControlCharacters ( text ) . length ;
13+ }
14+
15+ function padEndVisible ( text : string , targetLength : number ) {
16+ return text + " " . repeat ( Math . max ( 0 , targetLength - visibleLength ( text ) ) ) ;
17+ }
18+
19+ function formatSummaryBox ( content : string ) {
20+ const title = styleText ( "gray" , " Experiment summary " ) ;
21+ const lines = content . split ( "\n" ) ;
22+ const contentWidth = Math . max (
23+ visibleLength ( title ) ,
24+ ...lines . map ( ( line ) => visibleLength ( line ) + 2 ) ,
25+ ) ;
26+
27+ const horizontal = "─" ;
28+ const top =
29+ styleText ( "gray" , "╭" ) +
30+ title +
31+ styleText (
32+ "gray" ,
33+ horizontal . repeat ( contentWidth - visibleLength ( title ) ) + "╮" ,
34+ ) ;
35+ const body = lines
36+ . map (
37+ ( line ) =>
38+ `${ styleText ( "gray" , "│" ) } ${ padEndVisible ( line , contentWidth - 2 ) } ${ styleText ( "gray" , "│" ) } ` ,
39+ )
40+ . join ( "\n" ) ;
41+ const bottom = styleText ( "gray" , "╰" + horizontal . repeat ( contentWidth ) + "╯" ) ;
42+
43+ return top + "\n" + body + "\n" + bottom ;
44+ }
45+
1246function formatExperimentSummaryFancy ( summary : ExperimentSummary ) {
1347 let comparisonLine = "" ;
1448 if ( summary . comparisonExperimentName ) {
15- comparisonLine = `${ summary . comparisonExperimentName } ${ chalk . gray ( " (baseline)") } ← ${ summary . experimentName } ${ chalk . gray ( "(comparison)" ) } \n\n` ;
49+ comparisonLine = `${ summary . comparisonExperimentName } ${ styleText ( "gray" , " (baseline)") } ← ${ summary . experimentName } ${ styleText ( "gray" , "(comparison)" ) } \n\n` ;
1650 }
1751
1852 const tableParts : string [ ] = [ ] ;
@@ -22,13 +56,13 @@ function formatExperimentSummaryFancy(summary: ExperimentSummary) {
2256 const hasComparison = ! ! summary . comparisonExperimentName ;
2357
2458 if ( hasScores || hasMetrics ) {
25- const headers = [ chalk . gray ( " Name") , chalk . gray ( "Value" ) ] ;
59+ const headers = [ styleText ( "gray" , " Name") , styleText ( "gray" , "Value" ) ] ;
2660
2761 if ( hasComparison ) {
2862 headers . push (
29- chalk . gray ( "Change" ) ,
30- chalk . gray ( "Improvements" ) ,
31- chalk . gray ( "Regressions" ) ,
63+ styleText ( "gray" , "Change" ) ,
64+ styleText ( "gray" , "Improvements" ) ,
65+ styleText ( "gray" , "Regressions" ) ,
3266 ) ;
3367 }
3468
@@ -62,28 +96,28 @@ function formatExperimentSummaryFancy(summary: ExperimentSummary) {
6296 const scoreValues : ScoreSummary [ ] = Object . values ( summary . scores ) ;
6397 for ( const score of scoreValues ) {
6498 const scorePercent = ( score . score * 100 ) . toFixed ( 2 ) ;
65- const scoreValue = chalk . white ( `${ scorePercent } %` ) ;
99+ const scoreValue = styleText ( "white" , `${ scorePercent } %` ) ;
66100
67101 let diffString = "" ;
68102 if ( ! isEmpty ( score . diff ) ) {
69103 const diffPercent = ( score . diff ! * 100 ) . toFixed ( 2 ) ;
70104 const diffSign = score . diff ! > 0 ? "+" : "" ;
71- const diffColor = score . diff ! > 0 ? chalk . green : chalk . red ;
72- diffString = diffColor ( `${ diffSign } ${ diffPercent } %` ) ;
105+ const diffColor = score . diff ! > 0 ? " green" : " red" ;
106+ diffString = styleText ( diffColor , `${ diffSign } ${ diffPercent } %` ) ;
73107 } else {
74- diffString = chalk . gray ( "-" ) ;
108+ diffString = styleText ( "gray" , "-" ) ;
75109 }
76110
77111 const improvements =
78112 score . improvements > 0
79- ? chalk . dim . green ( score . improvements )
80- : chalk . gray ( "-" ) ;
113+ ? styleText ( [ " dim" , " green" ] , String ( score . improvements ) )
114+ : styleText ( "gray" , "-" ) ;
81115 const regressions =
82116 score . regressions > 0
83- ? chalk . dim . red ( score . regressions )
84- : chalk . gray ( "-" ) ;
117+ ? styleText ( [ " dim" , " red" ] , String ( score . regressions ) )
118+ : styleText ( "gray" , "-" ) ;
85119
86- const row = [ `${ chalk . blue ( "◯" ) } ${ score . name } ` , scoreValue ] ;
120+ const row = [ `${ styleText ( "blue" , "◯" ) } ${ score . name } ` , scoreValue ] ;
87121 if ( hasComparison ) {
88122 row . push ( diffString , improvements , regressions ) ;
89123 }
@@ -94,7 +128,8 @@ function formatExperimentSummaryFancy(summary: ExperimentSummary) {
94128 for ( const metric of metricValues ) {
95129 const fractionDigits = Number . isInteger ( metric . metric ) ? 0 : 2 ;
96130 const formattedValue = metric . metric . toFixed ( fractionDigits ) ;
97- const metricValue = chalk . white (
131+ const metricValue = styleText (
132+ "white" ,
98133 metric . unit === "$"
99134 ? `${ metric . unit } ${ formattedValue } `
100135 : `${ formattedValue } ${ metric . unit } ` ,
@@ -104,22 +139,22 @@ function formatExperimentSummaryFancy(summary: ExperimentSummary) {
104139 if ( ! isEmpty ( metric . diff ) ) {
105140 const diffPercent = ( metric . diff ! * 100 ) . toFixed ( 2 ) ;
106141 const diffSign = metric . diff ! > 0 ? "+" : "" ;
107- const diffColor = metric . diff ! > 0 ? chalk . green : chalk . red ;
108- diffString = diffColor ( `${ diffSign } ${ diffPercent } %` ) ;
142+ const diffColor = metric . diff ! > 0 ? " green" : " red" ;
143+ diffString = styleText ( diffColor , `${ diffSign } ${ diffPercent } %` ) ;
109144 } else {
110- diffString = chalk . gray ( "-" ) ;
145+ diffString = styleText ( "gray" , "-" ) ;
111146 }
112147
113148 const improvements =
114149 metric . improvements > 0
115- ? chalk . dim . green ( metric . improvements )
116- : chalk . gray ( "-" ) ;
150+ ? styleText ( [ " dim" , " green" ] , String ( metric . improvements ) )
151+ : styleText ( "gray" , "-" ) ;
117152 const regressions =
118153 metric . regressions > 0
119- ? chalk . dim . red ( metric . regressions )
120- : chalk . gray ( "-" ) ;
154+ ? styleText ( [ " dim" , " red" ] , String ( metric . regressions ) )
155+ : styleText ( "gray" , "-" ) ;
121156
122- const row = [ `${ chalk . magenta ( "◯" ) } ${ metric . name } ` , metricValue ] ;
157+ const row = [ `${ styleText ( "magenta" , "◯" ) } ${ metric . name } ` , metricValue ] ;
123158 if ( hasComparison ) {
124159 row . push ( diffString , improvements , regressions ) ;
125160 }
@@ -141,23 +176,10 @@ function formatExperimentSummaryFancy(summary: ExperimentSummary) {
141176
142177 const boxContent = [ content , footer ] . filter ( Boolean ) . join ( "\n\n" ) ;
143178
144- try {
145- return (
146- "\n" +
147- boxen ( boxContent , {
148- title : chalk . gray ( "Experiment summary" ) ,
149- titleAlignment : "left" ,
150- padding : 0.5 ,
151- borderColor : "gray" ,
152- borderStyle : "round" ,
153- } )
154- ) ;
155- } catch {
156- return "\n" + chalk . gray ( "Experiment summary" ) + "\n" + boxContent + "\n" ;
157- }
179+ return "\n" + formatSummaryBox ( boxContent ) ;
158180}
159181
160- export const warning = chalk . yellow ;
182+ export const warning = ( text : string ) => styleText ( " yellow" , text ) ;
161183
162184export const fancyReporter : ReporterDef < boolean > = {
163185 name : "Braintrust fancy reporter" ,
0 commit comments