Jelajahi Sumber

[Feature] Update commands to run full stack app (#1118)

Deshraj Yadav 1 tahun lalu
induk
melakukan
b4a59d1bd5
4 mengubah file dengan 442 tambahan dan 327 penghapusan
  1. 5 3
      docs/get-started/full-stack.mdx
  2. 119 323
      embedchain/cli.py
  3. 317 0
      embedchain/utils/cli.py
  4. 1 1
      pyproject.toml

+ 5 - 3
docs/get-started/full-stack.mdx

@@ -14,17 +14,19 @@ Make sure that you have installed the following:
 
 For the purpose of the demo, you have to set `OPENAI_API_KEY` to start with but you can choose any llm by changing the configuration easily.
 
-Now run the following command:
+Now run the following commands:
 
 ```bash
-ec runserver
+ec create-app my-app
+cd my-app
+ec start
 ```
 
 Once you run this command, Embedchain does the following:
 
 1. Fetch full stack template that uses FastAPI for backend, and Next.JS template for frontend
 2. Install necessary requirements
-3. Launch the frontend and backend server for you to interact with.
+3. Launch the frontend and backend server for you to interact with
 
 Once you are done, visit `http://localhost:3000` and you will see a chat UI as shown below.
 

+ 119 - 323
embedchain/cli.py

@@ -1,35 +1,33 @@
 import json
 import os
-import re
 import shutil
 import signal
 import subprocess
 import sys
 import tempfile
+import time
 import zipfile
 from pathlib import Path
 
 import click
-import pkg_resources
 import requests
 from rich.console import Console
 
 from embedchain.telemetry.posthog import AnonymousTelemetry
+from embedchain.utils.cli import (deploy_fly, deploy_gradio_app,
+                                  deploy_hf_spaces, deploy_modal,
+                                  deploy_render, deploy_streamlit,
+                                  get_pkg_path_from_name, setup_fly_io_app,
+                                  setup_gradio_app, setup_hf_app,
+                                  setup_modal_com_app, setup_render_com_app,
+                                  setup_streamlit_io_app)
 
 console = Console()
-
-
-@click.group()
-def cli():
-    pass
-
-
-anonymous_telemetry = AnonymousTelemetry()
-
-
 api_process = None
 ui_process = None
 
+anonymous_telemetry = AnonymousTelemetry()
+
 
 def signal_handler(sig, frame):
     """Signal handler to catch termination signals and kill server processes."""
@@ -44,110 +42,126 @@ def signal_handler(sig, frame):
     sys.exit(0)
 
 
-def get_pkg_path_from_name(template: str):
+@click.group()
+def cli():
+    pass
+
+
+@cli.command()
+@click.argument("app_name")
+@click.pass_context
+def create_app(ctx, app_name):
+    if Path(app_name).exists():
+        console.print(
+            f"❌ [red]Directory '{app_name}' already exists. Try using a new directory name, or remove it.[/red]"
+        )
+        return
+
+    os.makedirs(app_name)
+    os.chdir(app_name)
+
+    # Step 1: Download the zip file
+    zip_url = "http://github.com/embedchain/ec-admin/archive/main.zip"
+    console.print(f"Creating a new embedchain app in [green]{Path().resolve()}[/green]\n")
+    try:
+        response = requests.get(zip_url)
+        response.raise_for_status()
+        with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
+            tmp_file.write(response.content)
+            zip_file_path = tmp_file.name
+        console.print("✅ [bold green]Fetched template successfully.[/bold green]")
+    except requests.RequestException as e:
+        console.print(f"❌ [bold red]Failed to download zip file: {e}[/bold red]")
+        anonymous_telemetry.capture(event_name="ec_create_app", properties={"success": False})
+        return
+
+    # Step 2: Extract the zip file
     try:
-        # Determine the installation location of the embedchain package
-        package_path = pkg_resources.resource_filename("embedchain", "")
-    except ImportError:
-        console.print("❌ [bold red]Failed to locate the 'embedchain' package. Is it installed?[/bold red]")
+        with zipfile.ZipFile(zip_file_path, "r") as zip_ref:
+            # Get the name of the root directory inside the zip file
+            root_dir = Path(zip_ref.namelist()[0])
+            for member in zip_ref.infolist():
+                # Build the path to extract the file to, skipping the root directory
+                target_file = Path(member.filename).relative_to(root_dir)
+                source_file = zip_ref.open(member, "r")
+                if member.is_dir():
+                    # Create directory if it doesn't exist
+                    os.makedirs(target_file, exist_ok=True)
+                else:
+                    with open(target_file, "wb") as file:
+                        # Write the file
+                        shutil.copyfileobj(source_file, file)
+            console.print("✅ [bold green]Extracted zip file successfully.[/bold green]")
+            anonymous_telemetry.capture(event_name="ec_create_app", properties={"success": True})
+    except zipfile.BadZipFile:
+        console.print("❌ [bold red]Error in extracting zip file. The file might be corrupted.[/bold red]")
+        anonymous_telemetry.capture(event_name="ec_create_app", properties={"success": False})
         return
 
-    # Construct the source path from the embedchain package
-    src_path = os.path.join(package_path, "deployment", template)
+    ctx.invoke(install_reqs)
+
 
-    if not os.path.exists(src_path):
-        console.print(f"❌ [bold red]Template '{template}' not found.[/bold red]")
+@cli.command()
+def install_reqs():
+    try:
+        console.print("Installing python requirements...\n")
+        time.sleep(2)
+        os.chdir("api")
+        subprocess.run(["pip", "install", "-r", "requirements.txt"], check=True)
+        os.chdir("..")
+        console.print("\n ✅ [bold green]Installed API requirements successfully.[/bold green]\n")
+    except Exception as e:
+        console.print(f"❌ [bold red]Failed to install API requirements: {e}[/bold red]")
+        anonymous_telemetry.capture(event_name="ec_install_reqs", properties={"success": False})
         return
 
-    return src_path
+    try:
+        os.chdir("ui")
+        subprocess.run(["yarn"], check=True)
+        console.print("\n✅ [bold green]Successfully installed frontend requirements.[/bold green]")
+        anonymous_telemetry.capture(event_name="ec_install_reqs", properties={"success": True})
+    except Exception as e:
+        console.print(f"❌ [bold red]Failed to install frontend requirements. Error: {e}[/bold red]")
+        anonymous_telemetry.capture(event_name="ec_install_reqs", properties={"success": False})
+
 
+@cli.command()
+def start():
+    # Set up signal handling
+    signal.signal(signal.SIGINT, signal_handler)
+    signal.signal(signal.SIGTERM, signal_handler)
 
-def setup_fly_io_app(extra_args):
-    fly_launch_command = ["fly", "launch", "--region", "sjc", "--no-deploy"] + list(extra_args)
+    # Step 1: Start the API server
     try:
-        console.print(f"🚀 [bold cyan]Running: {' '.join(fly_launch_command)}[/bold cyan]")
-        shutil.move(".env.example", ".env")
-        subprocess.run(fly_launch_command, check=True)
-        console.print("✅ [bold green]'fly launch' executed successfully.[/bold green]")
-    except subprocess.CalledProcessError as e:
-        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
-    except FileNotFoundError:
-        console.print(
-            "❌ [bold red]'fly' command not found. Please ensure Fly CLI is installed and in your PATH.[/bold red]"
-        )
+        os.chdir("api")
+        api_process = subprocess.Popen(["python", "-m", "main"], stdout=None, stderr=None)
+        os.chdir("..")
+        console.print("✅ [bold green]API server started successfully.[/bold green]")
+    except Exception as e:
+        console.print(f"❌ [bold red]Failed to start the API server: {e}[/bold red]")
+        anonymous_telemetry.capture(event_name="ec_start", properties={"success": False})
+        return
 
+    # Sleep for 2 seconds to give the user time to read the message
+    time.sleep(2)
 
-def setup_modal_com_app(extra_args):
-    modal_setup_file = os.path.join(os.path.expanduser("~"), ".modal.toml")
-    if os.path.exists(modal_setup_file):
-        console.print(
-            """✅ [bold green]Modal setup already done. You can now install the dependencies by doing \n
-            `pip install -r requirements.txt`[/bold green]"""
-        )
-    else:
-        modal_setup_cmd = ["modal", "setup"] + list(extra_args)
-        console.print(f"🚀 [bold cyan]Running: {' '.join(modal_setup_cmd)}[/bold cyan]")
-        subprocess.run(modal_setup_cmd, check=True)
-    shutil.move(".env.example", ".env")
-    console.print(
-        """Great! Now you can install the dependencies by doing: \n
-                  `pip install -r requirements.txt`\n
-                  \n
-                  To run your app locally:\n
-                  `ec dev`
-                  """
-    )
-
-
-def setup_render_com_app():
-    render_setup_file = os.path.join(os.path.expanduser("~"), ".render/config.yaml")
-    if os.path.exists(render_setup_file):
-        console.print(
-            """✅ [bold green]Render setup already done. You can now install the dependencies by doing \n
-            `pip install -r requirements.txt`[/bold green]"""
-        )
-    else:
-        render_setup_cmd = ["render", "config", "init"]
-        console.print(f"🚀 [bold cyan]Running: {' '.join(render_setup_cmd)}[/bold cyan]")
-        subprocess.run(render_setup_cmd, check=True)
-    shutil.move(".env.example", ".env")
-    console.print(
-        """Great! Now you can install the dependencies by doing: \n
-                  `pip install -r requirements.txt`\n
-                  \n
-                  To run your app locally:\n
-                  `ec dev`
-                  """
-    )
-
-
-def setup_streamlit_io_app():
-    # nothing needs to be done here
-    console.print("Great! Now you can install the dependencies by doing `pip install -r requirements.txt`")
-
-
-def setup_gradio_app():
-    # nothing needs to be done here
-    console.print("Great! Now you can install the dependencies by doing `pip install -r requirements.txt`")
-
-
-def setup_hf_app():
-    subprocess.run(["pip", "install", "huggingface_hub[cli]"], check=True)
-    hf_setup_file = os.path.join(os.path.expanduser("~"), ".cache/huggingface/token")
-    if os.path.exists(hf_setup_file):
-        console.print(
-            """✅ [bold green]HuggingFace setup already done. You can now install the dependencies by doing \n
-            `pip install -r requirements.txt`[/bold green]"""
-        )
-    else:
-        console.print(
-            """🚀 [cyan]Running: huggingface-cli login \n
-                Please provide a [bold]WRITE[/bold] token so that we can directly deploy\n
-                your apps from the terminal.[/cyan]
-                """
-        )
-        subprocess.run(["huggingface-cli", "login"], check=True)
-    console.print("Great! Now you can install the dependencies by doing `pip install -r requirements.txt`")
+    # Step 2: Install UI requirements and start the UI server
+    try:
+        os.chdir("ui")
+        subprocess.run(["yarn"], check=True)
+        ui_process = subprocess.Popen(["yarn", "dev"])
+        console.print("✅ [bold green]UI server started successfully.[/bold green]")
+        anonymous_telemetry.capture(event_name="ec_start", properties={"success": True})
+    except Exception as e:
+        console.print(f"❌ [bold red]Failed to start the UI server: {e}[/bold red]")
+        anonymous_telemetry.capture(event_name="ec_start", properties={"success": False})
+
+    # Keep the script running until it receives a kill signal
+    try:
+        api_process.wait()
+        ui_process.wait()
+    except KeyboardInterrupt:
+        console.print("\n🛑 [bold yellow]Stopping server...[/bold yellow]")
 
 
 @cli.command()
@@ -277,141 +291,6 @@ def dev(debug, host, port):
         raise ValueError(f"Unknown template '{template}'.")
 
 
-def read_env_file(env_file_path):
-    """
-    Reads an environment file and returns a dictionary of key-value pairs.
-
-    Args:
-    env_file_path (str): The path to the .env file.
-
-    Returns:
-    dict: Dictionary of environment variables.
-    """
-    env_vars = {}
-    with open(env_file_path, "r") as file:
-        for line in file:
-            # Ignore comments and empty lines
-            if line.strip() and not line.strip().startswith("#"):
-                # Assume each line is in the format KEY=VALUE
-                key_value_match = re.match(r"(\w+)=(.*)", line.strip())
-                if key_value_match:
-                    key, value = key_value_match.groups()
-                    env_vars[key] = value
-    return env_vars
-
-
-def deploy_fly():
-    app_name = ""
-    with open("fly.toml", "r") as file:
-        for line in file:
-            if line.strip().startswith("app ="):
-                app_name = line.split("=")[1].strip().strip('"')
-
-    if not app_name:
-        console.print("❌ [bold red]App name not found in fly.toml[/bold red]")
-        return
-
-    env_vars = read_env_file(".env")
-    secrets_command = ["flyctl", "secrets", "set", "-a", app_name] + [f"{k}={v}" for k, v in env_vars.items()]
-
-    deploy_command = ["fly", "deploy"]
-    try:
-        # Set secrets
-        console.print(f"🔐 [bold cyan]Setting secrets for {app_name}[/bold cyan]")
-        subprocess.run(secrets_command, check=True)
-
-        # Deploy application
-        console.print(f"🚀 [bold cyan]Running: {' '.join(deploy_command)}[/bold cyan]")
-        subprocess.run(deploy_command, check=True)
-        console.print("✅ [bold green]'fly deploy' executed successfully.[/bold green]")
-
-    except subprocess.CalledProcessError as e:
-        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
-    except FileNotFoundError:
-        console.print(
-            "❌ [bold red]'fly' command not found. Please ensure Fly CLI is installed and in your PATH.[/bold red]"
-        )
-
-
-def deploy_modal():
-    modal_deploy_cmd = ["modal", "deploy", "app"]
-    try:
-        console.print(f"🚀 [bold cyan]Running: {' '.join(modal_deploy_cmd)}[/bold cyan]")
-        subprocess.run(modal_deploy_cmd, check=True)
-        console.print("✅ [bold green]'modal deploy' executed successfully.[/bold green]")
-    except subprocess.CalledProcessError as e:
-        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
-    except FileNotFoundError:
-        console.print(
-            "❌ [bold red]'modal' command not found. Please ensure Modal CLI is installed and in your PATH.[/bold red]"
-        )
-
-
-def deploy_streamlit():
-    streamlit_deploy_cmd = ["streamlit", "run", "app.py"]
-    try:
-        console.print(f"🚀 [bold cyan]Running: {' '.join(streamlit_deploy_cmd)}[/bold cyan]")
-        console.print(
-            """\n\n✅ [bold yellow]To deploy a streamlit app, you can directly it from the UI.\n
-        Click on the 'Deploy' button on the top right corner of the app.\n
-        For more information, please refer to https://docs.embedchain.ai/deployment/streamlit_io
-        [/bold yellow]
-                      \n\n"""
-        )
-        subprocess.run(streamlit_deploy_cmd, check=True)
-    except subprocess.CalledProcessError as e:
-        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
-    except FileNotFoundError:
-        console.print(
-            """❌ [bold red]'streamlit' command not found.\n
-            Please ensure Streamlit CLI is installed and in your PATH.[/bold red]"""
-        )
-
-
-def deploy_render():
-    render_deploy_cmd = ["render", "blueprint", "launch"]
-
-    try:
-        console.print(f"🚀 [bold cyan]Running: {' '.join(render_deploy_cmd)}[/bold cyan]")
-        subprocess.run(render_deploy_cmd, check=True)
-        console.print("✅ [bold green]'render blueprint launch' executed successfully.[/bold green]")
-    except subprocess.CalledProcessError as e:
-        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
-    except FileNotFoundError:
-        console.print(
-            "❌ [bold red]'render' command not found. Please ensure Render CLI is installed and in your PATH.[/bold red]"  # noqa:E501
-        )
-
-
-def deploy_gradio_app():
-    gradio_deploy_cmd = ["gradio", "deploy"]
-
-    try:
-        console.print(f"🚀 [bold cyan]Running: {' '.join(gradio_deploy_cmd)}[/bold cyan]")
-        subprocess.run(gradio_deploy_cmd, check=True)
-        console.print("✅ [bold green]'gradio deploy' executed successfully.[/bold green]")
-    except subprocess.CalledProcessError as e:
-        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
-    except FileNotFoundError:
-        console.print(
-            "❌ [bold red]'gradio' command not found. Please ensure Gradio CLI is installed and in your PATH.[/bold red]"  # noqa:E501
-        )
-
-
-def deploy_hf_spaces(ec_app_name):
-    if not ec_app_name:
-        console.print("❌ [bold red]'name' not found in embedchain.json[/bold red]")
-        return
-    hf_spaces_deploy_cmd = ["huggingface-cli", "upload", ec_app_name, ".", ".", "--repo-type=space"]
-
-    try:
-        console.print(f"🚀 [bold cyan]Running: {' '.join(hf_spaces_deploy_cmd)}[/bold cyan]")
-        subprocess.run(hf_spaces_deploy_cmd, check=True)
-        console.print("✅ [bold green]'huggingface-cli upload' executed successfully.[/bold green]")
-    except subprocess.CalledProcessError as e:
-        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
-
-
 @cli.command()
 def deploy():
     # Check for platform-specific files
@@ -437,86 +316,3 @@ def deploy():
         deploy_hf_spaces(ec_app_name)
     else:
         console.print("❌ [bold red]No recognized deployment platform found.[/bold red]")
-
-
-@cli.command()
-def runserver():
-    # Set up signal handling
-    signal.signal(signal.SIGINT, signal_handler)
-    signal.signal(signal.SIGTERM, signal_handler)
-
-    # Check if 'api' and 'ui' directories exist
-    if os.path.exists("api") and os.path.exists("ui"):
-        pass
-    else:
-        # Step 1: Download the zip file
-        zip_url = "http://github.com/embedchain/ec-admin/archive/main.zip"
-        try:
-            response = requests.get(zip_url)
-            response.raise_for_status()
-            with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
-                tmp_file.write(response.content)
-                zip_file_path = tmp_file.name
-            console.print("✅ [bold green]Downloaded zip file successfully.[/bold green]")
-        except requests.RequestException as e:
-            console.print(f"❌ [bold red]Failed to download zip file: {e}[/bold red]")
-            return
-
-        # Step 2: Extract the zip file
-        try:
-            with zipfile.ZipFile(zip_file_path, "r") as zip_ref:
-                # Get the name of the root directory inside the zip file
-                root_dir = Path(zip_ref.namelist()[0])
-                for member in zip_ref.infolist():
-                    # Build the path to extract the file to, skipping the root directory
-                    target_file = Path(member.filename).relative_to(root_dir)
-                    source_file = zip_ref.open(member, "r")
-                    if member.is_dir():
-                        # Create directory if it doesn't exist
-                        os.makedirs(target_file, exist_ok=True)
-                    else:
-                        with open(target_file, "wb") as file:
-                            # Write the file
-                            shutil.copyfileobj(source_file, file)
-                console.print("✅ [bold green]Extracted zip file successfully.[/bold green]")
-        except zipfile.BadZipFile:
-            console.print("❌ [bold red]Error in extracting zip file. The file might be corrupted.[/bold red]")
-            return
-
-        # Step 3: Install API requirements
-        try:
-            os.chdir("api")
-            subprocess.run(["pip", "install", "-r", "requirements.txt"], check=True)
-            os.chdir("..")
-            console.print("✅ [bold green]Installed API requirements successfully.[/bold green]")
-        except Exception as e:
-            console.print(f"❌ [bold red]Failed to install API requirements: {e}[/bold red]")
-            return
-
-    # Step 4: Start the API server
-    try:
-        os.chdir("api")
-        api_process = subprocess.Popen(
-            ["uvicorn", "main:app", "--reload", "--host", "127.0.0.1", "--port", "8000"], stdout=None, stderr=None
-        )
-        os.chdir("..")
-        console.print("✅ [bold green]API server started successfully.[/bold green]")
-    except Exception as e:
-        console.print(f"❌ [bold red]Failed to start the API server: {e}[/bold red]")
-        return
-
-    # Step 5: Install UI requirements and start the UI server
-    try:
-        os.chdir("ui")
-        subprocess.run(["yarn"], check=True)
-        subprocess.Popen(["yarn", "dev"])
-        console.print("✅ [bold green]UI server started successfully.[/bold green]")
-    except Exception as e:
-        console.print(f"❌ [bold red]Failed to start the UI server: {e}[/bold red]")
-
-    # Keep the script running until it receives a kill signal
-    try:
-        api_process.wait()
-        ui_process.wait()
-    except KeyboardInterrupt:
-        console.print("\n🛑 [bold yellow]Stopping server...[/bold yellow]")

+ 317 - 0
embedchain/utils/cli.py

@@ -0,0 +1,317 @@
+import os
+import re
+import shutil
+import subprocess
+
+import pkg_resources
+from rich.console import Console
+
+console = Console()
+
+
+def get_pkg_path_from_name(template: str):
+    try:
+        # Determine the installation location of the embedchain package
+        package_path = pkg_resources.resource_filename("embedchain", "")
+    except ImportError:
+        console.print("❌ [bold red]Failed to locate the 'embedchain' package. Is it installed?[/bold red]")
+        return
+
+    # Construct the source path from the embedchain package
+    src_path = os.path.join(package_path, "deployment", template)
+
+    if not os.path.exists(src_path):
+        console.print(f"❌ [bold red]Template '{template}' not found.[/bold red]")
+        return
+
+    return src_path
+
+
+def setup_fly_io_app(extra_args):
+    fly_launch_command = ["fly", "launch", "--region", "sjc", "--no-deploy"] + list(extra_args)
+    try:
+        console.print(f"🚀 [bold cyan]Running: {' '.join(fly_launch_command)}[/bold cyan]")
+        shutil.move(".env.example", ".env")
+        subprocess.run(fly_launch_command, check=True)
+        console.print("✅ [bold green]'fly launch' executed successfully.[/bold green]")
+    except subprocess.CalledProcessError as e:
+        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
+    except FileNotFoundError:
+        console.print(
+            "❌ [bold red]'fly' command not found. Please ensure Fly CLI is installed and in your PATH.[/bold red]"
+        )
+
+
+def setup_modal_com_app(extra_args):
+    modal_setup_file = os.path.join(os.path.expanduser("~"), ".modal.toml")
+    if os.path.exists(modal_setup_file):
+        console.print(
+            """✅ [bold green]Modal setup already done. You can now install the dependencies by doing \n
+            `pip install -r requirements.txt`[/bold green]"""
+        )
+    else:
+        modal_setup_cmd = ["modal", "setup"] + list(extra_args)
+        console.print(f"🚀 [bold cyan]Running: {' '.join(modal_setup_cmd)}[/bold cyan]")
+        subprocess.run(modal_setup_cmd, check=True)
+    shutil.move(".env.example", ".env")
+    console.print(
+        """Great! Now you can install the dependencies by doing: \n
+                  `pip install -r requirements.txt`\n
+                  \n
+                  To run your app locally:\n
+                  `ec dev`
+                  """
+    )
+
+
+def setup_render_com_app():
+    render_setup_file = os.path.join(os.path.expanduser("~"), ".render/config.yaml")
+    if os.path.exists(render_setup_file):
+        console.print(
+            """✅ [bold green]Render setup already done. You can now install the dependencies by doing \n
+            `pip install -r requirements.txt`[/bold green]"""
+        )
+    else:
+        render_setup_cmd = ["render", "config", "init"]
+        console.print(f"🚀 [bold cyan]Running: {' '.join(render_setup_cmd)}[/bold cyan]")
+        subprocess.run(render_setup_cmd, check=True)
+    shutil.move(".env.example", ".env")
+    console.print(
+        """Great! Now you can install the dependencies by doing: \n
+                  `pip install -r requirements.txt`\n
+                  \n
+                  To run your app locally:\n
+                  `ec dev`
+                  """
+    )
+
+
+def setup_streamlit_io_app():
+    # nothing needs to be done here
+    console.print("Great! Now you can install the dependencies by doing `pip install -r requirements.txt`")
+
+
+def setup_gradio_app():
+    # nothing needs to be done here
+    console.print("Great! Now you can install the dependencies by doing `pip install -r requirements.txt`")
+
+
+def setup_hf_app():
+    subprocess.run(["pip", "install", "huggingface_hub[cli]"], check=True)
+    hf_setup_file = os.path.join(os.path.expanduser("~"), ".cache/huggingface/token")
+    if os.path.exists(hf_setup_file):
+        console.print(
+            """✅ [bold green]HuggingFace setup already done. You can now install the dependencies by doing \n
+            `pip install -r requirements.txt`[/bold green]"""
+        )
+    else:
+        console.print(
+            """🚀 [cyan]Running: huggingface-cli login \n
+                Please provide a [bold]WRITE[/bold] token so that we can directly deploy\n
+                your apps from the terminal.[/cyan]
+                """
+        )
+        subprocess.run(["huggingface-cli", "login"], check=True)
+    console.print("Great! Now you can install the dependencies by doing `pip install -r requirements.txt`")
+
+
+def run_dev_fly_io(debug, host, port):
+    uvicorn_command = ["uvicorn", "app:app"]
+
+    if debug:
+        uvicorn_command.append("--reload")
+
+    uvicorn_command.extend(["--host", host, "--port", str(port)])
+
+    try:
+        console.print(f"🚀 [bold cyan]Running FastAPI app with command: {' '.join(uvicorn_command)}[/bold cyan]")
+        subprocess.run(uvicorn_command, check=True)
+    except subprocess.CalledProcessError as e:
+        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
+    except KeyboardInterrupt:
+        console.print("\n🛑 [bold yellow]FastAPI server stopped[/bold yellow]")
+
+
+def run_dev_modal_com():
+    modal_run_cmd = ["modal", "serve", "app"]
+    try:
+        console.print(f"🚀 [bold cyan]Running FastAPI app with command: {' '.join(modal_run_cmd)}[/bold cyan]")
+        subprocess.run(modal_run_cmd, check=True)
+    except subprocess.CalledProcessError as e:
+        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
+    except KeyboardInterrupt:
+        console.print("\n🛑 [bold yellow]FastAPI server stopped[/bold yellow]")
+
+
+def run_dev_streamlit_io():
+    streamlit_run_cmd = ["streamlit", "run", "app.py"]
+    try:
+        console.print(f"🚀 [bold cyan]Running Streamlit app with command: {' '.join(streamlit_run_cmd)}[/bold cyan]")
+        subprocess.run(streamlit_run_cmd, check=True)
+    except subprocess.CalledProcessError as e:
+        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
+    except KeyboardInterrupt:
+        console.print("\n🛑 [bold yellow]Streamlit server stopped[/bold yellow]")
+
+
+def run_dev_render_com(debug, host, port):
+    uvicorn_command = ["uvicorn", "app:app"]
+
+    if debug:
+        uvicorn_command.append("--reload")
+
+    uvicorn_command.extend(["--host", host, "--port", str(port)])
+
+    try:
+        console.print(f"🚀 [bold cyan]Running FastAPI app with command: {' '.join(uvicorn_command)}[/bold cyan]")
+        subprocess.run(uvicorn_command, check=True)
+    except subprocess.CalledProcessError as e:
+        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
+    except KeyboardInterrupt:
+        console.print("\n🛑 [bold yellow]FastAPI server stopped[/bold yellow]")
+
+
+def run_dev_gradio():
+    gradio_run_cmd = ["gradio", "app.py"]
+    try:
+        console.print(f"🚀 [bold cyan]Running Gradio app with command: {' '.join(gradio_run_cmd)}[/bold cyan]")
+        subprocess.run(gradio_run_cmd, check=True)
+    except subprocess.CalledProcessError as e:
+        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
+    except KeyboardInterrupt:
+        console.print("\n🛑 [bold yellow]Gradio server stopped[/bold yellow]")
+
+
+def read_env_file(env_file_path):
+    """
+    Reads an environment file and returns a dictionary of key-value pairs.
+
+    Args:
+    env_file_path (str): The path to the .env file.
+
+    Returns:
+    dict: Dictionary of environment variables.
+    """
+    env_vars = {}
+    with open(env_file_path, "r") as file:
+        for line in file:
+            # Ignore comments and empty lines
+            if line.strip() and not line.strip().startswith("#"):
+                # Assume each line is in the format KEY=VALUE
+                key_value_match = re.match(r"(\w+)=(.*)", line.strip())
+                if key_value_match:
+                    key, value = key_value_match.groups()
+                    env_vars[key] = value
+    return env_vars
+
+
+def deploy_fly():
+    app_name = ""
+    with open("fly.toml", "r") as file:
+        for line in file:
+            if line.strip().startswith("app ="):
+                app_name = line.split("=")[1].strip().strip('"')
+
+    if not app_name:
+        console.print("❌ [bold red]App name not found in fly.toml[/bold red]")
+        return
+
+    env_vars = read_env_file(".env")
+    secrets_command = ["flyctl", "secrets", "set", "-a", app_name] + [f"{k}={v}" for k, v in env_vars.items()]
+
+    deploy_command = ["fly", "deploy"]
+    try:
+        # Set secrets
+        console.print(f"🔐 [bold cyan]Setting secrets for {app_name}[/bold cyan]")
+        subprocess.run(secrets_command, check=True)
+
+        # Deploy application
+        console.print(f"🚀 [bold cyan]Running: {' '.join(deploy_command)}[/bold cyan]")
+        subprocess.run(deploy_command, check=True)
+        console.print("✅ [bold green]'fly deploy' executed successfully.[/bold green]")
+
+    except subprocess.CalledProcessError as e:
+        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
+    except FileNotFoundError:
+        console.print(
+            "❌ [bold red]'fly' command not found. Please ensure Fly CLI is installed and in your PATH.[/bold red]"
+        )
+
+
+def deploy_modal():
+    modal_deploy_cmd = ["modal", "deploy", "app"]
+    try:
+        console.print(f"🚀 [bold cyan]Running: {' '.join(modal_deploy_cmd)}[/bold cyan]")
+        subprocess.run(modal_deploy_cmd, check=True)
+        console.print("✅ [bold green]'modal deploy' executed successfully.[/bold green]")
+    except subprocess.CalledProcessError as e:
+        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
+    except FileNotFoundError:
+        console.print(
+            "❌ [bold red]'modal' command not found. Please ensure Modal CLI is installed and in your PATH.[/bold red]"
+        )
+
+
+def deploy_streamlit():
+    streamlit_deploy_cmd = ["streamlit", "run", "app.py"]
+    try:
+        console.print(f"🚀 [bold cyan]Running: {' '.join(streamlit_deploy_cmd)}[/bold cyan]")
+        console.print(
+            """\n\n✅ [bold yellow]To deploy a streamlit app, you can directly it from the UI.\n
+        Click on the 'Deploy' button on the top right corner of the app.\n
+        For more information, please refer to https://docs.embedchain.ai/deployment/streamlit_io
+        [/bold yellow]
+                      \n\n"""
+        )
+        subprocess.run(streamlit_deploy_cmd, check=True)
+    except subprocess.CalledProcessError as e:
+        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
+    except FileNotFoundError:
+        console.print(
+            """❌ [bold red]'streamlit' command not found.\n
+            Please ensure Streamlit CLI is installed and in your PATH.[/bold red]"""
+        )
+
+
+def deploy_render():
+    render_deploy_cmd = ["render", "blueprint", "launch"]
+
+    try:
+        console.print(f"🚀 [bold cyan]Running: {' '.join(render_deploy_cmd)}[/bold cyan]")
+        subprocess.run(render_deploy_cmd, check=True)
+        console.print("✅ [bold green]'render blueprint launch' executed successfully.[/bold green]")
+    except subprocess.CalledProcessError as e:
+        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
+    except FileNotFoundError:
+        console.print(
+            "❌ [bold red]'render' command not found. Please ensure Render CLI is installed and in your PATH.[/bold red]"  # noqa:E501
+        )
+
+
+def deploy_gradio_app():
+    gradio_deploy_cmd = ["gradio", "deploy"]
+
+    try:
+        console.print(f"🚀 [bold cyan]Running: {' '.join(gradio_deploy_cmd)}[/bold cyan]")
+        subprocess.run(gradio_deploy_cmd, check=True)
+        console.print("✅ [bold green]'gradio deploy' executed successfully.[/bold green]")
+    except subprocess.CalledProcessError as e:
+        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
+    except FileNotFoundError:
+        console.print(
+            "❌ [bold red]'gradio' command not found. Please ensure Gradio CLI is installed and in your PATH.[/bold red]"  # noqa:E501
+        )
+
+
+def deploy_hf_spaces(ec_app_name):
+    if not ec_app_name:
+        console.print("❌ [bold red]'name' not found in embedchain.json[/bold red]")
+        return
+    hf_spaces_deploy_cmd = ["huggingface-cli", "upload", ec_app_name, ".", ".", "--repo-type=space"]
+
+    try:
+        console.print(f"🚀 [bold cyan]Running: {' '.join(hf_spaces_deploy_cmd)}[/bold cyan]")
+        subprocess.run(hf_spaces_deploy_cmd, check=True)
+        console.print("✅ [bold green]'huggingface-cli upload' executed successfully.[/bold green]")
+    except subprocess.CalledProcessError as e:
+        console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")

+ 1 - 1
pyproject.toml

@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "embedchain"
-version = "0.1.53"
+version = "0.1.54"
 description = "Data platform for LLMs - Load, index, retrieve and sync any unstructured data"
 authors = [
     "Taranjeet Singh <taranjeet@embedchain.ai>",