@@ -55,7 +55,26 @@ function Delta({ v, theme }: { v: number; theme: Theme }) {
5555 ) ;
5656}
5757
58- function ModelRow ( { m, max, theme, total } : { m : ModelStat ; max : number ; theme : Theme ; total : number } ) {
58+ // Round each value's share to 1 decimal (%) via largest-remainder apportionment,
59+ // so the displayed percentages sum to exactly 100.0% (plain rounding wouldn't).
60+ function sharePcts ( values : number [ ] ) : number [ ] {
61+ const total = values . reduce ( ( s , v ) => s + v , 0 ) ;
62+ if ( total <= 0 ) return values . map ( ( ) => 0 ) ;
63+ const UNITS = 1000 ; // work in 0.1% units; target is 100.0%
64+ const raw = values . map ( ( v ) => ( v / total ) * UNITS ) ;
65+ const units = raw . map ( Math . floor ) ;
66+ const left = Math . round ( UNITS - units . reduce ( ( s , f ) => s + f , 0 ) ) ;
67+ raw
68+ . map ( ( r , i ) => ( { i, frac : r - Math . floor ( r ) } ) )
69+ . sort ( ( a , b ) => b . frac - a . frac )
70+ . slice ( 0 , left )
71+ . forEach ( ( { i } ) => ( units [ i ] += 1 ) ) ;
72+ return units . map ( ( u ) => u / 10 ) ;
73+ }
74+
75+ function ModelRow ( { m, max, theme, share } : { m : ModelStat ; max : number ; theme : Theme ; share : number } ) {
76+ // 1-decimal share; whole numbers drop the ".0" (100% not 100.0%).
77+ const pctStr = share % 1 === 0 ? share . toFixed ( 0 ) : share . toFixed ( 1 ) ;
5978 return (
6079 < div style = { { display : "flex" , alignItems : "center" , gap : 9 , padding : "5px 0" } } >
6180 < span style = { { width : 7 , height : 7 , borderRadius : 2 , background : m . color , flex : "0 0 auto" } } />
@@ -66,7 +85,7 @@ function ModelRow({ m, max, theme, total }: { m: ModelStat; max: number; theme:
6685 < div style = { { width : `${ ( m . tokens / max ) * 100 } %` , height : "100%" , background : m . color , borderRadius : 3 } } />
6786 </ div >
6887 < span style = { { font : `500 10.5px ${ theme . mono } ` , color : theme . dim , flex : "0 0 auto" , width : 42 , textAlign : "right" } } > { fmtTokens ( m . tokens ) } </ span >
69- < span style = { { font : `600 10.5px ${ theme . mono } ` , color : theme . text , flex : "0 0 auto" , width : 30 , textAlign : "right" } } > { pct ( m . tokens , total ) } %</ span >
88+ < span style = { { font : `600 10.5px ${ theme . mono } ` , color : theme . text , flex : "0 0 auto" , width : 40 , textAlign : "right" } } > { pctStr } %</ span >
7089 </ div >
7190 ) ;
7291}
@@ -149,11 +168,18 @@ function Panel({ dash, dark, onToggleTheme, openGen, active }: { dash: Dashboard
149168 const animTotal = useCountUp ( M . totalTokens , `${ period } :${ openGen } ` , active ) ;
150169 const models = P . models ;
151170 // Hide noise: 0% token-share rows, and $0 entries in the cost donut.
152- const tokenModels = models . filter ( ( m ) => pct ( m . tokens , M . totalTokens || 1 ) > 0 ) ;
171+ // Show models whose share is at least 0.1% when rounded to 1 decimal; below
172+ // that it'd render a meaningless "0.0%" (a negligible token share). Such a
173+ // model can still appear under Cost if it has a non-zero cost.
174+ const tokenModels = models . filter (
175+ ( m ) => Math . round ( ( m . tokens / ( M . totalTokens || 1 ) ) * 1000 ) / 10 >= 0.1
176+ ) ;
153177 const costModels = models . filter ( ( m ) => m . cost > 0 ) ;
154178 // models that were used but have no LiteLLM pricing (cost unknown, not $0)
155179 const unpricedModels = models . filter ( ( m ) => ! m . priced && m . tokens > 0 ) ;
156180 const maxM = Math . max ( ...tokenModels . map ( ( m ) => m . tokens ) , 1e-9 ) ;
181+ // Per-row shares that sum to exactly 100.0% (largest-remainder over visible rows).
182+ const tokenShares = sharePcts ( tokenModels . map ( ( m ) => m . tokens ) ) ;
157183 const trendSub = { Day : "today 24h" , Week : "this week" , Month : "this month" } [ period ] ;
158184
159185 return (
@@ -216,7 +242,7 @@ function Panel({ dash, dark, onToggleTheme, openGen, active }: { dash: Dashboard
216242 { /* models */ }
217243 < div style = { { marginBottom : 4 } } > < Label t = { t } > Tokens by model</ Label > </ div >
218244 { tokenModels . length === 0 && < div style = { { font : `500 10.5px ${ t . mono } ` , color : t . faint , padding : "4px 0" } } > No usage in this period</ div > }
219- { tokenModels . map ( ( m , i ) => < ModelRow key = { i } m = { m } max = { maxM } theme = { t } total = { M . totalTokens || 1 } /> ) }
245+ { tokenModels . map ( ( m , i ) => < ModelRow key = { i } m = { m } max = { maxM } theme = { t } share = { tokenShares [ i ] } /> ) }
220246 < SectionRule t = { t } m = "10px 0 10px" />
221247 { /* cost donut */ }
222248 < div style = { { marginBottom : 8 } } > < Label t = { t } > Cost by model</ Label > </ div >
0 commit comments