@@ -4,8 +4,8 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'
44
55import { Button } from './button'
66import {
7+ DEFAULT_FREEBUFF_MODEL_ID ,
78 FALLBACK_FREEBUFF_MODEL_ID ,
8- FREEBUFF_KIMI_MODEL_ID ,
99 FREEBUFF_MODELS ,
1010 getFreebuffDeploymentAvailabilityLabel ,
1111 isFreebuffModelAvailable ,
@@ -19,11 +19,16 @@ import { useTerminalDimensions } from '../hooks/use-terminal-dimensions'
1919import { useTheme } from '../hooks/use-theme'
2020import { nextFreebuffModelId } from '../utils/freebuff-model-navigation'
2121
22+ import type { FreebuffModelOption } from '@codebuff/common/constants/freebuff-models'
2223import type { KeyEvent } from '@opentui/core'
2324
24- const FREEBUFF_MODEL_SELECTOR_MODELS = [
25- ...FREEBUFF_MODELS . filter ( ( model ) => model . id === FREEBUFF_KIMI_MODEL_ID ) ,
26- ...FREEBUFF_MODELS . filter ( ( model ) => model . id !== FREEBUFF_KIMI_MODEL_ID ) ,
25+ // Widen the readonly tuple from FREEBUFF_MODELS to FreebuffModelOption[] so
26+ // the selector can branch on optional fields (e.g. `warning`) and on
27+ // availability values that aren't present in today's set but might be added
28+ // later, without TS narrowing the literal types away.
29+ const FREEBUFF_MODEL_SELECTOR_MODELS : readonly FreebuffModelOption [ ] = [
30+ ...FREEBUFF_MODELS . filter ( ( model ) => model . id === DEFAULT_FREEBUFF_MODEL_ID ) ,
31+ ...FREEBUFF_MODELS . filter ( ( model ) => model . id !== DEFAULT_FREEBUFF_MODEL_ID ) ,
2732]
2833
2934/**
@@ -69,7 +74,7 @@ export const FreebuffModelSelector: React.FC = () => {
6974 // unavailable (e.g. deployment hours close while the picker is open),
7075 // swap to the always-available fallback so Enter doesn't POST a model
7176 // the server will immediately reject. In-memory only — the user's saved
72- // preference (e.g. Kimi) is preserved for the next launch.
77+ // preference (e.g. Kimi or DeepSeek ) is preserved for the next launch.
7378 if (
7479 ( session ?. status === 'none' || ! session ) &&
7580 ! isFreebuffModelAvailable ( selectedModel , new Date ( now ) )
@@ -119,7 +124,7 @@ export const FreebuffModelSelector: React.FC = () => {
119124
120125 // Decide row vs column layout based on whether the buttons actually fit
121126 // side-by-side. Each button's inner text is
122- // "● {displayName} · {tagline} · {hours} {hint}",
127+ // "● {displayName} · {tagline} · {hours/warning } {hint}",
123128 // plus 2 cols of border and 2 cols of padding. Buttons are separated by a
124129 // gap of 2. If the total exceeds the terminal width, stack vertically.
125130 const stackVertically = useMemo ( ( ) => {
@@ -134,6 +139,7 @@ export const FreebuffModelSelector: React.FC = () => {
134139 ( model . availability === 'deployment_hours'
135140 ? 3 + deploymentAvailabilityLabel . length
136141 : 0 ) +
142+ ( model . warning ? 3 + model . warning . length : 0 ) +
137143 2 /* " " */ +
138144 hintWidth
139145 return sum + inner + BUTTON_CHROME + ( idx > 0 ? GAP : 0 )
@@ -302,6 +308,9 @@ export const FreebuffModelSelector: React.FC = () => {
302308 { model . availability === 'deployment_hours' && (
303309 < span fg = { theme . muted } > · { deploymentAvailabilityLabel } </ span >
304310 ) }
311+ { model . warning && (
312+ < span fg = { theme . secondary } > · { model . warning } </ span >
313+ ) }
305314 < span fg = { hintColor } > { hint . padEnd ( hintWidth ) } </ span >
306315 </ text >
307316 </ Button >
0 commit comments