Merge remote-tracking branch 'origin/dev' into db

This commit is contained in:
Gabriel Luiz Freitas Almeida 2023-06-05 22:18:07 -03:00
commit 77ee6ecf59
26 changed files with 947 additions and 151 deletions

View file

@ -75,6 +75,7 @@ toolkits:
- JsonToolkit - JsonToolkit
- VectorStoreInfo - VectorStoreInfo
- VectorStoreRouterToolkit - VectorStoreRouterToolkit
- VectorStoreToolkit
tools: tools:
- Search - Search
- PAL-MATH - PAL-MATH

View file

@ -1,4 +1,5 @@
import re import re
from typing import Any, Union
def validate_prompt(prompt: str): def validate_prompt(prompt: str):
@ -17,3 +18,14 @@ def fix_prompt(prompt: str):
def extract_input_variables_from_prompt(prompt: str) -> list[str]: def extract_input_variables_from_prompt(prompt: str) -> list[str]:
"""Extract input variables from prompt.""" """Extract input variables from prompt."""
return re.findall(r"{(.*?)}", prompt) return re.findall(r"{(.*?)}", prompt)
def flatten_list(list_of_lists: list[Union[list, Any]]) -> list:
"""Flatten list of lists."""
new_list = []
for item in list_of_lists:
if isinstance(item, list):
new_list.extend(item)
else:
new_list.append(item)
return new_list

View file

@ -174,6 +174,12 @@ class Vertex:
# turn result which is a function into a coroutine # turn result which is a function into a coroutine
# so that it can be awaited # so that it can be awaited
self.params["coroutine"] = sync_to_async(result) self.params["coroutine"] = sync_to_async(result)
if isinstance(result, list):
# If the result is a list, then we need to extend the list
# with the result but first check if the key exists
# if it doesn't, then we need to create a new list
if isinstance(self.params[key], list):
self.params[key].extend(result)
self.params[key] = result self.params[key] = result
elif isinstance(value, list) and all( elif isinstance(value, list) and all(

View file

@ -1,20 +1,20 @@
from typing import Any, Dict, List, Optional, Union from typing import Any, Dict, List, Optional, Union
from langflow.graph.vertex.base import Vertex from langflow.graph.vertex.base import Vertex
from langflow.graph.utils import extract_input_variables_from_prompt from langflow.graph.utils import extract_input_variables_from_prompt, flatten_list
class AgentVertex(Vertex): class AgentVertex(Vertex):
def __init__(self, data: Dict): def __init__(self, data: Dict):
super().__init__(data, base_type="agents") super().__init__(data, base_type="agents")
self.tools: List[ToolVertex] = [] self.tools: List[Union[ToolkitVertex, ToolVertex]] = []
self.chains: List[ChainVertex] = [] self.chains: List[ChainVertex] = []
def _set_tools_and_chains(self) -> None: def _set_tools_and_chains(self) -> None:
for edge in self.edges: for edge in self.edges:
source_node = edge.source source_node = edge.source
if isinstance(source_node, ToolVertex): if isinstance(source_node, (ToolVertex, ToolkitVertex)):
self.tools.append(source_node) self.tools.append(source_node)
elif isinstance(source_node, ChainVertex): elif isinstance(source_node, ChainVertex):
self.chains.append(source_node) self.chains.append(source_node)
@ -32,13 +32,6 @@ class AgentVertex(Vertex):
self._build() self._build()
#! Cannot deepcopy VectorStore, VectorStoreRouter, or SQL agents
if self.vertex_type in [
"VectorStoreAgent",
"VectorStoreRouterAgent",
"SQLAgent",
]:
return self._built_object
return self._built_object return self._built_object
@ -47,70 +40,6 @@ class ToolVertex(Vertex):
super().__init__(data, base_type="tools") super().__init__(data, base_type="tools")
class PromptVertex(Vertex):
def __init__(self, data: Dict):
super().__init__(data, base_type="prompts")
def build(
self,
force: bool = False,
tools: Optional[Union[List[Vertex], List[ToolVertex]]] = None,
) -> Any:
if not self._built or force:
if (
"input_variables" not in self.params
or self.params["input_variables"] is None
):
self.params["input_variables"] = []
# Check if it is a ZeroShotPrompt and needs a tool
if "ShotPrompt" in self.vertex_type:
tools = (
[tool_node.build() for tool_node in tools]
if tools is not None
else []
)
self.params["tools"] = tools
prompt_params = [
key
for key, value in self.params.items()
if isinstance(value, str) and key != "format_instructions"
]
else:
prompt_params = ["template"]
for param in prompt_params:
prompt_text = self.params[param]
variables = extract_input_variables_from_prompt(prompt_text)
self.params["input_variables"].extend(variables)
self.params["input_variables"] = list(set(self.params["input_variables"]))
self._build()
return self._built_object
class ChainVertex(Vertex):
def __init__(self, data: Dict):
super().__init__(data, base_type="chains")
def build(
self,
force: bool = False,
tools: Optional[Union[List[Vertex], List[ToolVertex]]] = None,
) -> Any:
if not self._built or force:
# Check if the chain requires a PromptNode
for key, value in self.params.items():
if isinstance(value, PromptVertex):
# Build the PromptNode, passing the tools if available
self.params[key] = value.build(tools=tools, force=force)
self._build()
#! Cannot deepcopy SQLDatabaseChain
if self.vertex_type in ["SQLDatabaseChain"]:
return self._built_object
return self._built_object
class LLMVertex(Vertex): class LLMVertex(Vertex):
built_node_type = None built_node_type = None
class_built_object = None class_built_object = None
@ -196,3 +125,68 @@ class TextSplitterVertex(Vertex):
return f"""{self.vertex_type}({len(self._built_object)} documents) return f"""{self.vertex_type}({len(self._built_object)} documents)
\nDocuments: {self._built_object[:3]}...""" \nDocuments: {self._built_object[:3]}..."""
return f"{self.vertex_type}()" return f"{self.vertex_type}()"
class ChainVertex(Vertex):
def __init__(self, data: Dict):
super().__init__(data, base_type="chains")
def build(
self,
force: bool = False,
tools: Optional[List[Union[ToolkitVertex, ToolVertex]]] = None,
) -> Any:
if not self._built or force:
# Check if the chain requires a PromptVertex
for key, value in self.params.items():
if isinstance(value, PromptVertex):
# Build the PromptVertex, passing the tools if available
self.params[key] = value.build(tools=tools, force=force)
self._build()
return self._built_object
class PromptVertex(Vertex):
def __init__(self, data: Dict):
super().__init__(data, base_type="prompts")
def build(
self,
force: bool = False,
tools: Optional[List[Union[ToolkitVertex, ToolVertex]]] = None,
) -> Any:
if not self._built or force:
if (
"input_variables" not in self.params
or self.params["input_variables"] is None
):
self.params["input_variables"] = []
# Check if it is a ZeroShotPrompt and needs a tool
if "ShotPrompt" in self.vertex_type:
tools = (
[tool_node.build() for tool_node in tools]
if tools is not None
else []
)
# flatten the list of tools if it is a list of lists
# first check if it is a list
if tools and isinstance(tools, list) and isinstance(tools[0], list):
tools = flatten_list(tools)
self.params["tools"] = tools
prompt_params = [
key
for key, value in self.params.items()
if isinstance(value, str) and key != "format_instructions"
]
else:
prompt_params = ["template"]
for param in prompt_params:
prompt_text = self.params[param]
variables = extract_input_variables_from_prompt(prompt_text)
self.params["input_variables"].extend(variables)
self.params["input_variables"] = list(set(self.params["input_variables"]))
self._build()
return self._built_object

View file

@ -69,7 +69,7 @@ class JsonAgent(CustomAgentExecutor):
@classmethod @classmethod
def from_toolkit_and_llm(cls, toolkit: JsonToolkit, llm: BaseLanguageModel): def from_toolkit_and_llm(cls, toolkit: JsonToolkit, llm: BaseLanguageModel):
tools = toolkit.get_tools() tools = toolkit if isinstance(toolkit, list) else toolkit.get_tools()
tool_names = {tool.name for tool in tools} tool_names = {tool.name for tool in tools}
prompt = ZeroShotAgent.create_prompt( prompt = ZeroShotAgent.create_prompt(
tools, tools,

View file

@ -110,8 +110,11 @@ def instantiate_tool(node_type, class_object, params):
def instantiate_toolkit(node_type, class_object, params): def instantiate_toolkit(node_type, class_object, params):
loaded_toolkit = class_object(**params) loaded_toolkit = class_object(**params)
if toolkits_creator.has_create_function(node_type): # Commenting this out for now to use toolkits as normal tools
return load_toolkits_executor(node_type, loaded_toolkit, params) # if toolkits_creator.has_create_function(node_type):
# return load_toolkits_executor(node_type, loaded_toolkit, params)
if isinstance(loaded_toolkit, BaseToolkit):
return loaded_toolkit.get_tools()
return loaded_toolkit return loaded_toolkit

View file

@ -42,24 +42,27 @@ class ToolkitCreator(LangChainTypeCreator):
def get_signature(self, name: str) -> Optional[Dict]: def get_signature(self, name: str) -> Optional[Dict]:
try: try:
return build_template_from_class(name, self.type_to_loader_dict) template = build_template_from_class(name, self.type_to_loader_dict)
# add Tool to base_classes
if "toolkit" in name.lower() and template:
template["base_classes"].append("Tool")
return template
except ValueError as exc: except ValueError as exc:
raise ValueError("Prompt not found") from exc raise ValueError("Toolkit not found") from exc
except AttributeError as exc: except AttributeError as exc:
logger.error(f"Prompt {name} not loaded: {exc}") logger.error(f"Toolkit {name} not loaded: {exc}")
return None return None
def to_list(self) -> List[str]: def to_list(self) -> List[str]:
return list(self.type_to_loader_dict.keys()) return list(self.type_to_loader_dict.keys())
def get_create_function(self, name: str) -> Callable: def get_create_function(self, name: str) -> Callable:
if loader_name := self.create_functions.get(name, None): if loader_name := self.create_functions.get(name):
# import loader
return import_module( return import_module(
f"from langchain.agents.agent_toolkits import {loader_name[0]}" f"from langchain.agents.agent_toolkits import {loader_name[0]}"
) )
else: else:
raise ValueError("Loader not found") raise ValueError("Toolkit not found")
def has_create_function(self, name: str) -> bool: def has_create_function(self, name: str) -> bool:
# check if the function list is not empty # check if the function list is not empty

View file

@ -146,7 +146,7 @@ class CSVAgentNode(FrontendNode):
), ),
], ],
) )
description: str = """Construct a json agent from a CSV and tools.""" description: str = """Construct a CSV agent from a CSV and tools."""
base_classes: list[str] = ["AgentExecutor"] base_classes: list[str] = ["AgentExecutor"]
def to_dict(self): def to_dict(self):
@ -194,7 +194,7 @@ class InitializeAgentNode(FrontendNode):
), ),
], ],
) )
description: str = """Construct a json agent from an LLM and tools.""" description: str = """Construct a zero shot agent from an LLM and tools."""
base_classes: list[str] = ["AgentExecutor", "function"] base_classes: list[str] = ["AgentExecutor", "function"]
def to_dict(self): def to_dict(self):

View file

@ -117,17 +117,30 @@ class FrontendNode(BaseModel):
) -> None: ) -> None:
"""Handles specific field values for certain fields.""" """Handles specific field values for certain fields."""
if key == "headers": if key == "headers":
field.value = """{'Authorization': field.value = """{'Authorization': 'Bearer <token>'}"""
'Bearer <token>'}""" FrontendNode._handle_model_specific_field_values(field, key, name)
if name == "OpenAI" and key == "model_name": FrontendNode._handle_api_key_specific_field_values(field, key, name)
field.options = constants.OPENAI_MODELS
field.is_list = True @staticmethod
elif name == "ChatOpenAI" and key == "model_name": def _handle_model_specific_field_values(
field.options = constants.CHAT_OPENAI_MODELS field: TemplateField, key: str, name: Optional[str] = None
field.is_list = True ) -> None:
elif (name == "Anthropic" or name == "ChatAnthropic") and key == "model_name": """Handles specific field values related to models."""
field.options = constants.ANTHROPIC_MODELS model_dict = {
"OpenAI": constants.OPENAI_MODELS,
"ChatOpenAI": constants.CHAT_OPENAI_MODELS,
"Anthropic": constants.ANTHROPIC_MODELS,
"ChatAnthropic": constants.ANTHROPIC_MODELS,
}
if name in model_dict and key == "model_name":
field.options = model_dict[name]
field.is_list = True field.is_list = True
@staticmethod
def _handle_api_key_specific_field_values(
field: TemplateField, key: str, name: Optional[str] = None
) -> None:
"""Handles specific field values related to API keys."""
if "api_key" in key and "OpenAI" in str(name): if "api_key" in key and "OpenAI" in str(name):
field.display_name = "OpenAI API Key" field.display_name = "OpenAI API Key"
field.required = False field.required = False

View file

@ -13,6 +13,7 @@
"@headlessui/react": "^1.7.10", "@headlessui/react": "^1.7.10",
"@heroicons/react": "^2.0.15", "@heroicons/react": "^2.0.15",
"@mui/material": "^5.11.9", "@mui/material": "^5.11.9",
"@radix-ui/react-tooltip": "^1.0.6",
"@tabler/icons-react": "^2.18.0", "@tabler/icons-react": "^2.18.0",
"@tailwindcss/forms": "^0.5.3", "@tailwindcss/forms": "^0.5.3",
"@tailwindcss/line-clamp": "^0.4.4", "@tailwindcss/line-clamp": "^0.4.4",
@ -20,7 +21,10 @@
"ansi-to-html": "^0.7.2", "ansi-to-html": "^0.7.2",
"axios": "^1.3.2", "axios": "^1.3.2",
"base64-js": "^1.5.1", "base64-js": "^1.5.1",
"class-variance-authority": "^0.6.0",
"clsx": "^1.2.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"lucide-react": "^0.233.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-ace": "^10.1.0", "react-ace": "^10.1.0",
"react-cookie": "^4.1.1", "react-cookie": "^4.1.1",
@ -37,6 +41,8 @@
"rehype-mathjax": "^4.0.2", "rehype-mathjax": "^4.0.2",
"remark-gfm": "^3.0.1", "remark-gfm": "^3.0.1",
"remark-math": "^5.1.1", "remark-math": "^5.1.1",
"tailwind-merge": "^1.13.0",
"tailwindcss-animate": "^1.0.5",
"uuid": "^9.0.0", "uuid": "^9.0.0",
"vite-plugin-svgr": "^3.2.0", "vite-plugin-svgr": "^3.2.0",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"
@ -911,6 +917,18 @@
"@floating-ui/core": "^1.2.6" "@floating-ui/core": "^1.2.6"
} }
}, },
"node_modules/@floating-ui/react-dom": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.0.tgz",
"integrity": "sha512-Ke0oU3SeuABC2C4OFu2mSAwHIP5WUiV98O9YWoHV4Q5aT6E9k06DV0Khi5uYspR8xmmBk08t8ZDcz3TR3ARkEg==",
"dependencies": {
"@floating-ui/dom": "^1.2.7"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/@headlessui/react": { "node_modules/@headlessui/react": {
"version": "1.7.10", "version": "1.7.10",
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.10.tgz", "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.10.tgz",
@ -1274,6 +1292,407 @@
"url": "https://opencollective.com/popperjs" "url": "https://opencollective.com/popperjs"
} }
}, },
"node_modules/@radix-ui/primitive": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz",
"integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==",
"dependencies": {
"@babel/runtime": "^7.13.10"
}
},
"node_modules/@radix-ui/react-arrow": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz",
"integrity": "sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/react-primitive": "1.0.3"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-compose-refs": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz",
"integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==",
"dependencies": {
"@babel/runtime": "^7.13.10"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-context": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz",
"integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==",
"dependencies": {
"@babel/runtime": "^7.13.10"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-dismissable-layer": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.4.tgz",
"integrity": "sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/primitive": "1.0.1",
"@radix-ui/react-compose-refs": "1.0.1",
"@radix-ui/react-primitive": "1.0.3",
"@radix-ui/react-use-callback-ref": "1.0.1",
"@radix-ui/react-use-escape-keydown": "1.0.3"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-id": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz",
"integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/react-use-layout-effect": "1.0.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-popper": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.2.tgz",
"integrity": "sha512-1CnGGfFi/bbqtJZZ0P/NQY20xdG3E0LALJaLUEoKwPLwl6PPPfbeiCqMVQnhoFRAxjJj4RpBRJzDmUgsex2tSg==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@floating-ui/react-dom": "^2.0.0",
"@radix-ui/react-arrow": "1.0.3",
"@radix-ui/react-compose-refs": "1.0.1",
"@radix-ui/react-context": "1.0.1",
"@radix-ui/react-primitive": "1.0.3",
"@radix-ui/react-use-callback-ref": "1.0.1",
"@radix-ui/react-use-layout-effect": "1.0.1",
"@radix-ui/react-use-rect": "1.0.1",
"@radix-ui/react-use-size": "1.0.1",
"@radix-ui/rect": "1.0.1"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-portal": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.3.tgz",
"integrity": "sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/react-primitive": "1.0.3"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-presence": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz",
"integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/react-compose-refs": "1.0.1",
"@radix-ui/react-use-layout-effect": "1.0.1"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-primitive": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz",
"integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/react-slot": "1.0.2"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-slot": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz",
"integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/react-compose-refs": "1.0.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-tooltip": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.0.6.tgz",
"integrity": "sha512-DmNFOiwEc2UDigsYj6clJENma58OelxD24O4IODoZ+3sQc3Zb+L8w1EP+y9laTuKCLAysPw4fD6/v0j4KNV8rg==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/primitive": "1.0.1",
"@radix-ui/react-compose-refs": "1.0.1",
"@radix-ui/react-context": "1.0.1",
"@radix-ui/react-dismissable-layer": "1.0.4",
"@radix-ui/react-id": "1.0.1",
"@radix-ui/react-popper": "1.1.2",
"@radix-ui/react-portal": "1.0.3",
"@radix-ui/react-presence": "1.0.1",
"@radix-ui/react-primitive": "1.0.3",
"@radix-ui/react-slot": "1.0.2",
"@radix-ui/react-use-controllable-state": "1.0.1",
"@radix-ui/react-visually-hidden": "1.0.3"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-callback-ref": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz",
"integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==",
"dependencies": {
"@babel/runtime": "^7.13.10"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-controllable-state": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz",
"integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/react-use-callback-ref": "1.0.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-escape-keydown": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz",
"integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/react-use-callback-ref": "1.0.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-layout-effect": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz",
"integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==",
"dependencies": {
"@babel/runtime": "^7.13.10"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-rect": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz",
"integrity": "sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/rect": "1.0.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-size": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz",
"integrity": "sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/react-use-layout-effect": "1.0.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-visually-hidden": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz",
"integrity": "sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/react-primitive": "1.0.3"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/rect": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.0.1.tgz",
"integrity": "sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==",
"dependencies": {
"@babel/runtime": "^7.13.10"
}
},
"node_modules/@reactflow/background": { "node_modules/@reactflow/background": {
"version": "11.1.7", "version": "11.1.7",
"resolved": "https://registry.npmjs.org/@reactflow/background/-/background-11.1.7.tgz", "resolved": "https://registry.npmjs.org/@reactflow/background/-/background-11.1.7.tgz",
@ -2422,7 +2841,7 @@
"version": "18.2.4", "version": "18.2.4",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.4.tgz", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.4.tgz",
"integrity": "sha512-G2mHoTMTL4yoydITgOGwWdWMVd8sNgyEP85xVmMKAPUBwQWm9wBPQUmvbeF4V3WBY1P7mmL4BkjQ0SqUpf1snw==", "integrity": "sha512-G2mHoTMTL4yoydITgOGwWdWMVd8sNgyEP85xVmMKAPUBwQWm9wBPQUmvbeF4V3WBY1P7mmL4BkjQ0SqUpf1snw==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"@types/react": "*" "@types/react": "*"
} }
@ -2947,6 +3366,25 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/class-variance-authority": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.6.0.tgz",
"integrity": "sha512-qdRDgfjx3GRb9fpwpSvn+YaidnT7IUJNe4wt5/SWwM+PmUwJUhQRk/8zAyNro0PmVfmen2635UboTjIBXXxy5A==",
"dependencies": {
"clsx": "1.2.1"
},
"funding": {
"url": "https://joebell.co.uk"
},
"peerDependencies": {
"typescript": ">= 4.5.5 < 6"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/classcat": { "node_modules/classcat": {
"version": "5.0.4", "version": "5.0.4",
"resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.4.tgz", "resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.4.tgz",
@ -4728,6 +5166,14 @@
"yallist": "^3.0.2" "yallist": "^3.0.2"
} }
}, },
"node_modules/lucide-react": {
"version": "0.233.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.233.0.tgz",
"integrity": "sha512-r0jMHF0vPDq2wBbZ0B3rtIcBjDyWDKpHu+vAjD2OHn2WLUr3HN5IHovtO0EMgQXuSI7YrMZbjsEZWC2uBHr8nQ==",
"peerDependencies": {
"react": "^16.5.1 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/lz-string": { "node_modules/lz-string": {
"version": "1.4.4", "version": "1.4.4",
"resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz",
@ -7001,6 +7447,15 @@
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="
}, },
"node_modules/tailwind-merge": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.13.0.tgz",
"integrity": "sha512-mUTmDbcU+IhOvJ0c42eLQ/nRkvolTqfpVaVQRSxfJAv9TabS6Y2zW/1wKpKLdKzyL3Gh8j6NTLl6MWNmvOM6kA==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/dcastil"
}
},
"node_modules/tailwindcss": { "node_modules/tailwindcss": {
"version": "3.3.2", "version": "3.3.2",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.2.tgz", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.2.tgz",
@ -7038,6 +7493,14 @@
"node": ">=14.0.0" "node": ">=14.0.0"
} }
}, },
"node_modules/tailwindcss-animate": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.5.tgz",
"integrity": "sha512-UU3qrOJ4lFQABY+MVADmBm+0KW3xZyhMdRvejwtXqYOL7YjHYxmuREFAZdmVG5LPe5E9CAst846SLC4j5I3dcw==",
"peerDependencies": {
"tailwindcss": ">=3.0.0 || insiders"
}
},
"node_modules/terser": { "node_modules/terser": {
"version": "5.16.3", "version": "5.16.3",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz", "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz",
@ -7156,7 +7619,7 @@
"version": "5.0.4", "version": "5.0.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz",
"integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==",
"dev": true, "devOptional": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"

View file

@ -8,6 +8,7 @@
"@headlessui/react": "^1.7.10", "@headlessui/react": "^1.7.10",
"@heroicons/react": "^2.0.15", "@heroicons/react": "^2.0.15",
"@mui/material": "^5.11.9", "@mui/material": "^5.11.9",
"@radix-ui/react-tooltip": "^1.0.6",
"@tabler/icons-react": "^2.18.0", "@tabler/icons-react": "^2.18.0",
"@tailwindcss/forms": "^0.5.3", "@tailwindcss/forms": "^0.5.3",
"@tailwindcss/line-clamp": "^0.4.4", "@tailwindcss/line-clamp": "^0.4.4",
@ -15,7 +16,10 @@
"ansi-to-html": "^0.7.2", "ansi-to-html": "^0.7.2",
"axios": "^1.3.2", "axios": "^1.3.2",
"base64-js": "^1.5.1", "base64-js": "^1.5.1",
"class-variance-authority": "^0.6.0",
"clsx": "^1.2.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"lucide-react": "^0.233.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-ace": "^10.1.0", "react-ace": "^10.1.0",
"react-cookie": "^4.1.1", "react-cookie": "^4.1.1",
@ -32,6 +36,8 @@
"rehype-mathjax": "^4.0.2", "rehype-mathjax": "^4.0.2",
"remark-gfm": "^3.0.1", "remark-gfm": "^3.0.1",
"remark-math": "^5.1.1", "remark-math": "^5.1.1",
"tailwind-merge": "^1.13.0",
"tailwindcss-animate": "^1.0.5",
"uuid": "^9.0.0", "uuid": "^9.0.0",
"vite-plugin-svgr": "^3.2.0", "vite-plugin-svgr": "^3.2.0",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"

View file

@ -1,6 +1,11 @@
import { Handle, Position, useUpdateNodeInternals } from "reactflow"; import { Handle, Position, useUpdateNodeInternals } from "reactflow";
import Tooltip from "../../../../components/TooltipComponent"; import Tooltip from "../../../../components/TooltipComponent";
import { classNames, isValidConnection } from "../../../../utils"; import {
classNames,
groupByFamily,
isValidConnection,
toFirstUpperCase,
} from "../../../../utils";
import { useContext, useEffect, useRef, useState } from "react"; import { useContext, useEffect, useRef, useState } from "react";
import InputComponent from "../../../../components/inputComponent"; import InputComponent from "../../../../components/inputComponent";
import ToggleComponent from "../../../../components/toggleComponent"; import ToggleComponent from "../../../../components/toggleComponent";
@ -15,6 +20,10 @@ import InputFileComponent from "../../../../components/inputFileComponent";
import { TabsContext } from "../../../../contexts/tabsContext"; import { TabsContext } from "../../../../contexts/tabsContext";
import IntComponent from "../../../../components/intComponent"; import IntComponent from "../../../../components/intComponent";
import PromptAreaComponent from "../../../../components/promptComponent"; import PromptAreaComponent from "../../../../components/promptComponent";
import { nodeNames, nodeIcons } from "../../../../utils";
import React from "react";
import { nodeColors } from "../../../../utils";
import ShadTooltip from "../../../../components/ShadTooltipComponent";
export default function ParameterComponent({ export default function ParameterComponent({
left, left,
@ -28,6 +37,7 @@ export default function ParameterComponent({
required = false, required = false,
}: ParameterComponentType) { }: ParameterComponentType) {
const ref = useRef(null); const ref = useRef(null);
const refHtml = useRef(null);
const updateNodeInternals = useUpdateNodeInternals(); const updateNodeInternals = useUpdateNodeInternals();
const [position, setPosition] = useState(0); const [position, setPosition] = useState(0);
useEffect(() => { useEffect(() => {
@ -48,6 +58,48 @@ export default function ParameterComponent({
let disabled = let disabled =
reactFlowInstance?.getEdges().some((e) => e.targetHandle === id) ?? false; reactFlowInstance?.getEdges().some((e) => e.targetHandle === id) ?? false;
const { save } = useContext(TabsContext); const { save } = useContext(TabsContext);
const [myData, setMyData] = useState(useContext(typesContext).data);
useEffect(() => {
const groupedObj = groupByFamily(myData, tooltipTitle);
refHtml.current = groupedObj.map((item, i) => (
<span
key={item}
className={classNames(
i > 0 ? "items-center flex mt-3" : "items-center flex"
)}
>
<div
className="h-5 w-5"
style={{
color: nodeColors[item.family],
}}
>
{React.createElement(nodeIcons[item.family])}
</div>
<span className="ps-2 text-gray-950">
{nodeNames[item.family] ?? ""}{" "}
<span className={classNames(left ? "hidden" : "")}>
{" "}
-&nbsp;
{item.type.split(", ").length > 2
? item.type.split(", ").map((el, i) => (
<>
<span key={el}>
{i == item.type.split(", ").length - 1
? el
: (el += `, `)}
</span>
{i % 2 == 0 && i > 0 && <br></br>}
</>
))
: item.type}
</span>
</span>
</span>
));
}, [tooltipTitle]);
return ( return (
<div <div
@ -69,7 +121,11 @@ export default function ParameterComponent({
type === "int") ? ( type === "int") ? (
<></> <></>
) : ( ) : (
<Tooltip title={tooltipTitle + (required ? " (required)" : "")}> <ShadTooltip
delayDuration={0}
content={refHtml.current}
side={left ? "left" : "right"}
>
<Handle <Handle
type={left ? "target" : "source"} type={left ? "target" : "source"}
position={left ? Position.Left : Position.Right} position={left ? Position.Left : Position.Right}
@ -86,7 +142,7 @@ export default function ParameterComponent({
top: position, top: position,
}} }}
></Handle> ></Handle>
</Tooltip> </ShadTooltip>
)} )}
{left === true && {left === true &&

View file

@ -28,8 +28,8 @@ import NodeModal from "../../modals/NodeModal";
import { useCallback } from "react"; import { useCallback } from "react";
import { TabsContext } from "../../contexts/tabsContext"; import { TabsContext } from "../../contexts/tabsContext";
import { debounce } from "../../utils"; import { debounce } from "../../utils";
import TooltipReact from "../../components/ReactTooltipComponent";
import Tooltip from "../../components/TooltipComponent"; import Tooltip from "../../components/TooltipComponent";
import ShadTooltip from "../../components/ShadTooltipComponent";
export default function GenericNode({ export default function GenericNode({
data, data,
selected, selected,
@ -115,14 +115,9 @@ export default function GenericNode({
}} }}
/> />
<div className="ml-2 truncate"> <div className="ml-2 truncate">
<TooltipReact <ShadTooltip delayDuration={1500} content={data.type}>
delayShow={1000}
selector={`node-selector-${data.type}`}
htmlContent={data.type}
position="top"
>
<div className="ml-2 truncate">{data.type}</div> <div className="ml-2 truncate">{data.type}</div>
</TooltipReact> </ShadTooltip>
</div> </div>
</div> </div>
<div className="flex gap-3"> <div className="flex gap-3">
@ -253,11 +248,7 @@ export default function GenericNode({
: toTitleCase(t) : toTitleCase(t)
} }
name={t} name={t}
tooltipTitle={ tooltipTitle={data.node.template[t].type}
"Type: " +
data.node.template[t].type +
(data.node.template[t].list ? " list" : "")
}
required={data.node.template[t].required} required={data.node.template[t].required}
id={data.node.template[t].type + "|" + t + "|" + data.id} id={data.node.template[t].type + "|" + t + "|" + data.id}
left={true} left={true}
@ -283,7 +274,7 @@ export default function GenericNode({
data={data} data={data}
color={nodeColors[types[data.type]] ?? nodeColors.unknown} color={nodeColors[types[data.type]] ?? nodeColors.unknown}
title={data.type} title={data.type}
tooltipTitle={`Type: ${data.node.base_classes.join(" | ")}`} tooltipTitle={`${data.node.base_classes.join("\n")}`}
id={[data.type, data.id, ...data.node.base_classes].join("|")} id={[data.type, data.id, ...data.node.base_classes].join("|")}
type={data.node.base_classes.join("|")} type={data.node.base_classes.join("|")}
left={false} left={false}

View file

@ -37,13 +37,15 @@ const TooltipReact: FC<TooltipProps> = ({
id={selector} id={selector}
content={content} content={content}
className={classNames( className={classNames(
"!bg-white !text-xs !font-normal !text-gray-700 !shadow-md !opacity-100 z-20", "!bg-white !text-xs !font-normal !text-gray-700 !shadow-md !opacity-100 z-[9999]",
className className
)} )}
place={position} place={position}
clickable={clickable} clickable={clickable}
isOpen={disabled ? false : undefined} isOpen={disabled ? false : undefined}
delayShow={delayShow} delayShow={delayShow}
positionStrategy="absolute"
float={true}
> >
{htmlContent && htmlContent} {htmlContent && htmlContent}
</ReactTooltip> </ReactTooltip>

View file

@ -0,0 +1,25 @@
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "../ui/tooltip";
const ShadTooltip = (props) => {
return (
<TooltipProvider>
<Tooltip delayDuration={props.delayDuration}>
<TooltipTrigger asChild>{props.children}</TooltipTrigger>
<TooltipContent
side={props.side}
avoidCollisions={false}
sticky="always"
>
{props.content}
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
};
export default ShadTooltip;

View file

@ -25,7 +25,9 @@ export default function Dropdown({
<> <>
<div className="relative mt-1 w-full"> <div className="relative mt-1 w-full">
<Listbox.Button className="relative w-full cursor-default rounded-md border border-gray-300 bg-white dark:bg-gray-900 py-2 pl-3 pr-10 text-left shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 sm:text-sm"> <Listbox.Button className="relative w-full cursor-default rounded-md border border-gray-300 bg-white dark:bg-gray-900 py-2 pl-3 pr-10 text-left shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 sm:text-sm">
<span className="block truncate w-full">{internalValue}</span> <span className="block truncate w-full dark:text-gray-300">
{internalValue}
</span>
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"> <span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
<ChevronUpDownIcon <ChevronUpDownIcon
className="h-5 w-5 text-gray-400" className="h-5 w-5 text-gray-400"

View file

@ -0,0 +1,29 @@
"use client";
import * as React from "react";
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
import { cn } from "../../utils";
const TooltipProvider = TooltipPrimitive.Provider;
const Tooltip = TooltipPrimitive.Root;
const TooltipTrigger = TooltipPrimitive.Trigger;
const TooltipContent = React.forwardRef<
React.ElementRef<typeof TooltipPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
<TooltipPrimitive.Content
ref={ref}
sideOffset={sideOffset}
className={cn(
"z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 data-[side=top]:slide-in-from-bottom-1",
className
)}
{...props}
/>
));
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };

View file

@ -13,13 +13,16 @@ const initialValue = {
export const darkContext = createContext<darkContextType>(initialValue); export const darkContext = createContext<darkContextType>(initialValue);
export function DarkProvider({ children }) { export function DarkProvider({ children }) {
const [dark, setDark] = useState(false); const [dark, setDark] = useState(
JSON.parse(window.localStorage.getItem("isDark")) ?? false
);
useEffect(() => { useEffect(() => {
if (dark) { if (dark) {
document.getElementById("body").classList.add("dark"); document.getElementById("body").classList.add("dark");
} else { } else {
document.getElementById("body").classList.remove("dark"); document.getElementById("body").classList.remove("dark");
} }
window.localStorage.setItem("isDark", dark.toString());
}, [dark]); }, [dark]);
return ( return (
<darkContext.Provider <darkContext.Provider

View file

@ -2,6 +2,74 @@
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 47.4% 11.2%;
--card: 0 0% 100%;
--card-foreground: 222.2 47.4% 11.2%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 100% 50%;
--destructive-foreground: 210 40% 98%;
--ring: 215 20.2% 65.1%;
--radius: 0.5rem;
}
.dark {
-background: 224 71% 4%;
-foreground: 213 31% 91%;
-muted: 223 47% 11%;
-muted-foreground: 215.4 16.3% 56.9%;
-popover: 224 71% 4%;
-popover-foreground: 215 20.2% 65.1%;
-card: 224 71% 4%;
-card-foreground: 213 31% 91%;
-border: 216 34% 17%;
-input: 216 34% 17%;
-primary: 210 40% 98%;
-primary-foreground: 222.2 47.4% 1.2%;
-secondary: 222.2 47.4% 11.2%;
-secondary-foreground: 210 40% 98%;
-accent: 216 34% 17%;
-accent-foreground: 210 40% 98%;
-destructive: 0 63% 31%;
-destructive-foreground: 210 40% 98%;
-ring: 216 34% 17%;
-radius: 0.5rem;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
font-feature-settings: "rlig" 1, "calt" 1;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
font-feature-settings: "rlig" 1, "calt" 1;
}
}
body { body {
margin: 0; margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
@ -16,8 +84,6 @@ code {
monospace; monospace;
} }
/* The style below sets the cursor property of the element with the class .react-flow__pane to the default cursor.
The cursor: default; property value restores the browser's default cursor style for the targeted element. By applying this style, the element will no longer have a custom cursor appearance such as "grab" or any other custom cursor defined elsewhere in the application. Instead, it will revert to the default cursor style determined by the browser, typically an arrow-shaped cursor. */
.react-flow__pane { .react-flow__pane {
cursor: default; cursor: default;
} }

View file

@ -9,8 +9,8 @@ import {
import { useContext, useEffect, useState, useRef } from "react"; import { useContext, useEffect, useState, useRef } from "react";
import { typesContext } from "../../../../contexts/typesContext"; import { typesContext } from "../../../../contexts/typesContext";
import { APIClassType, APIObjectType } from "../../../../types/api"; import { APIClassType, APIObjectType } from "../../../../types/api";
import TooltipReact from "../../../../components/ReactTooltipComponent";
import { MagnifyingGlassIcon } from "@heroicons/react/24/outline"; import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
import ShadTooltip from "../../../../components/ShadTooltipComponent";
export default function ExtraSidebar() { export default function ExtraSidebar() {
const { data } = useContext(typesContext); const { data } = useContext(typesContext);
@ -84,12 +84,10 @@ export default function ExtraSidebar() {
{Object.keys(dataFilter[d]) {Object.keys(dataFilter[d])
.sort() .sort()
.map((t: string, k) => ( .map((t: string, k) => (
<TooltipReact <ShadTooltip
selector={t} content={t}
htmlContent={t} delayDuration={1500}
position="right" side="right"
delayShow={1500}
key={k}
> >
<div key={k} data-tooltip-id={t}> <div key={k} data-tooltip-id={t}>
<div <div
@ -121,7 +119,7 @@ export default function ExtraSidebar() {
</div> </div>
</div> </div>
</div> </div>
</TooltipReact> </ShadTooltip>
))} ))}
</div> </div>
</DisclosureComponent> </DisclosureComponent>

View file

@ -116,7 +116,7 @@ export default function TabsManagerComponent() {
</button> </button>
</div> </div>
</div> </div>
<div className="w-full h-full"> <div className="w-full h-full dark:bg-gray-800">
<ReactFlowProvider> <ReactFlowProvider>
{flows[tabIndex] ? ( {flows[tabIndex] ? (
<FlowPage flow={flows[tabIndex]}></FlowPage> <FlowPage flow={flows[tabIndex]}></FlowPage>

View file

@ -3,6 +3,7 @@ import {
ReactElement, ReactElement,
ReactFragment, ReactFragment,
ReactNode, ReactNode,
SVGProps,
} from "react"; } from "react";
import { NodeDataType } from "../flow/index"; import { NodeDataType } from "../flow/index";
export type InputComponentType = { export type InputComponentType = {

View file

@ -48,6 +48,12 @@ import { WolframIcon } from "./icons/Wolfram";
import { WordIcon } from "./icons/Word"; import { WordIcon } from "./icons/Word";
import { SerperIcon } from "./icons/Serper"; import { SerperIcon } from "./icons/Serper";
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export function classNames(...classes: Array<string>) { export function classNames(...classes: Array<string>) {
return classes.filter(Boolean).join(" "); return classes.filter(Boolean).join(" ");
@ -635,3 +641,58 @@ export function updateIds(newFlow, getNodeId) {
e.targetHandle; e.targetHandle;
}); });
} }
export function groupByFamily(data, baseClasses) {
let arrOfParent: string[] = [];
let arrOfType: { family: string; type: string }[] = [];
Object.keys(data).map((d) => {
Object.keys(data[d]).map((n) => {
if (
data[d][n].base_classes.some((r) => baseClasses.split("\n").includes(r))
) {
arrOfParent.push(d);
}
});
});
let uniq = arrOfParent.filter(
(item, index) => arrOfParent.indexOf(item) === index
);
Object.keys(data).map((d) => {
Object.keys(data[d]).map((n) => {
baseClasses.split("\n").forEach((tol) => {
data[d][n].base_classes.forEach((data) => {
if (tol == data) {
arrOfType.push({
family: d,
type: data,
});
}
});
});
});
});
let groupedBy = arrOfType.filter((object, index, self) => {
const foundIndex = self.findIndex(
(o) => o.family === object.family && o.type === object.type
);
return foundIndex === index;
});
let groupedObj = groupedBy.reduce((result, item) => {
const existingGroup = result.find((group) => group.family === item.family);
if (existingGroup) {
existingGroup.type += `, ${item.type}`;
} else {
result.push({ family: item.family, type: item.type });
}
return result;
}, []);
return groupedObj;
}

View file

@ -1,11 +1,83 @@
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
const { fontFamily } = require("tailwindcss/defaultTheme")
import plugin from "tailwindcss/plugin"; import plugin from "tailwindcss/plugin";
module.exports = { module.exports = {
content: ["./index.html", "./src/**/*.{js,ts,tsx,jsx}"], content: ["./index.html", "./src/**/*.{js,ts,tsx,jsx}"],
darkMode: "class", darkMode: "class",
important: true, important: true,
theme: { theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
extend: { extend: {
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
},
borderRadius: {
lg: `var(--radius)`,
md: `calc(var(--radius) - 2px)`,
sm: "calc(var(--radius) - 4px)",
},
fontFamily: {
sans: ["var(--font-sans)", ...fontFamily.sans],
},
keyframes: {
"accordion-down": {
from: { height: 0 },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: 0 },
},
pulseGreen: {
"0%": { boxShadow: "0 0 0 0 rgba(72, 187, 120, 0.7)" },
"100%": { boxShadow: "0 0 0 10px rgba(72, 187, 120, 0)" },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
"pulse-green": "pulseGreen 1s linear",
'spin-once': 'spin 1s linear 0.7'
},
borderColor: { borderColor: {
"red-outline": "rgba(255, 0, 0, 0.8)", "red-outline": "rgba(255, 0, 0, 0.8)",
"green-outline": "rgba(72, 187, 120, 0.7)", "green-outline": "rgba(72, 187, 120, 0.7)",
@ -14,17 +86,6 @@ module.exports = {
"red-outline": "0 0 5px rgba(255, 0, 0, 0.5)", "red-outline": "0 0 5px rgba(255, 0, 0, 0.5)",
"green-outline": "0 0 5px rgba(72, 187, 120, 0.7)", "green-outline": "0 0 5px rgba(72, 187, 120, 0.7)",
}, },
animation: {
"pulse-green": "pulseGreen 1s linear",
'spin-once': 'spin 1s linear 0.7'
},
keyframes: {
pulseGreen: {
"0%": { boxShadow: "0 0 0 0 rgba(72, 187, 120, 0.7)" },
"100%": { boxShadow: "0 0 0 10px rgba(72, 187, 120, 0)" },
},
},
}, },
}, },
plugins: [ plugins: [

View file

@ -19,7 +19,8 @@
"isolatedModules": true, "isolatedModules": true,
"noEmit": true, "noEmit": true,
"jsx": "react-jsx", "jsx": "react-jsx",
"noImplicitAny": false "noImplicitAny": false,
"baseUrl": "."
}, },
"include": [ "include": [
"src" "src"

View file

@ -241,11 +241,10 @@ def test_build_params(basic_graph):
assert "memory" in root.params assert "memory" in root.params
def test_build(basic_graph, complex_graph, openapi_graph): def test_build(basic_graph, complex_graph):
"""Test Node's build method""" """Test Node's build method"""
assert_agent_was_built(basic_graph) assert_agent_was_built(basic_graph)
assert_agent_was_built(complex_graph) assert_agent_was_built(complex_graph)
assert_agent_was_built(openapi_graph)
def assert_agent_was_built(graph): def assert_agent_was_built(graph):