浏览代码

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

Deshraj Yadav 1 年之前
父节点
当前提交
b4a59d1bd5
共有 4 个文件被更改,包括 442 次插入327 次删除
  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.
 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
 ```bash
-ec runserver
+ec create-app my-app
+cd my-app
+ec start
 ```
 ```
 
 
 Once you run this command, Embedchain does the following:
 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
 1. Fetch full stack template that uses FastAPI for backend, and Next.JS template for frontend
 2. Install necessary requirements
 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.
 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 json
 import os
 import os
-import re
 import shutil
 import shutil
 import signal
 import signal
 import subprocess
 import subprocess
 import sys
 import sys
 import tempfile
 import tempfile
+import time
 import zipfile
 import zipfile
 from pathlib import Path
 from pathlib import Path
 
 
 import click
 import click
-import pkg_resources
 import requests
 import requests
 from rich.console import Console
 from rich.console import Console
 
 
 from embedchain.telemetry.posthog import AnonymousTelemetry
 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()
 console = Console()
-
-
-@click.group()
-def cli():
-    pass
-
-
-anonymous_telemetry = AnonymousTelemetry()
-
-
 api_process = None
 api_process = None
 ui_process = None
 ui_process = None
 
 
+anonymous_telemetry = AnonymousTelemetry()
+
 
 
 def signal_handler(sig, frame):
 def signal_handler(sig, frame):
     """Signal handler to catch termination signals and kill server processes."""
     """Signal handler to catch termination signals and kill server processes."""
@@ -44,110 +42,126 @@ def signal_handler(sig, frame):
     sys.exit(0)
     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:
     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
         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
 
 
-    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:
     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()
 @cli.command()
@@ -277,141 +291,6 @@ def dev(debug, host, port):
         raise ValueError(f"Unknown template '{template}'.")
         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()
 @cli.command()
 def deploy():
 def deploy():
     # Check for platform-specific files
     # Check for platform-specific files
@@ -437,86 +316,3 @@ def deploy():
         deploy_hf_spaces(ec_app_name)
         deploy_hf_spaces(ec_app_name)
     else:
     else:
         console.print("❌ [bold red]No recognized deployment platform found.[/bold red]")
         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]
 [tool.poetry]
 name = "embedchain"
 name = "embedchain"
-version = "0.1.53"
+version = "0.1.54"
 description = "Data platform for LLMs - Load, index, retrieve and sync any unstructured data"
 description = "Data platform for LLMs - Load, index, retrieve and sync any unstructured data"
 authors = [
 authors = [
     "Taranjeet Singh <taranjeet@embedchain.ai>",
     "Taranjeet Singh <taranjeet@embedchain.ai>",