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 (
{children}
@@ -258,7 +280,7 @@ const SidebarTrigger = React.forwardRef<
data-sidebar="trigger"
variant="ghost"
size="icon"
- className={cn("h-8 w-8", className)}
+ className={cn("h-7 w-7", className)}
onClick={(event) => {
onClick?.(event);
toggleSidebar();
@@ -310,7 +332,7 @@ const SidebarInset = React.forwardRef<
ref={ref}
className={cn(
"relative flex min-h-svh flex-1 flex-col bg-background",
- "peer-data-[variant=inset]:m-2 peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 peer-data-[variant=inset]:ml-0 peer-data-[variant=inset]:rounded-xl peer-data-[variant=inset]:shadow",
+ "peer-data-[variant=inset]:min-h-[calc(100svh-theme(spacing.4))] md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow",
className,
)}
{...props}
@@ -328,7 +350,7 @@ const SidebarInput = React.forwardRef<
ref={ref}
data-sidebar="input"
className={cn(
- "h-8 w-full bg-background shadow-none focus-visible:ring-1 focus-visible:ring-ring",
+ "h-8 w-full bg-background shadow-none focus-visible:ring-2 focus-visible:ring-ring",
className,
)}
{...props}
@@ -426,7 +448,7 @@ const SidebarGroupLabel = React.forwardRef<
ref={ref}
data-sidebar="group-label"
className={cn(
- "flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-semibold text-foreground/70 outline-none ring-ring transition-[margin,opa] duration-200 ease-linear focus-visible:ring-1 [&>svg]:size-4 [&>svg]:shrink-0",
+ "flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-semibold text-foreground/70 outline-none ring-ring transition-[margin,opa] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
"group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
className,
)}
@@ -447,9 +469,9 @@ const SidebarGroupAction = React.forwardRef<
ref={ref}
data-sidebar="group-action"
className={cn(
- "absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-foreground outline-none ring-ring transition-transform hover:bg-accent hover:text-accent-foreground focus-visible:ring-1 [&>svg]:size-4 [&>svg]:shrink-0",
+ "absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-foreground outline-none ring-ring transition-transform hover:bg-accent hover:text-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
// Increases the hit area of the button on mobile.
- "after:-inset-2 after:hidden",
+ "after:absolute after:-inset-2 after:md:hidden",
"group-data-[collapsible=icon]:hidden",
className,
)}
@@ -499,12 +521,11 @@ const SidebarMenuItem = React.forwardRef<
SidebarMenuItem.displayName = "SidebarMenuItem";
const sidebarMenuButtonVariants = cva(
- "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-ring transition-[width,height,padding] hover:bg-accent hover:text-accent-foreground focus-visible:ring-1 active:bg-accent active:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-accent data-[active=true]:font-medium data-[active=true]:text-accent-foreground data-[state=open]:hover:bg-accent data-[state=open]:hover:text-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
+ "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-ring transition-[width,height,padding] hover:bg-accent hover:text-accent-foreground focus-visible:ring-2 active:bg-accent active:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-accent data-[active=true]:font-medium data-[active=true]:text-accent-foreground data-[state=open]:hover:bg-accent data-[state=open]:hover:text-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
{
variants: {
variant: {
- default:
- "text-secondary-foreground hover:bg-accent hover:text-accent-foreground ",
+ default: "hover:bg-accent hover:text-accent-foreground",
outline:
"bg-background shadow-[0_0_0_1px_hsl(var(--border))] hover:bg-accent hover:text-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--accent))]",
},
@@ -542,7 +563,7 @@ const SidebarMenuButton = React.forwardRef<
ref,
) => {
const Comp = asChild ? Slot : "button";
- const { state } = useSidebar();
+ const { isMobile, state } = useSidebar();
const button = (
@@ -594,9 +615,9 @@ const SidebarMenuAction = React.forwardRef<
ref={ref}
data-sidebar="menu-action"
className={cn(
- "absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-foreground outline-none ring-ring transition-transform hover:bg-accent hover:text-accent-foreground focus-visible:ring-1 peer-hover/menu-button:text-accent-foreground [&>svg]:size-4 [&>svg]:shrink-0",
+ "absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-foreground outline-none ring-ring transition-transform hover:bg-accent hover:text-accent-foreground focus-visible:ring-2 peer-hover/menu-button:text-accent-foreground [&>svg]:size-4 [&>svg]:shrink-0",
// Increases the hit area of the button on mobile.
- "after:-inset-2 after:hidden",
+ "after:absolute after:-inset-2 after:md:hidden",
"peer-data-[size=sm]/menu-button:top-1",
"peer-data-[size=default]/menu-button:top-1.5",
"peer-data-[size=lg]/menu-button:top-2.5",
@@ -710,7 +731,7 @@ const SidebarMenuSubButton = React.forwardRef<
data-size={size}
data-active={isActive}
className={cn(
- "flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-foreground outline-none ring-ring hover:bg-accent hover:text-accent-foreground focus-visible:ring-1 active:bg-accent active:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-accent-foreground",
+ "flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-foreground outline-none ring-ring hover:bg-accent hover:text-accent-foreground focus-visible:ring-2 active:bg-accent active:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-accent-foreground",
"data-[active=true]:bg-accent data-[active=true]:text-accent-foreground",
size === "sm" && "text-xs",
size === "md" && "text-sm",
diff --git a/src/frontend/src/constants/constants.ts b/src/frontend/src/constants/constants.ts
index 0e227e5b5..bc390edf9 100644
--- a/src/frontend/src/constants/constants.ts
+++ b/src/frontend/src/constants/constants.ts
@@ -908,7 +908,7 @@ export const LANGFLOW_ACCESS_TOKEN_EXPIRE_SECONDS_ENV =
Number(process.env.ACCESS_TOKEN_EXPIRE_SECONDS) -
Number(process.env.ACCESS_TOKEN_EXPIRE_SECONDS) * 0.1;
export const TEXT_FIELD_TYPES: string[] = ["str", "SecretStr"];
-export const NODE_WIDTH = 400;
+export const NODE_WIDTH = 384;
export const NODE_HEIGHT = NODE_WIDTH * 3;
export const SHORTCUT_KEYS = ["cmd", "ctrl", "alt", "shift"];
diff --git a/src/frontend/src/controllers/API/helpers/constants.ts b/src/frontend/src/controllers/API/helpers/constants.ts
index 0bdba73f8..6a63eac70 100644
--- a/src/frontend/src/controllers/API/helpers/constants.ts
+++ b/src/frontend/src/controllers/API/helpers/constants.ts
@@ -21,6 +21,7 @@ export const URLs = {
VALIDATE: `validate`,
CONFIG: `config`,
STARTER_PROJECTS: `starter-projects`,
+ SIDEBAR_CATEGORIES: `sidebar_categories`,
} as const;
export function getURL(key: keyof typeof URLs, params: any = {}) {
diff --git a/src/frontend/src/hooks/use-mobile.ts b/src/frontend/src/hooks/use-mobile.ts
index 6066b9e2e..a93d58393 100644
--- a/src/frontend/src/hooks/use-mobile.ts
+++ b/src/frontend/src/hooks/use-mobile.ts
@@ -1,22 +1,21 @@
-import { useEffect, useState } from "react";
+import * as React from "react";
-export function useMobile(breakpoint: number = 768) {
- const [isMobile, setIsMobile] = useState(false);
+const MOBILE_BREAKPOINT = 768;
- useEffect(() => {
- const checkMobile = () => {
- setIsMobile(window.innerWidth < breakpoint);
+export function useIsMobile() {
+ const [isMobile, setIsMobile] = React.useState
(
+ undefined,
+ );
+
+ React.useEffect(() => {
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
+ const onChange = () => {
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
};
+ mql.addEventListener("change", onChange);
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
+ return () => mql.removeEventListener("change", onChange);
+ }, []);
- // Check initially
- checkMobile();
-
- // Add event listener
- window.addEventListener("resize", checkMobile);
-
- // Cleanup
- return () => window.removeEventListener("resize", checkMobile);
- }, [breakpoint]);
-
- return isMobile;
+ return !!isMobile;
}
diff --git a/src/frontend/src/hooks/useAddComponent.ts b/src/frontend/src/hooks/useAddComponent.ts
new file mode 100644
index 000000000..924b5ba60
--- /dev/null
+++ b/src/frontend/src/hooks/useAddComponent.ts
@@ -0,0 +1,70 @@
+import { NODE_WIDTH } from "@/constants/constants";
+import { track } from "@/customization/utils/analytics";
+import useFlowStore from "@/stores/flowStore";
+import { APIClassType } from "@/types/api";
+import { NodeType } from "@/types/flow";
+import { getNodeId } from "@/utils/reactflowUtils";
+import { getNodeRenderType } from "@/utils/utils";
+import { useCallback } from "react";
+import { useStoreApi } from "reactflow";
+
+export function useAddComponent() {
+ const store = useStoreApi();
+ const paste = useFlowStore((state) => state.paste);
+
+ const addComponent = useCallback(
+ (
+ component: APIClassType,
+ type: string,
+ position?: { x: number; y: number },
+ ) => {
+ track("Component Added", { componentType: component.display_name });
+
+ const {
+ height,
+ width,
+ transform: [transformX, transformY, zoomLevel],
+ } = store.getState();
+
+ const zoomMultiplier = 1 / zoomLevel;
+
+ let pos;
+
+ if (position) {
+ pos = position;
+ } else {
+ let centerX, centerY;
+
+ centerX = -transformX * zoomMultiplier + (width * zoomMultiplier) / 2;
+ centerY = -transformY * zoomMultiplier + (height * zoomMultiplier) / 2;
+
+ const nodeOffset = NODE_WIDTH / 2;
+
+ pos = {
+ x: -nodeOffset,
+ y: -nodeOffset,
+ paneX: centerX,
+ paneY: centerY,
+ };
+ }
+
+ const newId = getNodeId(type);
+
+ const newNode: NodeType = {
+ id: newId,
+ type: getNodeRenderType("genericnode"),
+ position: { x: 0, y: 0 },
+ data: {
+ node: component,
+ type: type,
+ id: newId,
+ },
+ };
+
+ paste({ nodes: [newNode], edges: [] }, pos);
+ },
+ [store, paste],
+ );
+
+ return addComponent;
+}
diff --git a/src/frontend/src/icons/AstraDB/AstraDB.jsx b/src/frontend/src/icons/AstraDB/AstraDB.jsx
index c4f4a0f54..76f993223 100644
--- a/src/frontend/src/icons/AstraDB/AstraDB.jsx
+++ b/src/frontend/src/icons/AstraDB/AstraDB.jsx
@@ -9,11 +9,11 @@ const AstraSVG = (props) => (
>
);
diff --git a/src/frontend/src/icons/AstraDB/index.tsx b/src/frontend/src/icons/AstraDB/index.tsx
index 4ea124878..fcf38b255 100644
--- a/src/frontend/src/icons/AstraDB/index.tsx
+++ b/src/frontend/src/icons/AstraDB/index.tsx
@@ -6,6 +6,6 @@ export const AstraDBIcon = forwardRef<
SVGSVGElement,
React.PropsWithChildren<{}>
>((props, ref) => {
- const isDark = useDarkStore((state) => state.dark);
- return ;
+ const isdark = useDarkStore((state) => state.dark);
+ return ;
});
diff --git a/src/frontend/src/icons/Azure/Azure.jsx b/src/frontend/src/icons/Azure/Azure.jsx
index 644fdd9f8..038fe264c 100644
--- a/src/frontend/src/icons/Azure/Azure.jsx
+++ b/src/frontend/src/icons/Azure/Azure.jsx
@@ -6,6 +6,7 @@ export const SvgAzure = (props) => (
height="35"
version="1"
viewBox="0 0 750 750"
+ {...props}
>
diff --git a/src/frontend/src/icons/CrewAI/CrewAiIcon.jsx b/src/frontend/src/icons/CrewAI/CrewAiIcon.jsx
index d2a02f8f3..8bf1a994c 100644
--- a/src/frontend/src/icons/CrewAI/CrewAiIcon.jsx
+++ b/src/frontend/src/icons/CrewAI/CrewAiIcon.jsx
@@ -7,6 +7,7 @@ const SvgCrewAiIcon = (props) => (
height="640"
viewBox="0 0 1856 640"
style={{ width: "20%", height: "25%" }}
+ {...props}
>
(
+const SvgGroqLogo = ({ ...props }) => (