Background revalidate provider models when model selector opens
On fresh startup the initial provider snapshot request can return before providers finish loading, leaving the model picker empty. The server broadcasts updates once providers are ready, but if the user opens the picker in the interim they see "No models match". Invalidate the React Query cache (background refetch, no loading flash) every time the model selector popup opens so stale data is silently refreshed.
This commit is contained in:
@@ -88,6 +88,7 @@ type ControlledAgentStatusBarProps = {
|
||||
features?: AgentFeature[];
|
||||
onSetFeature?: (featureId: string, value: unknown) => void;
|
||||
onDropdownClose?: () => void;
|
||||
onModelSelectorOpen?: () => void;
|
||||
};
|
||||
|
||||
export interface DraftAgentStatusBarProps {
|
||||
@@ -110,6 +111,7 @@ export interface DraftAgentStatusBarProps {
|
||||
features?: AgentFeature[];
|
||||
onSetFeature?: (featureId: string, value: unknown) => void;
|
||||
onDropdownClose?: () => void;
|
||||
onModelSelectorOpen?: () => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
@@ -217,6 +219,7 @@ function ControlledStatusBar({
|
||||
features,
|
||||
onSetFeature,
|
||||
onDropdownClose,
|
||||
onModelSelectorOpen,
|
||||
}: ControlledAgentStatusBarProps) {
|
||||
const { theme } = useUnistyles();
|
||||
const isWeb = Platform.OS === "web";
|
||||
@@ -411,6 +414,7 @@ function ControlledStatusBar({
|
||||
onToggleFavorite={onToggleFavoriteModel}
|
||||
isLoading={isModelLoading}
|
||||
disabled={modelDisabled}
|
||||
onOpen={onModelSelectorOpen}
|
||||
onClose={onDropdownClose}
|
||||
/>
|
||||
</View>
|
||||
@@ -662,6 +666,7 @@ function ControlledStatusBar({
|
||||
onToggleFavorite={onToggleFavoriteModel}
|
||||
isLoading={isModelLoading}
|
||||
disabled={modelDisabled}
|
||||
onOpen={onModelSelectorOpen}
|
||||
onClose={onDropdownClose}
|
||||
renderTrigger={({ selectedModelLabel }) => (
|
||||
<View
|
||||
@@ -875,6 +880,7 @@ export function AgentStatusBar({ agentId, serverId, onDropdownClose }: AgentStat
|
||||
entries: snapshotEntries,
|
||||
isLoading: snapshotIsLoading,
|
||||
isFetching: snapshotIsFetching,
|
||||
invalidate: invalidateSnapshot,
|
||||
} = useProvidersSnapshot(serverId);
|
||||
|
||||
const snapshotModels = useMemo(() => {
|
||||
@@ -1035,6 +1041,7 @@ export function AgentStatusBar({ agentId, serverId, onDropdownClose }: AgentStat
|
||||
});
|
||||
}}
|
||||
isModelLoading={snapshotIsLoading || snapshotIsFetching}
|
||||
onModelSelectorOpen={invalidateSnapshot}
|
||||
onDropdownClose={onDropdownClose}
|
||||
disabled={!client}
|
||||
/>
|
||||
@@ -1061,6 +1068,7 @@ export function DraftAgentStatusBar({
|
||||
features,
|
||||
onSetFeature,
|
||||
onDropdownClose,
|
||||
onModelSelectorOpen,
|
||||
disabled = false,
|
||||
}: DraftAgentStatusBarProps) {
|
||||
const isWeb = Platform.OS === "web";
|
||||
@@ -1105,6 +1113,7 @@ export function DraftAgentStatusBar({
|
||||
}}
|
||||
isLoading={isAllModelsLoading}
|
||||
disabled={disabled}
|
||||
onOpen={onModelSelectorOpen}
|
||||
onClose={onDropdownClose}
|
||||
/>
|
||||
<ControlledStatusBar
|
||||
@@ -1154,6 +1163,7 @@ export function DraftAgentStatusBar({
|
||||
onSelectThinkingOption={onSelectThinkingOption}
|
||||
features={features}
|
||||
onSetFeature={onSetFeature}
|
||||
onModelSelectorOpen={onModelSelectorOpen}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -59,6 +59,7 @@ interface CombinedModelSelectorProps {
|
||||
disabled: boolean;
|
||||
isOpen: boolean;
|
||||
}) => React.ReactNode;
|
||||
onOpen?: () => void;
|
||||
onClose?: () => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
@@ -517,6 +518,7 @@ export function CombinedModelSelector({
|
||||
favoriteKeys = new Set<string>(),
|
||||
onToggleFavorite,
|
||||
renderTrigger,
|
||||
onOpen,
|
||||
onClose,
|
||||
disabled = false,
|
||||
}: CombinedModelSelectorProps) {
|
||||
@@ -541,12 +543,14 @@ export function CombinedModelSelector({
|
||||
(open: boolean) => {
|
||||
setIsOpen(open);
|
||||
setView(singleProviderView ?? { kind: "all" });
|
||||
if (!open) {
|
||||
if (open) {
|
||||
onOpen?.();
|
||||
} else {
|
||||
setSearchQuery("");
|
||||
onClose?.();
|
||||
}
|
||||
},
|
||||
[onClose, singleProviderView],
|
||||
[onOpen, onClose, singleProviderView],
|
||||
);
|
||||
|
||||
const handleSelect = useCallback(
|
||||
|
||||
@@ -93,6 +93,7 @@ type UseAgentFormStateResult = {
|
||||
isModelLoading: boolean;
|
||||
modelError: string | null;
|
||||
refreshProviderModels: () => void;
|
||||
invalidateProviderModels: () => void;
|
||||
setProviderAndModelFromUser: (provider: AgentProvider, modelId: string) => void;
|
||||
workingDirIsEmpty: boolean;
|
||||
persistFormPreferences: () => Promise<void>;
|
||||
@@ -375,6 +376,7 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg
|
||||
isFetching: snapshotIsFetching,
|
||||
error: snapshotError,
|
||||
refresh: refreshSnapshot,
|
||||
invalidate: invalidateSnapshot,
|
||||
} = useProvidersSnapshot(formState.serverId);
|
||||
|
||||
const allProviderEntries = useMemo(() => snapshotEntries ?? [], [snapshotEntries]);
|
||||
@@ -648,6 +650,10 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg
|
||||
refreshSnapshot();
|
||||
}, [refreshSnapshot]);
|
||||
|
||||
const invalidateProviderModels = useCallback(() => {
|
||||
invalidateSnapshot();
|
||||
}, [invalidateSnapshot]);
|
||||
|
||||
const persistFormPreferences = useCallback(async () => {
|
||||
const resolvedModel = resolveEffectiveModel(availableModels, formState.model);
|
||||
const modelId = resolvedModel?.id ?? formState.model;
|
||||
@@ -714,6 +720,7 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg
|
||||
isModelLoading,
|
||||
modelError,
|
||||
refreshProviderModels,
|
||||
invalidateProviderModels,
|
||||
setProviderAndModelFromUser,
|
||||
workingDirIsEmpty,
|
||||
persistFormPreferences,
|
||||
@@ -745,6 +752,7 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg
|
||||
isModelLoading,
|
||||
modelError,
|
||||
refreshProviderModels,
|
||||
invalidateProviderModels,
|
||||
setProviderAndModelFromUser,
|
||||
workingDirIsEmpty,
|
||||
persistFormPreferences,
|
||||
|
||||
@@ -17,6 +17,7 @@ interface UseProvidersSnapshotResult {
|
||||
error: string | null;
|
||||
supportsSnapshot: boolean;
|
||||
refresh: () => void;
|
||||
invalidate: () => void;
|
||||
}
|
||||
|
||||
export function useProvidersSnapshot(serverId: string | null): UseProvidersSnapshotResult {
|
||||
@@ -66,6 +67,10 @@ export function useProvidersSnapshot(serverId: string | null): UseProvidersSnaps
|
||||
void client.refreshProvidersSnapshot();
|
||||
}, [client]);
|
||||
|
||||
const invalidate = useCallback(() => {
|
||||
void queryClient.invalidateQueries({ queryKey });
|
||||
}, [queryClient, queryKey]);
|
||||
|
||||
return {
|
||||
entries: snapshotQuery.data?.entries ?? undefined,
|
||||
isLoading: snapshotQuery.isLoading,
|
||||
@@ -73,6 +78,7 @@ export function useProvidersSnapshot(serverId: string | null): UseProvidersSnaps
|
||||
error: snapshotQuery.error instanceof Error ? snapshotQuery.error.message : null,
|
||||
supportsSnapshot,
|
||||
refresh,
|
||||
invalidate,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -226,6 +226,7 @@ function DraftAgentScreenContent({
|
||||
isModelLoading,
|
||||
modelError,
|
||||
refreshProviderModels,
|
||||
invalidateProviderModels,
|
||||
setProviderAndModelFromUser,
|
||||
persistFormPreferences,
|
||||
} = useAgentFormState({
|
||||
@@ -1268,6 +1269,7 @@ function DraftAgentScreenContent({
|
||||
onSelectThinkingOption: setThinkingOptionFromUser,
|
||||
features: draftFeatures,
|
||||
onSetFeature: setDraftFeatureValue,
|
||||
onModelSelectorOpen: invalidateProviderModels,
|
||||
disabled: isSubmitting,
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -80,6 +80,7 @@ export function WorkspaceDraftAgentTab({
|
||||
availableThinkingOptions,
|
||||
isModelLoading,
|
||||
setProviderAndModelFromUser,
|
||||
invalidateProviderModels,
|
||||
persistFormPreferences,
|
||||
} = useAgentFormState({
|
||||
initialServerId: serverId,
|
||||
@@ -373,6 +374,7 @@ export function WorkspaceDraftAgentTab({
|
||||
features: draftFeatures,
|
||||
onSetFeature: handleSetFeatureWithFocus,
|
||||
onDropdownClose: () => focusInputRef.current?.(),
|
||||
onModelSelectorOpen: invalidateProviderModels,
|
||||
disabled: isSubmitting,
|
||||
}}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user