fix(tui): support model picker refresh

This commit is contained in:
helix4u 2026-07-06 12:08:45 -06:00 committed by Teknium
parent 70c6ae609e
commit 4131ec380b
5 changed files with 30 additions and 4 deletions

View file

@ -183,6 +183,15 @@ describe('createSlashHandler', () => {
})
})
it('opens the model picker with refresh for /model --refresh', () => {
patchUiState({ sid: 'sid-abc' })
const ctx = buildCtx()
expect(createSlashHandler(ctx)('/model --refresh')).toBe(true)
expect(getOverlayState().modelPicker).toEqual({ refresh: true })
expect(ctx.gateway.rpc).not.toHaveBeenCalled()
})
it('honors TUI picker session scope without adding --global', async () => {
patchUiState({ sid: 'sid-abc' })

View file

@ -135,7 +135,7 @@ export interface OverlayState {
clarify: ClarifyReq | null
confirm: ConfirmReq | null
journey: boolean
modelPicker: boolean
modelPicker: boolean | { refresh?: boolean }
pager: null | PagerState
petPicker: boolean
pluginsHub: boolean

View file

@ -73,6 +73,10 @@ export const sessionCommands: SlashCommand[] = [
return patchOverlayState({ modelPicker: true })
}
if (arg.trim() === '--refresh') {
return patchOverlayState({ modelPicker: { refresh: true } })
}
const switchModel = (confirmExpensiveModel = false) =>
ctx.gateway
.rpc<ConfigSetResponse>('config.set', {

View file

@ -180,6 +180,7 @@ export function FloatingOverlays({
<FloatBox color={theme.color.border}>
<ModelPicker
gw={gw}
initialRefresh={typeof overlay.modelPicker === 'object' && overlay.modelPicker.refresh === true}
onCancel={() => patchOverlayState({ modelPicker: false })}
onSelect={onModelSelect}
sessionId={sid}

View file

@ -27,7 +27,15 @@ export function providerIndexAfterClearingFilter(providerRows: ProviderRow[], pr
return providerRows.findIndex(row => row.provider.slug === provider.slug)
}
export function ModelPicker({ allowPersistGlobal = true, gw, onCancel, onSelect, sessionId, t }: ModelPickerProps) {
export function ModelPicker({
allowPersistGlobal = true,
gw,
initialRefresh = false,
onCancel,
onSelect,
sessionId,
t
}: ModelPickerProps) {
const [providers, setProviders] = useState<ModelOptionProvider[]>([])
const [currentModel, setCurrentModel] = useState('')
const [err, setErr] = useState('')
@ -50,7 +58,10 @@ export function ModelPicker({ allowPersistGlobal = true, gw, onCancel, onSelect,
const width = Math.max(MIN_WIDTH, Math.min(MAX_WIDTH, (stdout?.columns ?? 80) - 6))
useEffect(() => {
gw.request<ModelOptionsResponse>('model.options', sessionId ? { session_id: sessionId } : {})
gw.request<ModelOptionsResponse>('model.options', {
...(sessionId ? { session_id: sessionId } : {}),
...(initialRefresh ? { refresh: true } : {})
})
.then(raw => {
const r = asRpcResult<ModelOptionsResponse>(raw)
@ -79,7 +90,7 @@ export function ModelPicker({ allowPersistGlobal = true, gw, onCancel, onSelect,
setErr(rpcErrorMessage(e))
setLoading(false)
})
}, [gw, sessionId])
}, [gw, initialRefresh, sessionId])
const names = useMemo(() => providerDisplayNames(providers), [providers])
@ -677,6 +688,7 @@ export function ModelPicker({ allowPersistGlobal = true, gw, onCancel, onSelect,
interface ModelPickerProps {
allowPersistGlobal?: boolean
gw: GatewayClient
initialRefresh?: boolean
onCancel: () => void
onSelect: (value: string) => void
sessionId: string | null