From 097fc7500cc5f57f39ca2011bf6358d735977b45 Mon Sep 17 00:00:00 2001 From: Jordan Frazier Date: Wed, 25 Mar 2026 15:34:25 -0400 Subject: [PATCH] fix(cloud): Tighten cloud compatibility truthfulness Keep preserved cloud-incompatible selections visible with inline warnings and make model empty states follow the filtered cloud-compatible set. Add a cloud default override for SearXNG and update the built component index so non-dev startup matches cloud mode behavior. --- .../__tests__/ModelInputComponent.test.tsx | 37 +++++++++++++ .../components/ModelTrigger.tsx | 23 +++++--- .../components/modelInputComponent/index.tsx | 17 ++++-- .../sortableListComponent/index.tsx | 48 +++++++++++++---- .../reproduce_issue.test.tsx | 25 ++++++++- .../parameterRenderComponent/index.test.tsx | 52 +++++++++++++++++++ .../core/parameterRenderComponent/index.tsx | 4 +- src/lfx/src/lfx/_assets/component_index.json | 12 +++-- src/lfx/src/lfx/components/tools/searxng.py | 5 ++ .../custom/test_cloud_default_overrides.py | 9 ++++ 10 files changed, 207 insertions(+), 25 deletions(-) create mode 100644 src/lfx/tests/unit/custom/test_cloud_default_overrides.py diff --git a/src/frontend/src/components/core/parameterRenderComponent/components/modelInputComponent/__tests__/ModelInputComponent.test.tsx b/src/frontend/src/components/core/parameterRenderComponent/components/modelInputComponent/__tests__/ModelInputComponent.test.tsx index 1a965a090f..6e6d276145 100644 --- a/src/frontend/src/components/core/parameterRenderComponent/components/modelInputComponent/__tests__/ModelInputComponent.test.tsx +++ b/src/frontend/src/components/core/parameterRenderComponent/components/modelInputComponent/__tests__/ModelInputComponent.test.tsx @@ -523,6 +523,43 @@ describe("ModelInputComponent", () => { mockCloudOnly = false; }); + it("should show a cloud-specific empty state when every provider is filtered out", async () => { + mockCloudOnly = true; + const user = userEvent.setup(); + const handleOnNewValue = jest.fn(); + + renderWithQueryClient( + , + ); + + expect( + screen.getByText("No cloud-compatible models"), + ).toBeInTheDocument(); + expect(handleOnNewValue).not.toHaveBeenCalled(); + + await user.click(screen.getByRole("combobox")); + + await waitFor(() => { + expect(screen.getByTestId("refresh-model-list")).toBeInTheDocument(); + }); + expect(screen.queryByTestId("llama3-option")).not.toBeInTheDocument(); + + mockCloudOnly = false; + }); + it("should show all providers when cloud mode is inactive", () => { mockCloudOnly = false; diff --git a/src/frontend/src/components/core/parameterRenderComponent/components/modelInputComponent/components/ModelTrigger.tsx b/src/frontend/src/components/core/parameterRenderComponent/components/modelInputComponent/components/ModelTrigger.tsx index cf081c1a34..4d0a4c9de2 100644 --- a/src/frontend/src/components/core/parameterRenderComponent/components/modelInputComponent/components/ModelTrigger.tsx +++ b/src/frontend/src/components/core/parameterRenderComponent/components/modelInputComponent/components/ModelTrigger.tsx @@ -4,12 +4,12 @@ import { Button } from "@/components/ui/button"; import { PopoverTrigger } from "@/components/ui/popover"; import { RECEIVING_INPUT_VALUE } from "@/constants/constants"; import { cn } from "@/utils/utils"; -import { ModelOption, SelectedModel } from "../types"; +import type { SelectedModel } from "../types"; interface ModelTriggerProps { open: boolean; disabled: boolean; - options: ModelOption[]; + visibleOptionsCount: number; selectedModel: SelectedModel | null; showCloudIncompatibleWarning?: boolean; placeholder?: string; @@ -18,12 +18,13 @@ interface ModelTriggerProps { id: string; refButton: RefObject; showEmptyState?: boolean; + emptyStateLabel?: string; } const ModelTrigger = ({ open, disabled, - options, + visibleOptionsCount, selectedModel, showCloudIncompatibleWarning = false, placeholder = "Setup Provider", @@ -32,9 +33,12 @@ const ModelTrigger = ({ id, refButton, showEmptyState = false, + emptyStateLabel = "No models enabled", }: ModelTriggerProps) => { + const hasVisibleOptions = visibleOptionsCount > 0; + const renderSelectedIcon = () => { - if (disabled || options.length === 0) { + if (disabled) { return null; } @@ -47,9 +51,9 @@ const ModelTrigger = ({ }; // Check if we're in empty state mode (showEmptyState=true and no options) - const isEmptyStateMode = showEmptyState && options.length === 0; + const isEmptyStateMode = showEmptyState && !hasVisibleOptions; - if (!hasEnabledProviders && !showEmptyState && options.length === 0) { + if (!hasEnabledProviders && !showEmptyState && !hasVisibleOptions) { return (