diff --git a/ui-tui/src/__tests__/createSlashHandler.test.ts b/ui-tui/src/__tests__/createSlashHandler.test.ts index c0487fad053..ca1af4cd9ab 100644 --- a/ui-tui/src/__tests__/createSlashHandler.test.ts +++ b/ui-tui/src/__tests__/createSlashHandler.test.ts @@ -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' }) diff --git a/ui-tui/src/app/interfaces.ts b/ui-tui/src/app/interfaces.ts index 65285467d9a..85586f66aaa 100644 --- a/ui-tui/src/app/interfaces.ts +++ b/ui-tui/src/app/interfaces.ts @@ -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 diff --git a/ui-tui/src/app/slash/commands/session.ts b/ui-tui/src/app/slash/commands/session.ts index 94e1b38c5de..6b1fe55481b 100644 --- a/ui-tui/src/app/slash/commands/session.ts +++ b/ui-tui/src/app/slash/commands/session.ts @@ -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('config.set', { diff --git a/ui-tui/src/components/appOverlays.tsx b/ui-tui/src/components/appOverlays.tsx index 9ab568f32ea..24b45d33e24 100644 --- a/ui-tui/src/components/appOverlays.tsx +++ b/ui-tui/src/components/appOverlays.tsx @@ -180,6 +180,7 @@ export function FloatingOverlays({ patchOverlayState({ modelPicker: false })} onSelect={onModelSelect} sessionId={sid} diff --git a/ui-tui/src/components/modelPicker.tsx b/ui-tui/src/components/modelPicker.tsx index c36a1505908..8752dd371a2 100644 --- a/ui-tui/src/components/modelPicker.tsx +++ b/ui-tui/src/components/modelPicker.tsx @@ -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([]) 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('model.options', sessionId ? { session_id: sessionId } : {}) + gw.request('model.options', { + ...(sessionId ? { session_id: sessionId } : {}), + ...(initialRefresh ? { refresh: true } : {}) + }) .then(raw => { const r = asRpcResult(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