File size: 6,042 Bytes
5da4770 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | #!/usr/bin/env python3
import subprocess
import sys
import platform
import os
import json
IS_WINDOWS = platform.system() == "Windows"
PROGRESS_FILE = ".setup_progress"
# --- ANSI Colors ---
class Colors:
HEADER = "\033[95m"
BLUE = "\033[94m"
CYAN = "\033[96m"
GREEN = "\033[92m"
YELLOW = "\033[93m"
RED = "\033[91m"
ENDC = "\033[0m"
BOLD = "\033[1m"
UNDERLINE = "\033[4m"
def load_progress():
"""Loads the last saved step and data from setup."""
if os.path.exists(PROGRESS_FILE):
with open(PROGRESS_FILE, "r") as f:
try:
return json.load(f)
except (json.JSONDecodeError, KeyError):
return {"step": 0, "data": {}}
return {"step": 0, "data": {}}
def get_setup_method():
"""Gets the setup method chosen during setup."""
progress = load_progress()
return progress.get("data", {}).get("setup_method")
def check_docker_compose_up():
result = subprocess.run(
["docker", "compose", "ps", "-q"],
capture_output=True,
text=True,
shell=IS_WINDOWS,
)
return len(result.stdout.strip()) > 0
def print_manual_instructions():
"""Prints instructions for manually starting Suna services."""
print(f"\n{Colors.BLUE}{Colors.BOLD}π Manual Startup Instructions{Colors.ENDC}\n")
print("To start Suna, you need to run these commands in separate terminals:\n")
print(f"{Colors.BOLD}1. Start Infrastructure (in project root):{Colors.ENDC}")
print(f"{Colors.CYAN} docker compose up redis rabbitmq -d{Colors.ENDC}\n")
print(f"{Colors.BOLD}2. Start Frontend (in a new terminal):{Colors.ENDC}")
print(f"{Colors.CYAN} cd frontend && npm run dev{Colors.ENDC}\n")
print(f"{Colors.BOLD}3. Start Backend (in a new terminal):{Colors.ENDC}")
print(f"{Colors.CYAN} cd backend && uv run api.py{Colors.ENDC}\n")
print(f"{Colors.BOLD}4. Start Background Worker (in a new terminal):{Colors.ENDC}")
print(
f"{Colors.CYAN} cd backend && uv run dramatiq run_agent_background{Colors.ENDC}\n"
)
print("Once all services are running, access Suna at: http://localhost:3000\n")
print(
f"{Colors.YELLOW}π‘ Tip:{Colors.ENDC} You can use '{Colors.CYAN}./start.py{Colors.ENDC}' to start/stop the infrastructure services."
)
def main():
setup_method = get_setup_method()
if "--help" in sys.argv:
print("Usage: ./start.py [OPTION]")
print("Manage Suna services based on your setup method")
print("\nOptions:")
print(" -f\tForce start containers without confirmation")
print(" --help\tShow this help message")
return
# If setup hasn't been run or method is not determined, default to docker
if not setup_method:
print(
f"{Colors.YELLOW}β οΈ Setup method not detected. Run './setup.py' first or using Docker Compose as default.{Colors.ENDC}"
)
setup_method = "docker"
if setup_method == "manual":
# For manual setup, we only manage infrastructure services (redis, rabbitmq)
# and show instructions for the rest
print(f"{Colors.BLUE}{Colors.BOLD}Manual Setup Detected{Colors.ENDC}")
print("Managing infrastructure services (Redis, RabbitMQ)...\n")
force = "-f" in sys.argv
if force:
print("Force awakened. Skipping confirmation.")
is_infra_up = subprocess.run(
["docker", "compose", "ps", "-q", "redis", "rabbitmq"],
capture_output=True,
text=True,
shell=IS_WINDOWS,
)
is_up = len(is_infra_up.stdout.strip()) > 0
if is_up:
action = "stop"
msg = "π Stop infrastructure services? [y/N] "
else:
action = "start"
msg = "β‘ Start infrastructure services? [Y/n] "
if not force:
response = input(msg).strip().lower()
if action == "stop":
if response != "y":
print("Aborting.")
return
else:
if response == "n":
print("Aborting.")
return
if action == "stop":
subprocess.run(["docker", "compose", "down"], shell=IS_WINDOWS)
print(f"\n{Colors.GREEN}β
Infrastructure services stopped.{Colors.ENDC}")
else:
subprocess.run(
["docker", "compose", "up", "redis", "rabbitmq", "-d"], shell=IS_WINDOWS
)
print(f"\n{Colors.GREEN}β
Infrastructure services started.{Colors.ENDC}")
print_manual_instructions()
else: # docker setup
print(f"{Colors.BLUE}{Colors.BOLD}Docker Setup Detected{Colors.ENDC}")
print("Managing all Suna services with Docker Compose...\n")
force = "-f" in sys.argv
if force:
print("Force awakened. Skipping confirmation.")
is_up = check_docker_compose_up()
if is_up:
action = "stop"
msg = "π Stop all Suna services? [y/N] "
else:
action = "start"
msg = "β‘ Start all Suna services? [Y/n] "
if not force:
response = input(msg).strip().lower()
if action == "stop":
if response != "y":
print("Aborting.")
return
else:
if response == "n":
print("Aborting.")
return
if action == "stop":
subprocess.run(["docker", "compose", "down"], shell=IS_WINDOWS)
print(f"\n{Colors.GREEN}β
All Suna services stopped.{Colors.ENDC}")
else:
subprocess.run(["docker", "compose", "up", "-d"], shell=IS_WINDOWS)
print(f"\n{Colors.GREEN}β
All Suna services started.{Colors.ENDC}")
print(f"{Colors.CYAN}π Access Suna at: http://localhost:3000{Colors.ENDC}")
if __name__ == "__main__":
main()
|