added py 3.13 and splited the cli and suport for windows and better port handling (#2404)
Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
fa81d0292b
commit
ad2ea8d069
128
skyvern/cli/run_commands.py
Normal file
128
skyvern/cli/run_commands.py
Normal file
@@ -0,0 +1,128 @@
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
import psutil
|
||||
import typer
|
||||
import uvicorn
|
||||
from dotenv import load_dotenv, set_key
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from rich.panel import Panel
|
||||
from rich.prompt import Confirm
|
||||
|
||||
from skyvern.utils import detect_os
|
||||
|
||||
from .console import console
|
||||
|
||||
run_app = typer.Typer()
|
||||
|
||||
mcp = FastMCP("Skyvern")
|
||||
|
||||
|
||||
def get_pids_on_port(port: int) -> List[int]:
|
||||
"""Return a list of PIDs listening on the given port."""
|
||||
pids = []
|
||||
try:
|
||||
for conn in psutil.net_connections(kind="inet"):
|
||||
if conn.laddr and conn.laddr.port == port and conn.pid:
|
||||
pids.append(conn.pid)
|
||||
except Exception:
|
||||
pass
|
||||
return list(set(pids))
|
||||
|
||||
|
||||
def kill_pids(pids: List[int]) -> None:
|
||||
"""Kill the given list of PIDs in a cross-platform way."""
|
||||
host_system = detect_os()
|
||||
for pid in pids:
|
||||
try:
|
||||
if host_system in {"windows", "wsl"}:
|
||||
subprocess.run(f"taskkill /PID {pid} /F", shell=True, check=False)
|
||||
else:
|
||||
os.kill(pid, 9)
|
||||
except Exception:
|
||||
console.print(f"[red]Failed to kill process {pid}[/red]")
|
||||
|
||||
|
||||
@run_app.command(name="server")
|
||||
def run_server() -> None:
|
||||
"""Run the Skyvern API server."""
|
||||
load_dotenv()
|
||||
load_dotenv(".env")
|
||||
from skyvern.config import settings
|
||||
|
||||
port = settings.PORT
|
||||
console.print(Panel(f"[bold green]Starting Skyvern API Server on port {port}...", border_style="green"))
|
||||
uvicorn.run(
|
||||
"skyvern.forge.api_app:app",
|
||||
host="0.0.0.0",
|
||||
port=port,
|
||||
log_level="info",
|
||||
)
|
||||
|
||||
|
||||
@run_app.command(name="ui")
|
||||
def run_ui() -> None:
|
||||
"""Run the Skyvern UI server."""
|
||||
console.print(Panel("[bold blue]Starting Skyvern UI Server...[/bold blue]", border_style="blue"))
|
||||
try:
|
||||
with console.status("[bold green]Checking for existing process on port 8080...") as status:
|
||||
pids = get_pids_on_port(8080)
|
||||
if pids:
|
||||
status.stop()
|
||||
response = Confirm.ask("Process already running on port 8080. [yellow]Kill it?[/yellow]")
|
||||
if response:
|
||||
kill_pids(pids)
|
||||
console.print("✅ [green]Process killed.[/green]")
|
||||
else:
|
||||
console.print("[yellow]UI server not started. Process already running on port 8080.[/yellow]")
|
||||
return
|
||||
status.stop()
|
||||
except Exception as e: # pragma: no cover - CLI safeguards
|
||||
console.print(f"[red]Error checking for process: {e}[/red]")
|
||||
|
||||
current_dir = Path(__file__).parent.parent.parent
|
||||
frontend_dir = current_dir / "skyvern-frontend"
|
||||
if not frontend_dir.exists():
|
||||
console.print(
|
||||
f"[bold red]ERROR: Skyvern Frontend directory not found at [path]{frontend_dir}[/path]. Are you in the right repo?[/bold red]"
|
||||
)
|
||||
return
|
||||
|
||||
if not (frontend_dir / ".env").exists():
|
||||
console.print("[bold blue]Setting up frontend .env file...[/bold blue]")
|
||||
shutil.copy(frontend_dir / ".env.example", frontend_dir / ".env")
|
||||
main_env_path = current_dir / ".env"
|
||||
if main_env_path.exists():
|
||||
load_dotenv(main_env_path)
|
||||
skyvern_api_key = os.getenv("SKYVERN_API_KEY")
|
||||
if skyvern_api_key:
|
||||
frontend_env_path = frontend_dir / ".env"
|
||||
set_key(str(frontend_env_path), "VITE_SKYVERN_API_KEY", skyvern_api_key)
|
||||
else:
|
||||
console.print("[red]ERROR: SKYVERN_API_KEY not found in .env file[/red]")
|
||||
else:
|
||||
console.print("[red]ERROR: .env file not found[/red]")
|
||||
|
||||
console.print("✅ [green]Successfully set up frontend .env file[/green]")
|
||||
|
||||
os.chdir(frontend_dir)
|
||||
|
||||
try:
|
||||
console.print("📦 [bold blue]Running npm install...[/bold blue]")
|
||||
subprocess.run("npm install --silent", shell=True, check=True)
|
||||
console.print("✅ [green]npm install complete.[/green]")
|
||||
console.print("🚀 [bold blue]Starting npm UI server...[/bold blue]")
|
||||
subprocess.run("npm run start", shell=True, check=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
console.print(f"[bold red]Error running UI server: {e}[/bold red]")
|
||||
return
|
||||
|
||||
|
||||
@run_app.command(name="mcp")
|
||||
def run_mcp() -> None:
|
||||
"""Run the MCP server."""
|
||||
console.print(Panel("[bold green]Starting MCP Server...[/bold green]", border_style="green"))
|
||||
mcp.run(transport="stdio")
|
||||
Reference in New Issue
Block a user