From 073b38d48d0e9889d6849e040444482dbe6cae47 Mon Sep 17 00:00:00 2001
From: "Ian Christopher B. de Jesus" <3683356+iandjx@users.noreply.github.com>
Date: Thu, 5 Sep 2024 13:36:19 +0800
Subject: [PATCH 01/28] Convert humaninput checkbox to select
---
webapp/src/components/TaskForm.tsx | 82 +++++++++++++++++++++---------
1 file changed, 59 insertions(+), 23 deletions(-)
diff --git a/webapp/src/components/TaskForm.tsx b/webapp/src/components/TaskForm.tsx
index 86582f78..326c53d9 100644
--- a/webapp/src/components/TaskForm.tsx
+++ b/webapp/src/components/TaskForm.tsx
@@ -133,6 +133,12 @@ export default function TaskForm({
const toolIds = toolState ? toolState.map(x => x?.value) : [];
const datasourceIds = datasourceState ? datasourceState.map(x => x?.value) : [];
const dedupedCombinedToolIds = [...new Set([...toolIds, ...datasourceIds])];
+
+ const displayOnlyFinalOutput =
+ taskState?.requiresHumanInput && (!formFields || formFields.length === 0)
+ ? false
+ : taskState.displayOnlyFinalOutput;
+
const body: any = {
_csrf: e.target._csrf.value,
resourceSlug,
@@ -142,10 +148,10 @@ export default function TaskForm({
toolIds: dedupedCombinedToolIds || [],
agentId: taskState?.agentId || null,
asyncExecution: false, //e.target.asyncExecution.checked,
- requiresHumanInput: e.target.requiresHumanInput.checked,
+ requiresHumanInput: taskState?.requiresHumanInput || null,
context: taskState?.context || [],
formFields: formFields || [],
- displayOnlyFinalOutput: e.target.displayOnlyFinalOutput.checked,
+ displayOnlyFinalOutput,
storeTaskOutput: e.target.storeTaskOutput.checked,
taskOutputFileName: e.target.taskOutputFileName?.value,
isStructuredOutput
@@ -612,7 +618,6 @@ export default function TaskForm({
*/}
- {/* human_input tool checkbox */}
+
{/* Form builder for human input */}
- {requiredHumanInput && (
+ {requiredHumanInput && formFields?.length > 0 && (
@@ -671,7 +700,14 @@ export default function TaskForm({
type='checkbox'
id='displayOnlyFinalOutput'
name='displayOnlyFinalOutput'
- checked={taskState?.displayOnlyFinalOutput === true}
+ disabled={
+ taskState?.requiresHumanInput && (!formFields || formFields.length === 0)
+ }
+ checked={
+ taskState?.requiresHumanInput && (!formFields || formFields.length === 0)
+ ? false
+ : taskState?.displayOnlyFinalOutput === true
+ }
onChange={e => {
setTask(oldTask => {
return {
@@ -680,7 +716,7 @@ export default function TaskForm({
};
});
}}
- className='mr-2 h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500'
+ className='mr-2 h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 disabled:bg-gray-500'
/>
Display Only Final Output
From 2ecfd8d4a3cfbaa824a310ff826827cfcc529621 Mon Sep 17 00:00:00 2001
From: "Ian Christopher B. de Jesus" <3683356+iandjx@users.noreply.github.com>
Date: Fri, 6 Sep 2024 11:59:37 +0800
Subject: [PATCH 02/28] Setup minio for local storage
---
agent-backend/poetry.lock | 118 ++++++++++++++++++++++++++++-
agent-backend/pyproject.toml | 1 +
agent-backend/src/storage/local.py | 101 +++++++++++++++++-------
docker-compose.yml | 13 ++++
4 files changed, 206 insertions(+), 27 deletions(-)
diff --git a/agent-backend/poetry.lock b/agent-backend/poetry.lock
index f29d2229..9a054b59 100644
--- a/agent-backend/poetry.lock
+++ b/agent-backend/poetry.lock
@@ -254,6 +254,63 @@ files = [
{file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
]
+[[package]]
+name = "argon2-cffi"
+version = "23.1.0"
+description = "Argon2 for Python"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea"},
+ {file = "argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08"},
+]
+
+[package.dependencies]
+argon2-cffi-bindings = "*"
+
+[package.extras]
+dev = ["argon2-cffi[tests,typing]", "tox (>4)"]
+docs = ["furo", "myst-parser", "sphinx", "sphinx-copybutton", "sphinx-notfound-page"]
+tests = ["hypothesis", "pytest"]
+typing = ["mypy"]
+
+[[package]]
+name = "argon2-cffi-bindings"
+version = "21.2.0"
+description = "Low-level CFFI bindings for Argon2"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3"},
+ {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367"},
+ {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d"},
+ {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae"},
+ {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c"},
+ {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86"},
+ {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_i686.whl", hash = "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f"},
+ {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e"},
+ {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win32.whl", hash = "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082"},
+ {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f"},
+ {file = "argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93"},
+ {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3e385d1c39c520c08b53d63300c3ecc28622f076f4c2b0e6d7e796e9f6502194"},
+ {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c3e3cc67fdb7d82c4718f19b4e7a87123caf8a93fde7e23cf66ac0337d3cb3f"},
+ {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a22ad9800121b71099d0fb0a65323810a15f2e292f2ba450810a7316e128ee5"},
+ {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9f8b450ed0547e3d473fdc8612083fd08dd2120d6ac8f73828df9b7d45bb351"},
+ {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:93f9bf70084f97245ba10ee36575f0c3f1e7d7724d67d8e5b08e61787c320ed7"},
+ {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3b9ef65804859d335dc6b31582cad2c5166f0c3e7975f324d9ffaa34ee7e6583"},
+ {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4966ef5848d820776f5f562a7d45fdd70c2f330c961d0d745b784034bd9f48d"},
+ {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ef543a89dee4db46a1a6e206cd015360e5a75822f76df533845c3cbaf72670"},
+ {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2937d286e2ad0cc79a7087d3c272832865f779430e0cc2b4f3718d3159b0cb"},
+ {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5e00316dabdaea0b2dd82d141cc66889ced0cdcbfa599e8b471cf22c620c329a"},
+]
+
+[package.dependencies]
+cffi = ">=1.0.1"
+
+[package.extras]
+dev = ["cogapp", "pre-commit", "pytest", "wheel"]
+tests = ["pytest"]
+
[[package]]
name = "arxiv"
version = "2.1.3"
@@ -2963,6 +3020,24 @@ pytz = ">=2024.1,<2025.0"
qdrant-client = ">=1.9.1,<2.0.0"
sqlalchemy = ">=2.0.31,<3.0.0"
+[[package]]
+name = "minio"
+version = "7.2.8"
+description = "MinIO Python SDK for Amazon S3 Compatible Cloud Storage"
+optional = false
+python-versions = ">3.8"
+files = [
+ {file = "minio-7.2.8-py3-none-any.whl", hash = "sha256:aa3b485788b63b12406a5798465d12a57e4be2ac2a58a8380959b6b748e64ddd"},
+ {file = "minio-7.2.8.tar.gz", hash = "sha256:f8af2dafc22ebe1aef3ac181b8e217037011c430aa6da276ed627e55aaf7c815"},
+]
+
+[package.dependencies]
+argon2-cffi = "*"
+certifi = "*"
+pycryptodome = "*"
+typing-extensions = "*"
+urllib3 = "*"
+
[[package]]
name = "mmh3"
version = "4.1.0"
@@ -4070,6 +4145,47 @@ files = [
{file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"},
]
+[[package]]
+name = "pycryptodome"
+version = "3.20.0"
+description = "Cryptographic library for Python"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+files = [
+ {file = "pycryptodome-3.20.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:f0e6d631bae3f231d3634f91ae4da7a960f7ff87f2865b2d2b831af1dfb04e9a"},
+ {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:baee115a9ba6c5d2709a1e88ffe62b73ecc044852a925dcb67713a288c4ec70f"},
+ {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:417a276aaa9cb3be91f9014e9d18d10e840a7a9b9a9be64a42f553c5b50b4d1d"},
+ {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a1250b7ea809f752b68e3e6f3fd946b5939a52eaeea18c73bdab53e9ba3c2dd"},
+ {file = "pycryptodome-3.20.0-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:d5954acfe9e00bc83ed9f5cb082ed22c592fbbef86dc48b907238be64ead5c33"},
+ {file = "pycryptodome-3.20.0-cp27-cp27m-win32.whl", hash = "sha256:06d6de87c19f967f03b4cf9b34e538ef46e99a337e9a61a77dbe44b2cbcf0690"},
+ {file = "pycryptodome-3.20.0-cp27-cp27m-win_amd64.whl", hash = "sha256:ec0bb1188c1d13426039af8ffcb4dbe3aad1d7680c35a62d8eaf2a529b5d3d4f"},
+ {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:5601c934c498cd267640b57569e73793cb9a83506f7c73a8ec57a516f5b0b091"},
+ {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d29daa681517f4bc318cd8a23af87e1f2a7bad2fe361e8aa29c77d652a065de4"},
+ {file = "pycryptodome-3.20.0-cp27-cp27mu-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3427d9e5310af6680678f4cce149f54e0bb4af60101c7f2c16fdf878b39ccccc"},
+ {file = "pycryptodome-3.20.0-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:3cd3ef3aee1079ae44afaeee13393cf68b1058f70576b11439483e34f93cf818"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac1c7c0624a862f2e53438a15c9259d1655325fc2ec4392e66dc46cdae24d044"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:76658f0d942051d12a9bd08ca1b6b34fd762a8ee4240984f7c06ddfb55eaf15a"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f35d6cee81fa145333137009d9c8ba90951d7d77b67c79cbe5f03c7eb74d8fe2"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76cb39afede7055127e35a444c1c041d2e8d2f1f9c121ecef573757ba4cd2c3c"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49a4c4dc60b78ec41d2afa392491d788c2e06edf48580fbfb0dd0f828af49d25"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fb3b87461fa35afa19c971b0a2b7456a7b1db7b4eba9a8424666104925b78128"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:acc2614e2e5346a4a4eab6e199203034924313626f9620b7b4b38e9ad74b7e0c"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:210ba1b647837bfc42dd5a813cdecb5b86193ae11a3f5d972b9a0ae2c7e9e4b4"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-win32.whl", hash = "sha256:8d6b98d0d83d21fb757a182d52940d028564efe8147baa9ce0f38d057104ae72"},
+ {file = "pycryptodome-3.20.0-cp35-abi3-win_amd64.whl", hash = "sha256:9b3ae153c89a480a0ec402e23db8d8d84a3833b65fa4b15b81b83be9d637aab9"},
+ {file = "pycryptodome-3.20.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:4401564ebf37dfde45d096974c7a159b52eeabd9969135f0426907db367a652a"},
+ {file = "pycryptodome-3.20.0-pp27-pypy_73-win32.whl", hash = "sha256:ec1f93feb3bb93380ab0ebf8b859e8e5678c0f010d2d78367cf6bc30bfeb148e"},
+ {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:acae12b9ede49f38eb0ef76fdec2df2e94aad85ae46ec85be3648a57f0a7db04"},
+ {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f47888542a0633baff535a04726948e876bf1ed880fddb7c10a736fa99146ab3"},
+ {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e0e4a987d38cfc2e71b4a1b591bae4891eeabe5fa0f56154f576e26287bfdea"},
+ {file = "pycryptodome-3.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c18b381553638414b38705f07d1ef0a7cf301bc78a5f9bc17a957eb19446834b"},
+ {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a60fedd2b37b4cb11ccb5d0399efe26db9e0dd149016c1cc6c8161974ceac2d6"},
+ {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:405002eafad114a2f9a930f5db65feef7b53c4784495dd8758069b89baf68eab"},
+ {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ab6ab0cb755154ad14e507d1df72de9897e99fd2d4922851a276ccc14f4f1a5"},
+ {file = "pycryptodome-3.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:acf6e43fa75aca2d33e93409f2dafe386fe051818ee79ee8a3e21de9caa2ac9e"},
+ {file = "pycryptodome-3.20.0.tar.gz", hash = "sha256:09609209ed7de61c2b560cc5c8c4fbf892f8b15b1faf7e4cbffac97db1fffda7"},
+]
+
[[package]]
name = "pydantic"
version = "2.9.0b1"
@@ -6033,4 +6149,4 @@ type = ["pytest-mypy"]
[metadata]
lock-version = "2.0"
python-versions = ">=3.11,<3.13"
-content-hash = "5c20801e1a5c02c62b557e36ba8ecc0d65ad2b1d9c62d6c3a3932d90ff8fbccb"
+content-hash = "8649342f7a7752a868dfde11d0a08ec306f1ccd1d22a74360218e6fe29276d94"
diff --git a/agent-backend/pyproject.toml b/agent-backend/pyproject.toml
index 4269480b..d83d5ee7 100644
--- a/agent-backend/pyproject.toml
+++ b/agent-backend/pyproject.toml
@@ -46,6 +46,7 @@ langgraph = "^0.0.51"
langchain-ollama = "^0.1.1"
pinecone-client = "^5.0.1"
langchain-google-genai = "^1.0.10"
+minio = "^7.2.8"
[build-system]
diff --git a/agent-backend/src/storage/local.py b/agent-backend/src/storage/local.py
index e0ec01c6..5603574f 100644
--- a/agent-backend/src/storage/local.py
+++ b/agent-backend/src/storage/local.py
@@ -3,48 +3,97 @@
from pathlib import Path
import shutil
from init.env_variables import UPLOADS_BASE_PATH
-
from storage.provider import StorageProvider
+from minio import Minio
+from minio.error import S3Error
logging.basicConfig(level=logging.DEBUG)
-log = logging.getLogger('storage.local')
+log = logging.getLogger("storage.local")
+
class LocalStorageProvider(StorageProvider):
- allowed_delete_error_codes = ['ENOENT']
+ allowed_delete_error_codes = ["ENOENT"]
def __init__(self):
self.base_path = UPLOADS_BASE_PATH if UPLOADS_BASE_PATH else "./uploads"
self.init()
-
+ self.minio_client = Minio(
+ os.getenv("MINIO_ENDPOINT", "localhost:9000"),
+ access_key=os.getenv("MINIO_ROOT_USER", "minioadmin"),
+ secret_key=os.getenv("MINIO_ROOT_PASSWORD", "minioadmin"),
+ secure=False,
+ )
+ self.bucket_name = os.getenv("MINIO_BUCKET_NAME", "uploads")
+ self.create_bucket()
def init(self):
Path(self.base_path).mkdir(parents=True, exist_ok=True)
- def upload_local_file(self, filename, file_folder, is_public=False):
-
- if not os.path.exists(os.path.join(self.base_path, file_folder)):
- os.makedirs(os.path.join(self.base_path, file_folder))
- original_file_path = os.path.join(Path(__file__).resolve().parent.parent,'outputs', filename) # Open from original path
- file_path = os.path.join(self.base_path, file_folder, filename) # Save to self.base_path
+ def create_bucket(self):
try:
- shutil.copyfile(original_file_path, file_path)
- log.debug(f"File '{filename}' uploaded successfully.")
- os.remove(original_file_path)
- except Exception as e:
- log.error(f"Failed to upload file: {e}")
+ if not self.minio_client.bucket_exists(self.bucket_name):
+ self.minio_client.make_bucket(self.bucket_name)
+ log.debug(f"Bucket '{self.bucket_name}' created successfully.")
+ else:
+ log.debug(f"Bucket '{self.bucket_name}' already exists.")
+ except S3Error as e:
+ log.error(f"Failed to create bucket: {e}")
raise e
-
- def delete_file(self, filename, file_folder):
- file_path = os.path.join(self.base_path, file_folder, filename)
+
+ def upload_file_buffer(self, buffer, filename, folder_path, is_public=False):
+ log.debug("Uploading buffer content as file %s", filename)
try:
- os.remove(file_path)
- log.debug(f"File '{filename}' deleted successfully.")
- except Exception as e:
- if e.errno not in self.allowed_delete_error_codes:
+ self.minio_client.put_object(
+ self.bucket_name,
+ f"{folder_path}/{filename}",
+ buffer,
+ len(buffer),
+ content_type="application/octet-stream",
+ )
+ log.debug("Buffer content uploaded successfully.")
+ except Exception as err:
+ log.error("Buffer upload error:", err)
+ raise err
+
+ def upload_local_file(self, filename, folder_path, is_public=False):
+ log.debug("Uploading file %s", filename)
+ original_file_path = os.path.join(
+ Path(__file__).resolve().parent.parent, "outputs", filename
+ )
+ try:
+ self.minio_client.fput_object(
+ self.bucket_name, f"{folder_path}/{filename}", original_file_path
+ )
+ log.debug("File uploaded successfully.")
+ os.remove(original_file_path)
+ except Exception as err:
+ log.error("File upload error:", err)
+ raise err
+
+ def delete_file(self, filename, file_folder, is_public=False):
+ log.debug("Deleting file %s", filename)
+ try:
+ self.minio_client.remove_object(
+ self.bucket_name, f"{file_folder}/{filename}"
+ )
+ log.debug("File deleted successfully.")
+ except S3Error as e:
+ if e.code not in self.allowed_delete_error_codes:
log.error(f"Failed to delete file: {e.message}")
raise e
-
- def get_signed_url(self, filename, file_folder):
- return "Downloading file not implemented in local storage provider"
-local_storage_provider = LocalStorageProvider()
\ No newline at end of file
+ def get_signed_url(self, filename, file_folder, is_public=False):
+ log.debug("Generating signed URL for file %s", filename)
+ try:
+ url = self.minio_client.presigned_get_object(
+ self.bucket_name,
+ f"{file_folder}/{filename}",
+ expires=60 * 60 * 24 * 365 * 100, # 100 years
+ )
+ return url
+ except S3Error as e:
+ log.error(f"Failed to get signed URL: {e}")
+ raise e
+
+
+local_storage_provider = LocalStorageProvider()
diff --git a/docker-compose.yml b/docker-compose.yml
index a4210893..c42a0c04 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -230,11 +230,24 @@ services:
volumes:
- qdrant_data:/qdrant_data
+ minio:
+ image: minio/minio
+ container_name: minio
+ ports:
+ - "9000:9000"
+ environment:
+ MINIO_ROOT_USER: "minioadmin"
+ MINIO_ROOT_PASSWORD: "minioadmin"
+ volumes:
+ - minio_data:/data
+ command: server /data
+
volumes:
mongodb_data_container:
redis_data:
datasource_files:
qdrant_data:
+ minio_data:
networks:
default:
From 214d6a416b6a54804cf67316e0c39cc9b5301b44 Mon Sep 17 00:00:00 2001
From: "Ian Christopher B. de Jesus" <3683356+iandjx@users.noreply.github.com>
Date: Fri, 6 Sep 2024 12:46:00 +0800
Subject: [PATCH 03/28] Use buffer.getbuffer().nbytes to get buffer size
---
agent-backend/src/storage/local.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/agent-backend/src/storage/local.py b/agent-backend/src/storage/local.py
index 5603574f..b079c1f9 100644
--- a/agent-backend/src/storage/local.py
+++ b/agent-backend/src/storage/local.py
@@ -1,3 +1,4 @@
+from datetime import timedelta
import os
import logging
from pathlib import Path
@@ -43,16 +44,17 @@ def create_bucket(self):
def upload_file_buffer(self, buffer, filename, folder_path, is_public=False):
log.debug("Uploading buffer content as file %s", filename)
try:
+ buffer_size = buffer.getbuffer().nbytes
self.minio_client.put_object(
self.bucket_name,
f"{folder_path}/{filename}",
buffer,
- len(buffer),
+ buffer_size,
content_type="application/octet-stream",
)
log.debug("Buffer content uploaded successfully.")
except Exception as err:
- log.error("Buffer upload error:", err)
+ log.error("Buffer upload error: %s", err)
raise err
def upload_local_file(self, filename, folder_path, is_public=False):
From 9ce0305163115ea7bad27e095ba60bf8dd8b636b Mon Sep 17 00:00:00 2001
From: "Ian Christopher B. de Jesus" <3683356+iandjx@users.noreply.github.com>
Date: Fri, 6 Sep 2024 12:46:10 +0800
Subject: [PATCH 04/28] Set max expiry as 7 days
---
agent-backend/src/storage/local.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/agent-backend/src/storage/local.py b/agent-backend/src/storage/local.py
index b079c1f9..c10b002a 100644
--- a/agent-backend/src/storage/local.py
+++ b/agent-backend/src/storage/local.py
@@ -87,10 +87,11 @@ def delete_file(self, filename, file_folder, is_public=False):
def get_signed_url(self, filename, file_folder, is_public=False):
log.debug("Generating signed URL for file %s", filename)
try:
+ expires = timedelta(days=7)
url = self.minio_client.presigned_get_object(
self.bucket_name,
f"{file_folder}/{filename}",
- expires=60 * 60 * 24 * 365 * 100, # 100 years
+ expires=expires,
)
return url
except S3Error as e:
From f14bc8a2f5f7a5361ab9ee53902e37282a7c8000 Mon Sep 17 00:00:00 2001
From: "Ian Christopher B. de Jesus" <3683356+iandjx@users.noreply.github.com>
Date: Fri, 6 Sep 2024 14:14:52 +0800
Subject: [PATCH 05/28] Instantiate provider when storage provider is set
---
agent-backend/src/storage/__init__.py | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/agent-backend/src/storage/__init__.py b/agent-backend/src/storage/__init__.py
index c69aec74..4e0ee7a1 100644
--- a/agent-backend/src/storage/__init__.py
+++ b/agent-backend/src/storage/__init__.py
@@ -1,11 +1,14 @@
-from .google import google_storage_provider
-from .local import local_storage_provider
import os
-STORAGE_PROVIDER = os.getenv('STORAGE_PROVIDER', 'local')
+STORAGE_PROVIDER = os.getenv("STORAGE_PROVIDER", "local")
+print(f"STORAGE_PROVIDER: {STORAGE_PROVIDER}")
+
+
+if STORAGE_PROVIDER == "google":
+ from .google import google_storage_provider
-if STORAGE_PROVIDER == 'google':
storage_provider = google_storage_provider
else:
- storage_provider = local_storage_provider
+ from .local import local_storage_provider
+ storage_provider = local_storage_provider
From 8baf0502df9d782a35cdcb692c9e60920a4dad02 Mon Sep 17 00:00:00 2001
From: "Ian Christopher B. de Jesus" <3683356+iandjx@users.noreply.github.com>
Date: Fri, 6 Sep 2024 14:15:27 +0800
Subject: [PATCH 06/28] Use internal endpoint for file upload and use external
endpoint for generating file url
---
agent-backend/src/storage/local.py | 40 ++++++++++++++++++++++--------
docker-compose.yml | 6 ++++-
2 files changed, 34 insertions(+), 12 deletions(-)
diff --git a/agent-backend/src/storage/local.py b/agent-backend/src/storage/local.py
index c10b002a..cd168e2a 100644
--- a/agent-backend/src/storage/local.py
+++ b/agent-backend/src/storage/local.py
@@ -1,4 +1,5 @@
from datetime import timedelta
+import json
import os
import logging
from pathlib import Path
@@ -19,7 +20,7 @@ def __init__(self):
self.base_path = UPLOADS_BASE_PATH if UPLOADS_BASE_PATH else "./uploads"
self.init()
self.minio_client = Minio(
- os.getenv("MINIO_ENDPOINT", "localhost:9000"),
+ os.getenv("MINIO_INTERNAL_ENDPOINT", "minio:9000"),
access_key=os.getenv("MINIO_ROOT_USER", "minioadmin"),
secret_key=os.getenv("MINIO_ROOT_PASSWORD", "minioadmin"),
secure=False,
@@ -40,6 +41,26 @@ def create_bucket(self):
except S3Error as e:
log.error(f"Failed to create bucket: {e}")
raise e
+ self.set_bucket_policy()
+
+ def set_bucket_policy(self):
+
+ policy = {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": "*",
+ "Action": "s3:GetObject",
+ "Resource": f"arn:aws:s3:::{self.bucket_name}/*",
+ }
+ ],
+ }
+
+ policy_str = json.dumps(policy)
+
+ self.minio_client.set_bucket_policy(self.bucket_name, policy_str)
+ print(f"Public read policy applied to bucket '{self.bucket_name}'.")
def upload_file_buffer(self, buffer, filename, folder_path, is_public=False):
log.debug("Uploading buffer content as file %s", filename)
@@ -85,17 +106,14 @@ def delete_file(self, filename, file_folder, is_public=False):
raise e
def get_signed_url(self, filename, file_folder, is_public=False):
- log.debug("Generating signed URL for file %s", filename)
+ log.debug("Generating public URL for file %s", filename)
try:
- expires = timedelta(days=7)
- url = self.minio_client.presigned_get_object(
- self.bucket_name,
- f"{file_folder}/{filename}",
- expires=expires,
- )
- return url
- except S3Error as e:
- log.error(f"Failed to get signed URL: {e}")
+ external_endpoint = os.getenv("MINIO_EXTERNAL_ENDPOINT", "localhost:9000")
+ file_url = f"http://{external_endpoint}/{self.bucket_name}/{file_folder}/{filename}"
+
+ return file_url
+ except Exception as e:
+ log.error(f"Failed to get public URL: {e}")
raise e
diff --git a/docker-compose.yml b/docker-compose.yml
index c42a0c04..6f60163b 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -179,7 +179,11 @@ services:
- UPLOADS_BASE_PATH=/tmp
- GOOGLE_APPLICATION_CREDENTIALS=keyfile.json
- PROJECT_ID=agentcloud-dev
- - STORAGE_PROVIDER=google
+ - STORAGE_PROVIDER=local
+ - MINIO_INTERNAL_ENDPOINT=minio:9000
+ - MINIO_EXTERNAL_ENDPOINT=localhost:9000
+ - MINIO_ROOT_USER=minioadmin
+ - MINIO_ROOT_PASSWORD=minioadmin
vector_db_proxy:
restart: always
From 285ad6960ff228c91e69d59f24343a7a0c23423d Mon Sep 17 00:00:00 2001
From: "Ian Christopher B. de Jesus" <3683356+iandjx@users.noreply.github.com>
Date: Sat, 7 Sep 2024 13:15:26 +0800
Subject: [PATCH 07/28] Add posthog key to dockerfile
---
webapp/Dockerfile | 1 +
1 file changed, 1 insertion(+)
diff --git a/webapp/Dockerfile b/webapp/Dockerfile
index 968210fc..b94a59f4 100644
--- a/webapp/Dockerfile
+++ b/webapp/Dockerfile
@@ -21,6 +21,7 @@ ARG NEXT_PUBLIC_HUBSPOT_MEETING_LINK
ARG NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
ARG NEXT_PUBLIC_GCS_BUCKET_NAME
ARG NEXT_PUBLIC_GCS_BUCKET_NAME_PRIVATE
+ARG NEXT_PUBLIC_POSTHOG_KEY
# Set environment variables based on ARGs
ENV NEXT_PUBLIC_SHORT_COMMIT_HASH=$SHORT_COMMIT_HASH
From 4de145609bf76d4b2576ded6ef5432f24d28d9e5 Mon Sep 17 00:00:00 2001
From: Thomas Lynch
Date: Tue, 10 Sep 2024 12:36:57 +1000
Subject: [PATCH 08/28] Don't send basic chunking strategy for basic, breaks on
localhost
---
vector-db-proxy/src/data/unstructuredio/apis.rs | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/vector-db-proxy/src/data/unstructuredio/apis.rs b/vector-db-proxy/src/data/unstructuredio/apis.rs
index 759f8a75..fa7fb4d9 100644
--- a/vector-db-proxy/src/data/unstructuredio/apis.rs
+++ b/vector-db-proxy/src/data/unstructuredio/apis.rs
@@ -29,8 +29,9 @@ fn chunking_strategy_to_form_data(
if let Some(strategy_config) = chunking_strategy {
let chunking_strategy = UnstructuredChunkingStrategy::as_str(&strategy_config.strategy);
- form = form.text("chunking_strategy", chunking_strategy);
-
+ if strategy_config.strategy != UnstructuredChunkingStrategy::Basic {
+ form = form.text("chunking_strategy", chunking_strategy);
+ }
let max_characters = strategy_config.max_characters.to_string();
form = form.text("max_characters", max_characters);
From 6968e8e6010e34990e824b8dfbd9e1abda8e979d Mon Sep 17 00:00:00 2001
From: Thomas Lynch
Date: Tue, 10 Sep 2024 12:45:17 +1000
Subject: [PATCH 09/28] add NEXT_PUBLIC_LOCAL_UNSTRUCTURED env to hide
unavailable/unsupported chunking strategies in frontend
---
docker-compose.yml | 2 ++
webapp/.env.example | 1 +
webapp/Dockerfile | 2 ++
webapp/src/components/DatasourceChunkingForm.tsx | 8 ++++++--
4 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index 6f60163b..16bb8679 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -51,6 +51,7 @@ services:
- NEXT_PUBLIC_POSTHOG_KEY=
- GOOGLE_APPLICATION_CREDENTIALS=/app/keyfile.json
- NEXT_PUBLIC_STORAGE_PROVIDER=local
+ - NEXT_PUBLIC_LOCAL_UNSTRUCTURED=1
ports:
- "127.0.0.1:3000:3000"
depends_on:
@@ -112,6 +113,7 @@ services:
- NEXT_PUBLIC_SECRET_PROVIDER=local
- MESSAGE_QUEUE_PROVIDER=rabbitmq
- UPLOADS_BASE_PATH=/tmp
+ - NEXT_PUBLIC_LOCAL_UNSTRUCTURED=1
# Note: Only google cloud functions supported currently, so agent-backend doesn't need a provider env (YET)
- FUNCTION_PROVIDER=google
- GOOGLE_FUNCTION_LOCATION=us-central1
diff --git a/webapp/.env.example b/webapp/.env.example
index b79546c3..5c637fda 100644
--- a/webapp/.env.example
+++ b/webapp/.env.example
@@ -58,3 +58,4 @@ STRIPE_WEBHOOK_SECRET=
STRIPE_ACCOUNT_SECRET=
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
WEBAPP_TEST_BASE_URL=http://localhost:3000
+NEXT_PUBLIC_LOCAL_UNSTRUCTURED=1
diff --git a/webapp/Dockerfile b/webapp/Dockerfile
index b94a59f4..e88808f6 100644
--- a/webapp/Dockerfile
+++ b/webapp/Dockerfile
@@ -22,6 +22,7 @@ ARG NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
ARG NEXT_PUBLIC_GCS_BUCKET_NAME
ARG NEXT_PUBLIC_GCS_BUCKET_NAME_PRIVATE
ARG NEXT_PUBLIC_POSTHOG_KEY
+ARG NEXT_PUBLIC_LOCAL_UNSTRUCTURED
# Set environment variables based on ARGs
ENV NEXT_PUBLIC_SHORT_COMMIT_HASH=$SHORT_COMMIT_HASH
@@ -35,6 +36,7 @@ ENV NEXT_PUBLIC_STORAGE_PROVIDER=$NEXT_PUBLIC_STORAGE_PROVIDER
ENV NEXT_PUBLIC_HUBSPOT_MEETING_LINK=$NEXT_PUBLIC_HUBSPOT_MEETING_LINK
ENV NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=$NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
ENV NEXT_PUBLIC_GCS_BUCKET_NAME_PRIVATE=$NEXT_PUBLIC_GCS_BUCKET_NAME_PRIVATE
+ENV NEXT_PUBLIC_LOCAL_UNSTRUCTURED=$NEXT_PUBLIC_LOCAL_UNSTRUCTURED
# Disable Next.js telemetry
RUN npx next telemetry disable
diff --git a/webapp/src/components/DatasourceChunkingForm.tsx b/webapp/src/components/DatasourceChunkingForm.tsx
index 4ff7c4da..621f42ee 100644
--- a/webapp/src/components/DatasourceChunkingForm.tsx
+++ b/webapp/src/components/DatasourceChunkingForm.tsx
@@ -77,8 +77,12 @@ export default function DatasourceChunkingForm({
>
-
-
+ {!process.env.NEXT_PUBLIC_LOCAL_UNSTRUCTURED && (
+ <>
+
+
+ >
+ )}
From 571c4f67686a77a2af54ad71589f1b401fae0f8f Mon Sep 17 00:00:00 2001
From: Thomas Lynch
Date: Tue, 10 Sep 2024 12:46:37 +1000
Subject: [PATCH 10/28] reduce vector-db-proxy logging verbosity in docker
---
docker-compose.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index 16bb8679..ae164db5 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -221,7 +221,7 @@ services:
- WEBAPP_HOST=webapp_next
- THREAD_PERCENTAGE_UTILISATION=0.8
- USE_GPU=false
- - LOGGING_LEVEL=debug
+ - LOGGING_LEVEL=warn
volumes:
- datasource_files:/tmp
From 1ff51bf7fe8e49defe928e69551a9d29c21e8b83 Mon Sep 17 00:00:00 2001
From: Thomas Lynch
Date: Tue, 10 Sep 2024 12:52:10 +1000
Subject: [PATCH 11/28] Flatten source defined primary key so it doesnt get an
extra nesting. Not actually the correct behaviour but we don't support
multiple arrays of nested keys for primary keys anyway, so its OK for now.
---
webapp/src/components/DatasourceStream.tsx | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/webapp/src/components/DatasourceStream.tsx b/webapp/src/components/DatasourceStream.tsx
index ca38bc92..d0c42a57 100644
--- a/webapp/src/components/DatasourceStream.tsx
+++ b/webapp/src/components/DatasourceStream.tsx
@@ -36,7 +36,9 @@ export function StreamRow({
const containsNestedFields =
sourceDefinedPrimaryKey?.length > 1 || defaultCursorField?.length > 1;
const [cursorField, setCursorField] = useState(streamState?.cursorField || defaultCursorField); //Note: is an array for nested fields which we dont yet fully support
- const [primaryKey, setPrimaryKey] = useState(streamState?.primaryKey || sourceDefinedPrimaryKey);
+ const [primaryKey, setPrimaryKey] = useState(
+ streamState?.primaryKey || sourceDefinedPrimaryKey?.flat() || []
+ );
const initialSyncMode =
streamProperty?.syncModes.find(m => m?.includes('incremental')) || streamProperty?.syncModes[0];
const [syncMode, setSyncMode] = useState(streamState?.syncMode || initialSyncMode);
From f9414dceeb5f249ef82aa6d77cca292be021d1e0 Mon Sep 17 00:00:00 2001
From: Thomas Lynch
Date: Tue, 10 Sep 2024 17:12:25 +1000
Subject: [PATCH 12/28] Add unstructured api to docker env for vector-db-proxy
---
docker-compose.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/docker-compose.yml b/docker-compose.yml
index ae164db5..c9b07a16 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -222,6 +222,7 @@ services:
- THREAD_PERCENTAGE_UTILISATION=0.8
- USE_GPU=false
- LOGGING_LEVEL=warn
+ - UNSTRUCTURED_API_URL=http://unstructured-api:9500/general/v0/general
volumes:
- datasource_files:/tmp
From c5fcb1141869ddb42eb7c2ef2fc89221c7bd4a4d Mon Sep 17 00:00:00 2001
From: Charles John <1017170+charl3sj@users.noreply.github.com>
Date: Wed, 11 Sep 2024 12:07:55 +0530
Subject: [PATCH 13/28] #544 Pretty print crew attributes after instantiation
---
agent-backend/src/crew/build_crew.py | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/agent-backend/src/crew/build_crew.py b/agent-backend/src/crew/build_crew.py
index fa9439d0..2be2ec50 100644
--- a/agent-backend/src/crew/build_crew.py
+++ b/agent-backend/src/crew/build_crew.py
@@ -1,9 +1,8 @@
import json
import logging
from io import BytesIO
-import os
-from pathlib import Path
import uuid
+from pprint import pprint
from typing import Any, List, Set, Type
from datetime import datetime
@@ -286,7 +285,10 @@ def build_crew(self):
agentcloud_socket=self.socket,
agentcloud_session_id=self.session_id
)
- print(f"CrewAI Crew(): {self.crew}")
+ print('---')
+ print('Crew attributes:')
+ pprint(self.crew.__dict__)
+ print('---')
except ValidationError as ve:
self.send_to_sockets(text=f"""Validation Error:
```
From fdf9a859deb857649888198d6ce8138e8094a261 Mon Sep 17 00:00:00 2001
From: "Ian Christopher B. de Jesus" <3683356+iandjx@users.noreply.github.com>
Date: Thu, 12 Sep 2024 08:39:22 +0800
Subject: [PATCH 14/28] Allow requiresHumanInput to be null
---
webapp/src/controllers/task.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/webapp/src/controllers/task.ts b/webapp/src/controllers/task.ts
index ebfcfd4e..e596c127 100644
--- a/webapp/src/controllers/task.ts
+++ b/webapp/src/controllers/task.ts
@@ -132,7 +132,7 @@ export async function addTaskApi(req, res, next) {
[
{ field: 'name', validation: { notEmpty: true, ofType: 'string' } },
{ field: 'description', validation: { notEmpty: true, ofType: 'string' } },
- { field: 'requiresHumanInput', validation: { notEmpty: true, ofType: 'boolean' } },
+ { field: 'requiresHumanInput', validation: { ofType: 'boolean' } },
{ field: 'expectedOutput', validation: { ofType: 'string' } },
{
field: 'toolIds',
From 22d5aece8418f3cb8f35b1df63ef6f276959630c Mon Sep 17 00:00:00 2001
From: "Ian Christopher B. de Jesus" <3683356+iandjx@users.noreply.github.com>
Date: Thu, 12 Sep 2024 08:44:19 +0800
Subject: [PATCH 15/28] Make expected output mandatory
---
webapp/src/components/TaskForm.tsx | 2 +-
webapp/src/controllers/task.ts | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/webapp/src/components/TaskForm.tsx b/webapp/src/components/TaskForm.tsx
index 86582f78..8407e1a8 100644
--- a/webapp/src/components/TaskForm.tsx
+++ b/webapp/src/components/TaskForm.tsx
@@ -358,7 +358,7 @@ export default function TaskForm({
htmlFor='expectedOutput'
className='block text-sm font-medium leading-6 text-gray-900 dark:text-slate-400'
>
- Expected Output
+ Expected Output *
diff --git a/webapp/src/controllers/task.ts b/webapp/src/controllers/task.ts
index ebfcfd4e..2ef50a2c 100644
--- a/webapp/src/controllers/task.ts
+++ b/webapp/src/controllers/task.ts
@@ -133,7 +133,7 @@ export async function addTaskApi(req, res, next) {
{ field: 'name', validation: { notEmpty: true, ofType: 'string' } },
{ field: 'description', validation: { notEmpty: true, ofType: 'string' } },
{ field: 'requiresHumanInput', validation: { notEmpty: true, ofType: 'boolean' } },
- { field: 'expectedOutput', validation: { ofType: 'string' } },
+ { field: 'expectedOutput', validation: { notEmpty: true, ofType: 'string' } },
{
field: 'toolIds',
validation: {
From 59437a741dece6195dfc5edb67716adaa1f36dab Mon Sep 17 00:00:00 2001
From: Nader
Date: Thu, 12 Sep 2024 11:57:51 +1000
Subject: [PATCH 16/28] lint
---
webapp/src/components/ChatAppForm.tsx | 38 +++++++++++++++------------
1 file changed, 21 insertions(+), 17 deletions(-)
diff --git a/webapp/src/components/ChatAppForm.tsx b/webapp/src/components/ChatAppForm.tsx
index 04c5d197..1b211f9e 100644
--- a/webapp/src/components/ChatAppForm.tsx
+++ b/webapp/src/components/ChatAppForm.tsx
@@ -22,6 +22,7 @@ import { App, AppType } from 'struct/app';
import { ChatAppAllowedModels, ModelType } from 'struct/model';
import { SharingMode } from 'struct/sharing';
import { ToolType } from 'struct/tool';
+
import ConfirmModal from './ConfirmModal';
export default function ChatAppForm({
@@ -48,9 +49,9 @@ export default function ChatAppForm({
const { step, setStep }: any = useStepContext();
const [accountContext]: any = useAccountContext();
const { account, csrf, teamName } = accountContext as any;
- const [ outsideOrg, setOutsideOrg ] = useState(false);
- const [ shareEmail, setShareEmail ]= useState(false);
- const [ saveButtonType, setSaveButtonType ] = useState('button')
+ const [outsideOrg, setOutsideOrg] = useState(false);
+ const [shareEmail, setShareEmail] = useState(false);
+ const [saveButtonType, setSaveButtonType] = useState('button');
const router = useRouter();
const { resourceSlug } = router.query;
const [icon, setIcon]: any = useState(app?.icon);
@@ -335,18 +336,21 @@ export default function ChatAppForm({
break;
case 'confirmOutsideOrg':
modal = (
- {
- setOutsideOrg(false);
- setModalOpen(false);
- }}
- cancelFunction={() => {
- setModalOpen(false);
- }}
- title={"Sharing Outside Team"}
- message={"You are sharing this app with people outside your team. After confirming pressing 'save' will save the app."}/>
+ {
+ setOutsideOrg(false);
+ setModalOpen(false);
+ }}
+ cancelFunction={() => {
+ setModalOpen(false);
+ }}
+ title={'Sharing Outside Team'}
+ message={
+ "You are sharing this app with people outside your team. After confirming pressing 'save' will save the app."
+ }
+ />
);
break;
default:
@@ -642,9 +646,9 @@ export default function ChatAppForm({