@@ -98,19 +98,26 @@ export const FreebuffModelSelector: React.FC = () => {
9898 ? session . rateLimitsByModel
9999 : undefined
100100
101- const getQuotaHint = useCallback (
102- ( modelId : string ) : string => {
103- const rateLimit = rateLimitsByModel ?. [ modelId ]
104- if ( rateLimit ) {
105- return `${ formatSessionUnits ( rateLimit . recentCount ) } /${ rateLimit . limit } used`
106- }
107- return isFreebuffPremiumModelId ( modelId )
108- ? `0/${ FREEBUFF_PREMIUM_SESSION_LIMIT } used`
109- : 'Unlimited'
110- } ,
101+ // All premium models share one quota pool: the server replicates the same
102+ // snapshot under each premium model id, so any entry has the right count.
103+ // Grab the first one (or 0 when the user has no usage and the map is
104+ // absent) so the footer can render the single shared counter.
105+ const sharedPremiumUsed = useMemo (
106+ ( ) =>
107+ rateLimitsByModel
108+ ? ( Object . values ( rateLimitsByModel ) [ 0 ] ?. recentCount ?? 0 )
109+ : 0 ,
111110 [ rateLimitsByModel ] ,
112111 )
113112
113+ // Per-row hint is a tier badge, not a quota counter: premium models share
114+ // the 5-session pool (shown once in the footer); MiniMax is unlimited.
115+ const getTierLabel = useCallback (
116+ ( modelId : string ) : string =>
117+ isFreebuffPremiumModelId ( modelId ) ? 'Premium' : 'Unlimited' ,
118+ [ ] ,
119+ )
120+
114121 const BUTTON_CHROME = 4 // 2 border + 2 padding
115122
116123 // Decide whether secondary details (warning / deployment hours) get their
@@ -130,7 +137,7 @@ export const FreebuffModelSelector: React.FC = () => {
130137 }
131138
132139 const hintLen = ( model : FreebuffModelOption ) : number =>
133- Math . max ( getQuotaHint ( model . id ) . length , 'Closed' . length )
140+ Math . max ( getTierLabel ( model . id ) . length , 'Closed' . length )
134141
135142 const oneLineLen = ( model : FreebuffModelOption ) : number => {
136143 const inlineDetails = detailsTextLen ( model )
@@ -140,7 +147,7 @@ export const FreebuffModelSelector: React.FC = () => {
140147 3 /* " · " */ +
141148 model . tagline . length +
142149 ( inlineDetails > 0 ? 3 + inlineDetails : 0 ) +
143- 1 /* space before hint */ +
150+ 3 /* " · " before hint */ +
144151 hintLen ( model )
145152 )
146153 }
@@ -150,7 +157,7 @@ export const FreebuffModelSelector: React.FC = () => {
150157 model . displayName . length +
151158 3 +
152159 model . tagline . length +
153- 1 +
160+ 3 +
154161 hintLen ( model )
155162
156163 const detailsLineLen = ( model : FreebuffModelOption ) : number => {
@@ -176,7 +183,7 @@ export const FreebuffModelSelector: React.FC = () => {
176183 contentMaxWidth ,
177184 ) ,
178185 }
179- } , [ contentMaxWidth , deploymentAvailabilityLabel , getQuotaHint ] )
186+ } , [ contentMaxWidth , deploymentAvailabilityLabel , getTierLabel ] )
180187
181188 const isJoinable = useCallback (
182189 ( modelId : string ) => {
@@ -255,8 +262,8 @@ export const FreebuffModelSelector: React.FC = () => {
255262 // anything except re-picking the queue we're already in.
256263 const interactable =
257264 ! pending && canJoin && model . id !== committedModelId
258- const quotaHint = getQuotaHint ( model . id )
259- const hint = isAvailable ? quotaHint : 'Closed'
265+ const tierLabel = getTierLabel ( model . id )
266+ const hint = isAvailable ? tierLabel : 'Closed'
260267
261268 // Focused row: green border + arrow indicator + bold name. The name
262269 // itself stays the normal foreground color so it doesn't shout — the
@@ -317,7 +324,7 @@ export const FreebuffModelSelector: React.FC = () => {
317324 { showInlineWarning && (
318325 < span fg = { warningColor } > · { model . warning } </ span >
319326 ) }
320- < span fg = { hintColor } > { hint } </ span >
327+ < span fg = { hintColor } > · { hint } </ span >
321328 </ text >
322329 { showWrappedDetails && (
323330 < text >
@@ -336,6 +343,14 @@ export const FreebuffModelSelector: React.FC = () => {
336343 </ Button >
337344 )
338345 } ) }
346+ { /* Single shared-quota footer. Replaces the per-row "X/5 used" hints
347+ which made it look like each premium model had its own pool.
348+ wrapMode: 'word' so the line reflows on narrow terminals instead of
349+ clipping. */ }
350+ < text style = { { fg : theme . muted , marginTop : 1 , wrapMode : 'word' } } >
351+ { formatSessionUnits ( sharedPremiumUsed ) } /{ ' ' }
352+ { FREEBUFF_PREMIUM_SESSION_LIMIT } premium sessions used today
353+ </ text >
339354 </ box >
340355 )
341356}
0 commit comments