Fix provider health banner showing during onboarding (#372)
* disable provider health query until edited is true, set initial provider health cache to true when onboarding mutation succeeds * fix scroll issue with model selector in dialog
This commit is contained in:
parent
2aecfc570c
commit
7e343ed1f2
5 changed files with 37 additions and 11 deletions
|
|
@ -7,6 +7,7 @@ import { useProviderHealthQuery } from "@/src/app/api/queries/useProviderHealthQ
|
||||||
import { Button } from "./ui/button";
|
import { Button } from "./ui/button";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useGetSettingsQuery } from "@/app/api/queries/useGetSettingsQuery";
|
import { useGetSettingsQuery } from "@/app/api/queries/useGetSettingsQuery";
|
||||||
|
import { ModelProvider } from "@/app/settings/helpers/model-helpers";
|
||||||
|
|
||||||
interface ProviderHealthBannerProps {
|
interface ProviderHealthBannerProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
|
@ -42,12 +43,22 @@ export function useProviderHealth() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const providerTitleMap: Record<ModelProvider, string> = {
|
||||||
|
openai: "OpenAI",
|
||||||
|
ollama: "Ollama",
|
||||||
|
watsonx: "IBM watsonx.ai",
|
||||||
|
};
|
||||||
|
|
||||||
export function ProviderHealthBanner({ className }: ProviderHealthBannerProps) {
|
export function ProviderHealthBanner({ className }: ProviderHealthBannerProps) {
|
||||||
const { isLoading, isHealthy, isUnhealthy, health } = useProviderHealth();
|
const { isLoading, isHealthy, isUnhealthy, health } = useProviderHealth();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const { data: settings = {} } = useGetSettingsQuery();
|
const { data: settings = {} } = useGetSettingsQuery();
|
||||||
|
|
||||||
|
const providerTitle =
|
||||||
|
providerTitleMap[settings.provider?.model_provider as ModelProvider] ||
|
||||||
|
"Provider";
|
||||||
|
|
||||||
// Only show banner when provider is unhealthy (not when backend is unavailable)
|
// Only show banner when provider is unhealthy (not when backend is unavailable)
|
||||||
if (isLoading || isHealthy) {
|
if (isLoading || isHealthy) {
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -71,7 +82,7 @@ export function ProviderHealthBanner({ className }: ProviderHealthBannerProps) {
|
||||||
icon={AlertTriangle}
|
icon={AlertTriangle}
|
||||||
/>
|
/>
|
||||||
<BannerTitle className="font-medium flex items-center gap-2">
|
<BannerTitle className="font-medium flex items-center gap-2">
|
||||||
{errorMessage}
|
{providerTitle} error - {errorMessage}
|
||||||
</BannerTitle>
|
</BannerTitle>
|
||||||
<Button size="sm" onClick={() => router.push(settingsUrl)}>
|
<Button size="sm" onClick={() => router.push(settingsUrl)}>
|
||||||
Fix Setup
|
Fix Setup
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import {
|
||||||
useQueryClient,
|
useQueryClient,
|
||||||
} from "@tanstack/react-query";
|
} from "@tanstack/react-query";
|
||||||
import type { Settings } from "../queries/useGetSettingsQuery";
|
import type { Settings } from "../queries/useGetSettingsQuery";
|
||||||
|
import { useGetCurrentProviderModelsQuery } from "../queries/useGetModelsQuery";
|
||||||
|
|
||||||
export interface UpdateSettingsRequest {
|
export interface UpdateSettingsRequest {
|
||||||
// Agent settings
|
// Agent settings
|
||||||
|
|
@ -37,6 +38,7 @@ export const useUpdateSettingsMutation = (
|
||||||
>
|
>
|
||||||
) => {
|
) => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
const { refetch: refetchModels } = useGetCurrentProviderModelsQuery();
|
||||||
|
|
||||||
async function updateSettings(
|
async function updateSettings(
|
||||||
variables: UpdateSettingsRequest
|
variables: UpdateSettingsRequest
|
||||||
|
|
@ -63,6 +65,7 @@ export const useUpdateSettingsMutation = (
|
||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
queryKey: ["settings"],
|
queryKey: ["settings"],
|
||||||
});
|
});
|
||||||
|
refetchModels(); // Refetch models for the settings page
|
||||||
options?.onSuccess?.(...args);
|
options?.onSuccess?.(...args);
|
||||||
},
|
},
|
||||||
onError: options?.onError,
|
onError: options?.onError,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { ModelProvider } from "@/app/settings/helpers/model-helpers";
|
|
||||||
import {
|
import {
|
||||||
type UseQueryOptions,
|
type UseQueryOptions,
|
||||||
useQuery,
|
useQuery,
|
||||||
useQueryClient,
|
useQueryClient,
|
||||||
} from "@tanstack/react-query";
|
} from "@tanstack/react-query";
|
||||||
|
import { useGetSettingsQuery } from "./useGetSettingsQuery";
|
||||||
|
|
||||||
export interface ProviderHealthDetails {
|
export interface ProviderHealthDetails {
|
||||||
llm_model: string;
|
llm_model: string;
|
||||||
|
|
@ -22,12 +22,6 @@ export interface ProviderHealthParams {
|
||||||
provider?: "openai" | "ollama" | "watsonx";
|
provider?: "openai" | "ollama" | "watsonx";
|
||||||
}
|
}
|
||||||
|
|
||||||
const providerTitleMap: Record<ModelProvider, string> = {
|
|
||||||
openai: "OpenAI",
|
|
||||||
ollama: "Ollama",
|
|
||||||
watsonx: "IBM watsonx.ai",
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useProviderHealthQuery = (
|
export const useProviderHealthQuery = (
|
||||||
params?: ProviderHealthParams,
|
params?: ProviderHealthParams,
|
||||||
options?: Omit<
|
options?: Omit<
|
||||||
|
|
@ -37,6 +31,8 @@ export const useProviderHealthQuery = (
|
||||||
) => {
|
) => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
const { data: settings = {} } = useGetSettingsQuery();
|
||||||
|
|
||||||
async function checkProviderHealth(): Promise<ProviderHealthResponse> {
|
async function checkProviderHealth(): Promise<ProviderHealthResponse> {
|
||||||
try {
|
try {
|
||||||
const url = new URL("/api/provider/health", window.location.origin);
|
const url = new URL("/api/provider/health", window.location.origin);
|
||||||
|
|
@ -84,6 +80,7 @@ export const useProviderHealthQuery = (
|
||||||
queryKey: ["provider", "health"],
|
queryKey: ["provider", "health"],
|
||||||
queryFn: checkProviderHealth,
|
queryFn: checkProviderHealth,
|
||||||
retry: false, // Don't retry health checks automatically
|
retry: false, // Don't retry health checks automatically
|
||||||
|
enabled: !!settings?.edited && options?.enabled !== false, // Only run after onboarding is complete
|
||||||
...options,
|
...options,
|
||||||
},
|
},
|
||||||
queryClient
|
queryClient
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ export function ModelSelector({
|
||||||
}, [options, value, custom, onValueChange]);
|
}, [options, value, custom, onValueChange]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover open={open} onOpenChange={setOpen}>
|
<Popover open={open} onOpenChange={setOpen} modal={false}>
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
{/** biome-ignore lint/a11y/useSemanticElements: has to be a Button */}
|
{/** biome-ignore lint/a11y/useSemanticElements: has to be a Button */}
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -99,7 +99,8 @@ export function ModelSelector({
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent
|
<PopoverContent
|
||||||
align="start"
|
align="start"
|
||||||
className=" p-0 w-[var(--radix-popover-trigger-width)]"
|
className="p-0 w-[var(--radix-popover-trigger-width)]"
|
||||||
|
onOpenAutoFocus={(e) => e.preventDefault()}
|
||||||
>
|
>
|
||||||
<Command>
|
<Command>
|
||||||
<CommandInput
|
<CommandInput
|
||||||
|
|
@ -107,7 +108,10 @@ export function ModelSelector({
|
||||||
value={searchValue}
|
value={searchValue}
|
||||||
onValueChange={setSearchValue}
|
onValueChange={setSearchValue}
|
||||||
/>
|
/>
|
||||||
<CommandList>
|
<CommandList
|
||||||
|
className="max-h-[300px] overflow-y-auto"
|
||||||
|
onWheel={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
<CommandEmpty>{noOptionsPlaceholder}</CommandEmpty>
|
<CommandEmpty>{noOptionsPlaceholder}</CommandEmpty>
|
||||||
<CommandGroup>
|
<CommandGroup>
|
||||||
{options.map((option) => (
|
{options.map((option) => (
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ import { IBMOnboarding } from "./ibm-onboarding";
|
||||||
import { OllamaOnboarding } from "./ollama-onboarding";
|
import { OllamaOnboarding } from "./ollama-onboarding";
|
||||||
import { OpenAIOnboarding } from "./openai-onboarding";
|
import { OpenAIOnboarding } from "./openai-onboarding";
|
||||||
import { TabTrigger } from "./tab-trigger";
|
import { TabTrigger } from "./tab-trigger";
|
||||||
|
import { ProviderHealthResponse } from "@/app/api/queries/useProviderHealthQuery";
|
||||||
|
import { useQueryClient } from "@tanstack/react-query";
|
||||||
|
|
||||||
interface OnboardingCardProps {
|
interface OnboardingCardProps {
|
||||||
onComplete: () => void;
|
onComplete: () => void;
|
||||||
|
|
@ -57,6 +59,8 @@ const OnboardingCard = ({
|
||||||
|
|
||||||
const [loadingStep, setLoadingStep] = useState<number>(0);
|
const [loadingStep, setLoadingStep] = useState<number>(0);
|
||||||
|
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
// Reset loading step when models start loading
|
// Reset loading step when models start loading
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isLoadingModels) {
|
if (isLoadingModels) {
|
||||||
|
|
@ -129,6 +133,13 @@ const OnboardingCard = ({
|
||||||
const onboardingMutation = useOnboardingMutation({
|
const onboardingMutation = useOnboardingMutation({
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
console.log("Onboarding completed successfully", data);
|
console.log("Onboarding completed successfully", data);
|
||||||
|
// Update provider health cache to healthy since backend just validated
|
||||||
|
const healthData: ProviderHealthResponse = {
|
||||||
|
status: "healthy",
|
||||||
|
message: "Provider is configured and working correctly",
|
||||||
|
provider: settings.model_provider,
|
||||||
|
};
|
||||||
|
queryClient.setQueryData(["provider", "health"], healthData);
|
||||||
setCurrentStep(0);
|
setCurrentStep(0);
|
||||||
setError(null);
|
setError(null);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue