merge fix

This commit is contained in:
Cristhian Zanforlin Lousa 2023-07-07 11:46:13 -03:00
commit fbc9eb6d1b
97 changed files with 2357 additions and 575 deletions

View file

@ -1,6 +1,6 @@
# LangFlow Demo Codespace Readme
# Langflow Demo Codespace Readme
These instructions will walk you through the process of running a LangFlow demo via GitHub Codespaces.
These instructions will walk you through the process of running a Langflow demo via GitHub Codespaces.
## Setup

47
.env.example Normal file
View file

@ -0,0 +1,47 @@
# Description: Example of .env file
# Usage: Copy this file to .env and change the values
# according to your needs
# Do not commit .env file to git
# Do not change .env.example file
# Database URL
# Postgres example: LANGFLOW_DATABASE_URL=postgresql://postgres:postgres@localhost:5432/langflow
# SQLite example:
LANGFLOW_DATABASE_URL=sqlite:///./langflow.db
# Cache type
LANGFLOW_LANGCHAIN_CACHE=SQLiteCache
# Server host
# Example: LANGFLOW_HOST=127.0.0.1
LANGFLOW_HOST=
# Worker processes
# Example: LANGFLOW_WORKERS=1
LANGFLOW_WORKERS=
# Server port
# Example: LANGFLOW_PORT=7860
LANGFLOW_PORT=
# Logging level
# Example: LANGFLOW_LOG_LEVEL=critical
LANGFLOW_LOG_LEVEL=
# Path to the log file
# Example: LANGFLOW_LOG_FILE=logs/langflow.log
LANGFLOW_LOG_FILE=
# Path to the frontend directory containing build files
# Example: LANGFLOW_FRONTEND_PATH=/path/to/frontend/build/files
LANGFLOW_FRONTEND_PATH=
# Whether to open the browser after starting the server
# Values: true, false
# Example: LANGFLOW_OPEN_BROWSER=true
LANGFLOW_OPEN_BROWSER=
# Whether to remove API keys from the projects saved in the database
# Values: true, false
# Example: LANGFLOW_REMOVE_API_KEYS=false
LANGFLOW_REMOVE_API_KEYS=

View file

@ -1,6 +1,6 @@
# Contributing to LangFlow
# Contributing to Langflow
Hello there! We appreciate your interest in contributing to LangFlow.
Hello there! We appreciate your interest in contributing to Langflow.
As an open-source project in a rapidly developing field, we are extremely open
to contributions, whether it be in the form of a new feature, improved infra, or better documentation.
@ -40,7 +40,7 @@ the system we use to tag our issues and pull requests.
### Local development
You can develop LangFlow using docker compose, or locally.
You can develop Langflow using docker compose, or locally.
We provide a .vscode/launch.json file for debugging the backend in VSCode, which is a lot faster than using docker compose.

View file

@ -13,7 +13,7 @@ This script sets up a Debian-based VM with the Langflow package, Nginx, and the
## Spot/Preemptible Instance
[![Open in Cloud Shell - Spot Instance](https://gstatic.com/cloudssh/images/open-btn.svg)](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/genome21/langflow&working_dir=scripts&shellonly=true&tutorial=walkthroughtutorial_spot.md)
[![Open in Cloud Shell - Spot Instance](https://gstatic.com/cloudssh/images/open-btn.svg)](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/logspace-ai/langflow&working_dir=scripts&shellonly=true&tutorial=walkthroughtutorial_spot.md)
When running as a [spot (preemptible) instance](https://cloud.google.com/compute/docs/instances/preemptible), the code and VM will behave the same way as in a regular instance, executing the startup script to configure the environment, install necessary dependencies, and run the Langflow application. However, **due to the nature of spot instances, the VM may be terminated at any time if Google Cloud needs to reclaim the resources**. This makes spot instances suitable for fault-tolerant, stateless, or interruptible workloads that can handle unexpected terminations and restarts.

View file

@ -1,6 +1,6 @@
<!-- Title -->
# ⛓️ LangFlow
# ⛓️ Langflow
~ An effortless way to experiment and prototype [LangChain](https://github.com/hwchase17/langchain) pipelines ~
@ -16,7 +16,7 @@
<p>
<a href="https://discord.gg/EqksyE2EX9"><img alt="Discord Server" src="https://dcbadge.vercel.app/api/server/EqksyE2EX9?compact=true&style=flat"/></a>
<a href="https://huggingface.co/spaces/Logspace/LangFlow"><img src="https://huggingface.co/datasets/huggingface/badges/raw/main/open-in-hf-spaces-sm.svg" alt="HuggingFace Spaces"></a>
<a href="https://huggingface.co/spaces/Logspace/Langflow"><img src="https://huggingface.co/datasets/huggingface/badges/raw/main/open-in-hf-spaces-sm.svg" alt="HuggingFace Spaces"></a>
</p>
<a href="https://github.com/logspace-ai/langflow">
@ -26,9 +26,26 @@
<p>
</p>
## 📦 Installation
# Table of Contents
- [⛓️ Langflow](#-langflow)
- [Table of Contents](#table-of-contents)
- [📦 Installation](#-installation)
- [Locally](#locally)
- [🖥️ Command Line Interface (CLI)](#-command-line-interface-cli)
- [Usage](#usage)
- [Environment Variables](#environment-variables)
- [Deployment](#deployment)
- [Deploy Langflow on Google Cloud Platform](#deploy-langflow-on-google-cloud-platform)
- [Deploy Langflow on Jina AI Cloud](#deploy-langflow-on-jina-ai-cloud)
- [API Usage](#api-usage)
- [🎨 Creating Flows](#-creating-flows)
- [👋 Contributing](#-contributing)
- [📄 License](#-license)
# 📦 Installation
### <b>Locally</b>
You can install LangFlow from pip:
You can install Langflow from pip:
```shell
pip install langflow
@ -41,9 +58,51 @@ python -m langflow
```
or
```shell
langflow
langflow # or langflow --help
```
# 🖥️ Command Line Interface (CLI)
Langflow provides a command-line interface (CLI) for easy management and configuration.
### Usage
You can run the Langflow using the following command:
```shell
langflow [OPTIONS]
```
Each option is detailed below:
- `--help`: Displays all available options.
- `--host`: Defines the host to bind the server to. Can be set using the `LANGFLOW_HOST` environment variable. The default is `127.0.0.1`.
- `--workers`: Sets the number of worker processes. Can be set using the `LANGFLOW_WORKERS` environment variable. The default is `1`.
- `--timeout`: Sets the worker timeout in seconds. The default is `60`.
- `--port`: Sets the port to listen on. Can be set using the `LANGFLOW_PORT` environment variable. The default is `7860`.
- `--config`: Defines the path to the configuration file. The default is `config.yaml`.
- `--env-file`: Specifies the path to the .env file containing environment variables. The default is `.env`.
- `--log-level`: Defines the logging level. Can be set using the `LANGFLOW_LOG_LEVEL` environment variable. The default is `critical`.
- `--log-file`: Specifies the path to the log file. Can be set using the `LANGFLOW_LOG_FILE` environment variable. The default is `logs/langflow.log`.
- `--cache`: Selects the type of cache to use. Options are `InMemoryCache` and `SQLiteCache`. Can be set using the `LANGFLOW_LANGCHAIN_CACHE` environment variable. The default is `SQLiteCache`.
- `--jcloud/--no-jcloud`: Toggles the option to deploy on Jina AI Cloud. The default is `no-jcloud`.
- `--dev/--no-dev`: Toggles the development mode. The default is `no-dev`.
- `--database-url`: Sets the database URL to connect to. If not provided, a local SQLite database will be used. Can be set using the `LANGFLOW_DATABASE_URL` environment variable.
- `--path`: Specifies the path to the frontend directory containing build files. This option is for development purposes only. Can be set using the `LANGFLOW_FRONTEND_PATH` environment variable.
- `--open-browser/--no-open-browser`: Toggles the option to open the browser after starting the server. Can be set using the `LANGFLOW_OPEN_BROWSER` environment variable. The default is `open-browser`.
- `--remove-api-keys/--no-remove-api-keys`: Toggles the option to remove API keys from the projects saved in the database. Can be set using the `LANGFLOW_REMOVE_API_KEYS` environment variable. The default is `no-remove-api-keys`.
- `--install-completion [bash|zsh|fish|powershell|pwsh]`: Installs completion for the specified shell.
- `--show-completion [bash|zsh|fish|powershell|pwsh]`: Shows completion for the specified shell, allowing you to copy it or customize the installation.
### Environment Variables
You can configure many of the CLI options using environment variables. These can be exported in your operating system or added to a `.env` file and loaded using the `--env-file` option.
A sample `.env` file named `.env.example` is included with the project. Copy this file to a new file named `.env` and replace the example values with your actual settings. If you're setting values in both your OS and the `.env` file, the `.env` settings will take precedence.
# Deployment
### Deploy Langflow on Google Cloud Platform
Follow our step-by-step guide to deploy Langflow on Google Cloud Platform (GCP) using Google Cloud Shell. The guide is available in the [**Langflow in Google Cloud Platform**](GCP_DEPLOYMENT.md) document.
@ -163,7 +222,7 @@ print(run_flow("Your message", flow_id=FLOW_ID, tweaks=TWEAKS))
## 🎨 Creating Flows
Creating flows with LangFlow is easy. Simply drag sidebar components onto the canvas and connect them together to create your pipeline. LangFlow provides a range of [LangChain components](https://api.python.langchain.com/en/latest/index.html) to choose from, including LLMs, prompt serializers, agents, and chains.
Creating flows with Langflow is easy. Simply drag sidebar components onto the canvas and connect them together to create your pipeline. Langflow provides a range of [LangChain components](https://langchain.readthedocs.io/en/latest/reference.html) to choose from, including LLMs, prompt serializers, agents, and chains.
Explore by editing prompt parameters, link chains and agents, track an agent's thought process, and export your flow.
@ -176,13 +235,13 @@ from langflow import load_flow_from_json
flow = load_flow_from_json("path/to/flow.json")
# Now you can use it like any chain
flow("Hey, have you heard of LangFlow?")
flow("Hey, have you heard of Langflow?")
```
## 👋 Contributing
We welcome contributions from developers of all levels to our open-source project on GitHub. If you'd like to contribute, please check our [contributing guidelines](./CONTRIBUTING.md) and help make LangFlow more accessible.
We welcome contributions from developers of all levels to our open-source project on GitHub. If you'd like to contribute, please check our [contributing guidelines](./CONTRIBUTING.md) and help make Langflow more accessible.
Join our [Discord](https://discord.com/invite/EqksyE2EX9) server to ask questions, make suggestions and showcase your projects! 🦾
@ -195,4 +254,4 @@ Join our [Discord](https://discord.com/invite/EqksyE2EX9) server to ask question
## 📄 License
LangFlow is released under the MIT License. See the LICENSE file for details.
Langflow is released under the MIT License. See the LICENSE file for details.

274
poetry.lock generated
View file

@ -170,14 +170,14 @@ typing-extensions = ">=4.1.1"
[[package]]
name = "anyio"
version = "3.7.0"
version = "3.7.1"
description = "High level compatibility layer for multiple asynchronous event loop implementations"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "anyio-3.7.0-py3-none-any.whl", hash = "sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0"},
{file = "anyio-3.7.0.tar.gz", hash = "sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce"},
{file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"},
{file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"},
]
[package.dependencies]
@ -186,7 +186,7 @@ idna = ">=2.8"
sniffio = ">=1.1"
[package.extras]
doc = ["Sphinx (>=6.1.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme", "sphinxcontrib-jquery"]
doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"]
test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
trio = ["trio (<0.22)"]
@ -1609,14 +1609,14 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"]
[[package]]
name = "google-api-python-client"
version = "2.91.0"
version = "2.92.0"
description = "Google API Client Library for Python"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "google-api-python-client-2.91.0.tar.gz", hash = "sha256:d9385ad6e7f95eecd40f7c81e3abfe4b6ad3a84f2c16bcdb66fb7b8dd814ed56"},
{file = "google_api_python_client-2.91.0-py2.py3-none-any.whl", hash = "sha256:6959d21d4b20c0f65c69662ca7b6a8a02fc08f3e7f72d70b28ae3e6e3a5f9ab2"},
{file = "google-api-python-client-2.92.0.tar.gz", hash = "sha256:f38a6e106a7417719715506d36f0a233ec253335e422bda311352866a86c4187"},
{file = "google_api_python_client-2.92.0-py2.py3-none-any.whl", hash = "sha256:e0b74ed5fa9bdb07a66fb030d3f4cae550ed1c07e23600d86450d3c3c5efae51"},
]
[package.dependencies]
@ -1761,14 +1761,14 @@ grpc = ["grpcio (>=1.38.0,<2.0dev)"]
[[package]]
name = "google-cloud-resource-manager"
version = "1.10.1"
version = "1.10.2"
description = "Google Cloud Resource Manager API client library"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "google-cloud-resource-manager-1.10.1.tar.gz", hash = "sha256:c974fb6f9810476cf7b63ea89394c1a8df47f7f2dc2303e728bb74b500bcde67"},
{file = "google_cloud_resource_manager-1.10.1-py2.py3-none-any.whl", hash = "sha256:41a2204532f084c707fde0bc1a9bc95c7e0b739d7072dd0b8a25106667a56184"},
{file = "google-cloud-resource-manager-1.10.2.tar.gz", hash = "sha256:9a7bdd0347ad553376cc66ad317c5223d1ae04bdcf74edcbfcd12605cff7b510"},
{file = "google_cloud_resource_manager-1.10.2-py2.py3-none-any.whl", hash = "sha256:9e074c28326bd1632f1a270c20cfea1ffe98f49cf821033e65bdac55661ffbd5"},
]
[package.dependencies]
@ -2808,14 +2808,14 @@ websockets = ["websockets"]
[[package]]
name = "jina-hubble-sdk"
version = "0.38.0"
version = "0.39.0"
description = "SDK for Hubble API at Jina AI."
category = "main"
optional = false
python-versions = ">=3.7.0"
files = [
{file = "jina-hubble-sdk-0.38.0.tar.gz", hash = "sha256:1667917ed16d75eddd1e0d3b8e9d78ffd611de59500abeca48b05040c7571c4c"},
{file = "jina_hubble_sdk-0.38.0-py3-none-any.whl", hash = "sha256:f887f5a5839b530b59393fe56e9b48d406f52a178739d3a5799c8e201bcf4015"},
{file = "jina-hubble-sdk-0.39.0.tar.gz", hash = "sha256:9021417794a6d3cf3fad8a880cf668a3a986b9d53d5be5fa391aae1767a5b9b0"},
{file = "jina_hubble_sdk-0.39.0-py3-none-any.whl", hash = "sha256:b0edd4b62d742c27d726d68f65a041b3c4d9aa6b3b9b203d5b0e729904161e3e"},
]
[package.dependencies]
@ -3070,96 +3070,100 @@ dev = ["Sphinx (==5.3.0)", "colorama (==0.4.5)", "colorama (==0.4.6)", "freezegu
[[package]]
name = "lxml"
version = "4.9.2"
version = "4.9.3"
description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API."
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*"
files = [
{file = "lxml-4.9.2-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:76cf573e5a365e790396a5cc2b909812633409306c6531a6877c59061e42c4f2"},
{file = "lxml-4.9.2-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b1f42b6921d0e81b1bcb5e395bc091a70f41c4d4e55ba99c6da2b31626c44892"},
{file = "lxml-4.9.2-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9f102706d0ca011de571de32c3247c6476b55bb6bc65a20f682f000b07a4852a"},
{file = "lxml-4.9.2-cp27-cp27m-win32.whl", hash = "sha256:8d0b4612b66ff5d62d03bcaa043bb018f74dfea51184e53f067e6fdcba4bd8de"},
{file = "lxml-4.9.2-cp27-cp27m-win_amd64.whl", hash = "sha256:4c8f293f14abc8fd3e8e01c5bd86e6ed0b6ef71936ded5bf10fe7a5efefbaca3"},
{file = "lxml-4.9.2-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2899456259589aa38bfb018c364d6ae7b53c5c22d8e27d0ec7609c2a1ff78b50"},
{file = "lxml-4.9.2-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6749649eecd6a9871cae297bffa4ee76f90b4504a2a2ab528d9ebe912b101975"},
{file = "lxml-4.9.2-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:a08cff61517ee26cb56f1e949cca38caabe9ea9fbb4b1e10a805dc39844b7d5c"},
{file = "lxml-4.9.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:85cabf64adec449132e55616e7ca3e1000ab449d1d0f9d7f83146ed5bdcb6d8a"},
{file = "lxml-4.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8340225bd5e7a701c0fa98284c849c9b9fc9238abf53a0ebd90900f25d39a4e4"},
{file = "lxml-4.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:1ab8f1f932e8f82355e75dda5413a57612c6ea448069d4fb2e217e9a4bed13d4"},
{file = "lxml-4.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:699a9af7dffaf67deeae27b2112aa06b41c370d5e7633e0ee0aea2e0b6c211f7"},
{file = "lxml-4.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9cc34af337a97d470040f99ba4282f6e6bac88407d021688a5d585e44a23184"},
{file = "lxml-4.9.2-cp310-cp310-win32.whl", hash = "sha256:d02a5399126a53492415d4906ab0ad0375a5456cc05c3fc0fc4ca11771745cda"},
{file = "lxml-4.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:a38486985ca49cfa574a507e7a2215c0c780fd1778bb6290c21193b7211702ab"},
{file = "lxml-4.9.2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:c83203addf554215463b59f6399835201999b5e48019dc17f182ed5ad87205c9"},
{file = "lxml-4.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:2a87fa548561d2f4643c99cd13131acb607ddabb70682dcf1dff5f71f781a4bf"},
{file = "lxml-4.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:d6b430a9938a5a5d85fc107d852262ddcd48602c120e3dbb02137c83d212b380"},
{file = "lxml-4.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3efea981d956a6f7173b4659849f55081867cf897e719f57383698af6f618a92"},
{file = "lxml-4.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:df0623dcf9668ad0445e0558a21211d4e9a149ea8f5666917c8eeec515f0a6d1"},
{file = "lxml-4.9.2-cp311-cp311-win32.whl", hash = "sha256:da248f93f0418a9e9d94b0080d7ebc407a9a5e6d0b57bb30db9b5cc28de1ad33"},
{file = "lxml-4.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:3818b8e2c4b5148567e1b09ce739006acfaa44ce3156f8cbbc11062994b8e8dd"},
{file = "lxml-4.9.2-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca989b91cf3a3ba28930a9fc1e9aeafc2a395448641df1f387a2d394638943b0"},
{file = "lxml-4.9.2-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:822068f85e12a6e292803e112ab876bc03ed1f03dddb80154c395f891ca6b31e"},
{file = "lxml-4.9.2-cp35-cp35m-win32.whl", hash = "sha256:be7292c55101e22f2a3d4d8913944cbea71eea90792bf914add27454a13905df"},
{file = "lxml-4.9.2-cp35-cp35m-win_amd64.whl", hash = "sha256:998c7c41910666d2976928c38ea96a70d1aa43be6fe502f21a651e17483a43c5"},
{file = "lxml-4.9.2-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:b26a29f0b7fc6f0897f043ca366142d2b609dc60756ee6e4e90b5f762c6adc53"},
{file = "lxml-4.9.2-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:ab323679b8b3030000f2be63e22cdeea5b47ee0abd2d6a1dc0c8103ddaa56cd7"},
{file = "lxml-4.9.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:689bb688a1db722485e4610a503e3e9210dcc20c520b45ac8f7533c837be76fe"},
{file = "lxml-4.9.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:f49e52d174375a7def9915c9f06ec4e569d235ad428f70751765f48d5926678c"},
{file = "lxml-4.9.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:36c3c175d34652a35475a73762b545f4527aec044910a651d2bf50de9c3352b1"},
{file = "lxml-4.9.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a35f8b7fa99f90dd2f5dc5a9fa12332642f087a7641289ca6c40d6e1a2637d8e"},
{file = "lxml-4.9.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:58bfa3aa19ca4c0f28c5dde0ff56c520fbac6f0daf4fac66ed4c8d2fb7f22e74"},
{file = "lxml-4.9.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc718cd47b765e790eecb74d044cc8d37d58562f6c314ee9484df26276d36a38"},
{file = "lxml-4.9.2-cp36-cp36m-win32.whl", hash = "sha256:d5bf6545cd27aaa8a13033ce56354ed9e25ab0e4ac3b5392b763d8d04b08e0c5"},
{file = "lxml-4.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:3ab9fa9d6dc2a7f29d7affdf3edebf6ece6fb28a6d80b14c3b2fb9d39b9322c3"},
{file = "lxml-4.9.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:05ca3f6abf5cf78fe053da9b1166e062ade3fa5d4f92b4ed688127ea7d7b1d03"},
{file = "lxml-4.9.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:a5da296eb617d18e497bcf0a5c528f5d3b18dadb3619fbdadf4ed2356ef8d941"},
{file = "lxml-4.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:04876580c050a8c5341d706dd464ff04fd597095cc8c023252566a8826505726"},
{file = "lxml-4.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c9ec3eaf616d67db0764b3bb983962b4f385a1f08304fd30c7283954e6a7869b"},
{file = "lxml-4.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2a29ba94d065945944016b6b74e538bdb1751a1db6ffb80c9d3c2e40d6fa9894"},
{file = "lxml-4.9.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a82d05da00a58b8e4c0008edbc8a4b6ec5a4bc1e2ee0fb6ed157cf634ed7fa45"},
{file = "lxml-4.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:223f4232855ade399bd409331e6ca70fb5578efef22cf4069a6090acc0f53c0e"},
{file = "lxml-4.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d17bc7c2ccf49c478c5bdd447594e82692c74222698cfc9b5daae7ae7e90743b"},
{file = "lxml-4.9.2-cp37-cp37m-win32.whl", hash = "sha256:b64d891da92e232c36976c80ed7ebb383e3f148489796d8d31a5b6a677825efe"},
{file = "lxml-4.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:a0a336d6d3e8b234a3aae3c674873d8f0e720b76bc1d9416866c41cd9500ffb9"},
{file = "lxml-4.9.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:da4dd7c9c50c059aba52b3524f84d7de956f7fef88f0bafcf4ad7dde94a064e8"},
{file = "lxml-4.9.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:821b7f59b99551c69c85a6039c65b75f5683bdc63270fec660f75da67469ca24"},
{file = "lxml-4.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:e5168986b90a8d1f2f9dc1b841467c74221bd752537b99761a93d2d981e04889"},
{file = "lxml-4.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8e20cb5a47247e383cf4ff523205060991021233ebd6f924bca927fcf25cf86f"},
{file = "lxml-4.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:13598ecfbd2e86ea7ae45ec28a2a54fb87ee9b9fdb0f6d343297d8e548392c03"},
{file = "lxml-4.9.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:880bbbcbe2fca64e2f4d8e04db47bcdf504936fa2b33933efd945e1b429bea8c"},
{file = "lxml-4.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7d2278d59425777cfcb19735018d897ca8303abe67cc735f9f97177ceff8027f"},
{file = "lxml-4.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5344a43228767f53a9df6e5b253f8cdca7dfc7b7aeae52551958192f56d98457"},
{file = "lxml-4.9.2-cp38-cp38-win32.whl", hash = "sha256:925073b2fe14ab9b87e73f9a5fde6ce6392da430f3004d8b72cc86f746f5163b"},
{file = "lxml-4.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:9b22c5c66f67ae00c0199f6055705bc3eb3fcb08d03d2ec4059a2b1b25ed48d7"},
{file = "lxml-4.9.2-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:5f50a1c177e2fa3ee0667a5ab79fdc6b23086bc8b589d90b93b4bd17eb0e64d1"},
{file = "lxml-4.9.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:090c6543d3696cbe15b4ac6e175e576bcc3f1ccfbba970061b7300b0c15a2140"},
{file = "lxml-4.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:63da2ccc0857c311d764e7d3d90f429c252e83b52d1f8f1d1fe55be26827d1f4"},
{file = "lxml-4.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:5b4545b8a40478183ac06c073e81a5ce4cf01bf1734962577cf2bb569a5b3bbf"},
{file = "lxml-4.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2e430cd2824f05f2d4f687701144556646bae8f249fd60aa1e4c768ba7018947"},
{file = "lxml-4.9.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6804daeb7ef69e7b36f76caddb85cccd63d0c56dedb47555d2fc969e2af6a1a5"},
{file = "lxml-4.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a6e441a86553c310258aca15d1c05903aaf4965b23f3bc2d55f200804e005ee5"},
{file = "lxml-4.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ca34efc80a29351897e18888c71c6aca4a359247c87e0b1c7ada14f0ab0c0fb2"},
{file = "lxml-4.9.2-cp39-cp39-win32.whl", hash = "sha256:6b418afe5df18233fc6b6093deb82a32895b6bb0b1155c2cdb05203f583053f1"},
{file = "lxml-4.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:f1496ea22ca2c830cbcbd473de8f114a320da308438ae65abad6bab7867fe38f"},
{file = "lxml-4.9.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:b264171e3143d842ded311b7dccd46ff9ef34247129ff5bf5066123c55c2431c"},
{file = "lxml-4.9.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0dc313ef231edf866912e9d8f5a042ddab56c752619e92dfd3a2c277e6a7299a"},
{file = "lxml-4.9.2-pp38-pypy38_pp73-macosx_10_15_x86_64.whl", hash = "sha256:16efd54337136e8cd72fb9485c368d91d77a47ee2d42b057564aae201257d419"},
{file = "lxml-4.9.2-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0f2b1e0d79180f344ff9f321327b005ca043a50ece8713de61d1cb383fb8ac05"},
{file = "lxml-4.9.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:7b770ed79542ed52c519119473898198761d78beb24b107acf3ad65deae61f1f"},
{file = "lxml-4.9.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efa29c2fe6b4fdd32e8ef81c1528506895eca86e1d8c4657fda04c9b3786ddf9"},
{file = "lxml-4.9.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7e91ee82f4199af8c43d8158024cbdff3d931df350252288f0d4ce656df7f3b5"},
{file = "lxml-4.9.2-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:b23e19989c355ca854276178a0463951a653309fb8e57ce674497f2d9f208746"},
{file = "lxml-4.9.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:01d36c05f4afb8f7c20fd9ed5badca32a2029b93b1750f571ccc0b142531caf7"},
{file = "lxml-4.9.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7b515674acfdcadb0eb5d00d8a709868173acece5cb0be3dd165950cbfdf5409"},
{file = "lxml-4.9.2.tar.gz", hash = "sha256:2455cfaeb7ac70338b3257f41e21f0724f4b5b0c0e7702da67ee6c3640835b67"},
{file = "lxml-4.9.3-cp27-cp27m-macosx_11_0_x86_64.whl", hash = "sha256:b0a545b46b526d418eb91754565ba5b63b1c0b12f9bd2f808c852d9b4b2f9b5c"},
{file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:075b731ddd9e7f68ad24c635374211376aa05a281673ede86cbe1d1b3455279d"},
{file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1e224d5755dba2f4a9498e150c43792392ac9b5380aa1b845f98a1618c94eeef"},
{file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c0781a98ff5e6586926293e59480b64ddd46282953203c76ae15dbbbf302e8bb"},
{file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cef2502e7e8a96fe5ad686d60b49e1ab03e438bd9123987994528febd569868e"},
{file = "lxml-4.9.3-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b86164d2cff4d3aaa1f04a14685cbc072efd0b4f99ca5708b2ad1b9b5988a991"},
{file = "lxml-4.9.3-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:42871176e7896d5d45138f6d28751053c711ed4d48d8e30b498da155af39aebd"},
{file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:411007c0d88188d9f621b11d252cce90c4a2d1a49db6c068e3c16422f306eab8"},
{file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:cd47b4a0d41d2afa3e58e5bf1f62069255aa2fd6ff5ee41604418ca925911d76"},
{file = "lxml-4.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e2cb47860da1f7e9a5256254b74ae331687b9672dfa780eed355c4c9c3dbd23"},
{file = "lxml-4.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1247694b26342a7bf47c02e513d32225ededd18045264d40758abeb3c838a51f"},
{file = "lxml-4.9.3-cp310-cp310-win32.whl", hash = "sha256:cdb650fc86227eba20de1a29d4b2c1bfe139dc75a0669270033cb2ea3d391b85"},
{file = "lxml-4.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:97047f0d25cd4bcae81f9ec9dc290ca3e15927c192df17331b53bebe0e3ff96d"},
{file = "lxml-4.9.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:1f447ea5429b54f9582d4b955f5f1985f278ce5cf169f72eea8afd9502973dd5"},
{file = "lxml-4.9.3-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:57d6ba0ca2b0c462f339640d22882acc711de224d769edf29962b09f77129cbf"},
{file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:71c52db65e4b56b8ddc5bb89fb2e66c558ed9d1a74a45ceb7dcb20c191c3df2f"},
{file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d73d8ecf8ecf10a3bd007f2192725a34bd62898e8da27eb9d32a58084f93962b"},
{file = "lxml-4.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0a3d3487f07c1d7f150894c238299934a2a074ef590b583103a45002035be120"},
{file = "lxml-4.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e28c51fa0ce5674be9f560c6761c1b441631901993f76700b1b30ca6c8378d6"},
{file = "lxml-4.9.3-cp311-cp311-win32.whl", hash = "sha256:0bfd0767c5c1de2551a120673b72e5d4b628737cb05414f03c3277bf9bed3305"},
{file = "lxml-4.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:25f32acefac14ef7bd53e4218fe93b804ef6f6b92ffdb4322bb6d49d94cad2bc"},
{file = "lxml-4.9.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:d3ff32724f98fbbbfa9f49d82852b159e9784d6094983d9a8b7f2ddaebb063d4"},
{file = "lxml-4.9.3-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:48d6ed886b343d11493129e019da91d4039826794a3e3027321c56d9e71505be"},
{file = "lxml-4.9.3-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9a92d3faef50658dd2c5470af249985782bf754c4e18e15afb67d3ab06233f13"},
{file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b4e4bc18382088514ebde9328da057775055940a1f2e18f6ad2d78aa0f3ec5b9"},
{file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fc9b106a1bf918db68619fdcd6d5ad4f972fdd19c01d19bdb6bf63f3589a9ec5"},
{file = "lxml-4.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:d37017287a7adb6ab77e1c5bee9bcf9660f90ff445042b790402a654d2ad81d8"},
{file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:56dc1f1ebccc656d1b3ed288f11e27172a01503fc016bcabdcbc0978b19352b7"},
{file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:578695735c5a3f51569810dfebd05dd6f888147a34f0f98d4bb27e92b76e05c2"},
{file = "lxml-4.9.3-cp35-cp35m-win32.whl", hash = "sha256:704f61ba8c1283c71b16135caf697557f5ecf3e74d9e453233e4771d68a1f42d"},
{file = "lxml-4.9.3-cp35-cp35m-win_amd64.whl", hash = "sha256:c41bfca0bd3532d53d16fd34d20806d5c2b1ace22a2f2e4c0008570bf2c58833"},
{file = "lxml-4.9.3-cp36-cp36m-macosx_11_0_x86_64.whl", hash = "sha256:64f479d719dc9f4c813ad9bb6b28f8390360660b73b2e4beb4cb0ae7104f1c12"},
{file = "lxml-4.9.3-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:dd708cf4ee4408cf46a48b108fb9427bfa00b9b85812a9262b5c668af2533ea5"},
{file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c31c7462abdf8f2ac0577d9f05279727e698f97ecbb02f17939ea99ae8daa98"},
{file = "lxml-4.9.3-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:4930be26af26ac545c3dffb662521d4e6268352866956672231887d18f0eaab2"},
{file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4aec80cde9197340bc353d2768e2a75f5f60bacda2bab72ab1dc499589b3878c"},
{file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:14e019fd83b831b2e61baed40cab76222139926b1fb5ed0e79225bc0cae14584"},
{file = "lxml-4.9.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0c0850c8b02c298d3c7006b23e98249515ac57430e16a166873fc47a5d549287"},
{file = "lxml-4.9.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:aca086dc5f9ef98c512bac8efea4483eb84abbf926eaeedf7b91479feb092458"},
{file = "lxml-4.9.3-cp36-cp36m-win32.whl", hash = "sha256:50baa9c1c47efcaef189f31e3d00d697c6d4afda5c3cde0302d063492ff9b477"},
{file = "lxml-4.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bef4e656f7d98aaa3486d2627e7d2df1157d7e88e7efd43a65aa5dd4714916cf"},
{file = "lxml-4.9.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:46f409a2d60f634fe550f7133ed30ad5321ae2e6630f13657fb9479506b00601"},
{file = "lxml-4.9.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:4c28a9144688aef80d6ea666c809b4b0e50010a2aca784c97f5e6bf143d9f129"},
{file = "lxml-4.9.3-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:53ace1c1fd5a74ef662f844a0413446c0629d151055340e9893da958a374f70d"},
{file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17a753023436a18e27dd7769e798ce302963c236bc4114ceee5b25c18c52c693"},
{file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7d298a1bd60c067ea75d9f684f5f3992c9d6766fadbc0bcedd39750bf344c2f4"},
{file = "lxml-4.9.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:081d32421db5df44c41b7f08a334a090a545c54ba977e47fd7cc2deece78809a"},
{file = "lxml-4.9.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:23eed6d7b1a3336ad92d8e39d4bfe09073c31bfe502f20ca5116b2a334f8ec02"},
{file = "lxml-4.9.3-cp37-cp37m-win32.whl", hash = "sha256:1509dd12b773c02acd154582088820893109f6ca27ef7291b003d0e81666109f"},
{file = "lxml-4.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:120fa9349a24c7043854c53cae8cec227e1f79195a7493e09e0c12e29f918e52"},
{file = "lxml-4.9.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4d2d1edbca80b510443f51afd8496be95529db04a509bc8faee49c7b0fb6d2cc"},
{file = "lxml-4.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8d7e43bd40f65f7d97ad8ef5c9b1778943d02f04febef12def25f7583d19baac"},
{file = "lxml-4.9.3-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:6fc3c450eaa0b56f815c7b62f2b7fba7266c4779adcf1cece9e6deb1de7305ce"},
{file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:65299ea57d82fb91c7f019300d24050c4ddeb7c5a190e076b5f48a2b43d19c42"},
{file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:eadfbbbfb41b44034a4c757fd5d70baccd43296fb894dba0295606a7cf3124aa"},
{file = "lxml-4.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3e9bdd30efde2b9ccfa9cb5768ba04fe71b018a25ea093379c857c9dad262c40"},
{file = "lxml-4.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fcdd00edfd0a3001e0181eab3e63bd5c74ad3e67152c84f93f13769a40e073a7"},
{file = "lxml-4.9.3-cp38-cp38-win32.whl", hash = "sha256:57aba1bbdf450b726d58b2aea5fe47c7875f5afb2c4a23784ed78f19a0462574"},
{file = "lxml-4.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:92af161ecbdb2883c4593d5ed4815ea71b31fafd7fd05789b23100d081ecac96"},
{file = "lxml-4.9.3-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:9bb6ad405121241e99a86efff22d3ef469024ce22875a7ae045896ad23ba2340"},
{file = "lxml-4.9.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8ed74706b26ad100433da4b9d807eae371efaa266ffc3e9191ea436087a9d6a7"},
{file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:303bf1edce6ced16bf67a18a1cf8339d0db79577eec5d9a6d4a80f0fb10aa2da"},
{file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:5515edd2a6d1a5a70bfcdee23b42ec33425e405c5b351478ab7dc9347228f96e"},
{file = "lxml-4.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:690dafd0b187ed38583a648076865d8c229661ed20e48f2335d68e2cf7dc829d"},
{file = "lxml-4.9.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b6420a005548ad52154c8ceab4a1290ff78d757f9e5cbc68f8c77089acd3c432"},
{file = "lxml-4.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bb3bb49c7a6ad9d981d734ef7c7193bc349ac338776a0360cc671eaee89bcf69"},
{file = "lxml-4.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d27be7405547d1f958b60837dc4c1007da90b8b23f54ba1f8b728c78fdb19d50"},
{file = "lxml-4.9.3-cp39-cp39-win32.whl", hash = "sha256:8df133a2ea5e74eef5e8fc6f19b9e085f758768a16e9877a60aec455ed2609b2"},
{file = "lxml-4.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:4dd9a263e845a72eacb60d12401e37c616438ea2e5442885f65082c276dfb2b2"},
{file = "lxml-4.9.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6689a3d7fd13dc687e9102a27e98ef33730ac4fe37795d5036d18b4d527abd35"},
{file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:f6bdac493b949141b733c5345b6ba8f87a226029cbabc7e9e121a413e49441e0"},
{file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c2006f5c8d28dee289f7020f721354362fa304acbaaf9745751ac4006650254b"},
{file = "lxml-4.9.3-pp38-pypy38_pp73-macosx_11_0_x86_64.whl", hash = "sha256:5c245b783db29c4e4fbbbfc9c5a78be496c9fea25517f90606aa1f6b2b3d5f7b"},
{file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4fb960a632a49f2f089d522f70496640fdf1218f1243889da3822e0a9f5f3ba7"},
{file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9719fe17307a9e814580af1f5c6e05ca593b12fb7e44fe62450a5384dbf61b4b"},
{file = "lxml-4.9.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:3331bece23c9ee066e0fb3f96c61322b9e0f54d775fccefff4c38ca488de283a"},
{file = "lxml-4.9.3-pp39-pypy39_pp73-macosx_11_0_x86_64.whl", hash = "sha256:ed667f49b11360951e201453fc3967344d0d0263aa415e1619e85ae7fd17b4e0"},
{file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8b77946fd508cbf0fccd8e400a7f71d4ac0e1595812e66025bac475a8e811694"},
{file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4"},
{file = "lxml-4.9.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f3df3db1d336b9356dd3112eae5f5c2b8b377f3bc826848567f10bfddfee77e9"},
{file = "lxml-4.9.3.tar.gz", hash = "sha256:48628bd53a426c9eb9bc066a923acaa0878d1e86129fd5359aee99285f4eed9c"},
]
[package.extras]
cssselect = ["cssselect (>=0.7)"]
html5 = ["html5lib"]
htmlsoup = ["BeautifulSoup4"]
source = ["Cython (>=0.29.7)"]
source = ["Cython (>=0.29.35)"]
[[package]]
name = "lz4"
@ -4625,14 +4629,14 @@ twisted = ["twisted"]
[[package]]
name = "prompt-toolkit"
version = "3.0.38"
version = "3.0.39"
description = "Library for building powerful interactive command lines in Python"
category = "dev"
optional = false
python-versions = ">=3.7.0"
files = [
{file = "prompt_toolkit-3.0.38-py3-none-any.whl", hash = "sha256:45ea77a2f7c60418850331366c81cf6b5b9cf4c7fd34616f733c5427e6abbb1f"},
{file = "prompt_toolkit-3.0.38.tar.gz", hash = "sha256:23ac5d50538a9a38c8bde05fecb47d0b403ecd0662857a86f886f798563d5b9b"},
{file = "prompt_toolkit-3.0.39-py3-none-any.whl", hash = "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88"},
{file = "prompt_toolkit-3.0.39.tar.gz", hash = "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac"},
]
[package.dependencies]
@ -5029,48 +5033,48 @@ files = [
[[package]]
name = "pydantic"
version = "1.10.10"
version = "1.10.11"
description = "Data validation and settings management using python type hints"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "pydantic-1.10.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:adad1ee4ab9888f12dac2529276704e719efcf472e38df7813f5284db699b4ec"},
{file = "pydantic-1.10.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7a7db03339893feef2092ff7b1afc9497beed15ebd4af84c3042a74abce02d48"},
{file = "pydantic-1.10.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67b3714b97ff84b2689654851c2426389bcabfac9080617bcf4306c69db606f6"},
{file = "pydantic-1.10.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edfdf0a5abc5c9bf2052ebaec20e67abd52e92d257e4f2d30e02c354ed3e6030"},
{file = "pydantic-1.10.10-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20a3b30fd255eeeb63caa9483502ba96b7795ce5bf895c6a179b3d909d9f53a6"},
{file = "pydantic-1.10.10-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:db4c7f7e60ca6f7d6c1785070f3e5771fcb9b2d88546e334d2f2c3934d949028"},
{file = "pydantic-1.10.10-cp310-cp310-win_amd64.whl", hash = "sha256:a2d5be50ac4a0976817144c7d653e34df2f9436d15555189f5b6f61161d64183"},
{file = "pydantic-1.10.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:566a04ba755e8f701b074ffb134ddb4d429f75d5dced3fbd829a527aafe74c71"},
{file = "pydantic-1.10.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f79db3652ed743309f116ba863dae0c974a41b688242482638b892246b7db21d"},
{file = "pydantic-1.10.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c62376890b819bebe3c717a9ac841a532988372b7e600e76f75c9f7c128219d5"},
{file = "pydantic-1.10.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4870f13a4fafd5bc3e93cff3169222534fad867918b188e83ee0496452978437"},
{file = "pydantic-1.10.10-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:990027e77cda6072a566e433b6962ca3b96b4f3ae8bd54748e9d62a58284d9d7"},
{file = "pydantic-1.10.10-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8c40964596809eb616d94f9c7944511f620a1103d63d5510440ed2908fc410af"},
{file = "pydantic-1.10.10-cp311-cp311-win_amd64.whl", hash = "sha256:ea9eebc2ebcba3717e77cdeee3f6203ffc0e78db5f7482c68b1293e8cc156e5e"},
{file = "pydantic-1.10.10-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:762aa598f79b4cac2f275d13336b2dd8662febee2a9c450a49a2ab3bec4b385f"},
{file = "pydantic-1.10.10-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dab5219659f95e357d98d70577b361383057fb4414cfdb587014a5f5c595f7b"},
{file = "pydantic-1.10.10-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3d4ee957a727ccb5a36f1b0a6dbd9fad5dedd2a41eada99a8df55c12896e18d"},
{file = "pydantic-1.10.10-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b69f9138dec566962ec65623c9d57bee44412d2fc71065a5f3ebb3820bdeee96"},
{file = "pydantic-1.10.10-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7aa75d1bd9cc275cf9782f50f60cddaf74cbaae19b6ada2a28e737edac420312"},
{file = "pydantic-1.10.10-cp37-cp37m-win_amd64.whl", hash = "sha256:9f62a727f5c590c78c2d12fda302d1895141b767c6488fe623098f8792255fe5"},
{file = "pydantic-1.10.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:aac218feb4af73db8417ca7518fb3bade4534fcca6e3fb00f84966811dd94450"},
{file = "pydantic-1.10.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:88546dc10a40b5b52cae87d64666787aeb2878f9a9b37825aedc2f362e7ae1da"},
{file = "pydantic-1.10.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c41bbaae89e32fc582448e71974de738c055aef5ab474fb25692981a08df808a"},
{file = "pydantic-1.10.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b71bd504d1573b0b722ae536e8ffb796bedeef978979d076bf206e77dcc55a5"},
{file = "pydantic-1.10.10-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e088e3865a2270ecbc369924cd7d9fbc565667d9158e7f304e4097ebb9cf98dd"},
{file = "pydantic-1.10.10-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3403a090db45d4027d2344859d86eb797484dfda0706cf87af79ace6a35274ef"},
{file = "pydantic-1.10.10-cp38-cp38-win_amd64.whl", hash = "sha256:e0014e29637125f4997c174dd6167407162d7af0da73414a9340461ea8573252"},
{file = "pydantic-1.10.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9965e49c6905840e526e5429b09e4c154355b6ecc0a2f05492eda2928190311d"},
{file = "pydantic-1.10.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:748d10ab6089c5d196e1c8be9de48274f71457b01e59736f7a09c9dc34f51887"},
{file = "pydantic-1.10.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86936c383f7c38fd26d35107eb669c85d8f46dfceae873264d9bab46fe1c7dde"},
{file = "pydantic-1.10.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a26841be620309a9697f5b1ffc47dce74909e350c5315ccdac7a853484d468a"},
{file = "pydantic-1.10.10-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:409b810f387610cc7405ab2fa6f62bdf7ea485311845a242ebc0bd0496e7e5ac"},
{file = "pydantic-1.10.10-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ce937a2a2c020bcad1c9fde02892392a1123de6dda906ddba62bfe8f3e5989a2"},
{file = "pydantic-1.10.10-cp39-cp39-win_amd64.whl", hash = "sha256:37ebddef68370e6f26243acc94de56d291e01227a67b2ace26ea3543cf53dd5f"},
{file = "pydantic-1.10.10-py3-none-any.whl", hash = "sha256:a5939ec826f7faec434e2d406ff5e4eaf1716eb1f247d68cd3d0b3612f7b4c8a"},
{file = "pydantic-1.10.10.tar.gz", hash = "sha256:3b8d5bd97886f9eb59260594207c9f57dce14a6f869c6ceea90188715d29921a"},
{file = "pydantic-1.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ff44c5e89315b15ff1f7fdaf9853770b810936d6b01a7bcecaa227d2f8fe444f"},
{file = "pydantic-1.10.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a6c098d4ab5e2d5b3984d3cb2527e2d6099d3de85630c8934efcfdc348a9760e"},
{file = "pydantic-1.10.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16928fdc9cb273c6af00d9d5045434c39afba5f42325fb990add2c241402d151"},
{file = "pydantic-1.10.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0588788a9a85f3e5e9ebca14211a496409cb3deca5b6971ff37c556d581854e7"},
{file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9baf78b31da2dc3d3f346ef18e58ec5f12f5aaa17ac517e2ffd026a92a87588"},
{file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:373c0840f5c2b5b1ccadd9286782852b901055998136287828731868027a724f"},
{file = "pydantic-1.10.11-cp310-cp310-win_amd64.whl", hash = "sha256:c3339a46bbe6013ef7bdd2844679bfe500347ac5742cd4019a88312aa58a9847"},
{file = "pydantic-1.10.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:08a6c32e1c3809fbc49debb96bf833164f3438b3696abf0fbeceb417d123e6eb"},
{file = "pydantic-1.10.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a451ccab49971af043ec4e0d207cbc8cbe53dbf148ef9f19599024076fe9c25b"},
{file = "pydantic-1.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b02d24f7b2b365fed586ed73582c20f353a4c50e4be9ba2c57ab96f8091ddae"},
{file = "pydantic-1.10.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f34739a89260dfa420aa3cbd069fbcc794b25bbe5c0a214f8fb29e363484b66"},
{file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e297897eb4bebde985f72a46a7552a7556a3dd11e7f76acda0c1093e3dbcf216"},
{file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d185819a7a059550ecb85d5134e7d40f2565f3dd94cfd870132c5f91a89cf58c"},
{file = "pydantic-1.10.11-cp311-cp311-win_amd64.whl", hash = "sha256:4400015f15c9b464c9db2d5d951b6a780102cfa5870f2c036d37c23b56f7fc1b"},
{file = "pydantic-1.10.11-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2417de68290434461a266271fc57274a138510dca19982336639484c73a07af6"},
{file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:331c031ba1554b974c98679bd0780d89670d6fd6f53f5d70b10bdc9addee1713"},
{file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8268a735a14c308923e8958363e3a3404f6834bb98c11f5ab43251a4e410170c"},
{file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:44e51ba599c3ef227e168424e220cd3e544288c57829520dc90ea9cb190c3248"},
{file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d7781f1d13b19700b7949c5a639c764a077cbbdd4322ed505b449d3ca8edcb36"},
{file = "pydantic-1.10.11-cp37-cp37m-win_amd64.whl", hash = "sha256:7522a7666157aa22b812ce14c827574ddccc94f361237ca6ea8bb0d5c38f1629"},
{file = "pydantic-1.10.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc64eab9b19cd794a380179ac0e6752335e9555d214cfcb755820333c0784cb3"},
{file = "pydantic-1.10.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8dc77064471780262b6a68fe67e013298d130414d5aaf9b562c33987dbd2cf4f"},
{file = "pydantic-1.10.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe429898f2c9dd209bd0632a606bddc06f8bce081bbd03d1c775a45886e2c1cb"},
{file = "pydantic-1.10.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:192c608ad002a748e4a0bed2ddbcd98f9b56df50a7c24d9a931a8c5dd053bd3d"},
{file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ef55392ec4bb5721f4ded1096241e4b7151ba6d50a50a80a2526c854f42e6a2f"},
{file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:41e0bb6efe86281623abbeeb0be64eab740c865388ee934cd3e6a358784aca6e"},
{file = "pydantic-1.10.11-cp38-cp38-win_amd64.whl", hash = "sha256:265a60da42f9f27e0b1014eab8acd3e53bd0bad5c5b4884e98a55f8f596b2c19"},
{file = "pydantic-1.10.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:469adf96c8e2c2bbfa655fc7735a2a82f4c543d9fee97bd113a7fb509bf5e622"},
{file = "pydantic-1.10.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e6cbfbd010b14c8a905a7b10f9fe090068d1744d46f9e0c021db28daeb8b6de1"},
{file = "pydantic-1.10.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abade85268cc92dff86d6effcd917893130f0ff516f3d637f50dadc22ae93999"},
{file = "pydantic-1.10.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9738b0f2e6c70f44ee0de53f2089d6002b10c33264abee07bdb5c7f03038303"},
{file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:787cf23e5a0cde753f2eabac1b2e73ae3844eb873fd1f5bdbff3048d8dbb7604"},
{file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:174899023337b9fc685ac8adaa7b047050616136ccd30e9070627c1aaab53a13"},
{file = "pydantic-1.10.11-cp39-cp39-win_amd64.whl", hash = "sha256:1954f8778489a04b245a1e7b8b22a9d3ea8ef49337285693cf6959e4b757535e"},
{file = "pydantic-1.10.11-py3-none-any.whl", hash = "sha256:008c5e266c8aada206d0627a011504e14268a62091450210eda7c07fabe6963e"},
{file = "pydantic-1.10.11.tar.gz", hash = "sha256:f66d479cf7eb331372c470614be6511eae96f1f120344c25f3f9bb59fb1b5528"},
]
[package.dependencies]
@ -7043,14 +7047,14 @@ files = [
[[package]]
name = "types-pillow"
version = "9.5.0.5"
version = "9.5.0.6"
description = "Typing stubs for Pillow"
category = "dev"
optional = false
python-versions = "*"
files = [
{file = "types-Pillow-9.5.0.5.tar.gz", hash = "sha256:de9877aa1e6226b6479459ca84df02fd7e999b970c79cfee3b8298840336e77c"},
{file = "types_Pillow-9.5.0.5-py3-none-any.whl", hash = "sha256:2b17f95c5c16e4962e4032bdb95494766a85569fa278ee21e5fcbbd318e9ccd2"},
{file = "types-Pillow-9.5.0.6.tar.gz", hash = "sha256:6a0cad40686e5c35fe7ada70f52bd3970395d31ece33486609e5420e820a9e4e"},
{file = "types_Pillow-9.5.0.6-py3-none-any.whl", hash = "sha256:1d238abaa9d529b04941d805b7f4d3f7df30702bb14521ec507617f117406fb4"},
]
[[package]]

View file

@ -1,6 +1,6 @@
[tool.poetry]
name = "langflow"
version = "0.2.11"
version = "0.2.13"
description = "A Python package with a built-in web application"
authors = ["Logspace <contact@logspace.ai>"]
maintainers = [
@ -48,7 +48,7 @@ psycopg2-binary = "^2.9.6"
pyarrow = "^12.0.0"
tiktoken = "~0.4.0"
wikipedia = "^1.4.0"
langchain-serve = { version = ">0.0.49", optional = true }
langchain-serve = { version = ">0.0.51", optional = true }
qdrant-client = "^1.3.0"
websockets = "^10.3"
weaviate-client = "^3.21.0"

View file

@ -35,7 +35,7 @@ fi
# Create a firewall rule to allow IAP traffic
firewall_iap_exists=$(gcloud compute firewall-rules list --filter="name=allow-iap" --format="value(name)")
if [[ -z "$firewall_iap_exists" ]]; then
gcloud compute firewall-rules create allow-iap --network $VPC_NAME --allow tcp:80,tcp:443,tcp:22,:tcp:3389 --source-ranges 35.235.240.0/20 --direction INGRESS
gcloud compute firewall-rules create allow-iap --network $VPC_NAME --allow tcp:80,tcp:443,tcp:22,tcp:3389 --source-ranges 35.235.240.0/20 --direction INGRESS
fi
# Define the startup script as a multiline Bash here-doc

View file

@ -1,6 +1,6 @@
from importlib import metadata
from langflow.cache import cache_manager
from langflow.processing.process import load_flow_from_json
from langflow.cache import cache_manager # noqa: E402
from langflow.processing.process import load_flow_from_json # noqa: E402
try:
__version__ = metadata.version(__package__)
@ -9,4 +9,5 @@ except metadata.PackageNotFoundError:
__version__ = ""
del metadata # optional, avoids polluting the results of dir(__package__)
__all__ = ["load_flow_from_json", "cache_manager"]

View file

@ -1,3 +1,4 @@
import os
import sys
import time
import httpx
@ -33,6 +34,10 @@ def update_settings(
remove_api_keys: bool = False,
):
"""Update the settings from a config file."""
# Check for database_url in the environment variables
database_url = database_url or os.getenv("langflow_database_url")
if config:
settings.update_from_yaml(config, dev=dev)
if database_url:
@ -43,6 +48,26 @@ def update_settings(
settings.update_settings(cache=cache)
def load_params():
"""
Load the parameters from the environment variables.
"""
global_vars = globals()
for key, value in global_vars.items():
env_key = f"LANGFLOW_{key.upper()}"
if env_key in os.environ:
if isinstance(value, bool):
# Handle booleans
global_vars[key] = os.getenv(env_key, str(value)).lower() == "true"
elif isinstance(value, int):
# Handle integers
global_vars[key] = int(os.getenv(env_key, str(value)))
elif isinstance(value, str) or value is None:
# Handle strings and None values
global_vars[key] = os.getenv(env_key, str(value))
def serve_on_jcloud():
"""
Deploy Langflow server on Jina AI Cloud
@ -91,19 +116,27 @@ def serve_on_jcloud():
@app.command()
def serve(
host: str = typer.Option("127.0.0.1", help="Host to bind the server to."),
workers: int = typer.Option(1, help="Number of worker processes."),
host: str = typer.Option(
"127.0.0.1", help="Host to bind the server to.", envvar="LANGFLOW_HOST"
),
workers: int = typer.Option(
1, help="Number of worker processes.", envvar="LANGFLOW_WORKERS"
),
timeout: int = typer.Option(60, help="Worker timeout in seconds."),
port: int = typer.Option(7860, help="Port to listen on."),
port: int = typer.Option(7860, help="Port to listen on.", envvar="LANGFLOW_PORT"),
config: str = typer.Option("config.yaml", help="Path to the configuration file."),
# .env file param
env_file: Path = typer.Option(
".env", help="Path to the .env file containing environment variables."
),
log_level: str = typer.Option("critical", help="Logging level."),
log_file: Path = typer.Option("logs/langflow.log", help="Path to the log file."),
cache: str = typer.Argument(
envvar="LANGCHAIN_CACHE",
log_level: str = typer.Option(
"critical", help="Logging level.", envvar="LANGFLOW_LOG_LEVEL"
),
log_file: Path = typer.Option(
"logs/langflow.log", help="Path to the log file.", envvar="LANGFLOW_LOG_FILE"
),
cache: str = typer.Option(
envvar="LANGFLOW_LANGCHAIN_CACHE",
help="Type of cache to use. (InMemoryCache, SQLiteCache)",
default="SQLiteCache",
),
@ -112,27 +145,35 @@ def serve(
database_url: str = typer.Option(
None,
help="Database URL to connect to. If not provided, a local SQLite database will be used.",
envvar="LANGFLOW_DATABASE_URL",
),
path: str = typer.Option(
None,
help="Path to the frontend directory containing build files. This is for development purposes only.",
envvar="LANGFLOW_FRONTEND_PATH",
),
open_browser: bool = typer.Option(
True, help="Open the browser after starting the server."
True,
help="Open the browser after starting the server.",
envvar="LANGFLOW_OPEN_BROWSER",
),
remove_api_keys: bool = typer.Option(
False, help="Remove API keys from the projects saved in the database."
False,
help="Remove API keys from the projects saved in the database.",
envvar="LANGFLOW_REMOVE_API_KEYS",
),
):
"""
Run the Langflow server.
"""
# override env variables with .env file
if env_file:
load_dotenv(env_file, override=True)
load_params()
if jcloud:
return serve_on_jcloud()
load_dotenv(env_file)
configure(log_level=log_level, log_file=log_file)
update_settings(
config,
@ -224,7 +265,7 @@ def get_free_port(port):
def print_banner(host, port):
# console = Console()
word = "LangFlow"
word = "Langflow"
colors = ["#3300cc"]
styled_word = ""

View file

@ -23,7 +23,7 @@ class GraphData(BaseModel):
class ExportedFlow(BaseModel):
"""Exported flow from LangFlow."""
"""Exported flow from Langflow."""
description: str
name: str

View file

@ -2,17 +2,34 @@ from langflow.settings import settings
from sqlmodel import SQLModel, Session, create_engine
from langflow.utils.logger import logger
if settings.database_url.startswith("sqlite"):
if settings.database_url and settings.database_url.startswith("sqlite"):
connect_args = {"check_same_thread": False}
else:
connect_args = {}
if not settings.database_url:
raise RuntimeError("No database_url provided")
engine = create_engine(settings.database_url, connect_args=connect_args)
def create_db_and_tables():
logger.debug("Creating database and tables")
SQLModel.metadata.create_all(engine)
logger.debug("Database and tables created")
try:
SQLModel.metadata.create_all(engine)
except Exception as exc:
logger.error(f"Error creating database and tables: {exc}")
raise RuntimeError("Error creating database and tables") from exc
# Now check if the table Flow exists, if not, something went wrong
# and we need to create the tables again.
from sqlalchemy import inspect
inspector = inspect(engine)
if "flow" not in inspector.get_table_names():
logger.error("Something went wrong creating the database and tables.")
logger.error("Please check your database settings.")
raise RuntimeError("Something went wrong creating the database and tables.")
else:
logger.debug("Database and tables created successfully")
def get_session():

View file

@ -217,7 +217,7 @@ class Vertex:
self.edges.append(edge)
def __repr__(self) -> str:
return f"Node(id={self.id}, data={self.data})"
return f"Vertex(id={self.id}, data={self.data})"
def __eq__(self, __o: object) -> bool:
return self.id == __o.id if isinstance(__o, Vertex) else False

View file

@ -66,17 +66,24 @@ def extract_input_variables_from_prompt(prompt: str) -> list[str]:
def setup_llm_caching():
"""Setup LLM caching."""
from langflow.settings import settings
try:
import langchain
from langflow.settings import settings
from langflow.interface.importing.utils import import_class
cache_class = import_class(f"langchain.cache.{settings.cache}")
logger.debug(f"Setting up LLM caching with {cache_class.__name__}")
langchain.llm_cache = cache_class()
logger.info(f"LLM caching setup with {cache_class.__name__}")
set_langchain_cache(settings)
except ImportError:
logger.warning(f"Could not import {settings.cache}. ")
except Exception as exc:
logger.warning(f"Could not setup LLM caching. Error: {exc}")
# TODO Rename this here and in `setup_llm_caching`
def set_langchain_cache(settings):
import langchain
from langflow.interface.importing.utils import import_class
cache_type = os.getenv("LANGFLOW_LANGCHAIN_CACHE")
cache_class = import_class(f"langchain.cache.{cache_type or settings.cache}")
logger.debug(f"Setting up LLM caching with {cache_class.__name__}")
langchain.llm_cache = cache_class()
logger.info(f"LLM caching setup with {cache_class.__name__}")

View file

@ -1,16 +1,15 @@
# This file is used by lc-serve to load the mounted app and serve it.
from pathlib import Path
import os
from fastapi.staticfiles import StaticFiles
# Use the JCLOUD_WORKSPACE for db URL if it's provided by JCloud.
if 'JCLOUD_WORKSPACE' in os.environ:
os.environ[
'LANGFLOW_DATABASE_URL'
] = f"sqlite:///{os.environ['JCLOUD_WORKSPACE']}/langflow.db"
from langflow.main import create_app
from langflow.main import setup_app
from langflow.utils.logger import configure
app = create_app()
path = Path(__file__).parent
static_files_dir = path / "frontend"
app.mount(
"/",
StaticFiles(directory=static_files_dir, html=True),
name="static",
)
configure(log_level="DEBUG")
app = setup_app()

View file

@ -61,7 +61,7 @@ def setup_static_files(app: FastAPI, static_files_dir: Path):
# app = create_app()
# setup_static_files(app, static_files_dir)
def setup_app(static_files_dir: Optional[Path]) -> FastAPI:
def setup_app(static_files_dir: Optional[Path] = None) -> FastAPI:
"""Setup the FastAPI app."""
# get the directory of the current file
if not static_files_dir:

View file

@ -1,4 +1,5 @@
import os
from typing import Optional
import yaml
from pydantic import BaseSettings, root_validator
@ -22,16 +23,18 @@ class Settings(BaseSettings):
utilities: dict = {}
output_parsers: dict = {}
dev: bool = False
database_url: str
database_url: Optional[str] = None
cache: str = "InMemoryCache"
remove_api_keys: bool = False
@root_validator(pre=True)
def set_database_url(cls, values):
if "database_url" not in values:
logger.debug("No database_url provided, trying DATABASE_URL env variable")
if database_url := os.getenv("DATABASE_URL"):
values["database_url"] = database_url
logger.debug(
"No database_url provided, trying LANGFLOW_DATABASE_URL env variable"
)
if langflow_database_url := os.getenv("LANGFLOW_DATABASE_URL"):
values["database_url"] = langflow_database_url
else:
logger.debug("No DATABASE_URL env variable, using sqlite database")
values["database_url"] = "sqlite:///./langflow.db"
@ -40,7 +43,6 @@ class Settings(BaseSettings):
class Config:
validate_assignment = True
extra = "ignore"
env_prefix = "LANGFLOW_"
@root_validator(allow_reuse=True)
def validate_lists(cls, values):

View file

@ -33,7 +33,6 @@ class DocumentLoaderFrontNode(FrontendNode):
"SlackDirectoryLoader": build_file_field(suffixes=[".zip"], fileTypes=["zip"]),
"EverNoteLoader": build_file_field(suffixes=[".xml"], fileTypes=["xml"]),
"FacebookChatLoader": build_file_field(suffixes=[".json"], fileTypes=["json"]),
"GutenbergLoader": build_file_field(suffixes=[".txt"], fileTypes=["txt"]),
"BSHTMLLoader": build_file_field(suffixes=[".html"], fileTypes=["html"]),
"UnstructuredHTMLLoader": build_file_field(
suffixes=[".html"], fileTypes=["html"]
@ -116,8 +115,11 @@ class DocumentLoaderFrontNode(FrontendNode):
"HNLoader",
"IFixitLoader",
"IMSDbLoader",
"GutenbergLoader",
}:
name = "web_path"
elif self.template.type_name in {"GutenbergLoader"}:
name = "file_path"
elif self.template.type_name in {"GitbookLoader"}:
name = "web_page"
elif self.template.type_name in {

View file

@ -65,6 +65,7 @@ class VectorStoreFrontendNode(FrontendNode):
show=True,
advanced=True,
multiline=False,
password=True,
value="",
)
extra_field2 = TemplateField(
@ -142,6 +143,7 @@ class VectorStoreFrontendNode(FrontendNode):
show=True,
advanced=True,
multiline=False,
password=True,
value="",
)
extra_fields.extend((extra_field, extra_field2, extra_field3, extra_field4))

View file

@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="/favicon.ico" />
<title>LangFlow</title>
<title>Langflow</title>
</head>
<body id='body' style="width: 100%; height:100%">
<noscript>You need to enable JavaScript to run this app.</noscript>

View file

@ -118,7 +118,7 @@ export default function App() {
const removeAlert = (id: string) => {
setAlertsList((prevAlertsList) =>
prevAlertsList.filter((alert) => alert.id !== id)
prevAlertsList.filter((alert) => alert.id !== id),
);
};
@ -139,7 +139,7 @@ export default function App() {
</ErrorBoundary>
<div></div>
<div
className="fixed bottom-5 left-5 flex flex-col-reverse"
className="app-div"
style={{ zIndex: 999 }}
>
{alertsList.map((alert) => (

View file

@ -81,30 +81,30 @@ export default function GenericNode({
<div
className={classNames(
selected ? "border border-ring" : "border",
"prompt-node relative flex w-96 flex-col justify-center rounded-lg bg-background"
"generic-node-div"
)}
>
<div className="flex w-full items-center justify-between gap-8 rounded-t-lg border-b bg-muted p-4 ">
<div className="flex w-full items-center truncate">
<div className="generic-node-div-title">
<div className="generic-node-title-arrangement">
<Icon
strokeWidth={1.5}
className="h-10 w-10 rounded p-1"
className="generic-node-icon"
style={{
color: nodeColors[types[data.type]] ?? nodeColors.unknown,
}}
/>
<div className="ml-2 flex-1 truncate">
<div className="generic-node-tooltip-div">
<ShadTooltip
delayDuration={1500}
content={data.node.display_name}
>
<div className="ml-2 truncate text-primary">
<div className="generic-node-tooltip-div text-primary">
{data.node.display_name}
</div>
</ShadTooltip>
</div>
</div>
<div className="flex gap-3">
<div className="round-button-div">
<button
className="relative"
onClick={(event) => {
@ -113,7 +113,7 @@ export default function GenericNode({
}}
></button>
</div>
<div className="flex gap-3">
<div className="round-button-div">
<div>
<Tooltip
title={
@ -131,29 +131,29 @@ export default function GenericNode({
)
}
>
<div className="relative top-[3px] h-5 w-5">
<div className="generic-node-status-position">
<div
className={classNames(
validationStatus && validationStatus.valid
? "h-4 w-4 rounded-full bg-status-green opacity-100"
: "hidden h-4 w-4 animate-spin rounded-full bg-ring opacity-0",
"absolute w-4 duration-200 ease-in-out hover:text-accent-foreground hover:transition-all"
? "green-status"
: "status-build-animation",
"status-div"
)}
></div>
<div
className={classNames(
validationStatus && !validationStatus.valid
? "h-4 w-4 rounded-full bg-status-red opacity-100"
: "hidden h-4 w-4 animate-spin rounded-full bg-ring opacity-0",
"absolute w-4 duration-200 ease-in-out hover:text-accent-foreground hover:transition-all"
? "red-status"
: "status-build-animation",
"status-div"
)}
></div>
<div
className={classNames(
!validationStatus || isBuilding
? "h-4 w-4 rounded-full bg-status-yellow opacity-100"
: "hidden h-4 w-4 animate-spin rounded-full bg-ring opacity-0",
"absolute w-4 duration-200 ease-in-out hover:text-accent-foreground hover:transition-all"
? "yellow-status"
: "status-build-animation",
"status-div"
)}
></div>
</div>
@ -162,8 +162,8 @@ export default function GenericNode({
</div>
</div>
<div className="h-full w-full py-5 text-foreground">
<div className="w-full px-5 pb-3 text-sm text-muted-foreground">
<div className="generic-node-desc">
<div className="generic-node-desc-text">
{data.node.description}
</div>
@ -234,7 +234,7 @@ export default function GenericNode({
<div
className={classNames(
Object.keys(data.node.template).length < 1 ? "hidden" : "",
"flex w-full justify-center"
"flex-max-width justify-center"
)}
>
{" "}

View file

@ -39,19 +39,19 @@ export default function ErrorAlert({
removeAlert(id);
}, 500);
}}
className="mt-6 w-96 cursor-pointer rounded-md bg-error-background p-4 shadow-xl"
className="error-build-message"
>
<div className="flex">
<div className="flex-shrink-0">
<XCircle className="h-5 w-5 text-status-red" aria-hidden="true" />
<XCircle className="error-build-message-circle" aria-hidden="true" />
</div>
<div className="ml-3">
<h3 className="text-sm font-medium text-error-foreground">
<h3 className="error-build-foreground">
{title}
</h3>
{list.length !== 0 ? (
<div className="mt-2 text-sm text-error-foreground">
<ul className="list-disc space-y-1 pl-5">
<div className="error-build-message-div">
<ul className="error-build-message-list">
{list.map((item, index) => (
<li key={index}>{item}</li>
))}

View file

@ -34,17 +34,17 @@ export default function SuccessAlert({
setShow(false);
removeAlert(id);
}}
className="mt-6 w-96 rounded-md bg-success-background p-4 shadow-xl"
className="success-alert"
>
<div className="flex">
<div className="flex-shrink-0">
<CheckCircle2
className="h-5 w-5 text-status-green"
className="success-alert-icon"
aria-hidden="true"
/>
</div>
<div className="ml-3">
<p className="text-sm font-medium text-success-foreground">
<p className="success-alert-message">
{title}
</p>
</div>

View file

@ -18,7 +18,7 @@ export default function AccordionComponent({
open = [],
}: AccordionComponentType) {
const [value, setValue] = useState(
open.length == 0 ? "" : getOpenAccordion()
open.length == 0 ? "" : getOpenAccordion(),
);
function getOpenAccordion() {

View file

@ -44,10 +44,10 @@ export const EditFlowSettings: React.FC<InputProps> = ({
return (
<>
<Label>
<div className="flex justify-between">
<div className="edit-flow-arrangement">
<span className="font-medium">Name</span>{" "}
{isMaxLength && (
<span className="ml-10 animate-pulse text-status-red">
<span className="edit-flow-span">
Character limit reached
</span>
)}

View file

@ -1,5 +1,5 @@
import { Disclosure } from "@headlessui/react";
import { useContext, useState } from "react";
import { useContext } from "react";
import { Link } from "react-router-dom";
import { classNames } from "../../utils";
import { locationContext } from "../../contexts/locationContext";
@ -18,13 +18,13 @@ export default function ExtraSidebar() {
<aside
className={` ${
isStackedOpen ? "w-52" : "w-0 "
} flex flex-shrink-0 flex-col overflow-hidden border-r transition-all duration-500`}
} unused-side-bar-aside`}
>
<div className="flex h-full w-52 flex-col items-start overflow-y-auto border bg-background scrollbar-hide">
<div className="flex w-full flex-grow flex-col">
<div className="unused-side-bar-arrangement">
<div className="unused-side-bar-division">
{extraNavigation.options ? (
<div className="p-4">
<nav className="flex-1 space-y-1">
<nav className="unused-side-bar-nav">
{extraNavigation.options.map((item) =>
!item.children ? (
<div key={item.name}>
@ -32,17 +32,17 @@ export default function ExtraSidebar() {
to={item.href}
className={classNames(
item.href.split("/")[2] === current[4]
? "bg-muted text-foreground"
: "bg-background text-muted-foreground hover:bg-muted hover:text-foreground",
"group flex w-full items-center rounded-md py-2 pl-2 text-sm font-medium"
? "unused-side-bar-link-colors-true"
: "unused-side-bar-link-colors-false",
"unused-side-bar-link"
)}
>
<item.icon
className={classNames(
item.href.split("/")[2] === current[4]
? "text-ring"
: "text-ring group-hover:text-accent-foreground",
"mr-3 h-6 w-6 flex-shrink-0"
: "unused-side-bar-icon-false",
"unused-side-bar-icon"
)}
/>
{item.name}
@ -59,20 +59,20 @@ export default function ExtraSidebar() {
<Disclosure.Button
className={classNames(
item.href.split("/")[2] === current[4]
? "bg-muted text-foreground"
: "bg-background text-muted-foreground hover:bg-muted hover:text-foreground",
"group flex w-full items-center rounded-md py-2 pl-2 pr-1 text-left text-sm font-medium focus:outline-none focus:ring-1 focus:ring-ring"
? "unused-side-bar-link-colors-true"
: "unused-side-bar-link-colors-false",
"unused-side-bar-disclosure"
)}
>
<item.icon
className="mr-3 h-6 w-6 flex-shrink-0 text-ring group-hover:text-accent-foreground"
className="unused-side-bar-disclosure-icon"
aria-hidden="true"
/>
<span className="flex-1">{item.name}</span>
<svg
className={classNames(
open ? "rotate-90 text-ring" : "text-ring",
"transition-rotate ml-3 h-5 w-5 flex-shrink-0 duration-150 ease-in-out group-hover:text-accent-foreground"
open ? "unused-side-bar-svg-true" : "text-ring",
"unused-side-bar-svg"
)}
viewBox="0 0 20 20"
aria-hidden="true"
@ -90,9 +90,9 @@ export default function ExtraSidebar() {
to={subItem.href}
className={classNames(
subItem.href.split("/")[3] === current[5]
? "bg-muted text-foreground"
: "bg-background text-muted-foreground hover:bg-muted hover:text-foreground",
"group flex w-full items-center rounded-md py-2 pl-11 pr-2 text-sm font-medium"
? "unused-side-bar-link-colors-true"
: "unused-side-bar-link-colors-false",
"unused-side-bar-disclosure-panel"
)}
>
{subItem.name}

View file

@ -38,22 +38,22 @@ export const CardComponent = ({
return (
<Card className="group">
<CardHeader>
<CardTitle className="flex w-full items-center gap-4">
<CardTitle className="card-component-title-display">
<span
className={
"flex h-7 w-7 items-center justify-center rounded-full text-2xl " +
"card-component-image " +
gradients[parseInt(flow.id.slice(0, 12), 16) % gradients.length]
}
></span>
<span className="inline-block w-full flex-1 break-words truncate-doubleline">
<span className="card-component-title-size">
{flow.name}
</span>
{onDelete && (
<Dialog>
<DialogTrigger asChild>
<button className="flex self-start">
<Trash2 className="h-4 w-4 text-primary opacity-0 transition-all group-hover:opacity-100" />
</button>
<button className="card-component-delete-button" onClick={onDelete}>
<Trash2 className="card-component-delete-icon" />
</button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
@ -72,8 +72,8 @@ export const CardComponent = ({
</Dialog>
)}
</CardTitle>
<CardDescription className="pb-2 pt-2">
<div className="truncate-doubleline">
<CardDescription className="card-component-desc">
<div className="card-component-desc-text">
{flow.description}
{/* {flow.description} */}
</div>
@ -81,8 +81,8 @@ export const CardComponent = ({
</CardHeader>
<CardFooter>
<div className="flex w-full items-end justify-between gap-2">
<div className="flex flex-wrap gap-2">
<div className="card-component-footer-arrangement">
<div className="card-component-footer">
{/* <Badge variant="secondary">Agent</Badge>
<Badge variant="secondary">
<div className="w-3">

View file

@ -137,7 +137,7 @@ export default function BuildTrigger({
async function enforceMinimumLoadingTime(
startTime: number,
minimumLoadingTime: number
minimumLoadingTime: number,
) {
const elapsedTime = Date.now() - startTime;
const remainingTime = minimumLoadingTime - elapsedTime;
@ -168,7 +168,7 @@ export default function BuildTrigger({
>
<div className="fixed bottom-20 right-4">
<div
className={`${eventClick} align-center shadow-round-btn-shadow hover:shadow-round-btn-shadow flex h-12 w-12 cursor-pointer justify-center rounded-full bg-border px-3 py-1 shadow-md`}
className={`${eventClick} round-button-form`}
onClick={() => {
handleBuild(flow);
}}
@ -176,7 +176,7 @@ export default function BuildTrigger({
onMouseLeave={handleMouseLeave}
>
<button>
<div className="flex items-center gap-3">
<div className="round-button-div">
{isBuilding && progress < 1 ? (
// Render your loading animation here when isBuilding is true
<RadialProgressComponent
@ -185,7 +185,10 @@ export default function BuildTrigger({
value={progress}
></RadialProgressComponent>
) : isBuilding ? (
<Loading strokeWidth={1.5} className="stroke-build-trigger" />
<Loading
strokeWidth={1.5}
className="build-trigger-loading-icon"
/>
) : (
<Zap
strokeWidth={1.5}

View file

@ -15,7 +15,7 @@ export default function CodeAreaComponent({
setNodeClass,
}: TextAreaComponentType) {
const [myValue, setMyValue] = useState(
typeof value == "string" ? value : JSON.stringify(value)
typeof value == "string" ? value : JSON.stringify(value),
);
const { openPopUp } = useContext(PopUpContext);
useEffect(() => {
@ -80,7 +80,7 @@ export default function CodeAreaComponent({
<ExternalLink
strokeWidth={1.5}
className={
"ml-3 h-6 w-6" +
"icons-parameters-comp" +
(disabled ? " text-ring" : " hover:text-accent-foreground")
}
/>

View file

@ -4,7 +4,6 @@ import { DropDownComponentType } from "../../types/components";
import { classNames } from "../../utils";
import { ChevronsUpDown, Check } from "lucide-react";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
export default function Dropdown({
value,
@ -39,20 +38,20 @@ export default function Dropdown({
<Listbox.Button
className={
editNode
? "border-1 input-edit-node relative pr-8"
: "input-primary py-2 pl-3 pr-10 text-left"
? "dropdown-component-outline"
: "dropdown-component-false-outline"
}
>
<span className="block w-full truncate bg-background">
<span className="dropdown-component-display">
{internalValue}
</span>
<span
className={
"pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2"
"dropdown-component-arrow"
}
>
<ChevronsUpDown
className="h-5 w-5 text-muted-foreground"
className="dropdown-component-arrow-color"
aria-hidden="true"
/>
</span>
@ -68,8 +67,8 @@ export default function Dropdown({
<Listbox.Options
className={classNames(
editNode
? "z-10 mt-1 max-h-60 w-[215px] overflow-auto rounded-md bg-background py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm"
: "nowheel overflow-y z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-background py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm ",
? "dropdown-component-true-options "
: "dropdown-component-false-options ",
apiModal ? "mb-2 w-[250px]" : "absolute"
)}
>
@ -80,8 +79,8 @@ export default function Dropdown({
classNames(
active ? " bg-accent" : "",
editNode
? "relative cursor-default select-none py-0.5 pl-3 pr-12"
: "relative cursor-default select-none py-2 pl-3 pr-9"
? "dropdown-component-false-option"
: "dropdown-component-true-option"
)
}
value={option}
@ -101,14 +100,14 @@ export default function Dropdown({
<span
className={classNames(
active ? "text-background " : "",
"absolute inset-y-0 right-0 flex items-center pr-4"
"dropdown-component-choosal"
)}
>
<Check
className={
active
? "h-5 w-5 text-black"
: "h-5 w-5 text-black"
? "dropdown-component-check-icon"
: "dropdown-component-check-icon"
}
aria-hidden="true"
/>

View file

@ -32,7 +32,7 @@ export default function FloatComponent({
return (
<div
className={
"w-full " + (disabled ? "pointer-events-none cursor-not-allowed" : "")
"w-full " + (disabled ? "float-component-pointer" : "")
}
>
<input

View file

@ -47,19 +47,19 @@ export const MenuBar = ({ flows, tabId }) => {
let current_flow = flows.find((flow) => flow.id === tabId);
return (
<div className="flex items-center gap-2">
<div className="round-button-div">
<Link to="/">
<ChevronLeft className="w-4" />
</Link>
<div className="flex items-center gap-0.5 rounded-md px-1.5 py-1 text-sm font-medium">
<div className="header-menu-bar">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
className="flex max-w-[200px] items-center gap-2"
className="header-menu-bar-display"
variant="primary"
size="sm"
>
<div className="flex-1 truncate">{current_flow.name}</div>
<div className="header-menu-flow-name">{current_flow.name}</div>
<ChevronDown className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
@ -71,7 +71,7 @@ export const MenuBar = ({ flows, tabId }) => {
}}
className="cursor-pointer"
>
<Plus className="mr-2 h-4 w-4" />
<Plus className="header-menu-options" />
New
</DropdownMenuItem>
<DropdownMenuItem
@ -80,7 +80,7 @@ export const MenuBar = ({ flows, tabId }) => {
}}
className="cursor-pointer"
>
<Settings2 className="mr-2 h-4 w-4 " />
<Settings2 className="header-menu-options " />
Settings
</DropdownMenuItem>
<DropdownMenuItem
@ -89,7 +89,7 @@ export const MenuBar = ({ flows, tabId }) => {
}}
className="cursor-pointer"
>
<Undo className="mr-2 h-4 w-4 " />
<Undo className="header-menu-options " />
Undo
</DropdownMenuItem>
<DropdownMenuItem
@ -98,7 +98,7 @@ export const MenuBar = ({ flows, tabId }) => {
}}
className="cursor-pointer"
>
<Redo className="mr-2 h-4 w-4 " />
<Redo className="header-menu-options " />
Redo
</DropdownMenuItem>
<DropdownMenuSeparator />

View file

@ -1,4 +1,4 @@
import { BellIcon, Home, MoonIcon, SunIcon, Users2 } from "lucide-react";
import { Home, MoonIcon, SunIcon, Users2 } from "lucide-react";
import { useContext, useEffect, useState } from "react";
import { FaDiscord, FaGithub, FaTwitter } from "react-icons/fa";
import { Button } from "../ui/button";
@ -36,8 +36,8 @@ export default function Header() {
fetchStars();
}, []);
return (
<div className="flex h-12 w-full items-center justify-between border-b bg-muted">
<div className="flex w-96 items-center justify-start gap-2">
<div className="header-arrangement">
<div className="header-start-display">
<Link to="/">
<span className="ml-4 text-2xl"></span>
</Link>
@ -45,7 +45,7 @@ export default function Header() {
<MenuBar flows={flows} tabId={tabId} />
)}
</div>
<div className="flex items-center gap-2">
<div className="round-button-div">
<Link to="/">
<Button
className="gap-2"
@ -69,17 +69,17 @@ export default function Header() {
</Button>
</Link>
</div>
<div className="flex w-96 justify-end px-2">
<div className="ml-auto mr-2 flex items-center gap-5">
<div className="header-end-division">
<div className="header-end-display">
<a
href="https://github.com/logspace-ai/langflow"
target="_blank"
rel="noreferrer"
className="inline-flex h-9 items-center justify-center rounded-md border border-input px-3 pr-0 text-sm font-medium text-muted-foreground shadow-sm ring-offset-background hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
className="header-github-link"
>
<FaGithub className="mr-2 h-5 w-5" />
Star
<div className="-mr-px ml-2 flex h-9 items-center justify-center rounded-md rounded-l-none border bg-background px-2 text-sm">
<div className="header-github-display">
{stars}
</div>
</a>
@ -89,7 +89,7 @@ export default function Header() {
rel="noreferrer"
className="text-muted-foreground"
>
<FaTwitter className="h-5 w-5 hover:text-accent-foreground" />
<FaTwitter className="side-bar-button-size" />
</a>
<a
href="https://discord.gg/EqksyE2EX9"
@ -97,24 +97,24 @@ export default function Header() {
rel="noreferrer"
className="text-muted-foreground"
>
<FaDiscord className="h-5 w-5 hover:text-accent-foreground" />
<FaDiscord className="side-bar-button-size" />
</a>
<Separator orientation="vertical" />
<button
className="text-muted-foreground hover:text-accent-foreground "
className="extra-side-bar-save-disable"
onClick={() => {
setDark(!dark);
}}
>
{dark ? (
<SunIcon className="h-5 w-5" />
<SunIcon className="side-bar-button-size" />
) : (
<MoonIcon className="h-5 w-5" />
<MoonIcon className="side-bar-button-size" />
)}
</button>
<button
className="relative text-muted-foreground hover:text-accent-foreground"
className="extra-side-bar-save-disable relative"
onClick={(event: React.MouseEvent<HTMLElement>) => {
setNotificationCenter(false);
const { top, left } = (
@ -128,15 +128,15 @@ export default function Header() {
>
<AlertDropdown />
</div>
<div className="fixed left-0 top-0 h-screen w-screen"></div>
<div className="header-notifications-box"></div>
</>
);
}}
>
{notificationCenter && (
<div className="absolute right-[3px] h-1.5 w-1.5 rounded-full bg-destructive"></div>
<div className="header-notifications"></div>
)}
<Bell className="h-5 w-5" aria-hidden="true" />
<Bell className="side-bar-button-size" aria-hidden="true" />
</button>
</div>
</div>

View file

@ -32,7 +32,7 @@ export default function InputComponent({
<div
className={
disabled
? "pointer-events-none relative cursor-not-allowed"
? "input-component-div"
: "relative"
}
>
@ -61,8 +61,8 @@ export default function InputComponent({
<button
className={classNames(
editNode
? "absolute inset-y-0 right-0 items-center pr-2 text-muted-foreground"
: "absolute inset-y-0 right-0 items-center px-4 text-muted-foreground"
? "input-component-true-button"
: "input-component-false-button"
)}
onClick={() => {
setPwdVisible(!pwdVisible);
@ -78,8 +78,8 @@ export default function InputComponent({
stroke="currentColor"
className={classNames(
editNode
? "absolute bottom-0.5 right-2 h-5 w-5"
: "absolute bottom-2 right-3 h-5 w-5"
? "input-component-true-svg"
: "input-component-false-svg"
)}
>
<path
@ -97,8 +97,8 @@ export default function InputComponent({
stroke="currentColor"
className={classNames(
editNode
? "absolute bottom-0.5 right-2 h-5 w-5"
: "absolute bottom-2 right-3 h-5 w-5"
? "input-component-true-svg"
: "input-component-false-svg"
)}
>
<path

View file

@ -94,10 +94,10 @@ export default function InputFileComponent({
return (
<div
className={
disabled ? "pointer-events-none w-full cursor-not-allowed" : "w-full"
disabled ? "input-component-div" : "w-full"
}
>
<div className="flex w-full items-center">
<div className="input-file-component">
<span
onClick={handleButtonClick}
className={
@ -112,7 +112,10 @@ export default function InputFileComponent({
{!editNode && !loading && (
<FileSearch2
strokeWidth={1.5}
className="h-6 w-6 hover:text-accent-foreground ml-3"
className={
"icons-parameters-comp" +
(disabled ? " text-ring " : " hover:text-accent-foreground")
}
/>
)}
{!editNode && loading && (

View file

@ -100,7 +100,7 @@ export default function PromptAreaComponent({
<ExternalLink
strokeWidth={1.5}
className={
"ml-3 h-6 w-6" +
"icons-parameters-comp" +
(disabled ? " text-ring" : " hover:text-accent-foreground")
}
/>

View file

@ -61,7 +61,7 @@ export default function TextAreaComponent({
setMyValue(t);
onChange(t);
}}
/>
/>,
);
}}
>
@ -69,7 +69,7 @@ export default function TextAreaComponent({
<ExternalLink
strokeWidth={1.5}
className={
"ml-3 h-6 w-6" +
"icons-parameters-comp" +
(disabled ? " text-ring" : " hover:text-accent-foreground")
}
/>

View file

@ -22,14 +22,14 @@ export default function ToggleComponent({
}}
className={classNames(
enabled ? "bg-primary" : "bg-input",
"relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-1 focus:ring-primary focus:ring-offset-1"
"toggle-component-switch "
)}
>
<span className="sr-only">Use setting</span>
<span
className={classNames(
enabled ? "translate-x-5" : "translate-x-0",
"pointer-events-none relative inline-block h-5 w-5 transform rounded-full shadow ring-0 transition duration-200 ease-in-out",
"toggle-component-span",
disabled ? "bg-input " : "bg-background"
)}
>
@ -38,7 +38,7 @@ export default function ToggleComponent({
enabled
? "opacity-0 duration-100 ease-out"
: "opacity-100 duration-200 ease-in",
"absolute inset-0 flex h-full w-full items-center justify-center transition-opacity"
"toggle-component-second-span"
)}
aria-hidden="true"
></span>
@ -47,7 +47,7 @@ export default function ToggleComponent({
enabled
? "opacity-100 duration-200 ease-in"
: "opacity-0 duration-100 ease-out",
"absolute inset-0 flex h-full w-full items-center justify-center transition-opacity"
"toggle-component-second-span"
)}
aria-hidden="true"
></span>

View file

@ -47,7 +47,7 @@ const AccordionContent = React.forwardRef<
ref={ref}
className={cn(
"overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
className
className,
)}
{...props}
>

View file

@ -25,7 +25,7 @@ const badgeVariants = cva(
defaultVariants: {
variant: "default",
},
}
},
);
export interface BadgeProps

View file

@ -30,7 +30,7 @@ const buttonVariants = cva(
variant: "default",
size: "default",
},
}
},
);
export interface ButtonProps
@ -49,7 +49,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
{...props}
/>
);
}
},
);
Button.displayName = "Button";

View file

@ -13,7 +13,7 @@ const Checkbox = React.forwardRef<
ref={ref}
className={cn(
"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
className
className,
)}
{...props}
>

View file

@ -28,7 +28,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
className={cn(
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
inset && "pl-8",
className
className,
)}
{...props}
>
@ -47,7 +47,7 @@ const DropdownMenuSubContent = React.forwardRef<
ref={ref}
className={cn(
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in 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
className,
)}
{...props}
/>
@ -65,7 +65,7 @@ const DropdownMenuContent = React.forwardRef<
sideOffset={sideOffset}
className={cn(
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
className,
)}
{...props}
/>
@ -84,7 +84,7 @@ const DropdownMenuItem = React.forwardRef<
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
inset && "pl-8",
className
className,
)}
{...props}
/>
@ -99,7 +99,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
className,
)}
checked={checked}
{...props}
@ -123,7 +123,7 @@ const DropdownMenuRadioItem = React.forwardRef<
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
className,
)}
{...props}
>
@ -148,7 +148,7 @@ const DropdownMenuLabel = React.forwardRef<
className={cn(
"px-2 py-1.5 pl-2 text-sm font-semibold",
inset && "pl-8",
className
className,
)}
{...props}
/>

View file

@ -11,13 +11,13 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
type={type}
className={cn(
"flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className
className,
)}
ref={ref}
{...props}
/>
);
}
},
);
Input.displayName = "Input";

View file

@ -6,7 +6,7 @@ import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "../../utils";
const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
);
const Label = React.forwardRef<

View file

@ -24,7 +24,7 @@ const Menubar = React.forwardRef<
ref={ref}
className={cn(
"flex h-10 items-center space-x-1 rounded-md border bg-background p-1",
className
className,
)}
{...props}
/>
@ -39,7 +39,7 @@ const MenubarTrigger = React.forwardRef<
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm px-3 py-1.5 text-sm font-medium outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
className
className,
)}
{...props}
/>
@ -57,7 +57,7 @@ const MenubarSubTrigger = React.forwardRef<
className={cn(
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
inset && "pl-8",
className
className,
)}
{...props}
>
@ -75,7 +75,7 @@ const MenubarSubContent = React.forwardRef<
ref={ref}
className={cn(
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in 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
className,
)}
{...props}
/>
@ -88,7 +88,7 @@ const MenubarContent = React.forwardRef<
>(
(
{ className, align = "start", alignOffset = -4, sideOffset = 8, ...props },
ref
ref,
) => (
<MenubarPrimitive.Portal>
<MenubarPrimitive.Content
@ -98,12 +98,12 @@ const MenubarContent = React.forwardRef<
sideOffset={sideOffset}
className={cn(
"z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in slide-in-from-top-1",
className
className,
)}
{...props}
/>
</MenubarPrimitive.Portal>
)
),
);
MenubarContent.displayName = MenubarPrimitive.Content.displayName;
@ -118,7 +118,7 @@ const MenubarItem = React.forwardRef<
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
inset && "pl-8",
className
className,
)}
{...props}
/>
@ -133,7 +133,7 @@ const MenubarCheckboxItem = React.forwardRef<
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
className,
)}
checked={checked}
{...props}
@ -156,7 +156,7 @@ const MenubarRadioItem = React.forwardRef<
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
className,
)}
{...props}
>
@ -181,7 +181,7 @@ const MenubarLabel = React.forwardRef<
className={cn(
"px-2 py-1.5 text-sm font-semibold",
inset && "pl-8",
className
className,
)}
{...props}
/>
@ -208,7 +208,7 @@ const MenubarShortcut = ({
<span
className={cn(
"ml-auto text-xs tracking-widest text-muted-foreground",
className
className,
)}
{...props}
/>

View file

@ -12,7 +12,7 @@ const Progress = React.forwardRef<
ref={ref}
className={cn(
"relative h-4 w-full overflow-hidden rounded-full bg-secondary",
className
className,
)}
{...props}
>

View file

@ -10,7 +10,7 @@ const Separator = React.forwardRef<
>(
(
{ className, orientation = "horizontal", decorative = true, ...props },
ref
ref,
) => (
<SeparatorPrimitive.Root
ref={ref}
@ -19,11 +19,11 @@ const Separator = React.forwardRef<
className={cn(
"shrink-0 bg-border",
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
className
className,
)}
{...props}
/>
)
),
);
Separator.displayName = SeparatorPrimitive.Root.displayName;

View file

@ -55,7 +55,7 @@ const TableRow = React.forwardRef<
ref={ref}
className={cn(
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
className
className,
)}
{...props}
/>
@ -70,7 +70,7 @@ const TableHead = React.forwardRef<
ref={ref}
className={cn(
"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
className
className,
)}
{...props}
/>

View file

@ -10,13 +10,13 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
<textarea
className={cn(
"flex min-h-[80px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className
className,
)}
ref={ref}
{...props}
/>
);
}
},
);
Textarea.displayName = "Textarea";

View file

@ -19,7 +19,7 @@ const TooltipContent = React.forwardRef<
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
className,
)}
{...props}
/>

View file

@ -150,7 +150,7 @@ TWEAKS = ${
}
flow = load_flow_from_json("${flowName}.json", tweaks=TWEAKS)
# Now you can use it like any chain
flow("Hey, have you heard of LangFlow?")`;
flow("Hey, have you heard of Langflow?")`;
};
function buildTweakObject(tweak) {

View file

@ -132,7 +132,7 @@ export function AlertProvider({ children }: { children: ReactNode }) {
function removeFromNotificationList(index: string) {
// set the notification list to a new array that filters out the alert with the matching id
setNotificationList((prevAlertsList) =>
prevAlertsList.filter((alert) => alert.id !== index)
prevAlertsList.filter((alert) => alert.id !== index),
);
}
return (

View file

@ -14,7 +14,7 @@ export const darkContext = createContext<darkContextType>(initialValue);
export function DarkProvider({ children }) {
const [dark, setDark] = useState(
JSON.parse(window.localStorage.getItem("isDark")) ?? false
JSON.parse(window.localStorage.getItem("isDark")) ?? false,
);
useEffect(() => {
if (dark) {

View file

@ -53,7 +53,7 @@ export const locationContext = createContext<locationContextType>(initialValue);
export function LocationProvider({ children }: { children: ReactNode }) {
const [current, setCurrent] = useState(initialValue.current);
const [isStackedOpen, setIsStackedOpen] = useState(
initialValue.isStackedOpen
initialValue.isStackedOpen,
);
const [showSideBar, setShowSideBar] = useState(initialValue.showSideBar);
const [extraNavigation, setExtraNavigation] = useState({ title: "" });

View file

@ -108,7 +108,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
// function loadCookie(cookie: string) {
// if (cookie && Object.keys(templates).length > 0) {
// let cookieObject: LangFlowState = JSON.parse(cookie);
// let cookieObject: LangflowState = JSON.parse(cookie);
// try {
// cookieObject.flows.forEach((flow) => {
// if (!flow.data) {

View file

@ -47,7 +47,7 @@ export function TypesProvider({ children }: { children: ReactNode }) {
acc[c] = result.data[curr][c];
});
return acc;
}, {})
}, {}),
);
// Set the types by reducing over the keys of the result data and updating the accumulator.
setTypes(
@ -62,10 +62,10 @@ export function TypesProvider({ children }: { children: ReactNode }) {
result.data[curr][c].base_classes?.forEach((b) => {
acc[b] = curr;
});
}
},
);
return acc;
}, {})
}, {}),
);
}
// Clear the interval if successful.
@ -99,12 +99,12 @@ export function TypesProvider({ children }: { children: ReactNode }) {
function deleteNode(idx: string) {
reactFlowInstance.setNodes(
reactFlowInstance.getNodes().filter((n: Node) => n.id !== idx)
reactFlowInstance.getNodes().filter((n: Node) => n.id !== idx),
);
reactFlowInstance.setEdges(
reactFlowInstance
.getEdges()
.filter((ns) => ns.source !== idx && ns.target !== idx)
.filter((ns) => ns.source !== idx && ns.target !== idx),
);
}
return (

View file

@ -52,7 +52,7 @@ export function UndoRedoProvider({ children }) {
const [past, setPast] = useState<HistoryItem[][]>(flows.map(() => []));
const [future, setFuture] = useState<HistoryItem[][]>(flows.map(() => []));
const [tabIndex, setTabIndex] = useState(
flows.findIndex((f) => f.id === tabId)
flows.findIndex((f) => f.id === tabId),
);
useEffect(() => {
@ -70,7 +70,7 @@ export function UndoRedoProvider({ children }) {
let newPast = cloneDeep(old);
newPast[tabIndex] = old[tabIndex].slice(
old[tabIndex].length - defaultOptions.maxHistorySize + 1,
old[tabIndex].length
old[tabIndex].length,
);
newPast[tabIndex].push({ nodes: getNodes(), edges: getEdges() });
return newPast;

View file

@ -25,7 +25,7 @@ const GITHUB_API_URL = "https://api.github.com";
export async function getRepoStars(owner, repo) {
try {
const response = await axios.get(
`${GITHUB_API_URL}/repos/${owner}/${repo}`
`${GITHUB_API_URL}/repos/${owner}/${repo}`,
);
return response.data.stargazers_count;
} catch (error) {
@ -45,7 +45,7 @@ export async function sendAll(data: sendAllProps) {
}
export async function postValidateCode(
code: string
code: string,
): Promise<AxiosResponse<errorsTypeAPI>> {
return await axios.post("/api/v1/validate/code", { code });
}
@ -128,7 +128,7 @@ export async function saveFlowToDatabase(newFlow: {
* @throws Will throw an error if the update fails.
*/
export async function updateFlowInDatabase(
updatedFlow: FlowType
updatedFlow: FlowType,
): Promise<FlowType> {
try {
const response = await axios.patch(`/api/v1/flows/${updatedFlow.id}`, {
@ -304,7 +304,7 @@ export async function getHealth() {
*
*/
export async function getBuildStatus(
flowId: string
flowId: string,
): Promise<BuildStatusTypeAPI> {
return await axios.get(`/api/v1/build/${flowId}/status`);
}
@ -317,7 +317,7 @@ export async function getBuildStatus(
*
*/
export async function postBuildInit(
flow: FlowType
flow: FlowType,
): Promise<AxiosResponse<InitTypeAPI>> {
return await axios.post(`/api/v1/build/init/${flow.id}`, flow);
}
@ -333,7 +333,7 @@ export async function postBuildInit(
*/
export async function uploadFile(
file: File,
id: string
id: string,
): Promise<AxiosResponse<UploadFileTypeAPI>> {
const formData = new FormData();
formData.append("file", file);

View file

@ -20,7 +20,7 @@ export const DESCRIPTIONS: string[] = [
"Generate, Innovate, Communicate.",
"Conversation Catalyst Engine.",
"Language Chainlink Master.",
"Design Dialogues with LangFlow.",
"Design Dialogues with Langflow.",
"Nurture NLP Nodes Here.",
"Conversational Cartography Unlocked.",
"Design, Develop, Dialogize.",
@ -31,7 +31,7 @@ export const DESCRIPTIONS: string[] = [
"Where Language Meets Logic.",
"Building Intelligent Interactions.",
"Your Passport to Linguistic Landscapes.",
"Create, Curate, Communicate with LangFlow.",
"Create, Curate, Communicate with Langflow.",
"Flow into the Future of Language.",
"Mapping Meaningful Conversations.",
"Unravel the Art of Articulation.",
@ -41,7 +41,7 @@ export const DESCRIPTIONS: string[] = [
"The Pinnacle of Prompt Generation.",
"Language Models, Mapped and Mastered.",
"Powerful Prompts, Perfectly Positioned.",
"Innovation in Interaction with LangFlow.",
"Innovation in Interaction with Langflow.",
"Your Toolkit for Text Generation.",
"Unfolding Linguistic Possibilities.",
"Building Powerful Solutions with Language Models.",

View file

@ -4,5 +4,5 @@ import { ReactComponent as AzSVG } from "./az_logo.svg";
export const AzIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
(props, ref) => {
return <AzSVG ref={ref} {...props} />;
}
},
);

View file

@ -4,5 +4,5 @@ import { ReactComponent as BingSVG } from "./bing.svg";
export const BingIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
(props, ref) => {
return <BingSVG ref={ref} {...props} />;
}
},
);

View file

@ -4,5 +4,5 @@ import { ReactComponent as FacebookMessengerSVG } from "./Facebook_Messenger_log
export const FBIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
(props, ref) => {
return <FacebookMessengerSVG ref={ref} {...props} />;
}
},
);

View file

@ -4,5 +4,5 @@ import { ReactComponent as IFixItSVG } from "./ifixit-seeklogo.com.svg";
export const IFixIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
(props, ref) => {
return <IFixItSVG ref={ref} {...props} />;
}
},
);

View file

@ -4,5 +4,5 @@ import { ReactComponent as MetaSVG } from "./meta-icon.svg";
export const MetaIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
(props, ref) => {
return <MetaSVG ref={ref} {...props} />;
}
},
);

View file

@ -4,5 +4,5 @@ import { ReactComponent as SearxSVG } from "./Searx_logo.svg";
export const SearxIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
(props, ref) => {
return <SearxSVG ref={ref} {...props} />;
}
},
);

View file

@ -4,5 +4,5 @@ import { ReactComponent as SlackSVG } from "./slack-icon.svg";
export const SlackIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
(props, ref) => {
return <SlackSVG ref={ref} {...props} />;
}
},
);

View file

@ -4,5 +4,5 @@ import { ReactComponent as WordSVG } from "./word.svg";
export const WordIcon = forwardRef<SVGSVGElement, React.PropsWithChildren<{}>>(
(props, ref) => {
return <WordSVG ref={ref} {...props} />;
}
},
);

View file

@ -145,6 +145,60 @@ The cursor: default; property value restores the browser's default cursor style
@layer components {
.round-buttons-position {
@apply fixed right-4
}
.side-bar-arrangement {
@apply flex h-full w-52 flex-col overflow-hidden border-r scrollbar-hide
}
.side-bar-search-div-placement {
@apply relative mx-auto mb-2 mt-2 flex items-center
}
.side-bar-components-icon {
@apply h-6 w-4 text-ring
}
.side-bar-components-text {
@apply w-full truncate pr-1 text-xs text-foreground
}
.side-bar-components-div-form {
@apply flex w-full items-center justify-between rounded-md rounded-l-none border border-l-0 border-dashed border-ring bg-white px-3 py-1 text-sm
}
.side-bar-components-border {
@apply cursor-grab rounded-l-md border-l-8
}
.side-bar-components-gap {
@apply flex flex-col gap-2 p-2
}
.side-bar-components-div-arrangement {
@apply w-full overflow-auto scrollbar-hide
}
.search-icon {
@apply absolute inset-y-0 right-0 flex items-center py-1.5 pr-3
}
.extra-side-bar-save-disable {
@apply text-muted-foreground
}
.extra-side-bar-save-disable:hover {
@apply hover:text-accent-foreground
}
.side-bar-button-size {
@apply h-5 w-5
}
.side-bar-button-size:hover {
@apply hover:text-accent-foreground
}
.side-bar-buttons-arrangement {
@apply mb-2 mt-2 flex w-full items-center justify-between gap-2 px-2
}
.extra-side-bar-buttons {
@apply relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground shadow-sm ring-1 ring-inset ring-input transition-all duration-500 ease-in-out
}
.extra-side-bar-buttons:hover {
@apply hover:bg-muted
}
.button-div-style {
@apply gap-2 flex
}
.input-primary:focus{
@apply focus:placeholder-transparent focus:ring-ring focus:border-ring
}
@ -163,4 +217,694 @@ The cursor: default; property value restores the browser's default cursor style
.input-dialog{
@apply text-ring cursor-pointer bg-transparent
}
.round-button-form {
@apply flex h-12 w-12 cursor-pointer justify-center rounded-full bg-border px-3 py-1 shadow-md
}
.round-button-div {
@apply flex items-center gap-3
}
.build-trigger-loading-icon {
@apply stroke-build-trigger
}
.build-trigger-icon {
@apply w-6 fill-build-trigger stroke-1 stroke-build-trigger
}
.message-button-position {
@apply absolute bottom-4 right-3
}
.message-button-icon {
@apply w-6 fill-chat-trigger stroke-chat-trigger stroke-1
}
.components-disclosure-arrangement {
@apply -mt-px flex w-full select-none items-center justify-between border-y border-y-input bg-muted px-3 py-2
}
.components-disclosure-title {
@apply flex items-center text-sm text-primary
}
.components-disclosure-div {
@apply flex gap-2
}
.flow-page-positioning {
@apply h-full w-full overflow-hidden
}
.logspace-page-icon {
@apply absolute bottom-2 left-7 flex h-6 cursor-pointer flex-col items-center justify-start overflow-hidden rounded-lg bg-foreground px-2 text-center font-sans text-xs tracking-wide text-secondary transition-all duration-500 ease-in-out
}
.logspace-page-icon:hover {
@apply hover:h-12
}
.flex-max-width {
@apply flex w-full
}
.main-page-panel {
@apply flex-max-width h-full flex-col overflow-auto bg-muted px-16
}
.main-page-nav-arrangement {
@apply flex-max-width justify-between px-6 py-12 pb-2
}
.main-page-nav-title {
@apply flex items-center justify-center gap-2 text-2xl font-semibold
}
.main-page-nav-button {
@apply mr-2 w-4
}
.main-page-description-text {
@apply flex w-[60%] px-6 pb-14 text-muted-foreground
}
.main-page-flows-display {
@apply grid w-full gap-4 p-4 md:grid-cols-2 lg:grid-cols-4
}
.community-page-arrangement {
@apply flex-max-width h-full flex-col overflow-auto bg-muted px-16
}
.community-page-nav-arrangement {
@apply flex-max-width justify-between px-6 py-12 pb-2
}
.community-page-nav-title {
@apply flex items-center justify-center gap-2 text-2xl font-semibold
}
.community-page-nav-button {
@apply flex gap-2
}
.community-page-description-text {
@apply flex w-[70%] px-6 pb-8 text-muted-foreground
}
.community-pages-flows-panel {
@apply grid w-full gap-4 p-4 md:grid-cols-2 lg:grid-cols-4
}
.generic-node-div {
@apply relative flex w-96 flex-col justify-center rounded-lg bg-background
}
.generic-node-div-title {
@apply flex w-full items-center justify-between gap-8 rounded-t-lg border-b bg-muted p-4
}
.generic-node-title-arrangement {
@apply flex-max-width items-center truncate
}
.generic-node-icon {
@apply h-10 w-10 rounded p-1
}
.generic-node-tooltip-div {
@apply ml-2 truncate
}
.generic-node-validation-div {
@apply max-h-96 overflow-auto
}
.generic-node-status-position {
@apply relative top-[3px] h-5 w-5
}
.generic-node-status-animation {
@apply hidden h-4 w-4 animate-spin rounded-full bg-ring opacity-0
}
.generic-node-status {
@apply h-4 w-4 rounded-full opacity-100
}
.green-status {
@apply generic-node-status bg-status-green
}
.red-status {
@apply generic-node-status bg-status-red
}
.yellow-status {
@apply generic-node-status bg-status-yellow
}
.status-build-animation {
@apply hidden h-4 w-4 animate-spin rounded-full bg-ring opacity-0
}
.status-div {
@apply absolute w-4 duration-200 ease-in-out
}
.status-div:hover {
@apply hover:text-accent-foreground hover:transition-all
}
.generic-node-desc {
@apply h-full w-full py-5 text-foreground
}
.generic-node-desc-text {
@apply w-full px-5 pb-3 text-sm text-muted-foreground
}
.alert-icon {
@apply h-5 w-5
}
.alert-font-size {
@apply text-sm font-medium
}
.error-build-message {
@apply mt-6 w-96 cursor-pointer rounded-md bg-error-background p-4 shadow-xl
}
.error-build-message-circle {
@apply text-status-red alert-icon
}
.error-build-text {
@apply text-error-foreground
}
.error-build-foreground {
@apply error-build-text alert-font-size
}
.error-build-message-div {
@apply mt-2 text-sm error-build-text
}
.error-build-message-list {
@apply list-disc space-y-1 pl-5
}
.success-alert {
@apply mt-6 w-96 rounded-md bg-success-background p-4 shadow-xl
}
.success-alert-icon {
@apply alert-icon text-status-green
}
.success-alert-message {
@apply alert-font-size text-success-foreground
}
.card-component-title-display {
@apply round-button-div flex-max-width
}
.card-component-image {
@apply flex h-7 w-7 items-center justify-center rounded-full text-2xl
}
.card-component-title-size {
@apply inline-block w-full flex-1 break-words truncate-doubleline
}
.card-component-delete-button {
@apply flex self-start
}
.card-component-delete-icon {
@apply h-4 w-4 text-primary opacity-0 transition-all group-hover:opacity-100
}
.card-component-desc {
@apply pb-2 pt-2
}
.card-component-desc-text {
@apply truncate-doubleline
}
.card-component-footer-arrangement {
@apply flex-max-width items-end justify-between gap-2
}
.card-component-footer {
@apply flex flex-wrap gap-2
}
.unused-side-bar-aside {
@apply flex flex-shrink-0 flex-col overflow-hidden border-r transition-all duration-500
}
.unused-side-bar-arrangement {
@apply flex h-full w-52 flex-col items-start overflow-y-auto border bg-background scrollbar-hide
}
.unused-side-bar-division {
@apply flex-max-width flex-grow flex-col
}
.unused-side-bar-nav {
@apply flex-1 space-y-1
}
.unused-side-bar-link {
@apply flex-max-width items-center rounded-md py-2 pl-2 text-sm font-medium
}
.unused-side-bar-link-colors-true {
@apply bg-muted text-foreground
}
.unused-side-bar-link-colors-false {
@apply bg-background text-muted-foreground hover:bg-muted hover:text-foreground
}
.unused-side-bar-icon {
@apply mr-3 flex-shrink-0 h-6 w-6
}
.unused-side-bar-icon-false {
@apply text-ring group-hover:text-accent-foreground
}
.unused-side-bar-disclosure {
@apply unused-side-bar-link pr-1 text-left
}
.unused-side-bar-disclosure:focus {
@apply focus:outline-none focus:ring-1 focus:ring-ring
}
.unused-side-bar-disclosure-icon {
@apply unused-side-bar-icon text-ring group-hover:text-accent-foreground
}
.unused-side-bar-svg-true {
@apply text-ring rotate-90
}
.unused-side-bar-svg {
@apply ml-3 h-5 w-5 flex-shrink-0 duration-150 ease-in-out group-hover:text-accent-foreground
}
.unused-side-bar-disclosure-panel {
@apply flex w-full items-center rounded-md py-2 pl-11 pr-2 text-sm font-medium
}
.code-area-component {
@apply pointer-events-none w-full cursor-not-allowed
}
.code-area-input-positioning {
@apply flex-max-width items-center
}
.code-area-external-link {
@apply w-6 h-6 ml-3
}
.code-area-external-link:hover {
@apply hover:text-accent-foreground
}
.dropdown-component-outline {
@apply input-edit-node relative pr-8
}
.dropdown-component-false-outline {
@apply input-primary py-2 pl-3 pr-10 text-left
}
.dropdown-component-display {
@apply block w-full truncate bg-background
}
.dropdown-component-arrow {
@apply pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2
}
.dropdown-component-arrow-color {
@apply h-5 w-5 extra-side-bar-save-disable
}
.dropdown-component-options {
@apply z-10 mt-1 max-h-60 overflow-auto rounded-md bg-background py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm
}
.dropdown-component-true-options {
@apply dropdown-component-options w-[215px]
}
.dropdown-component-false-options {
@apply dropdown-component-options w-full
}
.dropdown-component-option {
@apply relative cursor-default select-none
}
.dropdown-component-false-option {
@apply dropdown-component-option py-0.5 pl-3 pr-12
}
.dropdown-component-true-option {
@apply dropdown-component-option py-2 pl-3 pr-9
}
.dropdown-component-choosal {
@apply absolute inset-y-0 right-0 flex items-center pr-4
}
.dropdown-component-check-icon {
@apply h-5 w-5 text-black
}
.edit-flow-arrangement {
@apply flex justify-between
}
.edit-flow-span {
@apply ml-10 animate-pulse text-status-red
}
.float-component-pointer {
@apply pointer-events-none cursor-not-allowed
}
.header-menu-bar {
@apply flex items-center gap-0.5 rounded-md px-1.5 py-1 text-sm font-medium
}
.header-menu-bar-display {
@apply flex max-w-[200px] items-center gap-2
}
.header-menu-flow-name {
@apply flex-1 truncate
}
.header-menu-options {
@apply mr-2 h-4 w-4
}
.header-arrangement {
@apply flex-max-width h-12 items-center justify-between border-b bg-muted
}
.header-start-display {
@apply flex w-96 items-center justify-start gap-2
}
.header-end-division {
@apply flex w-96 justify-end px-2
}
.header-end-display {
@apply ml-auto mr-2 flex items-center gap-5
}
.header-github-link-box {
@apply border border-input h-9 px-3 pr-0 rounded-md inline-flex shadow-sm items-center justify-center
}
.header-github-link {
@apply text-sm font-medium disabled:opacity-50 disabled:pointer-events-none ring-offset-background text-muted-foreground header-github-link-box
}
.header-github-link:focus-visible {
@apply focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2
}
.header-github-link:hover {
@apply hover:bg-accent hover:text-accent-foreground
}
.header-github-display {
@apply -mr-px ml-2 flex h-9 items-center justify-center rounded-md rounded-l-none border bg-background px-2 text-sm
}
.header-notifications-box {
@apply fixed left-0 top-0 h-screen w-screen
}
.header-notifications {
@apply absolute right-[3px] h-1.5 w-1.5 rounded-full bg-destructive
}
.input-component-div {
@apply pointer-events-none relative cursor-not-allowed
}
.input-component-button {
@apply absolute inset-y-0 right-0 items-center text-muted-foreground
}
.input-component-true-button {
@apply input-component-button pr-2
}
.input-component-false-button {
@apply input-component-button px-4
}
.input-component-true-svg {
@apply absolute bottom-0.5 right-2 side-bar-button-size
}
.input-component-false-svg {
@apply absolute bottom-2 right-3 side-bar-button-size
}
.input-file-component {
@apply flex-max-width items-center
}
.toggle-component-switch {
@apply relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out
}
.toggle-component-switch:focus {
@apply focus:outline-none focus:ring-1 focus:ring-primary focus:ring-offset-1
}
.toggle-component-span {
@apply pointer-events-none relative inline-block h-5 w-5 transform rounded-full shadow ring-0 transition duration-200 ease-in-out
}
.toggle-component-second-span {
@apply absolute inset-0 flex h-full w-full items-center justify-center transition-opacity
}
.app-div {
@apply fixed bottom-5 left-5 flex flex-col-reverse
}
.chat-input-modal-txtarea {
@apply form-input block w-full rounded-md border-ring pr-10 custom-scroll sm:text-sm
}
.chat-input-modal-div {
@apply absolute bottom-0.5 right-3
}
.chat-input-modal-lock {
@apply side-bar-button-size animate-pulse text-ring
}
.chat-input-modal-send {
@apply side-bar-button-size text-ring hover:text-muted-foreground
}
.code-block-modal {
@apply flex items-center justify-between px-4 py-1.5
}
.code-block-modal-span {
@apply text-xs lowercase text-background
}
.code-block-modal-button {
@apply flex items-center gap-1.5 rounded bg-none p-1 text-xs text-background
}
.chat-message-modal {
@apply flex-max-width py-2 pl-2
}
.chat-message-modal-div {
@apply my-3 flex h-8 w-8 items-center justify-center overflow-hidden rounded-full
}
.chat-message-modal-img {
@apply absolute scale-150 transition-opacity duration-500
}
.chat-message-modal-display {
@apply flex-max-width items-center text-start
}
.chat-message-modal-text {
@apply relative inline-block w-full text-start text-sm font-normal text-muted-foreground
}
.chat-message-modal-icon-div {
@apply absolute -left-2 -top-1 cursor-pointer
}
.chat-message-modal-thought {
@apply ml-3 inline-block h-full w-[95%] rounded-md border border-ring bg-muted px-2 pb-3 pt-3 text-start text-muted-foreground chat-message-modal-thought-cursor
}
.chat-message-modal-thought-cursor {
@apply cursor-pointer scrollbar-hide overflow-scroll
}
.chat-message-modal-markdown {
@apply w-full px-4 pb-3 pr-8 pt-3
}
.chat-message-modal-markdown-span {
@apply mt-1 animate-pulse cursor-default
}
.chat-message-modal-alert {
@apply inline-block px-3 text-start text-muted-foreground
}
.file-card-modal-image-div {
@apply absolute right-0 top-0 rounded-bl-lg bg-muted px-1 text-sm font-bold text-foreground
}
.file-card-modal-image-button {
@apply px-2 py-1 text-ring
}
.file-card-modal-button {
@apply flex w-1/2 items-center justify-between rounded border border-ring bg-muted px-2 py-2 text-foreground shadow hover:drop-shadow-lg
}
.file-card-modal-div {
@apply mr-2 flex-max-width items-center gap-2 text-current
}
.file-card-modal-footer {
@apply flex flex-col items-start
}
.file-card-modal-name {
@apply truncate text-sm text-current
}
.file-card-modal-type {
@apply truncate text-xs text-ring
}
.send-message-modal-transition {
@apply fixed inset-0 bg-black bg-opacity-80 backdrop-blur-sm transition-opacity
}
.chat-modal-box {
@apply fixed inset-0 z-10 overflow-y-auto
}
.chat-modal-box-div {
@apply flex h-full items-end justify-center p-4 text-center sm:items-center sm:p-0
}
.chat-modal-dialog-panel {
@apply relative flex h-[95%] w-[690px] transform flex-col justify-between overflow-hidden rounded-lg bg-background text-left shadow-xl drop-shadow-2xl transition-all
}
.chat-modal-dialog-panel-div {
@apply relative w-full p-4
}
.chat-modal-dialog-trash-panel {
@apply absolute right-10 top-2 z-30 text-muted-foreground hover:text-status-red
}
.chat-modal-dialog-x-panel {
@apply absolute right-2 top-1.5 z-30 text-muted-foreground hover:text-status-red
}
.chat-modal-dialog-history {
@apply flex-max-width h-full flex-col items-center overflow-scroll border-t bg-background scrollbar-hide
}
.chat-modal-dialog-span-box {
@apply flex-max-width h-full flex-col items-center justify-center text-center align-middle
}
.chat-modal-dialog-desc {
@apply w-2/4 rounded-md border border-input bg-muted px-6 py-8
}
.chat-modal-input-div {
@apply flex-max-width flex-col items-center justify-between border-t bg-background p-3
}
.chat-modal-input {
@apply relative mt-1 w-full rounded-md shadow-sm
}
.code-area-modal-editor-div {
@apply mt-2 flex-max-width h-full
}
.code-area-modal-editor-box {
@apply h-[300px] w-full rounded-lg border-[1px] border-ring custom-scroll
}
.edit-node-modal-variable {
@apply h-5 w-5 stroke-2 pe-1 text-muted-foreground
}
.edit-node-modal-span {
@apply text-sm font-semibold text-primary
}
.edit-node-modal-arrangement {
@apply flex-max-width h-fit max-h-[400px]
}
.edit-node-modal-box {
@apply w-full rounded-lg border-[1px] border-input bg-background
}
.edit-node-modal-table {
@apply flex h-fit flex-col gap-5
}
.edit-node-modal-table-header {
@apply h-10 border-input text-xs font-medium text-ring
}
.edit-node-modal-table-cell {
@apply p-0 text-center text-sm text-foreground truncate sm:px-3
}
.edit-node-modal-second-cell {
@apply w-[300px] p-0 text-center text-xs text-foreground
}
.generic-modal-txtarea-div {
@apply mt-2 flex-max-width h-full
}
.button-box-modal-div {
@apply flex transform flex-col items-center justify-center rounded-lg border border-ring text-center shadow hover:scale-105 hover:shadow-lg
}
.dialog-header-modal-div {
@apply absolute left-0 top-2 z-50 hidden pl-4 pt-4 sm:block
}
.dialog-header-modal-button {
@apply rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2
}
.dialog-modal-examples-div {
@apply h-full w-full overflow-y-auto scrollbar-hide
}
.dialog-modal-example-true {
@apply mx-auto flex flex-row flex-wrap items-start justify-center overflow-auto
}
.dialog-modal-example-false {
@apply flex flex-row items-center justify-center
}
.dialog-modal-button-box-div {
@apply flex-max-width h-full items-center justify-evenly
}
.document-icon {
@apply h-10 w-10 flex-shrink-0
}
.loading-component-div {
@apply flex items-center justify-center align-middle
}
.dialog-modal-footer {
@apply mt-2 flex-max-width items-center justify-center
}
.dialog-modal-footer-link {
@apply flex items-center justify-center text-muted-foreground
}
.node-modal-div {
@apply fixed inset-0 bg-ring bg-opacity-75 transition-opacity
}
.node-modal-dialog-arrangement {
@apply fixed inset-0 z-10 overflow-y-auto
}
.node-modal-dialog-div {
@apply flex h-full items-end justify-center p-4 text-center sm:items-center sm:p-0
}
.node-modal-dialog-panel {
@apply relative flex h-[600px] w-[700px] transform flex-col justify-between overflow-hidden rounded-lg bg-background text-left shadow-xl transition-all sm:my-8
}
.node-modal-dialog-panel-div {
@apply absolute right-0 top-0 z-50 hidden pr-4 pt-4 sm:block
}
.node-modal-dialog-button {
@apply rounded-md text-ring hover:text-accent-foreground
}
.node-modal-dialog-icon-div {
@apply flex-max-width h-full flex-col items-center justify-center
}
.node-modal-icon-arrangement {
@apply z-10 flex-max-width justify-center pb-4 shadow-sm
}
.node-modal-icon {
@apply mt-4 h-10 w-10 rounded p-1
}
.node-modal-title-div {
@apply mt-4 text-center sm:ml-4 sm:text-left
}
.node-modal-title {
@apply text-lg font-medium leading-10 text-foreground
}
.node-modal-template-div {
@apply flex-max-width h-full flex-row items-center justify-center gap-4 bg-input p-4
}
.node-modal-template {
@apply w-full rounded-lg bg-background px-4 shadow sm:p-4
}
.node-modal-template-column {
@apply flex h-full flex-col gap-5
}
.node-modal-button-box {
@apply flex-max-width flex-row-reverse bg-input px-4 pb-3
}
.node-modal-button {
@apply inline-flex w-full justify-center rounded-md border border-transparent bg-status-red px-4 py-2 text-base font-medium text-background shadow-sm hover:bg-ring sm:ml-3 sm:w-auto sm:text-sm
}
.node-modal-button:focus {
@apply focus:outline-none focus:ring-1 focus:ring-ring focus:ring-offset-1
}
.prompt-modal-icon-box {
@apply mx-auto mt-4 flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-almost-light-blue sm:mx-0 sm:h-10 sm:w-10
}
.prompt-modal-icon {
@apply h-6 w-6 text-almost-medium-blue
}
.prompt-modal-txtarea-arrangement {
@apply flex-max-width h-full flex-row items-center justify-center gap-4 overflow-auto bg-accent p-4
}
.prompt-modal-txtarea-box {
@apply h-full w-full overflow-hidden rounded-lg bg-background px-4 py-5 shadow sm:p-6
}
.prompt-modal-txtarea {
@apply form-input h-full w-full rounded-lg border-ring
}
.txtarea-modal-arrangement {
@apply flex h-full w-full flex-row items-center justify-center gap-4 bg-input p-4
}
.txtarea-modal-box {
@apply w-full overflow-hidden rounded-lg bg-background px-4 py-5 shadow sm:p-6
}
.txtarea-modal-input {
@apply form-input h-full w-full
}
.api-modal-tabs {
@apply w-full h-full overflow-hidden text-center bg-muted rounded-md border
}
.api-modal-tablist-div {
@apply flex items-center justify-between px-2
}
.api-modal-tabs-content {
@apply overflow-hidden w-full h-full px-4 pb-4 -mt-1
}
.api-modal-accordion-display {
@apply flex w-full h-full mt-2
}
.api-modal-table-arrangement {
@apply flex flex-col gap-5 h-fit
}
.icons-parameters-comp{
@apply ml-3 h-6 w-6
}
}

View file

@ -8,13 +8,13 @@ import ContextWrapper from "./contexts";
import "./index.css";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
document.getElementById("root") as HTMLElement,
);
root.render(
<ContextWrapper>
<BrowserRouter>
<App />
</BrowserRouter>
</ContextWrapper>
</ContextWrapper>,
);
reportWebVitals();

View file

@ -158,7 +158,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
t.data.node.template[n].type === "code" ||
t.data.node.template[n].type === "prompt" ||
t.data.node.template[n].type === "file" ||
t.data.node.template[n].type === "int")
t.data.node.template[n].type === "int"),
)
.map((n, i) => {
arrNodesWithValues.push(t["id"]);
@ -182,7 +182,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
}
const existingTweak = tweak.current.find((element) =>
element.hasOwnProperty(tw)
element.hasOwnProperty(tw),
);
if (existingTweak) {
@ -278,7 +278,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
<Tabs
value={activeTab}
className="h-full w-full overflow-hidden rounded-md border bg-muted text-center"
className="api-modal-tabs"
onValueChange={(value) => {
setActiveTab(value);
if (value === "3") {
@ -286,7 +286,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
}
}}
>
<div className="flex items-center justify-between px-2">
<div className="api-modal-tablist-div">
<TabsList>
{tabs.map((tab, index) => (
<TabsTrigger key={index} value={index.toString()}>
@ -310,7 +310,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
{tabs.map((tab, index) => (
<TabsContent
value={index.toString()}
className="-mt-1 h-full w-full overflow-hidden px-4 pb-4"
className="api-modal-tabs-content"
key={index} // Remember to add a unique key prop
>
{index < 3 ? (
@ -323,13 +323,13 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
</SyntaxHighlighter>
) : index === 3 ? (
<>
<div className="mt-2 flex h-full w-full">
<div className="api-modal-according-display">
<div
className={classNames(
"h-[60vh] w-full rounded-lg bg-muted",
1 == 1
? "overflow-scroll overflow-x-hidden custom-scroll"
: "overflow-hidden"
: "overflow-hidden",
)}
>
{flow["data"]["nodes"].map((t: any, index) => (
@ -339,7 +339,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
trigger={t["data"]["id"]}
open={openAccordion}
>
<div className="flex h-fit flex-col gap-5">
<div className="api-modal-table-arrangement">
<Table className="table-fixed bg-muted outline-1">
<TableHeader className="h-10 border-input text-xs font-medium text-ring">
<TableRow className="dark:border-b-muted">
@ -370,7 +370,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
t.data.node.template[n].type ===
"file" ||
t.data.node.template[n].type ===
"int")
"int"),
)
.map((n, i) => {
//console.log(t.data.node.template[n]);
@ -413,7 +413,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
t["data"]["id"],
k,
t.data.node
.template[n]
.template[n],
);
}}
/>
@ -424,7 +424,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
content={buildContent(
t.data.node.template[
n
].value
].value,
)}
>
<div>
@ -437,14 +437,14 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
.value,
t.data,
t.data.node
.template[n]
.template[n],
)}
onChange={(k) => {
buildTweakObject(
t["data"]["id"],
k,
t.data.node
.template[n]
.template[n],
);
}}
/>
@ -466,14 +466,14 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
t.data,
t.data.node.template[
n
]
],
)}
onChange={(k) => {
buildTweakObject(
t["data"]["id"],
k,
t.data.node
.template[n]
.template[n],
);
}}
/>
@ -498,7 +498,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
e,
t.data.node.template[
n
]
],
);
}}
size="small"
@ -514,8 +514,8 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
t.data.node.template[n]
.value,
t.data,
t.data.node.template[n]
)
t.data.node.template[n],
),
)}
>
<div className="mx-auto">
@ -528,7 +528,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
].value ?? ""
}
onChange={(
k: any
k: any,
) => {}}
fileTypes={
t.data.node.template[
@ -541,7 +541,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
].suffixes
}
onFileChange={(
k: any
k: any,
) => {}}
></InputFileComponent>
</div>
@ -556,7 +556,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
t.data.node.template[n]
.value,
t.data,
t.data.node.template[n]
t.data.node.template[n],
)}
onChange={(k) => {
buildTweakObject(
@ -564,7 +564,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
k,
t.data.node.template[
n
]
],
);
}}
/>
@ -587,14 +587,14 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
k,
t.data.node.template[
n
]
],
);
}}
value={getValue(
t.data.node.template[n]
.value,
t.data,
t.data.node.template[n]
t.data.node.template[n],
)}
></Dropdown>
</div>
@ -608,7 +608,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
t.data.node.template[n]
.value,
t.data,
t.data.node.template[n]
t.data.node.template[n],
)}
onChange={(k) => {
buildTweakObject(
@ -616,7 +616,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
k,
t.data.node.template[
n
]
],
);
}}
/>
@ -630,8 +630,8 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
t.data.node.template[n]
.value,
t.data,
t.data.node.template[n]
)
t.data.node.template[n],
),
)}
>
<div className="mx-auto">
@ -645,14 +645,14 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
t.data,
t.data.node.template[
n
]
],
)}
onChange={(k) => {
buildTweakObject(
t["data"]["id"],
k,
t.data.node
.template[n]
.template[n],
);
}}
/>
@ -667,8 +667,8 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
t.data.node.template[n]
.value,
t.data,
t.data.node.template[n]
)
t.data.node.template[n],
),
)}
>
<div className="mx-auto">
@ -682,14 +682,14 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
t.data,
t.data.node.template[
n
]
],
)}
onChange={(k) => {
buildTweakObject(
t["data"]["id"],
k,
t.data.node
.template[n]
.template[n],
);
}}
/>

View file

@ -47,8 +47,8 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
data.node.template[t].type === "code" ||
data.node.template[t].type === "prompt" ||
data.node.template[t].type === "file" ||
data.node.template[t].type === "int")
).length
data.node.template[t].type === "int"),
).length,
);
const [nodeValue, setNodeValue] = useState(null);
const { closePopUp } = useContext(PopUpContext);
@ -90,27 +90,27 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
<DialogDescription>
{data.node?.description}
<div className="flex pt-3">
<Variable className="h-5 w-5 stroke-2 pe-1 text-muted-foreground "></Variable>
<span className="text-sm font-semibold text-primary">
<Variable className="edit-node-modal-variable "></Variable>
<span className="edit-node-modal-span">
Parameters
</span>
</div>
</DialogDescription>
</DialogHeader>
<div className="flex h-fit max-h-[400px] w-full">
<div className="edit-node-modal-arrangement">
<div
className={classNames(
"w-full rounded-lg border-[1px] border-input bg-background",
"edit-node-modal-box",
nodeLength > limitScrollFieldsModal
? "overflow-scroll overflow-x-hidden custom-scroll"
: "overflow-hidden"
: "overflow-hidden",
)}
>
{nodeLength > 0 && (
<div className="flex h-fit flex-col gap-5">
<div className="edit-node-modal-table">
<Table className="table-fixed bg-muted outline-1">
<TableHeader className="h-10 border-input text-xs font-medium text-ring">
<TableHeader className="edit-node-modal-table-header">
<TableRow className="">
<TableHead className="h-7 text-center">PARAM</TableHead>
<TableHead className="h-7 p-0 text-center">
@ -131,7 +131,7 @@ export default function EditNodeModal({ data }: { data: NodeDataType }) {
data.node.template[t].type === "code" ||
data.node.template[t].type === "prompt" ||
data.node.template[t].type === "file" ||
data.node.template[t].type === "int")
data.node.template[t].type === "int"),
)
.map((n, i) => (
<TableRow key={i} className="h-10">

View file

@ -21,7 +21,7 @@ export default function ModalField({
index,
}) {
const [enabled, setEnabled] = useState(
data.node.template[name]?.value ?? false
data.node.template[name]?.value ?? false,
);
const display =
type === "str" ||
@ -41,12 +41,12 @@ export default function ModalField({
(t) =>
t.charAt(0) !== "_" &&
data.node.template[t].advanced &&
data.node.template[t].show
data.node.template[t].show,
).length -
1 ===
index
? "pb-4"
: ""
: "",
)}
>
{display && (

View file

@ -45,11 +45,11 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-ring bg-opacity-75 transition-opacity" />
<div className="node-modal-div" />
</Transition.Child>
<div className="fixed inset-0 z-10 overflow-y-auto">
<div className="flex h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
<div className="node-modal-dialog-arrangement">
<div className="node-modal-dialog-div">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
@ -59,11 +59,11 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="relative flex h-[600px] w-[700px] transform flex-col justify-between overflow-hidden rounded-lg bg-background text-left shadow-xl transition-all sm:my-8">
<div className=" absolute right-0 top-0 z-50 hidden pr-4 pt-4 sm:block">
<Dialog.Panel className="node-modal-dialog-panel">
<div className=" node-modal-dialog-panel-div">
<button
type="button"
className="rounded-md text-ring hover:text-accent-foreground"
className="node-modal-dialog-button"
onClick={() => {
setModalOpen(false);
}}
@ -72,47 +72,47 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
<X className="h-6 w-6" aria-hidden="true" />
</button>
</div>
<div className="flex h-full w-full flex-col items-center justify-center">
<div className="z-10 flex w-full justify-center pb-4 shadow-sm">
<div className="node-modal-dialog-icon-div">
<div className="node-modal-icon-arrangement">
<Icon
strokeWidth={1.5}
className="mt-4 h-10 w-10 rounded p-1"
className="node-modal-icon"
style={{
color:
nodeColors[types[data.type]] ?? nodeColors.unknown,
}}
/>
<div className="mt-4 text-center sm:ml-4 sm:text-left">
<div className="node-modal-title-div">
<Dialog.Title
as="h3"
className="text-lg font-medium leading-10 text-foreground"
className="node-modal-title"
>
{data.type}
</Dialog.Title>
</div>
</div>
<div className="flex h-full w-full flex-row items-center justify-center gap-4 bg-input p-4">
<div className="flex h-[445px] w-full">
<div className="node-modal-template-div">
<div className="flex-max-width h-[445px]">
<div
className={classNames(
"w-full rounded-lg bg-background px-4 shadow sm:p-4",
"node-modal-template",
Object.keys(data.node.template).filter(
(t) =>
t.charAt(0) !== "_" &&
data.node.template[t].advanced &&
data.node.template[t].show
data.node.template[t].show,
).length > limitScrollFieldsModal
? "overflow-scroll overflow-x-hidden custom-scroll"
: "overflow-hidden"
: "overflow-hidden",
)}
>
<div className="flex h-full flex-col gap-5">
<div className="node-modal-template-column">
{Object.keys(data.node.template)
.filter(
(t) =>
t.charAt(0) !== "_" &&
data.node.template[t].advanced &&
data.node.template[t].show
data.node.template[t].show,
)
.map((t: string, idx) => {
return (
@ -144,10 +144,10 @@ export default function NodeModal({ data }: { data: NodeDataType }) {
</div>
</div>
</div>
<div className="flex w-full flex-row-reverse bg-input px-4 pb-3">
<div className="node-modal-button-box">
<button
type="button"
className="inline-flex w-full justify-center rounded-md border border-transparent bg-status-red px-4 py-2 text-base font-medium text-background shadow-sm hover:bg-ring focus:outline-none focus:ring-1 focus:ring-ring focus:ring-offset-1 sm:ml-3 sm:w-auto sm:text-sm"
className="node-modal-button"
onClick={() => {
setModalOpen(false);
}}

View file

@ -0,0 +1,161 @@
import { useEffect, useRef, useState } from "react";
import { ChatMessageType } from "../../../types/chat";
import { classNames } from "../../../utils";
import AiIcon from "../../../assets/Gooey Ring-5s-271px.svg";
import AiIconStill from "../../../assets/froze-flow.png";
import FileCard from "../fileComponent";
import ReactMarkdown from "react-markdown";
import rehypeMathjax from "rehype-mathjax";
import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
import { CodeBlock } from "./codeBlock";
import Convert from "ansi-to-html";
import { User2, MessageCircle } from "lucide-react";
import DOMPurify from "dompurify";
export default function ChatMessage({
chat,
lockChat,
lastMessage,
}: {
chat: ChatMessageType;
lockChat: boolean;
lastMessage: boolean;
}) {
const convert = new Convert({ newline: true });
const [message, setMessage] = useState("");
const imgRef = useRef(null);
useEffect(() => {
setMessage(chat.message);
}, [chat.message]);
const [hidden, setHidden] = useState(true);
return (
<div
className={classNames(
"chat-message-modal",
chat.isSend ? "bg-background " : "bg-input"
)}
>
<div
className={classNames(
"chat-message-modal-div"
)}
>
{!chat.isSend && (
<div className="relative h-8 w-8">
<img
className={
"chat-message-modal-img " +
(lockChat ? "opacity-100" : "opacity-0")
}
src={lastMessage ? AiIcon : AiIconStill}
/>
<img
className={
"chat-message-modal-img " +
(lockChat ? "opacity-0" : "opacity-100")
}
src={AiIconStill}
/>
</div>
)}
{chat.isSend && <User2 className="-mb-1 h-6 w-6 text-primary " />}
</div>
{!chat.isSend ? (
<div className="chat-message-modal-display">
<div className="chat-message-modal-text">
{hidden && chat.thought && chat.thought !== "" && (
<div
onClick={() => setHidden((prev) => !prev)}
className="chat-message-modal-icon-div"
>
<MessageCircle className="h-5 w-5 animate-bounce " />
</div>
)}
{chat.thought && chat.thought !== "" && !hidden && (
<div
onClick={() => setHidden((prev) => !prev)}
className=" chat-message-modal-thought"
dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(convert.toHtml(chat.thought)),
}}
></div>
)}
{chat.thought && chat.thought !== "" && !hidden && <br></br>}
<div className="chat-message-modal-markdown">
<div className="w-full">
<div className="w-full">
<ReactMarkdown
remarkPlugins={[remarkGfm, remarkMath]}
rehypePlugins={[rehypeMathjax]}
className="markdown prose text-muted-foreground "
components={{
code({ node, inline, className, children, ...props }) {
if (children.length) {
if (children[0] == "▍") {
return (
<span className="chat-message-modal-markdown-span">
</span>
);
}
children[0] = (children[0] as string).replace(
"`▍`",
"▍"
);
}
const match = /language-(\w+)/.exec(className || "");
return !inline ? (
<CodeBlock
key={Math.random()}
language={(match && match[1]) || ""}
value={String(children).replace(/\n$/, "")}
{...props}
/>
) : (
<code className={className} {...props}>
{children}
</code>
);
},
}}
>
{message}
</ReactMarkdown>
</div>
{chat.files && (
<div className="my-2 w-full">
{chat.files.map((file, index) => {
return (
<div key={index} className="my-2 w-full">
<FileCard
fileName={"Generated File"}
fileType={file.data_type}
content={file.data}
/>
</div>
);
})}
</div>
)}
</div>
</div>
</div>
</div>
) : (
<div className="flex w-full items-center">
<div className="chat-message-modal-alert ">
{message.split("\n").map((line, index) => (
<span key={index} className="text-muted-foreground ">
{line}
<br />
</span>
))}
</div>
</div>
)}
</div>
);
}

View file

@ -0,0 +1,418 @@
import { Dialog, Transition } from "@headlessui/react";
import { Fragment, useContext, useEffect, useRef, useState } from "react";
import { FlowType } from "../../types/flow";
import { alertContext } from "../../contexts/alertContext";
import { validateNodes } from "../../utils";
import { typesContext } from "../../contexts/typesContext";
import ChatMessage from "./chatMessage";
import { X, MessagesSquare, Eraser } from "lucide-react";
import { sendAllProps } from "../../types/api";
import { ChatMessageType } from "../../types/chat";
import ChatInput from "./chatInput";
import _ from "lodash";
import { getHealth } from "../../controllers/API";
export default function ChatModal({
flow,
open,
setOpen,
}: {
open: boolean;
setOpen: Function;
flow: FlowType;
}) {
const [chatValue, setChatValue] = useState("");
const [chatHistory, setChatHistory] = useState<ChatMessageType[]>([]);
const { reactFlowInstance } = useContext(typesContext);
const { setErrorData, setNoticeData } = useContext(alertContext);
const ws = useRef<WebSocket | null>(null);
const [lockChat, setLockChat] = useState(false);
const isOpen = useRef(open);
const messagesRef = useRef(null);
const id = useRef(flow.id);
useEffect(() => {
if (messagesRef.current) {
messagesRef.current.scrollTop = messagesRef.current.scrollHeight;
}
}, [chatHistory]);
useEffect(() => {
isOpen.current = open;
}, [open]);
useEffect(() => {
id.current = flow.id;
}, [flow.id]);
var isStream = false;
const addChatHistory = (
message: string,
isSend: boolean,
thought?: string,
files?: Array<any>
) => {
setChatHistory((old) => {
let newChat = _.cloneDeep(old);
if (files) {
newChat.push({ message, isSend, files, thought });
} else if (thought) {
newChat.push({ message, isSend, thought });
} else {
newChat.push({ message, isSend });
}
return newChat;
});
};
//add proper type signature for function
function updateLastMessage({
str,
thought,
end = false,
files,
}: {
str?: string;
thought?: string;
// end param default is false
end?: boolean;
files?: Array<any>;
}) {
setChatHistory((old) => {
let newChat = [...old];
if (str) {
if (end) {
newChat[newChat.length - 1].message = str;
} else {
newChat[newChat.length - 1].message =
newChat[newChat.length - 1].message + str;
}
}
if (thought) {
newChat[newChat.length - 1].thought = thought;
}
if (files) {
newChat[newChat.length - 1].files = files;
}
return newChat;
});
}
function handleOnClose(event: CloseEvent) {
if (isOpen.current) {
setErrorData({ title: event.reason });
setTimeout(() => {
connectWS();
setLockChat(false);
}, 1000);
}
}
function getWebSocketUrl(chatId, isDevelopment = false) {
const isSecureProtocol = window.location.protocol === "https:";
const webSocketProtocol = isSecureProtocol ? "wss" : "ws";
const host = isDevelopment ? "localhost:7860" : window.location.host;
const chatEndpoint = `/api/v1/chat/${chatId}`;
return `${
isDevelopment ? "ws" : webSocketProtocol
}://${host}${chatEndpoint}`;
}
function handleWsMessage(data: any) {
if (Array.isArray(data)) {
//set chat history
setChatHistory((_) => {
let newChatHistory: ChatMessageType[] = [];
data.forEach(
(chatItem: {
intermediate_steps?: "string";
is_bot: boolean;
message: string;
type: string;
files?: Array<any>;
}) => {
if (chatItem.message) {
newChatHistory.push(
chatItem.files
? {
isSend: !chatItem.is_bot,
message: chatItem.message,
thought: chatItem.intermediate_steps,
files: chatItem.files,
}
: {
isSend: !chatItem.is_bot,
message: chatItem.message,
thought: chatItem.intermediate_steps,
}
);
}
}
);
return newChatHistory;
});
}
if (data.type === "start") {
addChatHistory("", false);
isStream = true;
}
if (data.type === "end") {
if (data.message) {
updateLastMessage({ str: data.message, end: true });
}
if (data.intermediate_steps) {
updateLastMessage({
str: data.message,
thought: data.intermediate_steps,
end: true,
});
}
if (data.files) {
updateLastMessage({
end: true,
files: data.files,
});
}
setLockChat(false);
isStream = false;
}
if (data.type === "stream" && isStream) {
updateLastMessage({ str: data.message });
}
}
function connectWS() {
try {
const urlWs = getWebSocketUrl(
id.current,
process.env.NODE_ENV === "development"
);
const newWs = new WebSocket(urlWs);
newWs.onopen = () => {
console.log("WebSocket connection established!");
};
newWs.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log("Received data:", data);
handleWsMessage(data);
//get chat history
};
newWs.onclose = (event) => {
handleOnClose(event);
};
newWs.onerror = (ev) => {
getHealth()
.then((res) => {
if (res.status === 200) {
connectWS();
}
})
.catch((err) => {
setErrorData({
// message when the backend failed
title: "The backend is not responding. Please try again later.",
// possible solution list
list: [
"Check your internet connection.",
"Check if the backend is running.",
],
});
});
};
ws.current = newWs;
} catch (error) {
connectWS();
console.log(error);
}
}
useEffect(() => {
connectWS();
return () => {
console.log("unmount");
console.log(ws);
if (ws.current) {
ws.current.close();
}
};
}, []);
useEffect(() => {
if (
ws.current &&
(ws.current.readyState === ws.current.CLOSED ||
ws.current.readyState === ws.current.CLOSING)
) {
connectWS();
setLockChat(false);
}
}, [lockChat]);
async function sendAll(data: sendAllProps) {
try {
if (ws) {
ws.current.send(JSON.stringify(data));
}
} catch (error) {
setErrorData({
title: "There was an error sending the message",
list: [error.message],
});
setChatValue(data.message);
connectWS();
}
}
useEffect(() => {
if (ref.current) ref.current.scrollIntoView({ behavior: "smooth" });
}, [chatHistory]);
const ref = useRef(null);
useEffect(() => {
if (open && ref.current) {
ref.current.focus();
}
}, [open]);
function sendMessage() {
if (chatValue !== "") {
let nodeValidationErrors = validateNodes(reactFlowInstance);
if (nodeValidationErrors.length === 0) {
setLockChat(true);
let message = chatValue;
setChatValue("");
addChatHistory(message, true);
sendAll({
...reactFlowInstance.toObject(),
message,
chatHistory,
name: flow.name,
description: flow.description,
});
} else {
setErrorData({
title: "Oops! Looks like you missed some required information:",
list: nodeValidationErrors,
});
}
} else {
setErrorData({
title: "Error sending message",
list: ["The message cannot be empty."],
});
}
}
function clearChat() {
setChatHistory([]);
ws.current.send(JSON.stringify({ clear_history: true }));
if (lockChat) setLockChat(false);
}
function setModalOpen(x: boolean) {
setOpen(x);
}
return (
<Transition.Root show={open} appear={open} as={Fragment}>
<Dialog
as="div"
className="relative z-10"
onClose={setModalOpen}
initialFocus={ref}
>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="send-message-modal-transition" />
</Transition.Child>
<div className="chat-modal-box">
<div className="chat-modal-box-div">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className=" chat-modal-dialog-panel">
<div className="chat-modal-dialog-panel-div">
<button
onClick={() => clearChat()}
className="chat-modal-dialog-trash-panel"
>
<Eraser className="h-4 w-4" />
</button>
<button
onClick={() => setModalOpen(false)}
className="chat-modal-dialog-x-panel"
>
<X className="h-5 w-5" />
</button>
</div>
<div
ref={messagesRef}
className="chat-modal-dialog-history"
>
{chatHistory.length > 0 ? (
chatHistory.map((c, i) => (
<ChatMessage
lockChat={lockChat}
chat={c}
lastMessage={chatHistory.length - 1 == i ? true : false}
key={i}
/>
))
) : (
<div className="chat-modal-dialog-span-box">
<span>
👋{" "}
<span className="text-lg text-muted-foreground">
Langflow Chat
</span>
</span>
<br />
<div className="chat-modal-dialog-desc">
<span className="text-base text-ring">
Start a conversation and click the agents thoughts{" "}
<span>
<MessagesSquare className="mx-1 inline h-5 w-5 animate-bounce " />
</span>{" "}
to inspect the chaining process.
</span>
</div>
</div>
)}
<div ref={ref}></div>
</div>
<div className="chat-modal-input-div">
<div className="chat-modal-input">
<ChatInput
chatValue={chatValue}
lockChat={lockChat}
sendMessage={sendMessage}
setChatValue={setChatValue}
inputRef={ref}
/>
</div>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
);
}

View file

@ -109,7 +109,7 @@ export default function CodeAreaModal({
<DialogDescription>{CODE_PROMPT_DIALOG_SUBTITLE}</DialogDescription>
</DialogHeader>
<div className="mt-2 flex h-[60vh] w-full">
<div className="code-area-modal-editor-div">
<AceEditor
value={code}
mode="python"

View file

@ -37,7 +37,7 @@ export default function ExportModal() {
const [checked, setChecked] = useState(false);
const [name, setName] = useState(flows.find((f) => f.id === tabId).name);
const [description, setDescription] = useState(
flows.find((f) => f.id === tabId).description
flows.find((f) => f.id === tabId).description,
);
return (
<Dialog open={true} onOpenChange={setModalOpen}>

View file

@ -27,7 +27,7 @@ export default function FlowSettingsModal() {
const maxLength = 50;
const [name, setName] = useState(flows.find((f) => f.id === tabId).name);
const [description, setDescription] = useState(
flows.find((f) => f.id === tabId).description
flows.find((f) => f.id === tabId).description,
);
function setModalOpen(x: boolean) {
setOpen(x);

View file

@ -1,7 +1,7 @@
import { classNames } from "../../../utils";
import { useContext, useEffect, useRef, useState } from "react";
import { TabsContext } from "../../../contexts/tabsContext";
import { Eraser, Lock, LucideSend, Send } from "lucide-react";
import { Eraser, Lock, LucideSend } from "lucide-react";
export default function ChatInput({
lockChat,

View file

@ -48,19 +48,19 @@ export const CodeBlock: FC<Props> = memo(({ language, value }) => {
};
return (
<div className="codeblock font-sans text-[16px]">
<div className="flex items-center justify-between px-4 py-1.5">
<span className="text-xs lowercase text-background">{language}</span>
<div className="code-block-modal">
<span className="code-block-modal-span">{language}</span>
<div className="flex items-center">
<button
className="flex items-center gap-1.5 rounded bg-none p-1 text-xs text-background"
className="code-block-modal-button"
onClick={copyToClipboard}
>
{isCopied ? <IconCheck size={18} /> : <IconClipboard size={18} />}
{isCopied ? "Copied!" : "Copy code"}
</button>
<button
className="flex items-center rounded bg-none p-1 text-xs text-background"
className="code-block-modal-button"
onClick={downloadAsFile}
>
<IconDownload size={18} />

View file

@ -37,9 +37,9 @@ export default function FileCard({ fileName, content, fileType }) {
/>
{isHovered && (
<div
className={`absolute right-0 top-0 rounded-bl-lg bg-muted px-1 text-sm font-bold text-foreground `}
className={`file-card-modal-image-div `}
>
<button className="px-2 py-1 text-ring " onClick={handleDownload}>
<button className="file-card-modal-image-button " onClick={handleDownload}>
<DownloadCloud className="h-5 w-5 text-current hover:scale-110" />
</button>
</div>
@ -51,9 +51,9 @@ export default function FileCard({ fileName, content, fileType }) {
return (
<button
onClick={handleDownload}
className="flex w-1/2 items-center justify-between rounded border border-ring bg-muted px-2 py-2 text-foreground shadow hover:drop-shadow-lg"
className="file-card-modal-button"
>
<div className="mr-2 flex w-full items-center gap-2 text-current">
<div className="file-card-modal-div">
{" "}
{fileType === "image" ? (
<img
@ -64,10 +64,10 @@ export default function FileCard({ fileName, content, fileType }) {
) : (
<File className="h-8 w-8" />
)}
<div className="flex flex-col items-start">
<div className="file-card-modal-footer">
{" "}
<div className="truncate text-sm text-current">{fileName}</div>
<div className="truncate text-xs text-ring">{fileType}</div>
<div className="file-card-modal-name">{fileName}</div>
<div className="file-card-modal-type">{fileType}</div>
</div>
<DownloadCloud className="ml-auto h-6 w-6 text-current" />
</div>

View file

@ -77,11 +77,11 @@ export default function ButtonBox({
<button disabled={deactivate} onClick={onClick}>
<div
className={classNames(
"flex transform flex-col items-center justify-center rounded-lg border border-ring text-center shadow hover:scale-105 hover:shadow-lg",
"button-box-modal-div",
bgColor,
height,
width,
padding
padding,
)}
>
<div
@ -98,7 +98,7 @@ export default function ButtonBox({
className={classNames(
"w-full break-words font-semibold text-background truncate-multiline",
titleFontSize,
marginTop
marginTop,
)}
>
{title}

View file

@ -1,22 +1,18 @@
import {
XMarkIcon,
ArrowDownTrayIcon,
DocumentDuplicateIcon,
ComputerDesktopIcon,
ArrowUpTrayIcon,
ArrowLeftIcon,
CommandLineIcon,
} from "@heroicons/react/24/outline";
import { Fragment, useContext, useRef, useState } from "react";
import { useContext, useRef, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
import ButtonBox from "./buttonBox";
import { getExamples } from "../../controllers/API";
import { error } from "console";
import { alertContext } from "../../contexts/alertContext";
import LoadingComponent from "../../components/loadingComponent";
import { FlowType } from "../../types/flow";
import { classNames, snakeToSpaces, toNormalCase } from "../../utils";
import { classNames } from "../../utils";
import {
Dialog,
DialogContent,
@ -26,7 +22,6 @@ import {
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { Button } from "../../components/ui/button";
import { IMPORT_DIALOG_SUBTITLE } from "../../constants";
export default function ImportModal() {
@ -76,10 +71,10 @@ export default function ImportModal() {
<DialogTitle className="flex items-center">
{showExamples && (
<>
<div className="absolute left-0 top-2 z-50 hidden pl-4 pt-4 sm:block">
<div className="dialog-header-modal-div">
<button
type="button"
className="rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
className="dialog-header-modal-button disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
onClick={() => {
setShowExamples(false);
}}
@ -106,20 +101,20 @@ export default function ImportModal() {
<div
className={classNames(
"h-full w-full overflow-y-auto scrollbar-hide",
"dialog-modal-examples-div",
showExamples && !loadingExamples
? "start mx-auto flex flex-row flex-wrap items-start justify-center overflow-auto"
: "flex flex-row items-center justify-center"
? "dialog-modal-example-true"
: "dialog-modal-example-false"
)}
>
{!showExamples && (
<div className="flex h-full w-full items-center justify-evenly">
<div className="dialog-modal-button-box-div">
<ButtonBox
size="big"
bgColor="bg-medium-emerald "
description="Prebuilt Examples"
icon={
<DocumentDuplicateIcon className="h-10 w-10 flex-shrink-0" />
<DocumentDuplicateIcon className="document-icon" />
}
onClick={() => {
setShowExamples(true);
@ -133,7 +128,7 @@ export default function ImportModal() {
bgColor="bg-almost-dark-blue "
description="Import from Local"
icon={
<ComputerDesktopIcon className="h-10 w-10 flex-shrink-0" />
<ComputerDesktopIcon className="document-icon" />
}
onClick={() => {
uploadFlow();
@ -145,7 +140,7 @@ export default function ImportModal() {
</div>
)}
{showExamples && loadingExamples && (
<div className="flex items-center justify-center align-middle">
<div className="loading-component-div">
<LoadingComponent remSize={30} />
</div>
)}
@ -178,11 +173,11 @@ export default function ImportModal() {
</div>
<DialogFooter>
<div className="mt-2 flex w-full items-center justify-center">
<div className="dialog-modal-footer">
<a
href="https://github.com/logspace-ai/langflow_examples"
target="_blank"
className="flex items-center justify-center text-muted-foreground "
className="dialog-modal-footer-link "
rel="noreferrer"
>
<svg
@ -197,7 +192,7 @@ export default function ImportModal() {
fill="currentColor"
/>
</svg>
<span className="ml-2 ">LangFlow Examples</span>
<span className="ml-2 ">Langflow Examples</span>
</a>
</div>
</DialogFooter>

View file

@ -0,0 +1,154 @@
import { Dialog, Transition } from "@headlessui/react";
import { XMarkIcon, DocumentTextIcon } from "@heroicons/react/24/outline";
import { Fragment, useContext, useRef, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { darkContext } from "../../contexts/darkContext";
import { checkPrompt } from "../../controllers/API";
import { alertContext } from "../../contexts/alertContext";
export default function PromptAreaModal({
value,
setValue,
}: {
setValue: (value: string) => void;
value: string;
}) {
const [open, setOpen] = useState(true);
const [myValue, setMyValue] = useState(value);
const { dark } = useContext(darkContext);
const { setErrorData, setSuccessData } = useContext(alertContext);
const { closePopUp, setCloseEdit } = useContext(PopUpContext);
const ref = useRef();
function setModalOpen(x: boolean) {
setOpen(x);
if (x === false) {
setTimeout(() => {
setCloseEdit("prompt");
closePopUp();
}, 300);
}
}
return (
<Transition.Root show={open} appear={true} as={Fragment}>
<Dialog
as="div"
className="relative z-10"
onClose={setModalOpen}
initialFocus={ref}
>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="node-modal-div" />
</Transition.Child>
<div className="node-modal-dialog-arrangement">
<div className="node-modal-dialog-div">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="node-modal-dialog-panel">
<div className=" node-modal-dialog-panel-div ">
<button
type="button"
className="node-modal-dialog-button"
onClick={() => {
setModalOpen(false);
}}
>
<span className="sr-only">Close</span>
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
</button>
</div>
<div className="node-modal-dialog-icon-div">
<div className="node-modal-icon-arrangement">
<div className="prompt-modal-icon-box">
<DocumentTextIcon
className="prompt-modal-icon"
aria-hidden="true"
/>
</div>
<div className="node-modal-title-div ">
<Dialog.Title
as="h3"
className="node-modal-title"
>
Edit Prompt
</Dialog.Title>
</div>
</div>
<div className="prompt-modal-txtarea-arrangement">
<div className="flex-max-width h-full">
<div className="prompt-modal-txtarea-box">
<textarea
ref={ref}
className="prompt-modal-txtarea"
value={myValue}
onChange={(e) => {
setMyValue(e.target.value);
setValue(e.target.value);
}}
/>
</div>
</div>
</div>
<div className="node-modal-button-box">
<button
type="button"
className="node-modal-button"
onClick={() => {
checkPrompt(myValue)
.then((apiReturn) => {
if (apiReturn.data) {
let inputVariables =
apiReturn.data.input_variables;
if (inputVariables.length === 0) {
setErrorData({
title:
"The template you are attempting to use does not contain any variables for data entry.",
});
} else {
setSuccessData({
title: "Prompt is ready",
});
setModalOpen(false);
setValue(myValue);
}
} else {
setErrorData({
title: "Something went wrong, please try again",
});
}
})
.catch((error) => {
return setErrorData({
title:
"There is something wrong with this prompt, please review it",
list: [error.response.data.detail],
});
});
}}
>
Check & Save
</button>
</div>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
);
}

View file

@ -0,0 +1,124 @@
import { Dialog, Transition } from "@headlessui/react";
import {
XMarkIcon,
ClipboardDocumentListIcon,
} from "@heroicons/react/24/outline";
import { Fragment, useContext, useRef, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
export default function TextAreaModal({
value,
setValue,
}: {
setValue: (value: string) => void;
value: string | string[];
}) {
const [open, setOpen] = useState(true);
const [myValue, setMyValue] = useState(value);
const { closePopUp, setCloseEdit } = useContext(PopUpContext);
const ref = useRef();
function setModalOpen(x: boolean) {
setOpen(x);
if (x === false) {
setTimeout(() => {
setCloseEdit("textarea");
closePopUp();
}, 300);
}
}
return (
<Transition.Root show={open} appear={true} as={Fragment}>
<Dialog
as="div"
className="relative z-10"
onClose={setModalOpen}
initialFocus={ref}
>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="node-modal-div" />
</Transition.Child>
<div className="node-modal-dialog-arrangement">
<div className="node-modal-dialog-div">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="node-modal-dialog-panel">
<div className=" node-modal-dialog-panel-div">
<button
type="button"
className="node-modal-dialog-button"
onClick={() => {
setModalOpen(false);
}}
>
<span className="sr-only">Close</span>
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
</button>
</div>
<div className="node-modal-dialog-icon-div">
<div className="node-modal-icon-arrangement">
<div className="prompt-modal-icon-box">
<ClipboardDocumentListIcon
className="prompt-modal-icon"
aria-hidden="true"
/>
</div>
<div className="node-modal-title-div">
<Dialog.Title
as="h3"
className="node-modal-title"
>
Edit text
</Dialog.Title>
</div>
</div>
<div className="txtarea-modal-arrangement">
<div className="flex h-full w-full">
<div className="txtarea-modal-box">
<textarea
ref={ref}
className="txtarea-modal-input"
value={myValue}
onChange={(e) => {
setMyValue(e.target.value);
setValue(e.target.value);
}}
/>
</div>
</div>
</div>
<div className="node-modal-button-box">
<button
type="button"
className="node-modal-button"
onClick={() => {
setModalOpen(false);
}}
>
Finish editing
</button>
</div>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
);
}

View file

@ -37,31 +37,31 @@ export default function CommunityPage() {
handleExamples();
}, []);
return (
<div className="flex h-full w-full flex-col overflow-auto bg-muted px-16">
<div className="flex w-full justify-between px-6 py-12 pb-2">
<span className="flex items-center justify-center gap-2 text-2xl font-semibold">
<div className="community-page-arrangement">
<div className="community-page-nav-arrangement">
<span className="community-page-nav-title">
<Users2 className="w-6" />
Community Examples
</span>
<div className="flex gap-2">
<div className="community-page-nav-button">
<a
href="https://github.com/logspace-ai/langflow_examples"
target="_blank"
rel="noreferrer"
>
<Button variant="primary">
<GithubIcon className="mr-2 w-4" />
<GithubIcon className="main-page-nav-button" />
Add Your Example
</Button>
</a>
</div>
</div>
<span className="flex w-[70%] px-6 pb-8 text-muted-foreground">
Discover and learn from shared examples by the LangFlow community. We
<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="grid w-full gap-4 p-4 md:grid-cols-2 lg:grid-cols-4">
<div className="community-pages-flows-panel">
{!loadingExamples &&
examples.map((flow, idx) => (
<CardComponent
@ -79,7 +79,7 @@ export default function CommunityPage() {
});
}}
>
<GitFork className="mr-2 w-4" />
<GitFork className="main-page-nav-button" />
Fork Example
</Button>
}

View file

@ -12,14 +12,12 @@ export default function DisclosureComponent({
{({ open }) => (
<>
<div>
<Disclosure.Button className="-mt-px flex w-full select-none items-center justify-between border-y border-y-input bg-muted px-3 py-2">
<Disclosure.Button className="components-disclosure-arrangement">
<div className="flex gap-4">
<Icon strokeWidth={1.5} size={22} className="text-primary " />
<span className="flex items-center text-sm text-primary">
{title}
</span>
<Icon strokeWidth={1.5} size={22} className="text-primary" />
<span className="components-disclosure-title">{title}</span>
</div>
<div className="flex gap-2">
<div className="components-disclosure-div">
{buttons.map((x, index) => (
<button key={index} onClick={x.onClick}>
{x.Icon}
@ -35,7 +33,7 @@ export default function DisclosureComponent({
</div>
</Disclosure.Button>
</div>
<Disclosure.Panel as="div" className="-mt-px" static={openDisc}>
<Disclosure.Panel as="div" static={openDisc}>
{children}
</Disclosure.Panel>
</>

View file

@ -112,10 +112,10 @@ export default function Page({ flow }: { flow: FlowType }) {
const { setExtraComponent, setExtraNavigation } = useContext(locationContext);
const { setErrorData } = useContext(alertContext);
const [nodes, setNodes, onNodesChange] = useNodesState(
flow.data?.nodes ?? []
flow.data?.nodes ?? [],
);
const [edges, setEdges, onEdgesChange] = useEdgesState(
flow.data?.edges ?? []
flow.data?.edges ?? [],
);
const { setViewport } = useReactFlow();
const edgeUpdateSuccessful = useRef(true);
@ -158,7 +158,7 @@ export default function Page({ flow }: { flow: FlowType }) {
};
});
},
[onEdgesChange, setNodes, setTabsState, tabId]
[onEdgesChange, setNodes, setTabsState, tabId],
);
const onNodesChangeMod = useCallback(
@ -174,7 +174,7 @@ export default function Page({ flow }: { flow: FlowType }) {
};
});
},
[onNodesChange, setTabsState, tabId]
[onNodesChange, setTabsState, tabId],
);
const onConnect = useCallback(
@ -191,15 +191,15 @@ export default function Page({ flow }: { flow: FlowType }) {
: "stroke-foreground ",
animated: params.targetHandle.split("|")[0] === "Text",
},
eds
)
eds,
),
);
setNodes((x) => {
let newX = _.cloneDeep(x);
return newX;
});
},
[setEdges, setNodes, takeSnapshot]
[setEdges, setNodes, takeSnapshot],
);
const onNodeDragStart: NodeDragHandler = useCallback(() => {
@ -288,7 +288,7 @@ export default function Page({ flow }: { flow: FlowType }) {
}
},
// Specify dependencies for useCallback
[getNodeId, reactFlowInstance, setErrorData, setNodes, takeSnapshot]
[getNodeId, reactFlowInstance, setErrorData, setNodes, takeSnapshot],
);
useEffect(() => {
@ -304,11 +304,12 @@ export default function Page({ flow }: { flow: FlowType }) {
takeSnapshot();
setEdges(
edges.filter(
(ns) => !mynodes.some((n) => ns.source === n.id || ns.target === n.id)
)
(ns) =>
!mynodes.some((n) => ns.source === n.id || ns.target === n.id),
),
);
},
[takeSnapshot, edges, setEdges]
[takeSnapshot, edges, setEdges],
);
const onEdgeUpdateStart = useCallback(() => {
@ -322,7 +323,7 @@ export default function Page({ flow }: { flow: FlowType }) {
setEdges((els) => updateEdge(oldEdge, newConnection, els));
}
},
[]
[],
);
const onEdgeUpdateEnd = useCallback((_, edge) => {

View file

@ -59,48 +59,50 @@ export default function ExtraSidebar() {
}
return (
<div className="flex h-full w-52 flex-col overflow-hidden border-r scrollbar-hide">
<div className="mb-2 mt-2 flex w-full items-center justify-between gap-2 px-2">
<div className="side-bar-arrangement">
<div className="side-bar-buttons-arrangement">
<ShadTooltip content="Import" side="top">
<button
className="relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground shadow-sm ring-1 ring-inset ring-input transition-all duration-500 ease-in-out hover:bg-muted"
className="extra-side-bar-buttons"
onClick={() => {
// openPopUp(<ImportModal />);
uploadFlow();
}}
>
<FileUp strokeWidth={1.5} className="h-5 w-5 "></FileUp>
<FileUp
strokeWidth={1.5}
className="side-bar-button-size "
></FileUp>
</button>
</ShadTooltip>
<ShadTooltip content="Export" side="top">
<button
className={classNames(
"relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground shadow-sm ring-1 ring-inset ring-input transition-all duration-500 ease-in-out hover:bg-muted"
)}
className={classNames("extra-side-bar-buttons")}
onClick={(event) => {
openPopUp(<ExportModal />);
}}
>
<FileDown strokeWidth={1.5} className="h-5 w-5 "></FileDown>
<FileDown
strokeWidth={1.5}
className="side-bar-button-size"
></FileDown>
</button>
</ShadTooltip>
<ShadTooltip content="Code" side="top">
<button
className={classNames(
"relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground shadow-sm ring-1 ring-inset ring-input transition-all duration-500 ease-in-out hover:bg-muted"
)}
className={classNames("extra-side-bar-buttons")}
onClick={(event) => {
openPopUp(<ApiModal flow={flows.find((f) => f.id === tabId)} />);
}}
>
<Code2 strokeWidth={1.5} className="h-5 w-5 "></Code2>
<Code2 strokeWidth={1.5} className="side-bar-button-size"></Code2>
</button>
</ShadTooltip>
<ShadTooltip content="Save" side="top">
<button
className="relative inline-flex w-full items-center justify-center rounded-md bg-background px-2 py-2 text-foreground shadow-sm ring-1 ring-inset ring-input transition-all duration-500 ease-in-out hover:bg-muted"
className="extra-side-bar-buttons"
onClick={(event) => {
saveFlow(flows.find((f) => f.id === tabId));
setSuccessData({ title: "Changes saved successfully" });
@ -110,14 +112,15 @@ export default function ExtraSidebar() {
<Save
strokeWidth={1.5}
className={
"h-5 w-5" + (isPending ? " " : " text-muted-foreground")
"side-bar-button-size" +
(isPending ? " " : " extra-side-bar-save-disable")
}
></Save>
</button>
</ShadTooltip>
</div>
<Separator />
<div className="relative mx-auto mb-2 mt-2 flex items-center">
<div className="side-bar-search-div-placement">
<input
type="text"
name="search"
@ -129,13 +132,13 @@ export default function ExtraSidebar() {
setSearch(e.target.value);
}}
/>
<div className="absolute inset-y-0 right-0 flex items-center py-1.5 pr-3">
<div className="search-icon">
{/* ! replace hash color here */}
<Search size={20} strokeWidth={1.5} className="text-primary" />
</div>
</div>
<div className="w-full overflow-auto pb-10 scrollbar-hide">
<div className="side-bar-components-div-arrangement">
{Object.keys(dataFilter)
.sort()
.map((d: keyof APIObjectType, i) =>
@ -148,7 +151,7 @@ export default function ExtraSidebar() {
Icon: nodeIconsLucide[d] ?? nodeIconsLucide.unknown,
}}
>
<div className="flex flex-col gap-2 p-2">
<div className="side-bar-components-gap">
{Object.keys(dataFilter[d])
.sort()
.map((t: string, k) => (
@ -160,7 +163,7 @@ export default function ExtraSidebar() {
<div key={k} data-tooltip-id={t}>
<div
draggable
className={"cursor-grab rounded-l-md border-l-8"}
className={"side-bar-components-border"}
style={{
borderLeftColor:
nodeColors[d] ?? nodeColors.unknown,
@ -179,11 +182,11 @@ export default function ExtraSidebar() {
);
}}
>
<div className="flex w-full items-center justify-between rounded-md rounded-l-none border border-l-0 border-dashed border-ring bg-white px-3 py-1 text-sm">
<span className="w-full truncate pr-1 text-xs text-foreground">
<div className="side-bar-components-div-form">
<span className="side-bar-components-text">
{data[d][t].display_name}
</span>
<Menu className="h-6 w-4 text-ring " />
<Menu className="side-bar-components-icon " />
</div>
</div>
</div>

View file

@ -5,7 +5,6 @@ import { TabsContext } from "../../../../contexts/tabsContext";
import { useReactFlow } from "reactflow";
import EditNodeModal from "../../../../modals/EditNodeModal";
import ShadTooltip from "../../../../components/ShadTooltipComponent";
import { EllipsisVerticalIcon } from "@heroicons/react/24/outline";
const NodeToolbarComponent = (props) => {
const [nodeLength, setNodeLength] = useState(

View file

@ -20,7 +20,7 @@ export default function FlowPage() {
}, []);
return (
<div className="h-full w-full overflow-hidden">
<div className="flow-page-positioning">
{flows.length > 0 &&
tabId !== "" &&
flows.findIndex((flow) => flow.id === tabId) !== -1 && (
@ -29,9 +29,9 @@ export default function FlowPage() {
<a
target={"_blank"}
href="https://logspace.ai/"
className="absolute bottom-2 left-7 flex h-6 cursor-pointer flex-col items-center justify-start overflow-hidden rounded-lg bg-foreground px-2 text-center font-sans text-xs tracking-wide text-secondary transition-all duration-500 ease-in-out hover:h-12"
className="logspace-page-icon"
>
{version && <div className="mt-1"> LangFlow v{version}</div>}
{version && <div className="mt-1"> Langflow v{version}</div>}
<div className={version ? "mt-2" : "mt-1"}>Created by Logspace</div>
</a>
</div>

View file

@ -5,7 +5,6 @@ import { Button } from "../../components/ui/button";
import { Link, useNavigate } from "react-router-dom";
import { CardComponent } from "../../components/cardComponent";
import { USER_PROJECTS_HEADER } from "../../constants";
import { BUTTON_DIV_STYLE } from "../../constants";
export default function HomePage() {
const { flows, setTabId, downloadFlows, uploadFlows, addFlow, removeFlow } =
useContext(TabsContext);
@ -14,20 +13,20 @@ export default function HomePage() {
}, []);
const navigate = useNavigate();
return (
<div className="flex h-full w-full flex-col overflow-auto bg-muted px-16">
<div className="flex w-full justify-between px-6 py-12 pb-2">
<span className="flex items-center justify-center gap-2 text-2xl font-semibold">
<div className="main-page-panel">
<div className="main-page-nav-arrangement">
<span className="main-page-nav-title">
<Home className="w-6" />
{USER_PROJECTS_HEADER}
</span>
<div className={`${BUTTON_DIV_STYLE}`}>
<div className="button-div-style">
<Button
variant="primary"
onClick={() => {
downloadFlows();
}}
>
<Download className="mr-2 w-4" />
<Download className="main-page-nav-button" />
Download Collection
</Button>
<Button
@ -36,7 +35,7 @@ export default function HomePage() {
uploadFlows();
}}
>
<Upload className="mr-2 w-4" />
<Upload className="main-page-nav-button" />
Upload Collection
</Button>
<Button
@ -47,15 +46,15 @@ export default function HomePage() {
});
}}
>
<Plus className="mr-2 w-4" />
<Plus className="main-page-nav-button" />
New Project
</Button>
</div>
</div>
<span className="flex w-[60%] px-6 pb-14 text-muted-foreground">
<span className="main-page-description-text">
Manage your personal projects. Download or upload your collection.
</span>
<div className="grid w-full gap-4 p-4 md:grid-cols-2 lg:grid-cols-4">
<div className="main-page-flows-display">
{flows.map((flow, idx) => (
<CardComponent
key={idx}
@ -68,7 +67,7 @@ export default function HomePage() {
size="sm"
className="whitespace-nowrap "
>
<ExternalLink className="mr-2 w-4" />
<ExternalLink className="main-page-nav-button" />
Edit Flow
</Button>
</Link>

View file

@ -142,7 +142,7 @@ export type ShadTooltipProps = {
style?: string;
};
export type ShadToolTipType = {
content?: string;
content?: ReactNode;
side?: "top" | "right" | "bottom" | "left";
asChild?: boolean;
children?: ReactElement;

View file

@ -28,7 +28,7 @@ export type TabsContextType = {
setTabsState: Dispatch<SetStateAction<TabsState>>;
paste: (
selection: { nodes: any; edges: any },
position: { x: number; y: number; paneX?: number; paneY?: number }
position: { x: number; y: number; paneX?: number; paneY?: number },
) => void;
lastCopiedSelection: { nodes: any; edges: any };
setLastCopiedSelection: (selection: { nodes: any; edges: any }) => void;

View file

@ -492,7 +492,7 @@ export function cn(...inputs: ClassValue[]) {
export function measureTextHeight(
text: string,
width: number,
fontSize: number
fontSize: number,
) {
const charHeight = fontSize;
const lineHeight = charHeight * 1.5;
@ -519,7 +519,7 @@ export function toCamelCase(str: string) {
.map((word, index) =>
index === 0
? word.toLowerCase()
: word[0].toUpperCase() + word.slice(1).toLowerCase()
: word[0].toUpperCase() + word.slice(1).toLowerCase(),
)
.join("");
}
@ -580,7 +580,7 @@ export function getConnectedNodes(edge: Edge, nodes: Array<Node>): Array<Node> {
export function isValidConnection(
{ source, target, sourceHandle, targetHandle }: Connection,
reactFlowInstance: ReactFlowInstance
reactFlowInstance: ReactFlowInstance,
) {
if (
targetHandle
@ -634,7 +634,7 @@ export function removeApiKeys(flow: FlowType): FlowType {
export function updateObject<T extends Record<string, any>>(
reference: T,
objectToUpdate: T
objectToUpdate: T,
): T {
let clonedObject = _.cloneDeep(objectToUpdate);
// Loop through each key in the object to update
@ -665,7 +665,7 @@ export function debounce(func, wait) {
export function updateTemplate(
reference: APITemplateType,
objectToUpdate: APITemplateType
objectToUpdate: APITemplateType,
): APITemplateType {
let clonedObject: APITemplateType = _.cloneDeep(reference);
@ -723,7 +723,7 @@ export function toTitleCase(str: string) {
.map((word, index) => {
if (index === 0) {
return checkUpperWords(
word[0].toUpperCase() + word.slice(1).toLowerCase()
word[0].toUpperCase() + word.slice(1).toLowerCase(),
);
}
return checkUpperWords(word.toLowerCase());
@ -735,7 +735,7 @@ export function toTitleCase(str: string) {
.map((word, index) => {
if (index === 0) {
return checkUpperWords(
word[0].toUpperCase() + word.slice(1).toLowerCase()
word[0].toUpperCase() + word.slice(1).toLowerCase(),
);
}
return checkUpperWords(word.toLowerCase());
@ -912,7 +912,7 @@ export function buildTweaks(flow) {
}
export function validateNode(
n: NodeType,
reactFlowInstance: ReactFlowInstance
reactFlowInstance: ReactFlowInstance,
): Array<string> {
if (!n.data?.node?.template || !Object.keys(n.data.node.template)) {
return [
@ -938,16 +938,16 @@ export function validateNode(
.some(
(e) =>
e.targetHandle.split("|")[1] === t &&
e.targetHandle.split("|")[2] === n.id
e.targetHandle.split("|")[2] === n.id,
)
? [
`${type} is missing ${
template.display_name || toNormalCase(template[t].name)
}.`,
]
: []
: [],
),
[] as string[]
[] as string[],
);
}
@ -972,7 +972,7 @@ export function getRandomDescription(): string {
export function getRandomName(
retry: number = 0,
noSpace: boolean = false,
maxRetries: number = 3
maxRetries: number = 3,
): string {
const left: string[] = ADJECTIVES;
const right: string[] = NOUNS;