Merge branch 'main' into dev
This commit is contained in:
commit
500fc98a00
38 changed files with 610 additions and 1020 deletions
|
|
@ -0,0 +1,82 @@
|
|||
from langflow import CustomComponent
|
||||
from typing import Optional
|
||||
from langchain.prompts import SystemMessagePromptTemplate
|
||||
from langchain.tools import Tool
|
||||
from langchain.schema.memory import BaseMemory
|
||||
from langchain.chat_models import ChatOpenAI
|
||||
|
||||
from langchain.agents.agent import AgentExecutor
|
||||
from langchain.agents.openai_functions_agent.base import OpenAIFunctionsAgent
|
||||
from langchain.memory.token_buffer import ConversationTokenBufferMemory
|
||||
from langchain.prompts.chat import MessagesPlaceholder
|
||||
from langchain.agents.agent_toolkits.conversational_retrieval.openai_functions import (
|
||||
_get_default_system_message,
|
||||
)
|
||||
|
||||
|
||||
class ConversationalAgent(CustomComponent):
|
||||
display_name: str = "OpenAI Conversational Agent"
|
||||
description: str = "Conversational Agent that can use OpenAI's function calling API"
|
||||
|
||||
def build_config(self):
|
||||
openai_function_models = [
|
||||
"gpt-3.5-turbo-0613",
|
||||
"gpt-3.5-turbo-16k-0613",
|
||||
"gpt-4-0613",
|
||||
"gpt-4-32k-0613",
|
||||
]
|
||||
return {
|
||||
"tools": {"is_list": True, "display_name": "Tools"},
|
||||
"memory": {"display_name": "Memory"},
|
||||
"system_message": {"display_name": "System Message"},
|
||||
"max_token_limit": {"display_name": "Max Token Limit"},
|
||||
"model_name": {
|
||||
"display_name": "Model Name",
|
||||
"options": openai_function_models,
|
||||
"value": openai_function_models[0],
|
||||
},
|
||||
"code": {"show": False},
|
||||
}
|
||||
|
||||
def build(
|
||||
self,
|
||||
model_name: str,
|
||||
openai_api_key: str,
|
||||
openai_api_base: str,
|
||||
tools: Tool,
|
||||
memory: Optional[BaseMemory] = None,
|
||||
system_message: Optional[SystemMessagePromptTemplate] = None,
|
||||
max_token_limit: int = 2000,
|
||||
) -> AgentExecutor:
|
||||
llm = ChatOpenAI(
|
||||
model=model_name,
|
||||
openai_api_key=openai_api_key,
|
||||
openai_api_base=openai_api_base,
|
||||
)
|
||||
if not memory:
|
||||
memory_key = "chat_history"
|
||||
memory = ConversationTokenBufferMemory(
|
||||
memory_key=memory_key,
|
||||
return_messages=True,
|
||||
output_key="output",
|
||||
llm=llm,
|
||||
max_token_limit=max_token_limit,
|
||||
)
|
||||
else:
|
||||
memory_key = memory.memory_key # type: ignore
|
||||
|
||||
_system_message = system_message or _get_default_system_message()
|
||||
prompt = OpenAIFunctionsAgent.create_prompt(
|
||||
system_message=_system_message, # type: ignore
|
||||
extra_prompt_messages=[MessagesPlaceholder(variable_name=memory_key)],
|
||||
)
|
||||
agent = OpenAIFunctionsAgent(
|
||||
llm=llm, tools=tools, prompt=prompt # type: ignore
|
||||
)
|
||||
return AgentExecutor(
|
||||
agent=agent,
|
||||
tools=tools, # type: ignore
|
||||
memory=memory,
|
||||
verbose=True,
|
||||
return_intermediate_steps=True,
|
||||
)
|
||||
0
src/backend/langflow/components/agents/__init__.py
Normal file
0
src/backend/langflow/components/agents/__init__.py
Normal file
|
|
@ -3,6 +3,10 @@ from typing import Any, Union
|
|||
from langflow.interface.utils import extract_input_variables_from_prompt
|
||||
|
||||
|
||||
class UnbuiltObject:
|
||||
pass
|
||||
|
||||
|
||||
def validate_prompt(prompt: str):
|
||||
"""Validate prompt."""
|
||||
if extract_input_variables_from_prompt(prompt):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import ast
|
||||
from langflow.graph.utils import UnbuiltObject
|
||||
from langflow.interface.initialize import loading
|
||||
from langflow.interface.listing import lazy_load_dict
|
||||
from langflow.utils.constants import DIRECT_TYPES
|
||||
|
|
@ -22,7 +23,7 @@ class Vertex:
|
|||
self.edges: List["Edge"] = []
|
||||
self.base_type: Optional[str] = base_type
|
||||
self._parse_data()
|
||||
self._built_object = None
|
||||
self._built_object = UnbuiltObject()
|
||||
self._built = False
|
||||
self.artifacts: Dict[str, Any] = {}
|
||||
|
||||
|
|
@ -245,8 +246,14 @@ class Vertex:
|
|||
"""
|
||||
Checks if the built object is None and raises a ValueError if so.
|
||||
"""
|
||||
if self._built_object is None:
|
||||
raise ValueError(f"Node type {self.vertex_type} not found")
|
||||
if isinstance(self._built_object, UnbuiltObject):
|
||||
raise ValueError(f"{self.vertex_type}: {self._built_object_repr()}")
|
||||
elif self._built_object is None:
|
||||
message = f"{self.vertex_type} returned None."
|
||||
if self.base_type == "custom_components":
|
||||
message += " Make sure your build method returns a component."
|
||||
|
||||
raise ValueError(message)
|
||||
|
||||
def build(self, force: bool = False) -> Any:
|
||||
if not self._built or force:
|
||||
|
|
|
|||
|
|
@ -226,7 +226,12 @@ class PromptVertex(Vertex):
|
|||
# so the prompt format doesn't break
|
||||
artifacts.pop("handle_keys", None)
|
||||
try:
|
||||
template = self._built_object.template
|
||||
if not hasattr(self._built_object, "template") and hasattr(
|
||||
self._built_object, "prompt"
|
||||
):
|
||||
template = self._built_object.prompt.template
|
||||
else:
|
||||
template = self._built_object.template
|
||||
for key, value in artifacts.items():
|
||||
if value:
|
||||
replace_key = "{" + key + "}"
|
||||
|
|
|
|||
|
|
@ -8,10 +8,13 @@ from langchain.text_splitter import TextSplitter
|
|||
from langchain.tools import Tool
|
||||
from langchain.vectorstores.base import VectorStore
|
||||
from langchain.schema import BaseOutputParser
|
||||
|
||||
from langchain.schema.memory import BaseMemory
|
||||
from langchain.memory.chat_memory import BaseChatMemory
|
||||
from langchain.agents.agent import AgentExecutor
|
||||
|
||||
LANGCHAIN_BASE_TYPES = {
|
||||
"Chain": Chain,
|
||||
"AgentExecutor": AgentExecutor,
|
||||
"Tool": Tool,
|
||||
"BaseLLM": BaseLLM,
|
||||
"PromptTemplate": PromptTemplate,
|
||||
|
|
@ -22,6 +25,8 @@ LANGCHAIN_BASE_TYPES = {
|
|||
"Embeddings": Embeddings,
|
||||
"BaseRetriever": BaseRetriever,
|
||||
"BaseOutputParser": BaseOutputParser,
|
||||
"BaseMemory": BaseMemory,
|
||||
"BaseChatMemory": BaseChatMemory,
|
||||
}
|
||||
|
||||
# Langchain base types plus Python base types
|
||||
|
|
|
|||
|
|
@ -51,8 +51,8 @@ class CustomComponent(Component, extra=Extra.allow):
|
|||
|
||||
for type_hint in TYPE_HINT_LIST:
|
||||
if reader._is_type_hint_used_in_args(
|
||||
"Optional", code
|
||||
) and not reader._is_type_hint_imported("Optional", code):
|
||||
type_hint, code
|
||||
) and not reader._is_type_hint_imported(type_hint, code):
|
||||
error_detail = {
|
||||
"error": "Type hint Error",
|
||||
"traceback": f"Type hint '{type_hint}' is used but not imported in the code.",
|
||||
|
|
|
|||
|
|
@ -51,7 +51,9 @@ def handle_partial_variables(prompt, format_kwargs: Dict):
|
|||
}
|
||||
# Remove handle_keys otherwise LangChain raises an error
|
||||
partial_variables.pop("handle_keys", None)
|
||||
return prompt.partial(**partial_variables)
|
||||
if partial_variables and hasattr(prompt, "partial"):
|
||||
return prompt.partial(**partial_variables)
|
||||
return prompt
|
||||
|
||||
|
||||
def handle_variable(params: Dict, input_variable: str, format_kwargs: Dict):
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from langflow.api.v1.callback import (
|
|||
)
|
||||
from langflow.processing.process import fix_memory_inputs, format_actions
|
||||
from langflow.utils.logger import logger
|
||||
from langchain.agents.agent import AgentExecutor
|
||||
|
||||
|
||||
async def get_result_and_steps(langchain_object, inputs: Union[dict, str], **kwargs):
|
||||
|
|
@ -20,7 +21,8 @@ async def get_result_and_steps(langchain_object, inputs: Union[dict, str], **kwa
|
|||
# to display intermediate steps
|
||||
langchain_object.return_intermediate_steps = True
|
||||
try:
|
||||
fix_memory_inputs(langchain_object)
|
||||
if not isinstance(langchain_object, AgentExecutor):
|
||||
fix_memory_inputs(langchain_object)
|
||||
except Exception as exc:
|
||||
logger.error(f"Error fixing memory inputs: {exc}")
|
||||
|
||||
|
|
|
|||
|
|
@ -187,12 +187,17 @@ class Settings(BaseSettings):
|
|||
value = json.loads(str(value))
|
||||
if isinstance(value, list):
|
||||
for item in value:
|
||||
if isinstance(item, Path):
|
||||
item = str(item)
|
||||
if item not in getattr(self, key):
|
||||
getattr(self, key).append(item)
|
||||
logger.debug(f"Extended {key}")
|
||||
else:
|
||||
getattr(self, key).append(value)
|
||||
logger.debug(f"Appended {key}")
|
||||
if isinstance(value, Path):
|
||||
value = str(value)
|
||||
if value not in getattr(self, key):
|
||||
getattr(self, key).append(value)
|
||||
logger.debug(f"Appended {key}")
|
||||
|
||||
else:
|
||||
setattr(self, key, value)
|
||||
|
|
|
|||
774
src/frontend/package-lock.json
generated
774
src/frontend/package-lock.json
generated
|
|
@ -707,51 +707,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz",
|
||||
"integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww=="
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz",
|
||||
"integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz",
|
||||
"integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz",
|
||||
|
|
@ -767,276 +722,6 @@
|
|||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz",
|
||||
"integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz",
|
||||
"integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz",
|
||||
"integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz",
|
||||
"integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz",
|
||||
"integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz",
|
||||
"integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz",
|
||||
"integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz",
|
||||
"integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz",
|
||||
"integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz",
|
||||
"integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz",
|
||||
"integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.17.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz",
|
||||
"integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/core": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.4.1.tgz",
|
||||
|
|
@ -2904,150 +2589,6 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-darwin-x64": {
|
||||
"version": "1.3.74",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.74.tgz",
|
||||
"integrity": "sha512-KKEGE1wXneYXe15fWDRM8/oekd/Q4yAuccA0vWY/7i6nOSPqWYcSDR0nRtR030ltDxWt0rk/eCTmNkrOWrKs3A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm-gnueabihf": {
|
||||
"version": "1.3.74",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.74.tgz",
|
||||
"integrity": "sha512-HehH5DR6r/5fIVu7tu8ZqgrHkhSCQNewf1ztFQJgcmaQWn+H4AJERBjwkjosqh4TvUJucZv8vyRTvrFeBXaCSA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-gnu": {
|
||||
"version": "1.3.74",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.74.tgz",
|
||||
"integrity": "sha512-+xkbCRz/wczgdknoV4NwYxbRI2dD7x/qkIFcVM2buzLCq8oWLweuV8+aL4pRqu0qDh7ZSb1jcaVTUIsySCJznA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-musl": {
|
||||
"version": "1.3.74",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.74.tgz",
|
||||
"integrity": "sha512-maKFZSCD3tQznzPV7T3V+TtiWZFEFM8YrnSS5fQNNb+K9J65sL+170uTb3M7H4cFkG+9Sm5k5yCrCIutlvV48g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-gnu": {
|
||||
"version": "1.3.74",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.74.tgz",
|
||||
"integrity": "sha512-LEXpcShF6DLTWJSiBhMSYZkLQ27UvaQ24fCFhoIV/R3dhYaUpHmIyLPPBNC82T03lB3ONUFVwrRw6fxDJ/f00A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-musl": {
|
||||
"version": "1.3.74",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.74.tgz",
|
||||
"integrity": "sha512-sxsFctbFMZEFmDE7CmYljG0dMumH8XBTwwtGr8s6z0fYAzXBGNq2AFPcmEh2np9rPWkt7pE1m0ByESD+dMkbxQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-arm64-msvc": {
|
||||
"version": "1.3.74",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.74.tgz",
|
||||
"integrity": "sha512-F7hY9/BjFCozA4YPFYFH5FGCyWwa44vIXHqG66F5cDwXDGFn8ZtBsYIsiPfUYcx0AeAo1ojnVWKPxokZhYNYqA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-ia32-msvc": {
|
||||
"version": "1.3.74",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.74.tgz",
|
||||
"integrity": "sha512-qBAsiD1AlIdqED6wy3UNRHyAys9pWMUidX0LJ6mj24r/vfrzzTBAUrLJe5m7bzE+F1Rgi001avYJeEW1DLEJ+Q==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-x64-msvc": {
|
||||
"version": "1.3.74",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.74.tgz",
|
||||
"integrity": "sha512-S3YAvvLprTnPRwQuy9Dkwubb5SRLpVK3JJsqYDbGfgj8PGQyKHZcVJ5X3nfFsoWLy3j9B/3Os2nawprRSzeC5A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@szmarczak/http-timer": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
|
||||
|
|
@ -10530,51 +10071,6 @@
|
|||
"vite": "^2.6.0 || 3 || 4"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/android-arm": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.19.tgz",
|
||||
"integrity": "sha512-1uOoDurJYh5MNqPqpj3l/TQCI1V25BXgChEldCB7D6iryBYqYKrbZIhYO5AI9fulf66sM8UJpc3UcCly2Tv28w==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.19.tgz",
|
||||
"integrity": "sha512-4+jkUFQxZkQfQOOxfGVZB38YUWHMJX2ihZwF+2nh8m7bHdWXpixiurgGRN3c/KMSwlltbYI0/i929jwBRMFzbA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/android-x64": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.19.tgz",
|
||||
"integrity": "sha512-ae5sHYiP/Ogj2YNrLZbWkBmyHIDOhPgpkGvFnke7XFGQldBDWvc/AyYwSLpNuKw9UNkgnLlB/jPpnBmlF3G9Bg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.19.tgz",
|
||||
|
|
@ -10590,276 +10086,6 @@
|
|||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.19.tgz",
|
||||
"integrity": "sha512-m6JdvXJQt0thNLIcWOeG079h2ivhYH4B5sVCgqb/B29zTcFd7EE8/J1nIUHhdtwGeItdUeqKaqqb4towwxvglQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.19.tgz",
|
||||
"integrity": "sha512-G0p4EFMPZhGn/xVNspUyMQbORH3nlKTV0bFNHPIwLraBuAkTeMyxNviTe0ZXUbIXQrR1lrwniFjNFU4s+x7veQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.19.tgz",
|
||||
"integrity": "sha512-hBxgRlG42+W+j/1/cvlnSa+3+OBKeDCyO7OG2ICya1YJaSCYfSpuG30KfOnQHI7Ytgu4bRqCgrYXxQEzy0zM5Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.19.tgz",
|
||||
"integrity": "sha512-qtWyoQskfJlb9MD45mvzCEKeO4uCnDZ7lPFeNqbfaaJHqBiH9qA5Vu2EuckqYZuFMJWy1l4dxTf9NOulCVfUjg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.19.tgz",
|
||||
"integrity": "sha512-X8g33tczY0GsJq3lhyBrjnFtaKjWVpp1gMq5IlF9BQJ3TUfSK74nQnz9mRIEejmcV+OIYn6bkOJeUaU1Knrljg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.19.tgz",
|
||||
"integrity": "sha512-SAkRWJgb+KN+gOhmbiE6/wu23D6HRcGQi15cB13IVtBZZgXxygTV5GJlUAKLQ5Gcx0gtlmt+XIxEmSqA6sZTOw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.19.tgz",
|
||||
"integrity": "sha512-YLAslaO8NsB9UOxBchos82AOMRDbIAWChwDKfjlGrHSzS3v1kxce7dGlSTsrb0PJwo1KYccypN3VNjQVLtz7LA==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.19.tgz",
|
||||
"integrity": "sha512-vSYFtlYds/oTI8aflEP65xo3MXChMwBOG1eWPGGKs/ev9zkTeXVvciU+nifq8J1JYMz+eQ4J9JDN0O2RKF8+1Q==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.19.tgz",
|
||||
"integrity": "sha512-tgG41lRVwlzqO9tv9l7aXYVw35BxKXLtPam1qALScwSqPivI8hjkZLNH0deaaSCYCFT9cBIdB+hUjWFlFFLL9A==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.19.tgz",
|
||||
"integrity": "sha512-EgBZFLoN1S5RuB4cCJI31pBPsjE1nZ+3+fHRjguq9Ibrzo29bOLSBcH1KZJvRNh5qtd+fcYIGiIUia8Jw5r1lQ==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.19.tgz",
|
||||
"integrity": "sha512-q1V1rtHRojAzjSigZEqrcLkpfh5K09ShCoIsdTakozVBnM5rgV58PLFticqDp5UJ9uE0HScov9QNbbl8HBo6QQ==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.19.tgz",
|
||||
"integrity": "sha512-D0IiYjpZRXxGZLQfsydeAD7ZWqdGyFLBj5f2UshJpy09WPs3qizDCsEr8zyzcym6Woj/UI9ZzMIXwvoXVtyt0A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.19.tgz",
|
||||
"integrity": "sha512-3tt3SOS8L3D54R8oER41UdDshlBIAjYhdWRPiZCTZ1E41+shIZBpTjaW5UaN/jD1ENE/Ok5lkeqhoNMbxstyxw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.19.tgz",
|
||||
"integrity": "sha512-MxbhcuAYQPlfln1EMc4T26OUoeg/YQc6wNoEV8xvktDKZhLtBxjkoeESSo9BbPaGKhAPzusXYj5n8n5A8iZSrA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.19.tgz",
|
||||
"integrity": "sha512-m0/UOq1wj25JpWqOJxoWBRM9VWc3c32xiNzd+ERlYstUZ6uwx5SZsQUtkiFHaYmcaoj+f6+Tfcl7atuAz3idwQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.19.tgz",
|
||||
"integrity": "sha512-L4vb6pcoB1cEcXUHU6EPnUhUc4+/tcz4OqlXTWPcSQWxegfmcOprhmIleKKwmMNQVc4wrx/+jB7tGkjjDmiupg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.19.tgz",
|
||||
"integrity": "sha512-rQng7LXSKdrDlNDb7/v0fujob6X0GAazoK/IPd9C3oShr642ri8uIBkgM37/l8B3Rd5sBQcqUXoDdEy75XC/jg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.19.tgz",
|
||||
"integrity": "sha512-z69jhyG20Gq4QL5JKPLqUT+eREuqnDAFItLbza4JCmpvUnIlY73YNjd5djlO7kBiiZnvTnJuAbOjIoZIOa1GjA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/vite/node_modules/esbuild": {
|
||||
"version": "0.18.19",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.19.tgz",
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import ErrorAlert from "./alerts/error";
|
|||
import NoticeAlert from "./alerts/notice";
|
||||
import SuccessAlert from "./alerts/success";
|
||||
import CrashErrorComponent from "./components/CrashErrorComponent";
|
||||
import Header from "./components/headerComponent";
|
||||
import LoadingComponent from "./components/loadingComponent";
|
||||
import { alertContext } from "./contexts/alertContext";
|
||||
import { locationContext } from "./contexts/locationContext";
|
||||
import { TabsContext } from "./contexts/tabsContext";
|
||||
|
|
@ -25,6 +25,7 @@ export default function App() {
|
|||
setIsStackedOpen(true);
|
||||
}, [location.pathname, setCurrent, setIsStackedOpen, setShowSideBar]);
|
||||
const { hardReset } = useContext(TabsContext);
|
||||
|
||||
const {
|
||||
errorData,
|
||||
errorOpen,
|
||||
|
|
@ -35,6 +36,7 @@ export default function App() {
|
|||
successData,
|
||||
successOpen,
|
||||
setSuccessOpen,
|
||||
loading,
|
||||
} = useContext(alertContext);
|
||||
|
||||
// Initialize state variable for the list of alerts
|
||||
|
|
@ -46,10 +48,6 @@ export default function App() {
|
|||
}>
|
||||
>([]);
|
||||
|
||||
const isLoginPage = location.pathname.includes("login");
|
||||
const isAdminPage = location.pathname.includes("admin");
|
||||
const isSignUpPage = location.pathname.includes("signup");
|
||||
|
||||
// Use effect hook to update alertsList when a new alert is added
|
||||
useEffect(() => {
|
||||
// If there is an error alert open with data, add it to the alertsList
|
||||
|
|
@ -137,8 +135,15 @@ export default function App() {
|
|||
}}
|
||||
FallbackComponent={CrashErrorComponent}
|
||||
>
|
||||
{!isLoginPage && !isSignUpPage && <Header />}
|
||||
<Router />
|
||||
{loading ? (
|
||||
<div className="loading-page-panel">
|
||||
<LoadingComponent remSize={50} />
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<Router />
|
||||
</>
|
||||
)}
|
||||
</ErrorBoundary>
|
||||
<div></div>
|
||||
<div className="app-div" style={{ zIndex: 999 }}>
|
||||
|
|
|
|||
|
|
@ -32,6 +32,13 @@ export default function AccordionComponent({
|
|||
value === "" ? setValue(keyValue!) : setValue("");
|
||||
}
|
||||
|
||||
const handleKeyDown = (event) => {
|
||||
if (event.key === "Backspace") {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Accordion
|
||||
|
|
@ -39,6 +46,7 @@ export default function AccordionComponent({
|
|||
className="w-full"
|
||||
value={value}
|
||||
onValueChange={setValue}
|
||||
onKeyDown={handleKeyDown}
|
||||
>
|
||||
<AccordionItem value={keyValue!} className="border-b">
|
||||
<AccordionTrigger
|
||||
|
|
|
|||
|
|
@ -34,21 +34,34 @@ export const EditFlowSettings: React.FC<InputProps> = ({
|
|||
} else {
|
||||
setIsMaxLength(false);
|
||||
}
|
||||
if (invalidName !== undefined) {
|
||||
if (!nameLists.current.includes(value)) {
|
||||
setInvalidName(false);
|
||||
} else {
|
||||
setInvalidName(true);
|
||||
}
|
||||
}
|
||||
if (!nameLists.current.includes(value)) {
|
||||
setInvalidName!(false);
|
||||
} else {
|
||||
setInvalidName!(true);
|
||||
}
|
||||
setName(value);
|
||||
setCurrentName(value);
|
||||
};
|
||||
|
||||
const [desc, setDesc] = useState(
|
||||
flows.find((flow) => flow.id === tabId)?.description
|
||||
);
|
||||
const [currentName, setCurrentName] = useState(name);
|
||||
|
||||
const [currentDescription, setCurrentDescription] = useState(description);
|
||||
|
||||
useEffect(() => {
|
||||
setCurrentName(name);
|
||||
setCurrentDescription(description);
|
||||
}, [name, description]);
|
||||
|
||||
const handleDescriptionChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
|
||||
flows.find((flow) => flow.id === tabId)!.description = event.target.value;
|
||||
setDesc(flows.find((flow) => flow.id === tabId)?.description);
|
||||
flows.find((f) => f.id === tabId).description = event.target.value;
|
||||
setCurrentDescription(flows.find((f) => f.id === tabId).description);
|
||||
setDescription(event.target.value);
|
||||
};
|
||||
|
||||
|
|
@ -69,7 +82,7 @@ export const EditFlowSettings: React.FC<InputProps> = ({
|
|||
onChange={handleNameChange}
|
||||
type="text"
|
||||
name="name"
|
||||
value={name ?? ""}
|
||||
value={currentName ?? ""}
|
||||
placeholder="File name"
|
||||
id="name"
|
||||
maxLength={maxLength}
|
||||
|
|
@ -84,7 +97,7 @@ export const EditFlowSettings: React.FC<InputProps> = ({
|
|||
name="description"
|
||||
id="description"
|
||||
onChange={handleDescriptionChange}
|
||||
value={desc}
|
||||
value={currentDescription}
|
||||
placeholder="Flow description"
|
||||
className="mt-2 max-h-[100px] font-normal"
|
||||
rows={3}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { useEffect } from "react";
|
||||
import { FloatComponentType } from "../../types/components";
|
||||
import { handleKeyDown } from "../../utils/reactflowUtils";
|
||||
import { Input } from "../ui/input";
|
||||
|
||||
export default function FloatComponent({
|
||||
|
|
@ -43,6 +44,9 @@ export default function FloatComponent({
|
|||
onChange={(event) => {
|
||||
onChange(event.target.value);
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
handleKeyDown(e, value, "0");
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import * as Form from "@radix-ui/react-form";
|
||||
import { useEffect, useState } from "react";
|
||||
import { InputComponentType } from "../../types/components";
|
||||
import { handleKeyDown } from "../../utils/reactflowUtils";
|
||||
import { classNames } from "../../utils/utils";
|
||||
import { Input } from "../ui/input";
|
||||
|
||||
|
|
@ -45,6 +46,9 @@ export default function InputComponent({
|
|||
onChange={(e) => {
|
||||
onChange(e.target.value);
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
handleKeyDown(e, value, "");
|
||||
}}
|
||||
/>
|
||||
</Form.Control>
|
||||
) : (
|
||||
|
|
@ -65,6 +69,9 @@ export default function InputComponent({
|
|||
onChange={(e) => {
|
||||
onChange(e.target.value);
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
handleKeyDown(e, value, "");
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{password && (
|
||||
|
|
|
|||
|
|
@ -39,6 +39,12 @@ export default function InputListComponent({
|
|||
newInputList[idx] = event.target.value;
|
||||
onChange(newInputList);
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.ctrlKey && e.key === "Backspace") {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{idx === value.length - 1 ? (
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { useEffect } from "react";
|
||||
import { FloatComponentType } from "../../types/components";
|
||||
import { handleKeyDown } from "../../utils/reactflowUtils";
|
||||
import { Input } from "../ui/input";
|
||||
|
||||
export default function IntComponent({
|
||||
|
|
@ -37,6 +38,7 @@ export default function IntComponent({
|
|||
) {
|
||||
event.preventDefault();
|
||||
}
|
||||
handleKeyDown(event, value, "0");
|
||||
}}
|
||||
type="number"
|
||||
step="1"
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ export const INVALID_CHARACTERS = [
|
|||
*/
|
||||
|
||||
export const regexHighlight = /\{([^}]+)\}/g;
|
||||
export const specialCharsRegex = /[!@#$%^&*()\-_=+[\]{}|;:'",.<>/?\\`´]/;
|
||||
|
||||
export const programmingLanguages: languageMap = {
|
||||
javascript: ".js",
|
||||
|
|
@ -508,6 +509,9 @@ export const URL_EXCLUDED_FROM_ERROR_RETRIES = [
|
|||
"/api/v1/custom_component",
|
||||
"/api/v1/validate/prompt",
|
||||
];
|
||||
|
||||
export const skipNodeUpdate = ["CustomComponent"];
|
||||
|
||||
export const CONTROL_INPUT_STATE = {
|
||||
password: "",
|
||||
cnfPassword: "",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import _ from "lodash";
|
|||
const initialValue: alertContextType = {
|
||||
errorData: { title: "", list: [] },
|
||||
setErrorData: () => {},
|
||||
loading: true,
|
||||
setLoading: () => {},
|
||||
errorOpen: false,
|
||||
setErrorOpen: () => {},
|
||||
noticeData: { title: "", link: "" },
|
||||
|
|
@ -34,6 +36,7 @@ export function AlertProvider({ children }: { children: ReactNode }) {
|
|||
list?: Array<string>;
|
||||
}>({ title: "", list: [] });
|
||||
const [errorOpen, setErrorOpen] = useState(false);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [noticeData, setNoticeDataState] = useState<{
|
||||
title: string;
|
||||
link?: string;
|
||||
|
|
@ -120,6 +123,8 @@ export function AlertProvider({ children }: { children: ReactNode }) {
|
|||
removeFromNotificationList,
|
||||
clearNotificationList,
|
||||
notificationList,
|
||||
loading,
|
||||
setLoading,
|
||||
pushNotificationList,
|
||||
setNotificationCenter,
|
||||
notificationCenter,
|
||||
|
|
|
|||
|
|
@ -16,17 +16,17 @@ export default function ContextWrapper({ children }: { children: ReactNode }) {
|
|||
<TooltipProvider>
|
||||
<ReactFlowProvider>
|
||||
<DarkProvider>
|
||||
<TypesProvider>
|
||||
<LocationProvider>
|
||||
<AlertProvider>
|
||||
<AlertProvider>
|
||||
<TypesProvider>
|
||||
<LocationProvider>
|
||||
<SSEProvider>
|
||||
<TabsProvider>
|
||||
<UndoRedoProvider>{children}</UndoRedoProvider>
|
||||
</TabsProvider>
|
||||
</SSEProvider>
|
||||
</AlertProvider>
|
||||
</LocationProvider>
|
||||
</TypesProvider>
|
||||
</LocationProvider>
|
||||
</TypesProvider>
|
||||
</AlertProvider>
|
||||
</DarkProvider>
|
||||
</ReactFlowProvider>
|
||||
</TooltipProvider>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
} from "react";
|
||||
import { Edge, Node, ReactFlowJsonObject, addEdge } from "reactflow";
|
||||
import ShortUniqueId from "short-unique-id";
|
||||
import { skipNodeUpdate } from "../constants/constants";
|
||||
import {
|
||||
deleteFlowFromDatabase,
|
||||
downloadFlowsFromDatabase,
|
||||
|
|
@ -167,6 +168,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
|||
function processFlowNodes(flow: FlowType) {
|
||||
if (!flow.data || !flow.data.nodes) return;
|
||||
flow.data.nodes.forEach((node: NodeType) => {
|
||||
if (skipNodeUpdate.includes(node.data.type)) return;
|
||||
const template = templates[node.data.type];
|
||||
if (!template) {
|
||||
setErrorData({ title: `Unknown node type: ${node.data.type}` });
|
||||
|
|
@ -512,6 +514,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
|||
|
||||
const updateNodes = (nodes: Node[], edges: Edge[]) => {
|
||||
nodes.forEach((node) => {
|
||||
if (skipNodeUpdate.includes(node.data.type)) return;
|
||||
const template = templates[node.data.type];
|
||||
if (!template) {
|
||||
setErrorData({ title: `Unknown node type: ${node.data.type}` });
|
||||
|
|
|
|||
|
|
@ -1,8 +1,15 @@
|
|||
import { createContext, ReactNode, useEffect, useState } from "react";
|
||||
import {
|
||||
createContext,
|
||||
ReactNode,
|
||||
useContext,
|
||||
useEffect,
|
||||
useState,
|
||||
} from "react";
|
||||
import { Node, ReactFlowInstance } from "reactflow";
|
||||
import { getAll } from "../controllers/API";
|
||||
import { APIKindType } from "../types/api";
|
||||
import { typesContextType } from "../types/typesContext";
|
||||
import { alertContext } from "./alertContext";
|
||||
|
||||
//context to share types adn functions from nodes to flow
|
||||
|
||||
|
|
@ -26,6 +33,7 @@ export function TypesProvider({ children }: { children: ReactNode }) {
|
|||
useState<ReactFlowInstance | null>(null);
|
||||
const [templates, setTemplates] = useState({});
|
||||
const [data, setData] = useState({});
|
||||
const { setLoading } = useContext(alertContext);
|
||||
|
||||
useEffect(() => {
|
||||
let delay = 1000; // Start delay of 1 second
|
||||
|
|
@ -41,6 +49,7 @@ export function TypesProvider({ children }: { children: ReactNode }) {
|
|||
const result = await getAll();
|
||||
// Make sure to only update the state if the component is still mounted.
|
||||
if (isMounted) {
|
||||
setLoading(false);
|
||||
setData(result.data);
|
||||
setTemplates(
|
||||
Object.keys(result.data).reduce((acc, curr) => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ReactNode, forwardRef, useContext, useState } from "react";
|
||||
import { ReactNode, forwardRef, useContext, useEffect, useState } from "react";
|
||||
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
|
||||
import IconComponent from "../../components/genericIconComponent";
|
||||
import { Button } from "../../components/ui/button";
|
||||
|
|
@ -10,17 +10,17 @@ import BaseModal from "../baseModal";
|
|||
|
||||
const ExportModal = forwardRef(
|
||||
(props: { children: ReactNode }, ref): JSX.Element => {
|
||||
const { flows, tabId, updateFlow, downloadFlow, saveFlow } =
|
||||
useContext(TabsContext);
|
||||
const { flows, tabId, updateFlow, downloadFlow } = useContext(TabsContext);
|
||||
const [checked, setChecked] = useState(false);
|
||||
const [name, setName] = useState(
|
||||
flows.find((flow) => flow.id === tabId)?.name
|
||||
);
|
||||
const [invalidName, setInvalidName] = useState(false);
|
||||
const [description, setDescription] = useState(
|
||||
flows.find((flow) => flow.id === tabId)?.description
|
||||
);
|
||||
const flow = flows.find((f) => f.id === tabId);
|
||||
useEffect(() => {
|
||||
setName(flow.name);
|
||||
setDescription(flow.description);
|
||||
}, [flow.name, flow.description]);
|
||||
const [name, setName] = useState(flow.name);
|
||||
const [description, setDescription] = useState(flow.description);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<BaseModal size="smaller" open={open} setOpen={setOpen}>
|
||||
<BaseModal.Trigger>{props.children}</BaseModal.Trigger>
|
||||
|
|
@ -34,19 +34,18 @@ const ExportModal = forwardRef(
|
|||
</BaseModal.Header>
|
||||
<BaseModal.Content>
|
||||
<EditFlowSettings
|
||||
invalidName={invalidName}
|
||||
setInvalidName={setInvalidName}
|
||||
name={name!}
|
||||
description={description!}
|
||||
name={name}
|
||||
description={description}
|
||||
flows={flows}
|
||||
tabId={tabId}
|
||||
setName={setName}
|
||||
setDescription={setDescription}
|
||||
updateFlow={updateFlow}
|
||||
/>
|
||||
<div className="mt-3 flex items-center space-x-2">
|
||||
<Checkbox
|
||||
id="terms"
|
||||
onCheckedChange={(event: boolean): void => {
|
||||
onCheckedChange={(event: boolean) => {
|
||||
setChecked(event);
|
||||
}}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useContext, useRef, useState } from "react";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
|
||||
import IconComponent from "../../components/genericIconComponent";
|
||||
import { Button } from "../../components/ui/button";
|
||||
|
|
@ -12,16 +12,15 @@ export default function FlowSettingsModal({
|
|||
open,
|
||||
setOpen,
|
||||
}: FlowSettingsPropsType): JSX.Element {
|
||||
const { setErrorData, setSuccessData } = useContext(alertContext);
|
||||
const ref = useRef();
|
||||
const { setSuccessData } = useContext(alertContext);
|
||||
const { flows, tabId, updateFlow, saveFlow } = useContext(TabsContext);
|
||||
const maxLength = 50;
|
||||
const [name, setName] = useState(
|
||||
flows.find((flow) => flow.id === tabId)!.name
|
||||
);
|
||||
const [description, setDescription] = useState(
|
||||
flows.find((flow) => flow.id === tabId)!.description
|
||||
);
|
||||
const flow = flows.find((f) => f.id === tabId);
|
||||
useEffect(() => {
|
||||
setName(flow.name);
|
||||
setDescription(flow.description);
|
||||
}, [flow.name, flow.description]);
|
||||
const [name, setName] = useState(flow.name);
|
||||
const [description, setDescription] = useState(flow.description);
|
||||
const [invalidName, setInvalidName] = useState(false);
|
||||
|
||||
function handleClick(): void {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import { TypeModal } from "../../constants/enums";
|
|||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { postValidatePrompt } from "../../controllers/API";
|
||||
import { genericModalPropsType } from "../../types/components";
|
||||
import { handleKeyDown } from "../../utils/reactflowUtils";
|
||||
import {
|
||||
classNames,
|
||||
getRandomKeyByssmm,
|
||||
|
|
@ -203,6 +204,9 @@ export default function GenericModal({
|
|||
checkVariables(event.target.value);
|
||||
}}
|
||||
placeholder="Type message here."
|
||||
onKeyDown={(e) => {
|
||||
handleKeyDown(e, inputValue, "");
|
||||
}}
|
||||
/>
|
||||
) : type === TypeModal.PROMPT && !isEdit ? (
|
||||
<TextAreaContentView />
|
||||
|
|
@ -216,6 +220,9 @@ export default function GenericModal({
|
|||
setInputValue(event.target.value);
|
||||
}}
|
||||
placeholder="Type message here."
|
||||
onKeyDown={(e) => {
|
||||
handleKeyDown(e, value, "");
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { TabsContext } from "../../contexts/tabsContext";
|
|||
import { useNavigate } from "react-router-dom";
|
||||
import { CardComponent } from "../../components/cardComponent";
|
||||
import IconComponent from "../../components/genericIconComponent";
|
||||
import Header from "../../components/headerComponent";
|
||||
import { getExamples } from "../../controllers/API";
|
||||
import { FlowType } from "../../types/flow";
|
||||
export default function CommunityPage(): JSX.Element {
|
||||
|
|
@ -42,61 +43,65 @@ export default function CommunityPage(): JSX.Element {
|
|||
handleExamples();
|
||||
}, []);
|
||||
return (
|
||||
<div className="community-page-arrangement">
|
||||
<div className="community-page-nav-arrangement">
|
||||
<span className="community-page-nav-title">
|
||||
<IconComponent name="Users2" className="w-6" />
|
||||
Community Examples
|
||||
<>
|
||||
<Header />
|
||||
|
||||
<div className="community-page-arrangement">
|
||||
<div className="community-page-nav-arrangement">
|
||||
<span className="community-page-nav-title">
|
||||
<IconComponent name="Users2" className="w-6" />
|
||||
Community Examples
|
||||
</span>
|
||||
<div className="community-page-nav-button">
|
||||
<a
|
||||
href="https://github.com/logspace-ai/langflow_examples"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button variant="primary">
|
||||
<IconComponent
|
||||
name="GithubIcon"
|
||||
className="main-page-nav-button"
|
||||
/>
|
||||
Add Your Example
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<span className="community-page-description-text">
|
||||
Discover and learn from shared examples by the Langflow community. We
|
||||
welcome new example contributions that can help our community explore
|
||||
new and powerful features.
|
||||
</span>
|
||||
<div className="community-page-nav-button">
|
||||
<a
|
||||
href="https://github.com/logspace-ai/langflow_examples"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button variant="primary">
|
||||
<IconComponent
|
||||
name="GithubIcon"
|
||||
className="main-page-nav-button"
|
||||
<div className="community-pages-flows-panel">
|
||||
{!loadingExamples &&
|
||||
examples.map((flow, idx) => (
|
||||
<CardComponent
|
||||
key={idx}
|
||||
flow={flow}
|
||||
id={flow.id}
|
||||
button={
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="whitespace-nowrap "
|
||||
onClick={() => {
|
||||
addFlow(flow, true).then((id) => {
|
||||
navigate("/flow/" + id);
|
||||
});
|
||||
}}
|
||||
>
|
||||
<IconComponent
|
||||
name="GitFork"
|
||||
className="main-page-nav-button"
|
||||
/>
|
||||
Fork Example
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
Add Your Example
|
||||
</Button>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<span className="community-page-description-text">
|
||||
Discover and learn from shared examples by the Langflow community. We
|
||||
welcome new example contributions that can help our community explore
|
||||
new and powerful features.
|
||||
</span>
|
||||
<div className="community-pages-flows-panel">
|
||||
{!loadingExamples &&
|
||||
examples.map((flow, idx) => (
|
||||
<CardComponent
|
||||
key={idx}
|
||||
flow={flow}
|
||||
id={flow.id}
|
||||
button={
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="whitespace-nowrap "
|
||||
onClick={() => {
|
||||
addFlow(flow, true).then((id) => {
|
||||
navigate("/flow/" + id);
|
||||
});
|
||||
}}
|
||||
>
|
||||
<IconComponent
|
||||
name="GitFork"
|
||||
className="main-page-nav-button"
|
||||
/>
|
||||
Fork Example
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,13 @@ const nodeTypes = {
|
|||
genericNode: GenericNode,
|
||||
};
|
||||
|
||||
export default function Page({ flow }: { flow: FlowType }): JSX.Element {
|
||||
export default function Page({
|
||||
flow,
|
||||
view,
|
||||
}: {
|
||||
flow: FlowType;
|
||||
view?: boolean;
|
||||
}): JSX.Element {
|
||||
let {
|
||||
updateFlow,
|
||||
uploadFlow,
|
||||
|
|
@ -371,7 +377,7 @@ export default function Page({ flow }: { flow: FlowType }): JSX.Element {
|
|||
|
||||
return (
|
||||
<div className="flex h-full overflow-hidden">
|
||||
<ExtraSidebar />
|
||||
{!view && <ExtraSidebar />}
|
||||
{/* Main area */}
|
||||
<main className="flex flex-1">
|
||||
{/* Primary column */}
|
||||
|
|
@ -412,14 +418,21 @@ export default function Page({ flow }: { flow: FlowType }): JSX.Element {
|
|||
className="theme-attribution"
|
||||
minZoom={0.01}
|
||||
maxZoom={8}
|
||||
zoomOnScroll={!view}
|
||||
zoomOnPinch={!view}
|
||||
panOnDrag={!view}
|
||||
>
|
||||
<Background className="" />
|
||||
<Controls
|
||||
className="bg-muted fill-foreground stroke-foreground text-primary
|
||||
{!view && (
|
||||
<Controls
|
||||
className="bg-muted fill-foreground stroke-foreground text-primary
|
||||
[&>button]:border-b-border hover:[&>button]:bg-border"
|
||||
></Controls>
|
||||
></Controls>
|
||||
)}
|
||||
</ReactFlow>
|
||||
<Chat flow={flow} reactFlowInstance={reactFlowInstance!} />
|
||||
{!view && (
|
||||
<Chat flow={flow} reactFlowInstance={reactFlowInstance!} />
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { useContext, useEffect, useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import Header from "../../components/headerComponent";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { getVersion } from "../../controllers/API";
|
||||
import Page from "./components/PageComponent";
|
||||
|
|
@ -22,20 +23,23 @@ export default function FlowPage(): JSX.Element {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<div className="flow-page-positioning">
|
||||
{flows.length > 0 &&
|
||||
tabId !== "" &&
|
||||
flows.findIndex((flow) => flow.id === tabId) !== -1 && (
|
||||
<Page flow={flows.find((flow) => flow.id === tabId)!} />
|
||||
)}
|
||||
<a
|
||||
target={"_blank"}
|
||||
href="https://logspace.ai/"
|
||||
className="logspace-page-icon"
|
||||
>
|
||||
{version && <div className="mt-1">⛓️ Langflow v{version}</div>}
|
||||
<div className={version ? "mt-2" : "mt-1"}>Created by Logspace</div>
|
||||
</a>
|
||||
</div>
|
||||
<>
|
||||
<Header />
|
||||
<div className="flow-page-positioning">
|
||||
{flows.length > 0 &&
|
||||
tabId !== "" &&
|
||||
flows.findIndex((flow) => flow.id === tabId) !== -1 && (
|
||||
<Page flow={flows.find((flow) => flow.id === tabId)!} />
|
||||
)}
|
||||
<a
|
||||
target={"_blank"}
|
||||
href="https://logspace.ai/"
|
||||
className="logspace-page-icon"
|
||||
>
|
||||
{version && <div className="mt-1">⛓️ Langflow v{version}</div>}
|
||||
<div className={version ? "mt-2" : "mt-1"}>Created by Logspace</div>
|
||||
</a>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { useContext, useEffect } from "react";
|
|||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { CardComponent } from "../../components/cardComponent";
|
||||
import IconComponent from "../../components/genericIconComponent";
|
||||
import Header from "../../components/headerComponent";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { USER_PROJECTS_HEADER } from "../../constants/constants";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
|
|
@ -17,74 +18,77 @@ export default function HomePage(): JSX.Element {
|
|||
|
||||
// Personal flows display
|
||||
return (
|
||||
<div className="main-page-panel">
|
||||
<div className="main-page-nav-arrangement">
|
||||
<span className="main-page-nav-title">
|
||||
<IconComponent name="Home" className="w-6" />
|
||||
{USER_PROJECTS_HEADER}
|
||||
<>
|
||||
<Header />
|
||||
<div className="main-page-panel">
|
||||
<div className="main-page-nav-arrangement">
|
||||
<span className="main-page-nav-title">
|
||||
<IconComponent name="Home" className="w-6" />
|
||||
{USER_PROJECTS_HEADER}
|
||||
</span>
|
||||
<div className="button-div-style">
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => {
|
||||
downloadFlows();
|
||||
}}
|
||||
>
|
||||
<IconComponent name="Download" className="main-page-nav-button" />
|
||||
Download Collection
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => {
|
||||
uploadFlows();
|
||||
}}
|
||||
>
|
||||
<IconComponent name="Upload" className="main-page-nav-button" />
|
||||
Upload Collection
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => {
|
||||
addFlow(null!, true).then((id) => {
|
||||
navigate("/flow/" + id);
|
||||
});
|
||||
}}
|
||||
>
|
||||
<IconComponent name="Plus" className="main-page-nav-button" />
|
||||
New Project
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<span className="main-page-description-text">
|
||||
Manage your personal projects. Download or upload your collection.
|
||||
</span>
|
||||
<div className="button-div-style">
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => {
|
||||
downloadFlows();
|
||||
}}
|
||||
>
|
||||
<IconComponent name="Download" className="main-page-nav-button" />
|
||||
Download Collection
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => {
|
||||
uploadFlows();
|
||||
}}
|
||||
>
|
||||
<IconComponent name="Upload" className="main-page-nav-button" />
|
||||
Upload Collection
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => {
|
||||
addFlow(null!, true).then((id) => {
|
||||
navigate("/flow/" + id);
|
||||
});
|
||||
}}
|
||||
>
|
||||
<IconComponent name="Plus" className="main-page-nav-button" />
|
||||
New Project
|
||||
</Button>
|
||||
<div className="main-page-flows-display">
|
||||
{flows.map((flow, idx) => (
|
||||
<CardComponent
|
||||
key={idx}
|
||||
flow={flow}
|
||||
id={flow.id}
|
||||
button={
|
||||
<Link to={"/flow/" + flow.id}>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="whitespace-nowrap "
|
||||
>
|
||||
<IconComponent
|
||||
name="ExternalLink"
|
||||
className="main-page-nav-button"
|
||||
/>
|
||||
Edit Flow
|
||||
</Button>
|
||||
</Link>
|
||||
}
|
||||
onDelete={() => {
|
||||
removeFlow(flow.id);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<span className="main-page-description-text">
|
||||
Manage your personal projects. Download or upload your collection.
|
||||
</span>
|
||||
<div className="main-page-flows-display">
|
||||
{flows.map((flow, idx) => (
|
||||
<CardComponent
|
||||
key={idx}
|
||||
flow={flow}
|
||||
id={flow.id}
|
||||
button={
|
||||
<Link to={"/flow/" + flow.id}>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="whitespace-nowrap "
|
||||
>
|
||||
<IconComponent
|
||||
name="ExternalLink"
|
||||
className="main-page-nav-button"
|
||||
/>
|
||||
Edit Flow
|
||||
</Button>
|
||||
</Link>
|
||||
}
|
||||
onDelete={() => {
|
||||
removeFlow(flow.id);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
33
src/frontend/src/pages/ViewPage/index.tsx
Normal file
33
src/frontend/src/pages/ViewPage/index.tsx
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import { useContext, useEffect, useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { TabsContext } from "../../contexts/tabsContext";
|
||||
import { getVersion } from "../../controllers/API";
|
||||
import Page from "../FlowPage/components/PageComponent";
|
||||
|
||||
export default function ViewPage() {
|
||||
const { flows, tabId, setTabId } = useContext(TabsContext);
|
||||
const { id } = useParams();
|
||||
|
||||
// Set flow tab id
|
||||
useEffect(() => {
|
||||
setTabId(id);
|
||||
}, [id]);
|
||||
|
||||
// Initialize state variable for the version
|
||||
const [version, setVersion] = useState("");
|
||||
useEffect(() => {
|
||||
getVersion().then((data) => {
|
||||
setVersion(data.version);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="flow-page-positioning">
|
||||
{flows.length > 0 &&
|
||||
tabId !== "" &&
|
||||
flows.findIndex((flow) => flow.id === tabId) !== -1 && (
|
||||
<Page view flow={flows.find((flow) => flow.id === tabId)} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import LoginAdminPage from "./pages/AdminPage/LoginPage";
|
|||
import CommunityPage from "./pages/CommunityPage";
|
||||
import FlowPage from "./pages/FlowPage";
|
||||
import HomePage from "./pages/MainPage";
|
||||
import ViewPage from "./pages/ViewPage";
|
||||
import DeleteAccountPage from "./pages/deleteAccountPage";
|
||||
import LoginPage from "./pages/loginPage";
|
||||
|
||||
|
|
@ -14,6 +15,7 @@ const Router = () => {
|
|||
<Route path="/community" element={<CommunityPage />} />
|
||||
<Route path="/flow/:id/">
|
||||
<Route path="" element={<FlowPage />} />
|
||||
<Route path="view" element={<ViewPage />} />
|
||||
</Route>
|
||||
<Route path="*" element={<HomePage />} />
|
||||
|
||||
|
|
|
|||
|
|
@ -192,6 +192,10 @@
|
|||
@apply flex w-full;
|
||||
}
|
||||
|
||||
.loading-page-panel {
|
||||
@apply h-full w-full flex justify-center items-center bg-muted;
|
||||
}
|
||||
|
||||
.main-page-panel {
|
||||
@apply flex-max-width h-full flex-col overflow-auto bg-muted px-16;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ export type alertContextType = {
|
|||
pushNotificationList: (Object: AlertItemType) => void;
|
||||
clearNotificationList: () => void;
|
||||
removeFromNotificationList: (index: string) => void;
|
||||
loading: boolean;
|
||||
setLoading: (newState: boolean) => void;
|
||||
};
|
||||
|
||||
export type darkContextType = {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import {
|
|||
ReactFlowInstance,
|
||||
ReactFlowJsonObject,
|
||||
} from "reactflow";
|
||||
import { specialCharsRegex } from "../constants/constants";
|
||||
import { APITemplateType } from "../types/api";
|
||||
import { FlowType, NodeType } from "../types/flow";
|
||||
import { cleanEdgesType } from "../types/utils/reactflowUtils";
|
||||
|
|
@ -241,6 +242,34 @@ export function addVersionToDuplicates(flow: FlowType, flows: FlowType[]) {
|
|||
return newName;
|
||||
}
|
||||
|
||||
export function handleKeyDown(
|
||||
e: React.KeyboardEvent<HTMLInputElement>,
|
||||
inputValue: string | string[] | null,
|
||||
block: string
|
||||
) {
|
||||
console.log(e, inputValue, block);
|
||||
//condition to fix bug control+backspace on Windows/Linux
|
||||
if (
|
||||
(typeof inputValue === "string" &&
|
||||
(e.metaKey === true || e.ctrlKey === true) &&
|
||||
e.key === "Backspace" &&
|
||||
(inputValue === block ||
|
||||
inputValue?.charAt(inputValue?.length - 1) === " " ||
|
||||
specialCharsRegex.test(inputValue?.charAt(inputValue?.length - 1)))) ||
|
||||
(navigator.userAgent.toUpperCase().includes("MAC") &&
|
||||
e.ctrlKey === true &&
|
||||
e.key === "Backspace")
|
||||
) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
if (e.ctrlKey === true && e.key === "Backspace" && inputValue === block) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
export function getConnectedNodes(
|
||||
edge: Edge,
|
||||
nodes: Array<NodeType>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue