feat(models): expose refreshClaudeModels to bust cache and re-fetch from 9router

This commit is contained in:
Zac Gaetano 2026-06-02 12:28:26 -04:00
parent 7ed22b9077
commit e7514c08cc

View file

@ -90,32 +90,37 @@ export function useChatProviderState({ selectedSession }: UseChatProviderStateAr
load('gemini', setGeminiModelState, GEMINI_MODELS.DEFAULT); load('gemini', setGeminiModelState, GEMINI_MODELS.DEFAULT);
}, [selectedSession?.id]); }, [selectedSession?.id]);
// Fetch live Claude model list and validate the current claude model // Fetch and apply live Claude model list, validating the current selection.
useEffect(() => { const fetchAndSetClaudeModels = useCallback(async () => {
authenticatedFetch('/api/models') const res = await authenticatedFetch('/api/models');
.then((res) => { if (!res.ok) return;
if (!res.ok) return; const data = await res.json();
return res.json(); if (!Array.isArray(data?.claude) || data.claude.length === 0) return;
}) const options: ModelOption[] = data.claude;
.then((data) => { setClaudeModelOptions(options);
if (!Array.isArray(data?.claude) || data.claude.length === 0) return; setClaudeModelState((current) => {
const options: ModelOption[] = data.claude; const valid = options.some((o) => o.value === current);
setClaudeModelOptions(options); if (valid) return current;
const fallback = options[0]?.value ?? CLAUDE_MODELS.DEFAULT;
localStorage.setItem(globalModelKey('claude'), fallback);
if (selectedSession?.id) {
localStorage.setItem(sessionModelKey('claude', selectedSession.id), fallback);
}
return fallback;
});
}, [selectedSession?.id]);
setClaudeModelState((current) => { // Bust the server-side cache then re-fetch the model list.
const valid = options.some((o) => o.value === current); const refreshClaudeModels = useCallback(async () => {
if (valid) return current; await authenticatedFetch('/api/models/refresh', { method: 'POST' });
const fallback = options[0]?.value ?? CLAUDE_MODELS.DEFAULT; await fetchAndSetClaudeModels();
localStorage.setItem(globalModelKey('claude'), fallback); }, [fetchAndSetClaudeModels]);
if (selectedSession?.id) {
localStorage.setItem(sessionModelKey('claude', selectedSession.id), fallback); // Fetch live Claude model list on mount
} useEffect(() => {
return fallback; fetchAndSetClaudeModels().catch(() => {
}); // Static fallback already in place
}) });
.catch(() => {
// Static fallback already in place
});
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
@ -209,5 +214,6 @@ export function useChatProviderState({ selectedSession }: UseChatProviderStateAr
pendingPermissionRequests, pendingPermissionRequests,
setPendingPermissionRequests, setPendingPermissionRequests,
cyclePermissionMode, cyclePermissionMode,
refreshClaudeModels,
}; };
} }