From 5811857ca271b5f8561ecbf34f2cc63bb0140901 Mon Sep 17 00:00:00 2001 From: Edwin Jose Date: Wed, 23 Oct 2024 18:44:00 -0400 Subject: [PATCH 1/5] refactor: Tool Output Management: Add Component-Specific Variable for Conditional Tool Output (#4259) Implement conditional tool output handling - Updated `component.py` to check for `FEATURE_FLAGS.add_toolkit_output` and call `_append_tool_output` if the component has the `add_tool_output` attribute set to True. - Ensured that the tool output behavior is correctly managed based on feature flags and component attributes in `custom_component.py`. --- .../custom/custom_component/component.py | 4 ++-- .../custom_component/custom_component.py | 2 ++ .../unit/test_custom_component_with_client.py | 19 +++++++++++++++++-- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/backend/base/langflow/custom/custom_component/component.py b/src/backend/base/langflow/custom/custom_component/component.py index b816f6af0fd..feed7ee6bb3 100644 --- a/src/backend/base/langflow/custom/custom_component/component.py +++ b/src/backend/base/langflow/custom/custom_component/component.py @@ -91,9 +91,9 @@ def __init__(self, **kwargs) -> None: self.__inputs = inputs self.__config = config self._reset_all_output_values() - if FEATURE_FLAGS.add_toolkit_output and hasattr(self, "_append_tool_output"): - self._append_tool_output() super().__init__(**config) + if (FEATURE_FLAGS.add_toolkit_output) and hasattr(self, "_append_tool_output") and self.add_tool_output: + self._append_tool_output() if hasattr(self, "_trace_type"): self.trace_type = self._trace_type if not hasattr(self, "trace_type"): diff --git a/src/backend/base/langflow/custom/custom_component/custom_component.py b/src/backend/base/langflow/custom/custom_component/custom_component.py index 7c5a6eec496..3f25f4dd761 100644 --- a/src/backend/base/langflow/custom/custom_component/custom_component.py +++ b/src/backend/base/langflow/custom/custom_component/custom_component.py @@ -59,6 +59,8 @@ class CustomComponent(BaseComponent): is_input: bool | None = None """The input state of the component. Defaults to None. If True, the component must have a field named 'input_value'.""" + add_tool_output: bool | None = False + """Indicates whether the component will be treated as a tool. Defaults to False.""" is_output: bool | None = None """The output state of the component. Defaults to None. If True, the component must have a field named 'input_value'.""" diff --git a/src/backend/tests/unit/test_custom_component_with_client.py b/src/backend/tests/unit/test_custom_component_with_client.py index 3c029be45ed..cc81f89bc67 100644 --- a/src/backend/tests/unit/test_custom_component_with_client.py +++ b/src/backend/tests/unit/test_custom_component_with_client.py @@ -14,6 +14,16 @@ def code_component_with_multiple_outputs(): return Component(_code=code) +@pytest.fixture +def code_component_with_multiple_outputs_with_add_tool_output(): + code = Path("src/backend/tests/data/component_multiple_outputs.py").read_text(encoding="utf-8") + code = code.replace( + "class MultipleOutputsComponent(Component):", + "class MultipleOutputsComponent(Component):\n add_tool_output = True", + ) + return Component(_code=code) + + @pytest.fixture def component( client, # noqa: ARG001 @@ -43,9 +53,14 @@ def test_list_flows_return_type(component): assert isinstance(flows, list) -def test_feature_flags_add_toolkit_output(active_user, code_component_with_multiple_outputs): +def test_feature_flags_add_toolkit_output( + active_user, code_component_with_multiple_outputs, code_component_with_multiple_outputs_with_add_tool_output +): frontnd_node_dict, _ = build_custom_component_template(code_component_with_multiple_outputs, active_user.id) len_outputs = len(frontnd_node_dict["outputs"]) FEATURE_FLAGS.add_toolkit_output = True - frontnd_node_dict, _ = build_custom_component_template(code_component_with_multiple_outputs, active_user.id) + code_component_with_multiple_outputs_with_add_tool_output.add_tool_output = True + frontnd_node_dict, _ = build_custom_component_template( + code_component_with_multiple_outputs_with_add_tool_output, active_user.id + ) assert len(frontnd_node_dict["outputs"]) == len_outputs + 1 From 374d3af9c6025371dfc9b246557dab1ba8482bc4 Mon Sep 17 00:00:00 2001 From: Cristhian Zanforlin Lousa Date: Thu, 24 Oct 2024 13:12:29 -0300 Subject: [PATCH 2/5] fix: correctly call the /variable endpoint after the user is authenticated (#4267) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ (authContext.tsx): Add functionality to fetch global variables on authentication 🔧 (api.tsx): Replace universal-cookie import with react-cookie for consistency 🔧 (authStore.ts): Replace universal-cookie import with react-cookie for consistency 🔧 (use-get-global-variables.ts): Add check to only fetch global variables if user is authenticated ✨ (use-get-mutation-global-variables.ts): Add mutation function to fetch and update global variables 🔧 (authStore.ts): Replace universal-cookie import with react-cookie for consistency * ✨ (use-get-folders.ts): add authentication check before fetching folders data to ensure only authenticated users can access the data --- src/frontend/src/contexts/authContext.tsx | 9 ++++- src/frontend/src/controllers/API/api.tsx | 20 +++++++---- .../API/queries/folders/use-get-folders.ts | 4 +++ .../variables/use-get-global-variables.ts | 4 +++ .../use-get-mutation-global-variables.ts | 33 +++++++++++++++++++ src/frontend/src/stores/authStore.ts | 2 +- 6 files changed, 63 insertions(+), 9 deletions(-) create mode 100644 src/frontend/src/controllers/API/queries/variables/use-get-mutation-global-variables.ts diff --git a/src/frontend/src/contexts/authContext.tsx b/src/frontend/src/contexts/authContext.tsx index 5a80266294d..cb8108001d1 100644 --- a/src/frontend/src/contexts/authContext.tsx +++ b/src/frontend/src/contexts/authContext.tsx @@ -5,9 +5,10 @@ import { LANGFLOW_REFRESH_TOKEN, } from "@/constants/constants"; import { useGetUserData } from "@/controllers/API/queries/auth"; +import { useGetGlobalVariablesMutation } from "@/controllers/API/queries/variables/use-get-mutation-global-variables"; import useAuthStore from "@/stores/authStore"; import { createContext, useEffect, useState } from "react"; -import Cookies from "universal-cookie"; +import { Cookies } from "react-cookie"; import { useStoreStore } from "../stores/storeStore"; import { Users } from "../types/api"; import { AuthContextType } from "../types/contexts/auth"; @@ -41,6 +42,7 @@ export function AuthProvider({ children }): React.ReactElement { const setIsAuthenticated = useAuthStore((state) => state.setIsAuthenticated); const { mutate: mutateLoggedUser } = useGetUserData(); + const { mutate: mutateGetGlobalVariables } = useGetGlobalVariablesMutation(); useEffect(() => { const storedAccessToken = cookies.get(LANGFLOW_ACCESS_TOKEN); @@ -86,12 +88,17 @@ export function AuthProvider({ children }): React.ReactElement { setAccessToken(newAccessToken); setIsAuthenticated(true); getUser(); + getGlobalVariables(); } function storeApiKey(apikey: string) { setApiKey(apikey); } + function getGlobalVariables() { + mutateGetGlobalVariables({}); + } + return ( // !! to convert string to boolean state.autoLogin); const setErrorData = useAlertStore((state) => state.setErrorData); - let { accessToken, authenticationErrorCount } = useContext(AuthContext); + const accessToken = useAuthStore((state) => state.accessToken); + const authenticationErrorCount = useAuthStore( + (state) => state.authenticationErrorCount, + ); + const setAuthenticationErrorCount = useAuthStore( + (state) => state.setAuthenticationErrorCount, + ); + const { mutate: mutationLogout } = useLogout(); const { mutate: mutationRenewAccessToken } = useRefreshAccessToken(); const isLoginPage = location.pathname.includes("login"); @@ -149,10 +155,10 @@ function ApiInterceptor() { function checkErrorCount() { if (isLoginPage) return; - authenticationErrorCount = authenticationErrorCount + 1; + setAuthenticationErrorCount(authenticationErrorCount + 1); if (authenticationErrorCount > 3) { - authenticationErrorCount = 0; + setAuthenticationErrorCount(0); mutationLogout(); return false; } @@ -169,9 +175,9 @@ function ApiInterceptor() { } mutationRenewAccessToken(undefined, { onSuccess: async () => { - authenticationErrorCount = 0; + setAuthenticationErrorCount(0); await remakeRequest(error); - authenticationErrorCount = 0; + setAuthenticationErrorCount(0); }, onError: (error) => { console.error(error); diff --git a/src/frontend/src/controllers/API/queries/folders/use-get-folders.ts b/src/frontend/src/controllers/API/queries/folders/use-get-folders.ts index 58df288b0a1..00f00b18459 100644 --- a/src/frontend/src/controllers/API/queries/folders/use-get-folders.ts +++ b/src/frontend/src/controllers/API/queries/folders/use-get-folders.ts @@ -1,5 +1,6 @@ import { DEFAULT_FOLDER, STARTER_FOLDER_NAME } from "@/constants/constants"; import { FolderType } from "@/pages/MainPage/entities"; +import useAuthStore from "@/stores/authStore"; import { useFolderStore } from "@/stores/foldersStore"; import { useTypesStore } from "@/stores/typesStore"; import { useQueryFunctionType } from "@/types/api"; @@ -18,7 +19,10 @@ export const useGetFoldersQuery: useQueryFunctionType< const setMyCollectionId = useFolderStore((state) => state.setMyCollectionId); const setFolders = useFolderStore((state) => state.setFolders); + const isAuthenticated = useAuthStore((state) => state.isAuthenticated); + const getFoldersFn = async (): Promise => { + if (!isAuthenticated) return []; const res = await api.get(`${getURL("FOLDERS")}/`); const data = res.data; diff --git a/src/frontend/src/controllers/API/queries/variables/use-get-global-variables.ts b/src/frontend/src/controllers/API/queries/variables/use-get-global-variables.ts index dbb400a3963..431cdec85b2 100644 --- a/src/frontend/src/controllers/API/queries/variables/use-get-global-variables.ts +++ b/src/frontend/src/controllers/API/queries/variables/use-get-global-variables.ts @@ -1,3 +1,4 @@ +import useAuthStore from "@/stores/authStore"; import { useGlobalVariablesStore } from "@/stores/globalVariablesStore/globalVariables"; import getUnavailableFields from "@/stores/globalVariablesStore/utils/get-unavailable-fields"; import { useQueryFunctionType } from "@/types/api"; @@ -20,7 +21,10 @@ export const useGetGlobalVariables: useQueryFunctionType< (state) => state.setUnavailableFields, ); + const isAuthenticated = useAuthStore((state) => state.isAuthenticated); + const getGlobalVariablesFn = async (): Promise => { + if (!isAuthenticated) return []; const res = await api.get(`${getURL("VARIABLES")}/`); setGlobalVariablesEntries(res.data.map((entry) => entry.name)); setUnavailableFields(getUnavailableFields(res.data)); diff --git a/src/frontend/src/controllers/API/queries/variables/use-get-mutation-global-variables.ts b/src/frontend/src/controllers/API/queries/variables/use-get-mutation-global-variables.ts new file mode 100644 index 00000000000..c3cac686c65 --- /dev/null +++ b/src/frontend/src/controllers/API/queries/variables/use-get-mutation-global-variables.ts @@ -0,0 +1,33 @@ +import { useGlobalVariablesStore } from "@/stores/globalVariablesStore/globalVariables"; +import getUnavailableFields from "@/stores/globalVariablesStore/utils/get-unavailable-fields"; +import { useMutationFunctionType } from "@/types/api"; +import { GlobalVariable } from "@/types/global_variables"; +import { UseMutationOptions, UseMutationResult } from "@tanstack/react-query"; +import { api } from "../../api"; +import { getURL } from "../../helpers/constants"; +import { UseRequestProcessor } from "../../services/request-processor"; + +export const useGetGlobalVariablesMutation: useMutationFunctionType< + undefined +> = (options?) => { + const { mutate } = UseRequestProcessor(); + + const setGlobalVariablesEntries = useGlobalVariablesStore( + (state) => state.setGlobalVariablesEntries, + ); + const setUnavailableFields = useGlobalVariablesStore( + (state) => state.setUnavailableFields, + ); + + const getGlobalVariablesFn = async (): Promise => { + const res = await api.get(`${getURL("VARIABLES")}/`); + setGlobalVariablesEntries(res.data.map((entry) => entry.name)); + setUnavailableFields(getUnavailableFields(res.data)); + return res.data; + }; + + const mutation: UseMutationResult = + mutate(["useGetGlobalVariables"], getGlobalVariablesFn, options); + + return mutation; +}; diff --git a/src/frontend/src/stores/authStore.ts b/src/frontend/src/stores/authStore.ts index a588ed4c0a2..40282c6742e 100644 --- a/src/frontend/src/stores/authStore.ts +++ b/src/frontend/src/stores/authStore.ts @@ -1,7 +1,7 @@ // authStore.js import { LANGFLOW_ACCESS_TOKEN } from "@/constants/constants"; import { AuthStoreType } from "@/types/zustand/auth"; -import Cookies from "universal-cookie"; +import { Cookies } from "react-cookie"; import { create } from "zustand"; const cookies = new Cookies(); From 5be41ae13e9297f3501e4b07ca5db914c0fdf6b0 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 24 Oct 2024 13:47:02 -0300 Subject: [PATCH 3/5] fix: make sure data is json serializable (#4269) * Refactor `recursive_serialize_or_str` function into a separate module - Moved the `recursive_serialize_or_str` function from `schema.py` to a new `serialize.py` module for better modularity and reusability. - Updated imports in `data.py`, `artifact.py`, and `schema.py` to reflect the new location of the `recursive_serialize_or_str` function. - Enhanced the `recursive_serialize_or_str` function to handle `datetime` objects by converting them to ISO format. * Enhance data serialization with recursive handling in `to_json` method --------- Co-authored-by: Edwin Jose --- src/backend/base/langflow/schema/artifact.py | 2 +- src/backend/base/langflow/schema/data.py | 2 + src/backend/base/langflow/schema/schema.py | 40 +---------------- src/backend/base/langflow/schema/serialize.py | 43 +++++++++++++++++++ 4 files changed, 48 insertions(+), 39 deletions(-) create mode 100644 src/backend/base/langflow/schema/serialize.py diff --git a/src/backend/base/langflow/schema/artifact.py b/src/backend/base/langflow/schema/artifact.py index 8f22e5351d6..d4e77ce4861 100644 --- a/src/backend/base/langflow/schema/artifact.py +++ b/src/backend/base/langflow/schema/artifact.py @@ -7,7 +7,7 @@ from langflow.schema.data import Data from langflow.schema.message import Message -from langflow.schema.schema import recursive_serialize_or_str +from langflow.schema.serialize import recursive_serialize_or_str class ArtifactType(str, Enum): diff --git a/src/backend/base/langflow/schema/data.py b/src/backend/base/langflow/schema/data.py index fbf73f50440..96971678cb6 100644 --- a/src/backend/base/langflow/schema/data.py +++ b/src/backend/base/langflow/schema/data.py @@ -8,6 +8,7 @@ from loguru import logger from pydantic import BaseModel, model_serializer, model_validator +from langflow.schema.serialize import recursive_serialize_or_str from langflow.utils.constants import MESSAGE_SENDER_AI, MESSAGE_SENDER_USER if TYPE_CHECKING: @@ -199,6 +200,7 @@ def __str__(self) -> str: # return a JSON string representation of the Data atributes try: data = {k: v.to_json() if hasattr(v, "to_json") else v for k, v in self.data.items()} + data = recursive_serialize_or_str(data) return json.dumps(data, indent=4) except Exception: # noqa: BLE001 logger.opt(exception=True).debug("Error converting Data to JSON") diff --git a/src/backend/base/langflow/schema/schema.py b/src/backend/base/langflow/schema/schema.py index de1e89f7b84..87520065526 100644 --- a/src/backend/base/langflow/schema/schema.py +++ b/src/backend/base/langflow/schema/schema.py @@ -1,14 +1,13 @@ -from collections.abc import AsyncIterator, Generator, Iterator +from collections.abc import Generator from enum import Enum from typing import Literal -from loguru import logger from pydantic import BaseModel -from pydantic.v1 import BaseModel as BaseModelV1 from typing_extensions import TypedDict from langflow.schema.data import Data from langflow.schema.message import Message +from langflow.schema.serialize import recursive_serialize_or_str INPUT_FIELD_NAME = "input_value" @@ -113,38 +112,3 @@ def build_output_logs(vertex, result) -> dict: outputs |= {name: OutputValue(message=message, type=_type).model_dump()} return outputs - - -def recursive_serialize_or_str(obj): - try: - if isinstance(obj, str): - return obj - if isinstance(obj, dict): - return {k: recursive_serialize_or_str(v) for k, v in obj.items()} - if isinstance(obj, list): - return [recursive_serialize_or_str(v) for v in obj] - if isinstance(obj, BaseModel | BaseModelV1): - if hasattr(obj, "model_dump"): - obj_dict = obj.model_dump() - elif hasattr(obj, "dict"): - obj_dict = obj.dict() - return {k: recursive_serialize_or_str(v) for k, v in obj_dict.items()} - - if isinstance(obj, AsyncIterator | Generator | Iterator): - # contain memory addresses - # without consuming the iterator - # return list(obj) consumes the iterator - # return f"{obj}" this generates '' - # it is not useful - return "Unconsumed Stream" - if hasattr(obj, "dict"): - return {k: recursive_serialize_or_str(v) for k, v in obj.dict().items()} - if hasattr(obj, "model_dump"): - return {k: recursive_serialize_or_str(v) for k, v in obj.model_dump().items()} - if isinstance(obj, type) and issubclass(obj, BaseModel): - # This a type BaseModel and not an instance of it - return repr(obj) - return str(obj) - except Exception: # noqa: BLE001 - logger.debug(f"Cannot serialize object {obj}") - return str(obj) diff --git a/src/backend/base/langflow/schema/serialize.py b/src/backend/base/langflow/schema/serialize.py new file mode 100644 index 00000000000..d2ed1790ab8 --- /dev/null +++ b/src/backend/base/langflow/schema/serialize.py @@ -0,0 +1,43 @@ +from collections.abc import AsyncIterator, Generator, Iterator +from datetime import datetime + +from loguru import logger +from pydantic import BaseModel +from pydantic.v1 import BaseModel as BaseModelV1 + + +def recursive_serialize_or_str(obj): + try: + if isinstance(obj, str): + return obj + if isinstance(obj, datetime): + return obj.isoformat() + if isinstance(obj, dict): + return {k: recursive_serialize_or_str(v) for k, v in obj.items()} + if isinstance(obj, list): + return [recursive_serialize_or_str(v) for v in obj] + if isinstance(obj, BaseModel | BaseModelV1): + if hasattr(obj, "model_dump"): + obj_dict = obj.model_dump() + elif hasattr(obj, "dict"): + obj_dict = obj.dict() + return {k: recursive_serialize_or_str(v) for k, v in obj_dict.items()} + + if isinstance(obj, AsyncIterator | Generator | Iterator): + # contain memory addresses + # without consuming the iterator + # return list(obj) consumes the iterator + # return f"{obj}" this generates '' + # it is not useful + return "Unconsumed Stream" + if hasattr(obj, "dict"): + return {k: recursive_serialize_or_str(v) for k, v in obj.dict().items()} + if hasattr(obj, "model_dump"): + return {k: recursive_serialize_or_str(v) for k, v in obj.model_dump().items()} + if isinstance(obj, type) and issubclass(obj, BaseModel): + # This a type BaseModel and not an instance of it + return repr(obj) + return str(obj) + except Exception: # noqa: BLE001 + logger.debug(f"Cannot serialize object {obj}") + return str(obj) From 78e6ee1a8aed70b0a847f2169204900b454bd24b Mon Sep 17 00:00:00 2001 From: Edwin Jose Date: Thu, 24 Oct 2024 13:52:52 -0400 Subject: [PATCH 4/5] fix: Solves Issues with Set Function in Component Class and Enhance Input Handling (#4258) * Enhance Component Input Handling and Add Unit Tests Enhance component input handling and add unit tests for mixed input scenarios. * [autofix.ci] apply automated fixes * fix: handle JSON serialization for lists and dicts in _process_connection_or_parameters - Updated the _process_connection_or_parameters function to handle lists and dictionaries properly. - Ensured that each element in a list is checked for serializability and converted to a string if necessary. - Added logic to convert dictionaries to JSON strings, handling non-serializable contents by converting them to strings. - This change prevents JSON serialization errors when processing component parameters. * reverting the changes * [autofix.ci] apply automated fixes * Update component.py updates _process_connection_or_parameters to handles situations where the list is not all component. Also handles any serialisation isseus caused by _process_connection_or_parameters * [autofix.ci] apply automated fixes * Update component.py update make sure it is not a list str | int | float | bool | type(None) Serialisation removed --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- .../langflow/base/tools/component_tool.py | 2 + .../custom/custom_component/component.py | 3 +- .../test_componet_set_functionality.py | 49 +++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/backend/tests/unit/custom/component/test_componet_set_functionality.py diff --git a/src/backend/base/langflow/base/tools/component_tool.py b/src/backend/base/langflow/base/tools/component_tool.py index 0cc08b54d10..fcbb0444e0e 100644 --- a/src/backend/base/langflow/base/tools/component_tool.py +++ b/src/backend/base/langflow/base/tools/component_tool.py @@ -47,6 +47,8 @@ def build_description(component: Component, output: Output) -> str: def _build_output_function(component: Component, output_method: Callable): def output_function(*args, **kwargs): + # set the component with the arguments + # set functionality was updatedto handle list of components and other values separately component.set(*args, **kwargs) return output_method() diff --git a/src/backend/base/langflow/custom/custom_component/component.py b/src/backend/base/langflow/custom/custom_component/component.py index feed7ee6bb3..b2343c6c456 100644 --- a/src/backend/base/langflow/custom/custom_component/component.py +++ b/src/backend/base/langflow/custom/custom_component/component.py @@ -442,7 +442,8 @@ def _process_connection_or_parameter(self, key, value) -> None: def _process_connection_or_parameters(self, key, value) -> None: # if value is a list of components, we need to process each component - if isinstance(value, list): + # Note this update make sure it is not a list str | int | float | bool | type(None) + if isinstance(value, list) and not any(isinstance(val, str | int | float | bool | type(None)) for val in value): for val in value: self._process_connection_or_parameter(key, val) else: diff --git a/src/backend/tests/unit/custom/component/test_componet_set_functionality.py b/src/backend/tests/unit/custom/component/test_componet_set_functionality.py new file mode 100644 index 00000000000..d6591f40f3e --- /dev/null +++ b/src/backend/tests/unit/custom/component/test_componet_set_functionality.py @@ -0,0 +1,49 @@ +import pytest +from langflow.custom import Component +from langflow.inputs.inputs import MessageTextInput, StrInput + + +@pytest.fixture +def setup_component(): + # Create a sample component for testing + component = Component() + # Define inputs for the component + component.inputs = [ + MessageTextInput(name="list_message_input", is_list=True), # Input for a mock component + StrInput(name="mixed_input"), # Input for a mixed list + ] + return component + + +def test_set_with_mixed_list_input(setup_component): + component = setup_component + # Create a mock component to include in the list + mock_component = Component() + message_input_1 = "message data1" + message_input_2 = "message data2" + data = {"mixed_input": [message_input_1, message_input_2], "list_message_input": [message_input_1, mock_component]} + component.set(**data) + + # Assert that the mixed input was set correctly + assert hasattr(component, "mixed_input") + assert len(component.mixed_input) == 2 + assert component.mixed_input[0] == message_input_1 + assert component.mixed_input[1] == message_input_2 + assert component.list_message_input[0] == message_input_1 + assert component.list_message_input[1] == mock_component + + +def test_set_with_message_text_input_list(setup_component): + component = setup_component + # Create a list of MessageTextInput instances + message_input_1 = "message data1" + message_input_2 = "message data2" + data = {"mixed_input": [message_input_1, message_input_2], "list_message_input": [message_input_1, message_input_2]} + # Set a list containing MessageTextInput instances + component.set(**data) + + # Assert that the mixed input was set correctly + assert hasattr(component, "mixed_input") + assert len(component.list_message_input) == 2 + assert component.list_message_input[0] == message_input_1 + assert component.list_message_input[1] == message_input_2 From 1f69dae79948dc37e516054d583d5c1d6bc86e5b Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2024 20:14:04 +0000 Subject: [PATCH 5/5] [autofix.ci] apply automated fixes --- src/frontend/src/components/dropdownComponent/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/src/components/dropdownComponent/index.tsx b/src/frontend/src/components/dropdownComponent/index.tsx index 9685cf60f1c..4b101a34cdc 100644 --- a/src/frontend/src/components/dropdownComponent/index.tsx +++ b/src/frontend/src/components/dropdownComponent/index.tsx @@ -101,7 +101,7 @@ export default function Dropdown({