diff --git a/src/backend/base/langflow/api/v1/endpoints.py b/src/backend/base/langflow/api/v1/endpoints.py index 38dc6c297..fa93f799d 100644 --- a/src/backend/base/langflow/api/v1/endpoints.py +++ b/src/backend/base/langflow/api/v1/endpoints.py @@ -6,7 +6,16 @@ from typing import TYPE_CHECKING, Annotated from uuid import UUID import sqlalchemy as sa -from fastapi import APIRouter, BackgroundTasks, Body, Depends, HTTPException, Request, UploadFile, status +from fastapi import ( + APIRouter, + BackgroundTasks, + Body, + Depends, + HTTPException, + Request, + UploadFile, + status, +) from loguru import logger from sqlmodel import select @@ -17,7 +26,6 @@ from langflow.api.v1.schemas import ( CustomComponentResponse, InputValueRequest, RunResponse, - SidebarCategoriesResponse, SimplifiedAPIRequest, TaskStatusResponse, UpdateCustomComponentRequest, @@ -37,7 +45,9 @@ from langflow.services.auth.utils import api_key_security, get_current_active_us from langflow.services.cache.utils import save_uploaded_file from langflow.services.database.models.flow import Flow from langflow.services.database.models.flow.model import FlowRead -from langflow.services.database.models.flow.utils import get_all_webhook_components_in_flow +from langflow.services.database.models.flow.utils import ( + get_all_webhook_components_in_flow, +) from langflow.services.database.models.user.model import User, UserRead from langflow.services.deps import ( get_session_service, @@ -47,7 +57,6 @@ from langflow.services.deps import ( ) from langflow.services.settings.feature_flags import FEATURE_FLAGS from langflow.services.telemetry.schema import RunPayload -from langflow.utils.constants import SIDEBAR_CATEGORIES from langflow.utils.version import get_version_info if TYPE_CHECKING: @@ -110,7 +119,11 @@ async def simple_run_flow( graph_data = process_tweaks(graph_data, input_request.tweaks or {}, stream=stream) graph = Graph.from_payload(graph_data, flow_id=flow_id_str, user_id=str(user_id), flow_name=flow.name) inputs = [ - InputValueRequest(components=[], input_value=input_request.input_value, type=input_request.input_type) + InputValueRequest( + components=[], + input_value=input_request.input_value, + type=input_request.input_type, + ) ] if input_request.output_component: outputs = [input_request.output_component] @@ -248,7 +261,10 @@ async def simplified_run_flow( background_tasks.add_task( telemetry_service.log_package_run, RunPayload( - run_is_webhook=False, run_seconds=int(end_time - start_time), run_success=True, run_error_message="" + run_is_webhook=False, + run_seconds=int(end_time - start_time), + run_success=True, + run_error_message="", ), ) @@ -360,7 +376,11 @@ async def webhook_run_flow( return {"message": "Task started in the background", "status": "in progress"} -@router.post("/run/advanced/{flow_id}", response_model=RunResponse, response_model_exclude_none=True) +@router.post( + "/run/advanced/{flow_id}", + response_model=RunResponse, + response_model_exclude_none=True, +) async def experimental_run_flow( *, session: DbSession, @@ -631,11 +651,9 @@ async def get_config(): settings_service: SettingsService = get_settings_service() - return {"feature_flags": FEATURE_FLAGS, **settings_service.settings.model_dump()} + return { + "feature_flags": FEATURE_FLAGS, + **settings_service.settings.model_dump(), + } except Exception as exc: raise HTTPException(status_code=500, detail=str(exc)) from exc - - -@router.get("/sidebar_categories") -async def get_sidebar_categories() -> SidebarCategoriesResponse: - return SidebarCategoriesResponse(categories=SIDEBAR_CATEGORIES) diff --git a/src/backend/base/langflow/api/v1/schemas.py b/src/backend/base/langflow/api/v1/schemas.py index 78e9dc585..9d9b21018 100644 --- a/src/backend/base/langflow/api/v1/schemas.py +++ b/src/backend/base/langflow/api/v1/schemas.py @@ -4,7 +4,14 @@ from pathlib import Path from typing import Any from uuid import UUID -from pydantic import BaseModel, ConfigDict, Field, field_serializer, field_validator, model_serializer +from pydantic import ( + BaseModel, + ConfigDict, + Field, + field_serializer, + field_validator, + model_serializer, +) from langflow.graph.schema import RunOutputs from langflow.graph.utils import serialize_field @@ -316,7 +323,11 @@ class InputValueRequest(BaseModel): }, {"components": ["Component Name"], "input_value": "input_value"}, {"input_value": "input_value"}, - {"components": ["Component Name"], "input_value": "input_value", "session": "session_id"}, + { + "components": ["Component Name"], + "input_value": "input_value", + "session": "session_id", + }, {"input_value": "input_value", "session": "session_id"}, {"type": "chat", "input_value": "input_value"}, {"type": "json", "input_value": '{"key": "value"}'}, @@ -357,14 +368,3 @@ class ConfigResponse(BaseModel): auto_saving_interval: int health_check_max_retries: int max_file_size_upload: int - - -class SidebarCategory(BaseModel): - display_name: str - name: str - icon: str - beta: bool = False - - -class SidebarCategoriesResponse(BaseModel): - categories: list[SidebarCategory] diff --git a/src/backend/base/langflow/base/constants.py b/src/backend/base/langflow/base/constants.py index bb4886fe0..07de77c65 100644 --- a/src/backend/base/langflow/base/constants.py +++ b/src/backend/base/langflow/base/constants.py @@ -10,7 +10,15 @@ import orjson STREAM_INFO_TEXT = "Stream the response from the model. Streaming works only in Chat." -NODE_FORMAT_ATTRIBUTES = ["beta", "icon", "display_name", "output_types", "edited", "metadata"] +NODE_FORMAT_ATTRIBUTES = [ + "beta", + "legacy", + "icon", + "display_name", + "output_types", + "edited", + "metadata", +] FIELD_FORMAT_ATTRIBUTES = [ diff --git a/src/backend/base/langflow/components/__init__.py b/src/backend/base/langflow/components/__init__.py index fbe764f24..22b771454 100644 --- a/src/backend/base/langflow/components/__init__.py +++ b/src/backend/base/langflow/components/__init__.py @@ -1,6 +1,7 @@ from . import ( agents, chains, + custom_component, documentloaders, embeddings, helpers, @@ -26,6 +27,7 @@ __all__ = [ "helpers", "inputs", "link_extractors", + "custom_component", "memories", "models", "output_parsers", diff --git a/src/backend/base/langflow/components/agents/json.py b/src/backend/base/langflow/components/agents/json.py index 52bd2c681..05732c830 100644 --- a/src/backend/base/langflow/components/agents/json.py +++ b/src/backend/base/langflow/components/agents/json.py @@ -14,11 +14,22 @@ class JsonAgentComponent(LCAgentComponent): display_name = "JsonAgent" description = "Construct a json agent from an LLM and tools." name = "JsonAgent" + legacy: bool = True inputs = [ *LCAgentComponent._base_inputs, - HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True), - FileInput(name="path", display_name="File Path", file_types=["json", "yaml", "yml"], required=True), + HandleInput( + name="llm", + display_name="Language Model", + input_types=["LanguageModel"], + required=True, + ), + FileInput( + name="path", + display_name="File Path", + file_types=["json", "yaml", "yml"], + required=True, + ), ] def build_agent(self) -> AgentExecutor: diff --git a/src/backend/base/langflow/components/agents/vector_store.py b/src/backend/base/langflow/components/agents/vector_store.py index 86f38b313..8d161fb51 100644 --- a/src/backend/base/langflow/components/agents/vector_store.py +++ b/src/backend/base/langflow/components/agents/vector_store.py @@ -9,11 +9,22 @@ class VectorStoreAgentComponent(LCAgentComponent): display_name = "VectorStoreAgent" description = "Construct an agent from a Vector Store." name = "VectorStoreAgent" + legacy: bool = True inputs = [ *LCAgentComponent._base_inputs, - HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True), - HandleInput(name="vectorstore", display_name="Vector Store", input_types=["VectorStoreInfo"], required=True), + HandleInput( + name="llm", + display_name="Language Model", + input_types=["LanguageModel"], + required=True, + ), + HandleInput( + name="vectorstore", + display_name="Vector Store", + input_types=["VectorStoreInfo"], + required=True, + ), ] def build_agent(self) -> AgentExecutor: diff --git a/src/backend/base/langflow/components/agents/vector_store_router.py b/src/backend/base/langflow/components/agents/vector_store_router.py index efea4e08e..6c44c2d5c 100644 --- a/src/backend/base/langflow/components/agents/vector_store_router.py +++ b/src/backend/base/langflow/components/agents/vector_store_router.py @@ -9,10 +9,16 @@ class VectorStoreRouterAgentComponent(LCAgentComponent): display_name = "VectorStoreRouterAgent" description = "Construct an agent from a Vector Store Router." name = "VectorStoreRouterAgent" + legacy: bool = True inputs = [ *LCAgentComponent._base_inputs, - HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True), + HandleInput( + name="llm", + display_name="Language Model", + input_types=["LanguageModel"], + required=True, + ), HandleInput( name="vectorstores", display_name="Vector Stores", diff --git a/src/backend/base/langflow/components/chains/conversation.py b/src/backend/base/langflow/components/chains/conversation.py index f1bb74ef9..b6d59fcd0 100644 --- a/src/backend/base/langflow/components/chains/conversation.py +++ b/src/backend/base/langflow/components/chains/conversation.py @@ -9,12 +9,21 @@ class ConversationChainComponent(LCChainComponent): display_name = "ConversationChain" description = "Chain to have a conversation and load context from memory." name = "ConversationChain" + legacy: bool = True inputs = [ MultilineInput( - name="input_value", display_name="Input", info="The input value to pass to the chain.", required=True + name="input_value", + display_name="Input", + info="The input value to pass to the chain.", + required=True, + ), + HandleInput( + name="llm", + display_name="Language Model", + input_types=["LanguageModel"], + required=True, ), - HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True), HandleInput( name="memory", display_name="Memory", @@ -28,7 +37,10 @@ class ConversationChainComponent(LCChainComponent): else: chain = ConversationChain(llm=self.llm, memory=self.memory) - result = chain.invoke({"input": self.input_value}, config={"callbacks": self.get_langchain_callbacks()}) + result = chain.invoke( + {"input": self.input_value}, + config={"callbacks": self.get_langchain_callbacks()}, + ) if isinstance(result, dict): result = result.get(chain.output_key, "") diff --git a/src/backend/base/langflow/components/chains/llm_checker.py b/src/backend/base/langflow/components/chains/llm_checker.py index 68796afae..9f8294dde 100644 --- a/src/backend/base/langflow/components/chains/llm_checker.py +++ b/src/backend/base/langflow/components/chains/llm_checker.py @@ -10,18 +10,28 @@ class LLMCheckerChainComponent(LCChainComponent): description = "Chain for question-answering with self-verification." documentation = "https://python.langchain.com/docs/modules/chains/additional/llm_checker" name = "LLMCheckerChain" + legacy: bool = True inputs = [ MultilineInput( - name="input_value", display_name="Input", info="The input value to pass to the chain.", required=True + name="input_value", + display_name="Input", + info="The input value to pass to the chain.", + required=True, + ), + HandleInput( + name="llm", + display_name="Language Model", + input_types=["LanguageModel"], + required=True, ), - HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True), ] def invoke_chain(self) -> Message: chain = LLMCheckerChain.from_llm(llm=self.llm) response = chain.invoke( - {chain.input_key: self.input_value}, config={"callbacks": self.get_langchain_callbacks()} + {chain.input_key: self.input_value}, + config={"callbacks": self.get_langchain_callbacks()}, ) result = response.get(chain.output_key, "") result = str(result) diff --git a/src/backend/base/langflow/components/chains/llm_math.py b/src/backend/base/langflow/components/chains/llm_math.py index b95d67845..940d75e96 100644 --- a/src/backend/base/langflow/components/chains/llm_math.py +++ b/src/backend/base/langflow/components/chains/llm_math.py @@ -11,12 +11,21 @@ class LLMMathChainComponent(LCChainComponent): description = "Chain that interprets a prompt and executes python code to do math." documentation = "https://python.langchain.com/docs/modules/chains/additional/llm_math" name = "LLMMathChain" + legacy: bool = True inputs = [ MultilineInput( - name="input_value", display_name="Input", info="The input value to pass to the chain.", required=True + name="input_value", + display_name="Input", + info="The input value to pass to the chain.", + required=True, + ), + HandleInput( + name="llm", + display_name="Language Model", + input_types=["LanguageModel"], + required=True, ), - HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True), ] outputs = [Output(display_name="Text", name="text", method="invoke_chain")] @@ -24,7 +33,8 @@ class LLMMathChainComponent(LCChainComponent): def invoke_chain(self) -> Message: chain = LLMMathChain.from_llm(llm=self.llm) response = chain.invoke( - {chain.input_key: self.input_value}, config={"callbacks": self.get_langchain_callbacks()} + {chain.input_key: self.input_value}, + config={"callbacks": self.get_langchain_callbacks()}, ) result = response.get(chain.output_key, "") result = str(result) diff --git a/src/backend/base/langflow/components/chains/retrieval_qa.py b/src/backend/base/langflow/components/chains/retrieval_qa.py index cb70589ea..d3d55db1f 100644 --- a/src/backend/base/langflow/components/chains/retrieval_qa.py +++ b/src/backend/base/langflow/components/chains/retrieval_qa.py @@ -9,10 +9,14 @@ class RetrievalQAComponent(LCChainComponent): display_name = "Retrieval QA" description = "Chain for question-answering querying sources from a retriever." name = "RetrievalQA" + legacy: bool = True inputs = [ MultilineInput( - name="input_value", display_name="Input", info="The input value to pass to the chain.", required=True + name="input_value", + display_name="Input", + info="The input value to pass to the chain.", + required=True, ), DropdownInput( name="chain_type", @@ -22,8 +26,18 @@ class RetrievalQAComponent(LCChainComponent): value="Stuff", advanced=True, ), - HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True), - HandleInput(name="retriever", display_name="Retriever", input_types=["Retriever"], required=True), + HandleInput( + name="llm", + display_name="Language Model", + input_types=["LanguageModel"], + required=True, + ), + HandleInput( + name="retriever", + display_name="Retriever", + input_types=["Retriever"], + required=True, + ), HandleInput( name="memory", display_name="Memory", @@ -52,7 +66,10 @@ class RetrievalQAComponent(LCChainComponent): return_source_documents=True, ) - result = runnable.invoke({"query": self.input_value}, config={"callbacks": self.get_langchain_callbacks()}) + result = runnable.invoke( + {"query": self.input_value}, + config={"callbacks": self.get_langchain_callbacks()}, + ) source_docs = self.to_data(result.get("source_documents", keys=[])) result_str = str(result.get("result", "")) diff --git a/src/backend/base/langflow/components/chains/sql_generator.py b/src/backend/base/langflow/components/chains/sql_generator.py index d2c412e23..a516a8c3d 100644 --- a/src/backend/base/langflow/components/chains/sql_generator.py +++ b/src/backend/base/langflow/components/chains/sql_generator.py @@ -16,17 +16,38 @@ class SQLGeneratorComponent(LCChainComponent): display_name = "Natural Language to SQL" description = "Generate SQL from natural language." name = "SQLGenerator" + legacy: bool = True inputs = [ MultilineInput( - name="input_value", display_name="Input", info="The input value to pass to the chain.", required=True + name="input_value", + display_name="Input", + info="The input value to pass to the chain.", + required=True, + ), + HandleInput( + name="llm", + display_name="Language Model", + input_types=["LanguageModel"], + required=True, + ), + HandleInput( + name="db", + display_name="SQLDatabase", + input_types=["SQLDatabase"], + required=True, ), - HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True), - HandleInput(name="db", display_name="SQLDatabase", input_types=["SQLDatabase"], required=True), IntInput( - name="top_k", display_name="Top K", info="The number of results per select statement to return.", value=5 + name="top_k", + display_name="Top K", + info="The number of results per select statement to return.", + value=5, + ), + MultilineInput( + name="prompt", + display_name="Prompt", + info="The prompt must contain `{question}`.", ), - MultilineInput(name="prompt", display_name="Prompt", info="The prompt must contain `{question}`."), ] outputs = [Output(display_name="Text", name="text", method="invoke_chain")] @@ -48,7 +69,8 @@ class SQLGeneratorComponent(LCChainComponent): sql_query_chain = create_sql_query_chain(llm=self.llm, db=self.db, prompt=prompt_template, k=self.top_k) query_writer: Runnable = sql_query_chain | {"query": lambda x: x.replace("SQLQuery:", "").strip()} response = query_writer.invoke( - {"question": self.input_value}, config={"callbacks": self.get_langchain_callbacks()} + {"question": self.input_value}, + config={"callbacks": self.get_langchain_callbacks()}, ) query = response.get("query") self.status = query diff --git a/src/backend/base/langflow/components/custom_component/__init__.py b/src/backend/base/langflow/components/custom_component/__init__.py new file mode 100644 index 000000000..fa37797fe --- /dev/null +++ b/src/backend/base/langflow/components/custom_component/__init__.py @@ -0,0 +1,5 @@ +from .custom_component import CustomComponent + +__all__ = [ + "CustomComponent", +] diff --git a/src/backend/base/langflow/components/helpers/custom_component.py b/src/backend/base/langflow/components/custom_component/custom_component.py similarity index 100% rename from src/backend/base/langflow/components/helpers/custom_component.py rename to src/backend/base/langflow/components/custom_component/custom_component.py diff --git a/src/backend/base/langflow/components/helpers/__init__.py b/src/backend/base/langflow/components/helpers/__init__.py index c30861d2b..b78c7fdee 100644 --- a/src/backend/base/langflow/components/helpers/__init__.py +++ b/src/backend/base/langflow/components/helpers/__init__.py @@ -2,7 +2,6 @@ from .combine_text import CombineTextComponent from .create_list import CreateListComponent from .csv_to_data import CSVToDataComponent from .current_date import CurrentDateComponent -from .custom_component import CustomComponent from .data_conditional_router import DataConditionalRouterComponent from .extract_key import ExtractDataKeyComponent from .filter_data import FilterDataComponent @@ -25,7 +24,6 @@ __all__ = [ "CombineTextComponent", "CreateListComponent", "CurrentDateComponent", - "CustomComponent", "DataConditionalRouterComponent", "DataFilterComponent", "ExtractDataKeyComponent", diff --git a/src/backend/base/langflow/components/langchain_utilities/json_document_builder.py b/src/backend/base/langflow/components/langchain_utilities/json_document_builder.py index b6303c952..402a65182 100644 --- a/src/backend/base/langflow/components/langchain_utilities/json_document_builder.py +++ b/src/backend/base/langflow/components/langchain_utilities/json_document_builder.py @@ -21,6 +21,7 @@ class JSONDocumentBuilder(CustomComponent): display_name: str = "JSON Document Builder" description: str = "Build a Document containing a JSON object using a key and another Document page content." name = "JSONDocumentBuilder" + legacy: bool = True output_types: list[str] = ["Document"] documentation: str = "https://docs.langflow.org/components/utilities#json-document-builder" diff --git a/src/backend/base/langflow/components/retrievers/amazon_kendra.py b/src/backend/base/langflow/components/retrievers/amazon_kendra.py index 43fefeec2..21c12c003 100644 --- a/src/backend/base/langflow/components/retrievers/amazon_kendra.py +++ b/src/backend/base/langflow/components/retrievers/amazon_kendra.py @@ -11,6 +11,7 @@ class AmazonKendraRetrieverComponent(CustomComponent): description: str = "Retriever that uses the Amazon Kendra API." name = "AmazonKendra" icon = "Amazon" + legacy: bool = True def build_config(self): return { diff --git a/src/backend/base/langflow/components/retrievers/cohere_rerank.py b/src/backend/base/langflow/components/retrievers/cohere_rerank.py index 3a4882a8a..177899954 100644 --- a/src/backend/base/langflow/components/retrievers/cohere_rerank.py +++ b/src/backend/base/langflow/components/retrievers/cohere_rerank.py @@ -3,7 +3,10 @@ from typing import cast from langchain.retrievers import ContextualCompressionRetriever from langchain_cohere import CohereRerank -from langflow.base.vectorstores.model import LCVectorStoreComponent, check_cached_vector_store +from langflow.base.vectorstores.model import ( + LCVectorStoreComponent, + check_cached_vector_store, +) from langflow.field_typing import Retriever, VectorStore from langflow.io import ( DropdownInput, @@ -22,6 +25,7 @@ class CohereRerankComponent(LCVectorStoreComponent): description = "Rerank documents using the Cohere API and a retriever." name = "CohereRerank" icon = "Cohere" + legacy: bool = True inputs = [ MultilineInput( diff --git a/src/backend/base/langflow/components/retrievers/metal.py b/src/backend/base/langflow/components/retrievers/metal.py index 083031560..f7dba35eb 100644 --- a/src/backend/base/langflow/components/retrievers/metal.py +++ b/src/backend/base/langflow/components/retrievers/metal.py @@ -11,6 +11,7 @@ class MetalRetrieverComponent(CustomComponent): display_name: str = "Metal Retriever" description: str = "Retriever that uses the Metal API." name = "MetalRetriever" + legacy: bool = True def build_config(self): return { diff --git a/src/backend/base/langflow/components/retrievers/multi_query.py b/src/backend/base/langflow/components/retrievers/multi_query.py index 5baa50025..6d381affc 100644 --- a/src/backend/base/langflow/components/retrievers/multi_query.py +++ b/src/backend/base/langflow/components/retrievers/multi_query.py @@ -9,6 +9,7 @@ class MultiQueryRetrieverComponent(CustomComponent): description = "Initialize from llm using default template." documentation = "https://python.langchain.com/docs/modules/data_connection/retrievers/how_to/MultiQueryRetriever" name = "MultiQueryRetriever" + legacy: bool = True def build_config(self): return { diff --git a/src/backend/base/langflow/components/retrievers/nvidia_rerank.py b/src/backend/base/langflow/components/retrievers/nvidia_rerank.py index d0a68f6a2..1092e0343 100644 --- a/src/backend/base/langflow/components/retrievers/nvidia_rerank.py +++ b/src/backend/base/langflow/components/retrievers/nvidia_rerank.py @@ -2,9 +2,18 @@ from typing import Any, cast from langchain.retrievers import ContextualCompressionRetriever -from langflow.base.vectorstores.model import LCVectorStoreComponent, check_cached_vector_store +from langflow.base.vectorstores.model import ( + LCVectorStoreComponent, + check_cached_vector_store, +) from langflow.field_typing import Retriever, VectorStore -from langflow.io import DropdownInput, HandleInput, MultilineInput, SecretStrInput, StrInput +from langflow.io import ( + DropdownInput, + HandleInput, + MultilineInput, + SecretStrInput, + StrInput, +) from langflow.schema import Data from langflow.schema.dotdict import dotdict from langflow.template.field.base import Output @@ -14,6 +23,7 @@ class NvidiaRerankComponent(LCVectorStoreComponent): display_name = "NVIDIA Rerank" description = "Rerank documents using the NVIDIA API and a retriever." icon = "NVIDIA" + legacy: bool = True inputs = [ MultilineInput( @@ -28,7 +38,10 @@ class NvidiaRerankComponent(LCVectorStoreComponent): info="The base URL of the NVIDIA API. Defaults to https://integrate.api.nvidia.com/v1.", ), DropdownInput( - name="model", display_name="Model", options=["nv-rerank-qa-mistral-4b:1"], value="nv-rerank-qa-mistral-4b:1" + name="model", + display_name="Model", + options=["nv-rerank-qa-mistral-4b:1"], + value="nv-rerank-qa-mistral-4b:1", ), SecretStrInput(name="api_key", display_name="API Key"), HandleInput(name="retriever", display_name="Retriever", input_types=["Retriever"]), diff --git a/src/backend/base/langflow/components/retrievers/self_query.py b/src/backend/base/langflow/components/retrievers/self_query.py index e732e3c35..86aaeb71f 100644 --- a/src/backend/base/langflow/components/retrievers/self_query.py +++ b/src/backend/base/langflow/components/retrievers/self_query.py @@ -13,6 +13,7 @@ class SelfQueryRetrieverComponent(Component): description = "Retriever that uses a vector store and an LLM to generate the vector store queries." name = "SelfQueryRetriever" icon = "LangChain" + legacy: bool = True inputs = [ HandleInput( @@ -48,7 +49,11 @@ class SelfQueryRetrieverComponent(Component): ] outputs = [ - Output(display_name="Retrieved Documents", name="documents", method="retrieve_documents"), + Output( + display_name="Retrieved Documents", + name="documents", + method="retrieve_documents", + ), ] def retrieve_documents(self) -> list[Data]: diff --git a/src/backend/base/langflow/components/retrievers/vector_store.py b/src/backend/base/langflow/components/retrievers/vector_store.py index b4ef2c846..6243725e5 100644 --- a/src/backend/base/langflow/components/retrievers/vector_store.py +++ b/src/backend/base/langflow/components/retrievers/vector_store.py @@ -8,6 +8,7 @@ class VectoStoreRetrieverComponent(CustomComponent): display_name = "VectorStore Retriever" description = "A vector store retriever" name = "VectorStoreRetriever" + legacy: bool = True def build_config(self): return { diff --git a/src/backend/base/langflow/components/toolkits/vector_store_info.py b/src/backend/base/langflow/components/toolkits/vector_store_info.py index 3b7d752f6..5961756b0 100644 --- a/src/backend/base/langflow/components/toolkits/vector_store_info.py +++ b/src/backend/base/langflow/components/toolkits/vector_store_info.py @@ -9,6 +9,7 @@ class VectorStoreInfoComponent(Component): display_name = "VectorStoreInfo" description = "Information about a VectorStore" name = "VectorStoreInfo" + legacy: bool = True inputs = [ MessageTextInput( @@ -41,5 +42,7 @@ class VectorStoreInfoComponent(Component): "description": self.vectorstore_description, } return VectorStoreInfo( - vectorstore=self.input_vectorstore, description=self.vectorstore_description, name=self.vectorstore_name + vectorstore=self.input_vectorstore, + description=self.vectorstore_description, + name=self.vectorstore_name, ) diff --git a/src/backend/base/langflow/components/tools/python_code_structured_tool.py b/src/backend/base/langflow/components/tools/python_code_structured_tool.py index f3028731d..8d715c91a 100644 --- a/src/backend/base/langflow/components/tools/python_code_structured_tool.py +++ b/src/backend/base/langflow/components/tools/python_code_structured_tool.py @@ -10,7 +10,14 @@ from pydantic.v1.fields import Undefined from typing_extensions import override from langflow.base.langchain_utilities.model import LCToolComponent -from langflow.inputs.inputs import BoolInput, DropdownInput, FieldTypes, HandleInput, MessageTextInput, MultilineInput +from langflow.inputs.inputs import ( + BoolInput, + DropdownInput, + FieldTypes, + HandleInput, + MessageTextInput, + MultilineInput, +) from langflow.io import Output from langflow.schema import Data from langflow.schema.dotdict import dotdict @@ -36,6 +43,7 @@ class PythonCodeStructuredTool(LCToolComponent): name = "PythonCodeStructuredTool" icon = "🐍" field_order = ["name", "description", "tool_code", "return_direct", "tool_function"] + legacy: bool = True inputs = [ MultilineInput( @@ -47,7 +55,12 @@ class PythonCodeStructuredTool(LCToolComponent): real_time_refresh=True, refresh_button=True, ), - MessageTextInput(name="tool_name", display_name="Tool Name", info="Enter the name of the tool.", required=True), + MessageTextInput( + name="tool_name", + display_name="Tool Name", + info="Enter the name of the tool.", + required=True, + ), MessageTextInput( name="tool_description", display_name="Description", @@ -192,7 +205,10 @@ class PythonCodeStructuredTool(LCToolComponent): schema_annotation = Any schema_fields[field_name] = ( schema_annotation, - Field(default=func_arg.get("default", Undefined), description=field_description), + Field( + default=func_arg.get("default", Undefined), + description=field_description, + ), ) if "temp_annotation_type" in _globals: @@ -214,7 +230,9 @@ class PythonCodeStructuredTool(LCToolComponent): """This function is called after the code validation is done.""" frontend_node = super().post_code_processing(new_frontend_node, current_frontend_node) frontend_node["template"] = self.update_build_config( - frontend_node["template"], frontend_node["template"]["tool_code"]["value"], "tool_code" + frontend_node["template"], + frontend_node["template"]["tool_code"]["value"], + "tool_code", ) frontend_node = super().post_code_processing(new_frontend_node, current_frontend_node) for key in frontend_node["template"]: diff --git a/src/backend/base/langflow/components/tools/searxng.py b/src/backend/base/langflow/components/tools/searxng.py index 3227b56e0..9d379c494 100644 --- a/src/backend/base/langflow/components/tools/searxng.py +++ b/src/backend/base/langflow/components/tools/searxng.py @@ -19,6 +19,7 @@ class SearXNGToolComponent(LCToolComponent): display_name = "SearXNG Search Tool" description = "A component that searches for tools using SearXNG." name = "SearXNGTool" + legacy: bool = True inputs = [ MessageTextInput( @@ -127,7 +128,10 @@ class SearXNGToolComponent(LCToolComponent): schema_fields = { "query": (str, Field(..., description="The query to search for.")), - "categories": (list[str], Field(default=[], description="The categories to search in.")), + "categories": ( + list[str], + Field(default=[], description="The categories to search in."), + ), } searx_search_schema = create_model("SearxSearchSchema", **schema_fields) diff --git a/src/backend/base/langflow/custom/attributes.py b/src/backend/base/langflow/custom/attributes.py index 0070d13c9..fadede40f 100644 --- a/src/backend/base/langflow/custom/attributes.py +++ b/src/backend/base/langflow/custom/attributes.py @@ -61,6 +61,7 @@ ATTR_FUNC_MAPPING: dict[str, Callable] = { "display_name": getattr_return_str, "description": getattr_return_str, "beta": getattr_return_bool, + "legacy": getattr_return_bool, "documentation": getattr_return_str, "icon": validate_icon, "frozen": getattr_return_bool, diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Agent Flow.json b/src/backend/base/langflow/initial_setup/starter_projects/Agent Flow.json index 19cc0cd2d..82153f047 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Agent Flow.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Agent Flow.json @@ -158,6 +158,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "lf_version": "1.0.16", "metadata": {}, "output_types": [], @@ -380,6 +381,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "lf_version": "1.0.16", "metadata": {}, "output_types": [], @@ -589,6 +591,7 @@ ], "frozen": false, "icon": "OpenAI", + "legacy": false, "lf_version": "1.0.16", "metadata": {}, "output_types": [], @@ -1203,6 +1206,7 @@ ], "frozen": false, "icon": "calculator", + "legacy": false, "lf_version": "1.0.16", "metadata": {}, "official": false, @@ -1322,6 +1326,7 @@ "code" ], "frozen": false, + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting (Hello, World).json b/src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting (Hello, World).json index b91e1b0c5..6ebd89572 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting (Hello, World).json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting (Hello, World).json @@ -108,6 +108,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -324,6 +325,7 @@ ], "frozen": false, "icon": "prompts", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -445,6 +447,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -647,6 +650,7 @@ ], "frozen": false, "icon": "OpenAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json b/src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json index 39f15075b..99b83df6a 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json @@ -156,6 +156,7 @@ ], "frozen": false, "icon": "layout-template", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -288,6 +289,7 @@ ], "frozen": false, "icon": "braces", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -425,6 +427,7 @@ ], "frozen": false, "icon": "prompts", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -667,6 +670,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -869,6 +873,7 @@ ], "frozen": false, "icon": "OpenAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Complex Agent.json b/src/backend/base/langflow/initial_setup/starter_projects/Complex Agent.json index 607126fa7..5d69c3dcd 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Complex Agent.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Complex Agent.json @@ -629,6 +629,7 @@ ], "frozen": false, "icon": "CrewAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -876,6 +877,7 @@ ], "frozen": false, "icon": "OpenAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1202,6 +1204,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1388,6 +1391,7 @@ ], "frozen": false, "icon": "CrewAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1528,6 +1532,7 @@ ], "frozen": false, "icon": "CrewAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1783,6 +1788,7 @@ ], "frozen": false, "icon": "CrewAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -2043,6 +2049,7 @@ ], "frozen": false, "icon": "OpenAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -2373,6 +2380,7 @@ "is_composition": null, "is_input": null, "is_output": null, + "legacy": false, "metadata": {}, "name": "", "output_types": [], @@ -2488,6 +2496,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -2814,6 +2823,7 @@ ], "frozen": false, "icon": "OpenAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -3264,6 +3274,7 @@ ], "frozen": false, "icon": "OpenAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -3738,6 +3749,7 @@ ], "frozen": false, "icon": "OpenAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -4070,6 +4082,7 @@ "is_composition": null, "is_input": null, "is_output": null, + "legacy": false, "metadata": {}, "name": "", "output_types": [], @@ -4237,6 +4250,7 @@ "search_params" ], "frozen": false, + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Document QA.json b/src/backend/base/langflow/initial_setup/starter_projects/Document QA.json index 9080d2f92..63bba535a 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Document QA.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Document QA.json @@ -161,6 +161,7 @@ ], "frozen": false, "icon": "prompts", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -306,6 +307,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -523,6 +525,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -725,6 +728,7 @@ ], "frozen": false, "icon": "OpenAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1048,6 +1052,7 @@ ], "frozen": false, "icon": "braces", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1181,6 +1186,7 @@ ], "frozen": false, "icon": "file-text", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Hierarchical Agent.json b/src/backend/base/langflow/initial_setup/starter_projects/Hierarchical Agent.json index 6e6f30ea6..5f39b1160 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Hierarchical Agent.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Hierarchical Agent.json @@ -326,6 +326,7 @@ ], "frozen": false, "icon": "CrewAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -576,6 +577,7 @@ ], "frozen": false, "icon": "OpenAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -906,6 +908,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1097,6 +1100,7 @@ ], "frozen": false, "icon": "CrewAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1242,6 +1246,7 @@ ], "frozen": false, "icon": "CrewAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1501,6 +1506,7 @@ ], "frozen": false, "icon": "CrewAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1763,6 +1769,7 @@ ], "frozen": false, "icon": "OpenAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -2097,6 +2104,7 @@ "is_composition": null, "is_input": null, "is_output": null, + "legacy": false, "metadata": {}, "name": "", "output_types": [], @@ -2216,6 +2224,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -2436,6 +2445,7 @@ ], "frozen": false, "icon": "CrewAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -2687,6 +2697,7 @@ "search_params" ], "frozen": false, + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Memory Chatbot.json b/src/backend/base/langflow/initial_setup/starter_projects/Memory Chatbot.json index feea5b9a5..1cc4c6d8b 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Memory Chatbot.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Memory Chatbot.json @@ -135,6 +135,7 @@ ], "frozen": false, "icon": "prompts", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -280,6 +281,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -504,6 +506,7 @@ ], "frozen": false, "icon": "OpenAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -830,6 +833,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1023,6 +1027,7 @@ ], "frozen": false, "icon": "message-square-more", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Sequential Agent.json b/src/backend/base/langflow/initial_setup/starter_projects/Sequential Agent.json index 0973b30f6..c7ba32ab2 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Sequential Agent.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Sequential Agent.json @@ -389,6 +389,7 @@ ], "frozen": false, "icon": "CrewAI", + "legacy": false, "lf_version": "1.0.15", "metadata": {}, "output_types": [], @@ -588,6 +589,7 @@ ], "frozen": false, "icon": "OpenAI", + "legacy": false, "lf_version": "1.0.15", "metadata": {}, "output_types": [], @@ -915,6 +917,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "lf_version": "1.0.15", "metadata": {}, "output_types": [], @@ -1199,6 +1202,7 @@ ], "frozen": false, "icon": "prompts", + "legacy": false, "lf_version": "1.0.15", "metadata": {}, "output_types": [], @@ -1320,6 +1324,7 @@ ], "frozen": false, "icon": "prompts", + "legacy": false, "lf_version": "1.0.15", "metadata": {}, "output_types": [], @@ -1441,6 +1446,7 @@ ], "frozen": false, "icon": "prompts", + "legacy": false, "lf_version": "1.0.15", "metadata": {}, "output_types": [], @@ -1569,6 +1575,7 @@ ], "frozen": false, "icon": "CrewAI", + "legacy": false, "lf_version": "1.0.15", "metadata": {}, "output_types": [], @@ -1920,6 +1927,7 @@ ], "frozen": false, "icon": "CrewAI", + "legacy": false, "lf_version": "1.0.15", "metadata": {}, "output_types": [], @@ -2271,6 +2279,7 @@ ], "frozen": false, "icon": "CrewAI", + "legacy": false, "lf_version": "1.0.15", "metadata": {}, "output_types": [], diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Travel Planning Agents.json b/src/backend/base/langflow/initial_setup/starter_projects/Travel Planning Agents.json index 19cbd20ad..2482d8138 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Travel Planning Agents.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Travel Planning Agents.json @@ -398,6 +398,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "lf_version": "1.0.15", "metadata": {}, "output_types": [], @@ -620,6 +621,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "lf_version": "1.0.15", "metadata": {}, "output_types": [], @@ -829,6 +831,7 @@ ], "frozen": false, "icon": "OpenAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1442,6 +1445,7 @@ "search_params" ], "frozen": false, + "legacy": false, "lf_version": "1.0.15", "metadata": {}, "official": false, @@ -2319,6 +2323,7 @@ ], "frozen": false, "icon": "calculator", + "legacy": false, "lf_version": "1.0.15", "metadata": {}, "official": false, diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json b/src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json index be00e8bec..012104864 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json @@ -291,6 +291,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -524,6 +525,7 @@ ], "frozen": false, "icon": "AstraDB", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1020,6 +1022,7 @@ ], "frozen": false, "icon": "braces", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1157,6 +1160,7 @@ ], "frozen": false, "icon": "prompts", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1302,6 +1306,7 @@ ], "frozen": false, "icon": "MessagesSquare", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1494,6 +1499,7 @@ ], "frozen": false, "icon": "scissors-line-dashed", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1639,6 +1645,7 @@ ], "frozen": false, "icon": "file-text", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -1788,6 +1795,7 @@ ], "frozen": false, "icon": "AstraDB", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -2302,6 +2310,7 @@ ], "frozen": false, "icon": "OpenAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -2778,6 +2787,7 @@ ], "frozen": false, "icon": "OpenAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ @@ -3246,6 +3256,7 @@ ], "frozen": false, "icon": "OpenAI", + "legacy": false, "metadata": {}, "output_types": [], "outputs": [ diff --git a/src/backend/base/langflow/template/frontend_node/base.py b/src/backend/base/langflow/template/frontend_node/base.py index bf80442e0..4df292120 100644 --- a/src/backend/base/langflow/template/frontend_node/base.py +++ b/src/backend/base/langflow/template/frontend_node/base.py @@ -49,6 +49,8 @@ class FrontendNode(BaseModel): """Order of the fields in the frontend node.""" beta: bool = False """Whether the frontend node is in beta.""" + legacy: bool = False + """Whether the frontend node is legacy.""" error: str | None = None """Error message for the frontend node.""" edited: bool = False @@ -81,7 +83,10 @@ class FrontendNode(BaseModel): if "output_types" in result and not result.get("outputs"): for base_class in result["output_types"]: output = Output( - display_name=base_class, name=base_class.lower(), types=[base_class], selected=base_class + display_name=base_class, + name=base_class.lower(), + types=[base_class], + selected=base_class, ) result["outputs"].append(output.model_dump()) diff --git a/src/backend/base/langflow/template/frontend_node/custom_components.py b/src/backend/base/langflow/template/frontend_node/custom_components.py index 4f733c15e..b9a820070 100644 --- a/src/backend/base/langflow/template/frontend_node/custom_components.py +++ b/src/backend/base/langflow/template/frontend_node/custom_components.py @@ -47,6 +47,7 @@ class CustomComponentFrontendNode(FrontendNode): name: str = "CustomComponent" display_name: str | None = "CustomComponent" beta: bool = False + legacy: bool = False template: Template = Template( type_name="CustomComponent", fields=[ @@ -72,6 +73,7 @@ class ComponentFrontendNode(FrontendNode): name: str = "Component" display_name: str | None = "Component" beta: bool = False + legacy: bool = False template: Template = Template( type_name="Component", fields=[ diff --git a/src/backend/base/langflow/utils/constants.py b/src/backend/base/langflow/utils/constants.py index 45d3d7e70..1b720652a 100644 --- a/src/backend/base/langflow/utils/constants.py +++ b/src/backend/base/langflow/utils/constants.py @@ -52,7 +52,18 @@ def python_function(text: str) -> str: PYTHON_BASIC_TYPES = [str, bool, int, float, tuple, list, dict, set] -DIRECT_TYPES = ["str", "bool", "dict", "int", "float", "Any", "prompt", "code", "NestedDict", "table"] +DIRECT_TYPES = [ + "str", + "bool", + "dict", + "int", + "float", + "Any", + "prompt", + "code", + "NestedDict", + "table", +] LOADERS_INFO: list[dict[str, Any]] = [ @@ -175,29 +186,3 @@ MESSAGE_SENDER_NAME_AI = "AI" MESSAGE_SENDER_NAME_USER = "User" MAX_TEXT_LENGTH = 99999 - - -SIDEBAR_CATEGORIES = [ - {"display_name": "Saved", "name": "saved_components", "icon": "GradientSave"}, - {"display_name": "Inputs", "name": "inputs", "icon": "Download"}, - {"display_name": "Outputs", "name": "outputs", "icon": "Upload"}, - {"display_name": "Prompts", "name": "prompts", "icon": "TerminalSquare"}, - {"display_name": "Data", "name": "data", "icon": "Database"}, - {"display_name": "Models", "name": "models", "icon": "BrainCircuit"}, - {"display_name": "Helpers", "name": "helpers", "icon": "Wand2"}, - {"display_name": "Vector Stores", "name": "vectorstores", "icon": "Layers"}, - {"display_name": "Embeddings", "name": "embeddings", "icon": "Binary"}, - {"display_name": "Agents", "name": "agents", "icon": "Bot"}, - {"display_name": "Astra Assistants", "name": "astra_assistants", "icon": "Sparkles"}, - {"display_name": "Chains", "name": "chains", "icon": "Link"}, - {"display_name": "Loaders", "name": "documentloaders", "icon": "Paperclip"}, - {"display_name": "Utilities", "name": "langchain_utilities", "icon": "PocketKnife"}, - {"display_name": "Link Extractors", "name": "link_extractors", "icon": "Link2"}, - {"display_name": "Memories", "name": "memories", "icon": "Cpu"}, - {"display_name": "Output Parsers", "name": "output_parsers", "icon": "Compass"}, - {"display_name": "Prototypes", "name": "prototypes", "icon": "FlaskConical"}, - {"display_name": "Retrievers", "name": "retrievers", "icon": "FileSearch"}, - {"display_name": "Text Splitters", "name": "textsplitters", "icon": "Scissors"}, - {"display_name": "Toolkits", "name": "toolkits", "icon": "Package2"}, - {"display_name": "Tools", "name": "tools", "icon": "Hammer"}, -] diff --git a/src/backend/tests/unit/api/v1/test_endpoints.py b/src/backend/tests/unit/api/v1/test_endpoints.py index 15d96e9aa..908b4edaf 100644 --- a/src/backend/tests/unit/api/v1/test_endpoints.py +++ b/src/backend/tests/unit/api/v1/test_endpoints.py @@ -23,14 +23,3 @@ async def test_get_config(client: AsyncClient): assert "auto_saving" in result, "The dictionary must contain a key called 'auto_saving'" assert "health_check_max_retries" in result, "The dictionary must contain a 'health_check_max_retries' key" assert "max_file_size_upload" in result, "The dictionary must contain a key called 'max_file_size_upload'" - - -async def test_get_sidebar_components(client: AsyncClient): - response = await client.get("api/v1/sidebar_categories") - result = response.json() - - assert response.status_code == status.HTTP_200_OK - assert isinstance(result, dict), "The result must be a dictionary" - assert "categories" in result, "The dictionary must contain a key called 'categories'" - assert len(result["categories"]) > 0, "The categories list must not be empty" - assert isinstance(result["categories"], list), "The categories must be a list" diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json index 7aaf8a3ca..046cf7d98 100644 --- a/src/frontend/package-lock.json +++ b/src/frontend/package-lock.json @@ -14,7 +14,8 @@ "@million/lint": "^1.0.0-rc.26", "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-checkbox": "^1.0.4", - "@radix-ui/react-dialog": "^1.1.1", + "@radix-ui/react-collapsible": "^1.1.1", + "@radix-ui/react-dialog": "^1.1.2", "@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-form": "^0.0.3", "@radix-ui/react-icons": "^1.3.0", diff --git a/src/frontend/package.json b/src/frontend/package.json index 7c072f75d..34df5f5c7 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -9,7 +9,8 @@ "@million/lint": "^1.0.0-rc.26", "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-checkbox": "^1.0.4", - "@radix-ui/react-dialog": "^1.1.1", + "@radix-ui/react-collapsible": "^1.1.1", + "@radix-ui/react-dialog": "^1.1.2", "@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-form": "^0.0.3", "@radix-ui/react-icons": "^1.3.0", diff --git a/src/frontend/src/components/appHeaderComponent/components/GithubStarButton/index.tsx b/src/frontend/src/components/appHeaderComponent/components/GithubStarButton/index.tsx index cc13c466f..fd8a0a655 100644 --- a/src/frontend/src/components/appHeaderComponent/components/GithubStarButton/index.tsx +++ b/src/frontend/src/components/appHeaderComponent/components/GithubStarButton/index.tsx @@ -9,7 +9,7 @@ export const GithubStarComponent = () => {
Star
- {stars.toLocaleString() ?? 0} + {stars?.toLocaleString() ?? 0}
); diff --git a/src/frontend/src/components/ui/badge.tsx b/src/frontend/src/components/ui/badge.tsx index 6eea7971a..ad3a2638f 100644 --- a/src/frontend/src/components/ui/badge.tsx +++ b/src/frontend/src/components/ui/badge.tsx @@ -15,13 +15,15 @@ const badgeVariants = cva( destructive: "bg-destructive hover:bg-destructive/80 border-transparent text-destructive-foreground", outline: "text-primary/80 border-ring/60", + secondaryStatic: "bg-input text-muted-foreground", + pinkStatic: "bg-accent-pink text-accent-pink-foreground", }, size: { sm: "h-4 text-xs", md: "h-5 text-sm", lg: "h-6 text-base", - sq: "h-6 text-sm font-normal rounded-md", - xq: "h-5 text-xs font-normal rounded-md", + sq: "h-6 px-1.5 text-sm font-medium rounded-md", + xq: "h-5 px-1 text-xs font-medium rounded-md", }, }, defaultVariants: { diff --git a/src/frontend/src/components/ui/button.tsx b/src/frontend/src/components/ui/button.tsx index 140c7b0e3..027d9bf15 100644 --- a/src/frontend/src/components/ui/button.tsx +++ b/src/frontend/src/components/ui/button.tsx @@ -18,8 +18,10 @@ const buttonVariants = cva( "border bg-background text-secondary-foreground hover:bg-muted dark:hover:bg-muted hover:shadow-sm", secondary: "border border-muted bg-muted text-secondary-foreground hover:bg-secondary-foreground/5", - ghost: "hover:bg-accent hover:text-accent-foreground", - menu: "hover:bg-muted hover:text-accent-foreground focus-visible:!ring-offset-0", + ghost: "text-foreground hover:bg-accent hover:text-accent-foreground", + ghostActive: + "bg-muted text-foreground hover:bg-accent hover:text-accent-foreground", + menu: "hover:bg-muted hover:text-accent-foreground focus:!ring-0 focus-visible:!ring-0", "menu-active": "font-semibold hover:bg-muted hover:text-accent-foreground focus-visible:!ring-offset-0", link: "underline-offset-4 hover:underline text-primary", @@ -29,7 +31,9 @@ const buttonVariants = cva( sm: "h-9 px-3 rounded-md", xs: "py-0.5 px-3 rounded-md", lg: "h-11 px-8 rounded-md", - icon: "py-1 px-1 rounded-md", + iconMd: "p-1.5 rounded-md", + icon: "p-1 rounded-md", + iconSm: "p-0.5 rounded-md", "node-toolbar": "py-[6px] px-[6px] rounded-md", }, }, diff --git a/src/frontend/src/components/ui/collapsible.tsx b/src/frontend/src/components/ui/collapsible.tsx new file mode 100644 index 000000000..1fe76f5d1 --- /dev/null +++ b/src/frontend/src/components/ui/collapsible.tsx @@ -0,0 +1,11 @@ +"use client"; + +import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"; + +const Collapsible = CollapsiblePrimitive.Root; + +const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger; + +const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent; + +export { Collapsible, CollapsibleContent, CollapsibleTrigger }; diff --git a/src/frontend/src/components/ui/disclosure.tsx b/src/frontend/src/components/ui/disclosure.tsx new file mode 100644 index 000000000..77ca775c4 --- /dev/null +++ b/src/frontend/src/components/ui/disclosure.tsx @@ -0,0 +1,191 @@ +"use client"; +import { + AnimatePresence, + motion, + MotionConfig, + Transition, + Variant, + Variants, +} from "framer-motion"; +import * as React from "react"; +import { createContext, useContext, useEffect, useId, useState } from "react"; +import { cn } from "../../utils/utils"; + +type DisclosureContextType = { + open: boolean; + toggle: () => void; + variants?: { expanded: Variant; collapsed: Variant }; +}; + +const DisclosureContext = createContext( + undefined, +); + +type DisclosureProviderProps = { + children: React.ReactNode; + open: boolean; + onOpenChange?: (open: boolean) => void; + variants?: { expanded: Variant; collapsed: Variant }; +}; + +function DisclosureProvider({ + children, + open: openProp, + onOpenChange, + variants, +}: DisclosureProviderProps) { + const [internalOpenValue, setInternalOpenValue] = useState(openProp); + + useEffect(() => { + setInternalOpenValue(openProp); + }, [openProp]); + + const toggle = () => { + const newOpen = !internalOpenValue; + setInternalOpenValue(newOpen); + if (onOpenChange) { + onOpenChange(newOpen); + } + }; + + return ( + + {children} + + ); +} + +function useDisclosure() { + const context = useContext(DisclosureContext); + if (!context) { + throw new Error("useDisclosure must be used within a DisclosureProvider"); + } + return context; +} + +type DisclosureProps = { + open?: boolean; + onOpenChange?: (open: boolean) => void; + children: React.ReactNode; + className?: string; + variants?: { expanded: Variant; collapsed: Variant }; + transition?: Transition; +}; + +export function Disclosure({ + open: openProp = false, + onOpenChange, + children, + className, + transition, + variants, +}: DisclosureProps) { + return ( + +
+ + {React.Children.toArray(children)[0]} + {React.Children.toArray(children)[1]} + +
+
+ ); +} + +export function DisclosureTrigger({ + children, + className, +}: { + children: React.ReactNode; + className?: string; +}) { + const { toggle, open } = useDisclosure(); + + return ( + <> + {React.Children.map(children, (child) => { + return React.isValidElement(child) + ? React.cloneElement(child, { + onClick: toggle, + role: "button", + "aria-expanded": open, + tabIndex: 0, + onKeyDown: (e: { key: string; preventDefault: () => void }) => { + if (e.key === "Enter" || e.key === " ") { + e.preventDefault(); + toggle(); + } + }, + className: cn( + className, + (child as React.ReactElement).props.className, + ), + ...(child as React.ReactElement).props, + }) + : child; + })} + + ); +} + +export function DisclosureContent({ + children, + className, +}: { + children: React.ReactNode; + className?: string; +}) { + const { open, variants } = useDisclosure(); + const uniqueId = useId(); + + const BASE_VARIANTS: Variants = { + expanded: { + height: "auto", + opacity: 1, + }, + collapsed: { + height: 0, + opacity: 0, + }, + }; + + const combinedVariants = { + expanded: { ...BASE_VARIANTS.expanded, ...variants?.expanded }, + collapsed: { ...BASE_VARIANTS.collapsed, ...variants?.collapsed }, + }; + + return ( +
+ + {open && ( + + {children} + + )} + +
+ ); +} + +export default { + Disclosure, + DisclosureProvider, + DisclosureTrigger, + DisclosureContent, +}; diff --git a/src/frontend/src/components/ui/sheet.tsx b/src/frontend/src/components/ui/sheet.tsx index e48bc1d99..adac8151e 100644 --- a/src/frontend/src/components/ui/sheet.tsx +++ b/src/frontend/src/components/ui/sheet.tsx @@ -65,7 +65,7 @@ const SheetContent = React.forwardRef< {...props} > {children} - + Close diff --git a/src/frontend/src/components/ui/sidebar.tsx b/src/frontend/src/components/ui/sidebar.tsx index 4941106ea..328ff9629 100644 --- a/src/frontend/src/components/ui/sidebar.tsx +++ b/src/frontend/src/components/ui/sidebar.tsx @@ -5,10 +5,12 @@ import { VariantProps, cva } from "class-variance-authority"; import { PanelLeft } from "lucide-react"; import * as React from "react"; +import { useIsMobile } from "../../hooks/use-mobile"; import { cn } from "../../utils/utils"; import { Button } from "./button"; import { Input } from "./input"; import { Separator } from "./separator"; +import { Sheet, SheetContent } from "./sheet"; import { Skeleton } from "./skeleton"; import { Tooltip, @@ -20,13 +22,17 @@ import { const SIDEBAR_COOKIE_NAME = "sidebar:state"; const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7; const SIDEBAR_WIDTH = "19rem"; -const SIDEBAR_WIDTH_ICON = "4rem"; +const SIDEBAR_WIDTH_MOBILE = "18rem"; +const SIDEBAR_WIDTH_ICON = "3rem"; const SIDEBAR_KEYBOARD_SHORTCUT = "b"; type SidebarContext = { state: "expanded" | "collapsed"; open: boolean; setOpen: (open: boolean) => void; + openMobile: boolean; + setOpenMobile: (open: boolean) => void; + isMobile: boolean; toggleSidebar: () => void; }; @@ -47,7 +53,6 @@ const SidebarProvider = React.forwardRef< defaultOpen?: boolean; open?: boolean; onOpenChange?: (open: boolean) => void; - width?: string; } >( ( @@ -58,11 +63,13 @@ const SidebarProvider = React.forwardRef< className, style, children, - width = SIDEBAR_WIDTH, ...props }, ref, ) => { + const isMobile = useIsMobile(); + const [openMobile, setOpenMobile] = React.useState(false); + // This is the internal state of the sidebar. // We use openProp and setOpenProp for control from outside the component. const [_open, _setOpen] = React.useState(defaultOpen); @@ -85,8 +92,10 @@ const SidebarProvider = React.forwardRef< // Helper to toggle the sidebar. const toggleSidebar = React.useCallback(() => { - return setOpen((open) => !open); - }, [setOpen]); + return isMobile + ? setOpenMobile((open) => !open) + : setOpen((open) => !open); + }, [isMobile, setOpen, setOpenMobile]); // Adds a keyboard shortcut to toggle the sidebar. React.useEffect(() => { @@ -113,9 +122,20 @@ const SidebarProvider = React.forwardRef< state, open, setOpen, + isMobile, + openMobile, + setOpenMobile, toggleSidebar, }), - [state, open, setOpen, toggleSidebar], + [ + state, + open, + setOpen, + isMobile, + openMobile, + setOpenMobile, + toggleSidebar, + ], ); return ( @@ -124,7 +144,7 @@ const SidebarProvider = React.forwardRef<
{ - const { state } = useSidebar(); + const { isMobile, state, openMobile, setOpenMobile } = useSidebar(); if (collapsible === "none") { return (
-
- {children} -
+ {children}
); } + if (isMobile) { + return ( + + +
{children}
+
+
+ ); + } + return (