Files
Dorod-Sky/skyvern/cli/init_command.py

169 lines
8.1 KiB
Python
Raw Normal View History

import asyncio
import subprocess
import uuid
import typer
from rich.padding import Padding
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, TextColumn
from rich.prompt import Confirm, Prompt
from skyvern.forge.forge_app_initializer import start_forge_app
from skyvern.utils import migrate_db
from skyvern.utils.env_paths import resolve_backend_env_path
from .browser import setup_browser_config
from .console import console
from .database import setup_postgresql
from .llm_setup import setup_llm_providers, update_or_add_env_var
from .mcp import setup_local_organization, setup_mcp
2025-12-04 21:14:48 -07:00
def init_env(
no_postgres: bool = typer.Option(False, "--no-postgres", help="Skip starting PostgreSQL container"),
database_string: str = typer.Option(
"",
"--database-string",
help="Custom database connection string (e.g., postgresql+psycopg://user:password@host:port/dbname). When provided, skips Docker PostgreSQL setup.",
),
2025-12-04 21:14:48 -07:00
) -> bool:
"""Interactive initialization command for Skyvern."""
console.print(
Panel(
"[bold green]Welcome to Skyvern CLI Initialization![/bold green]",
border_style="green",
expand=False,
)
)
console.print("[italic]This wizard will help you set up Skyvern.[/italic]")
infra_choice = Prompt.ask(
"Would you like to run Skyvern [bold blue]local[/bold blue]ly or in the [bold purple]cloud[/bold purple]?",
choices=["local", "cloud"],
)
run_local = infra_choice == "local"
if run_local:
if database_string:
console.print("🔗 [bold blue]Using custom database connection...[/bold blue]")
update_or_add_env_var("DATABASE_STRING", database_string)
console.print("✅ [green]Database connection string set in .env file.[/green]")
else:
setup_postgresql(no_postgres)
console.print("📊 [bold blue]Running database migrations...[/bold blue]")
migrate_db()
console.print("✅ [green]Database migration complete.[/green]")
console.print("🔑 [bold blue]Generating local organization API key...[/bold blue]")
start_forge_app()
api_key = asyncio.run(setup_local_organization())
if api_key:
console.print("✅ [green]Local organization API key generated.[/green]")
else:
console.print("[red]Failed to generate local organization API key. Please check server logs.[/red]")
backend_env_path = resolve_backend_env_path()
if backend_env_path.exists():
console.print(f"💡 [{backend_env_path}] file already exists.", style="yellow", markup=False)
redo_llm_setup = Confirm.ask(
"Do you want to go through [bold yellow]LLM provider setup again[/bold yellow]?",
default=False,
)
if not redo_llm_setup:
console.print("[green]Skipping LLM setup.[/green]")
else:
console.print("\n[bold blue]Initializing .env file for LLM providers...[/bold blue]")
setup_llm_providers()
else:
console.print("\n[bold blue]Initializing .env file...[/bold blue]")
setup_llm_providers()
console.print("\n[bold blue]Configuring browser settings...[/bold blue]")
browser_type, browser_location, remote_debugging_url = setup_browser_config()
update_or_add_env_var("BROWSER_TYPE", browser_type)
if browser_location:
update_or_add_env_var("CHROME_EXECUTABLE_PATH", browser_location)
if remote_debugging_url:
update_or_add_env_var("BROWSER_REMOTE_DEBUGGING_URL", remote_debugging_url)
console.print("✅ [green]Browser configuration complete.[/green]")
console.print("🌐 [bold blue]Setting Skyvern Base URL to: http://localhost:8000[/bold blue]")
update_or_add_env_var("SKYVERN_BASE_URL", "http://localhost:8000")
2025-05-26 18:50:11 -07:00
console.print("\n[bold yellow]To run Skyvern you can either:[/bold yellow]")
console.print("• [green]skyvern run server[/green] (reuses the DB we just created)")
2025-05-26 18:50:11 -07:00
console.print(
"• [cyan]docker compose up -d[/cyan] (starts a new Postgres inside Compose; you may stop the first container with: [magenta]docker rm -f postgresql-container[/magenta])"
)
console.print(
"\n[italic]Only one Postgres container can run on the host's port 5432 at a time. If you switch to Docker Compose, remove the original with:[/italic] [magenta]docker rm -f postgresql-container[/magenta]"
)
else:
console.print(Panel("[bold purple]Cloud Deployment Setup[/bold purple]", border_style="purple"))
base_url = Prompt.ask("Enter Skyvern base URL", default="https://api.skyvern.com", show_default=True)
if not base_url:
base_url = "https://api.skyvern.com"
console.print("\n[bold]To get your API key:[/bold]")
console.print("1. Create an account at [link]https://app.skyvern.com[/link]")
console.print("2. Go to [bold cyan]Settings[/bold cyan]")
console.print("3. [bold green]Copy your API key[/bold green]")
api_key = Prompt.ask("Enter your Skyvern API key", password=True)
if not api_key:
console.print("[red]API key is required.[/red]")
api_key = Prompt.ask("Please re-enter your Skyvern API key", password=True)
if not api_key:
console.print("[bold red]Error: API key cannot be empty. Aborting initialization.[/bold red]")
2025-12-04 21:14:48 -07:00
return False
update_or_add_env_var("SKYVERN_BASE_URL", base_url)
analytics_id_input = Prompt.ask("Please enter your email for analytics (press enter to skip)", default="")
analytics_id = analytics_id_input if analytics_id_input else str(uuid.uuid4())
update_or_add_env_var("ANALYTICS_ID", analytics_id)
update_or_add_env_var("SKYVERN_API_KEY", api_key)
console.print(f"✅ [green]{resolve_backend_env_path()} file has been initialized.[/green]")
if Confirm.ask("\nWould you like to [bold yellow]configure the MCP server[/bold yellow]?", default=True):
setup_mcp()
if not run_local:
console.print(
"\n🎉 [bold green]MCP configuration is complete! Your AI applications are now ready to use Skyvern Cloud.[/bold green]"
)
if run_local:
console.print("\n⬇️ [bold blue]Installing Chromium browser...[/bold blue]")
with Progress(
SpinnerColumn(), TextColumn("[progress.description]{task.description}"), transient=True, console=console
) as progress:
progress.add_task("[bold blue]Downloading Chromium, this may take a moment...", total=None)
subprocess.run(["playwright", "install", "chromium"], check=True)
console.print("✅ [green]Chromium installation complete.[/green]")
console.print("\n🎉 [bold green]Skyvern setup complete![/bold green]")
console.print("[bold]To start using Skyvern, run:[/bold]")
console.print(Padding("skyvern run server", (1, 4), style="reverse green"))
2025-12-04 21:14:48 -07:00
return run_local
def init_browser() -> None:
"""Initialize only the browser configuration and install Chromium."""
console.print("\n[bold blue]Configuring browser settings...[/bold blue]")
browser_type, browser_location, remote_debugging_url = setup_browser_config()
update_or_add_env_var("BROWSER_TYPE", browser_type)
if browser_location:
update_or_add_env_var("CHROME_EXECUTABLE_PATH", browser_location)
if remote_debugging_url:
update_or_add_env_var("BROWSER_REMOTE_DEBUGGING_URL", remote_debugging_url)
console.print("✅ [green]Browser configuration complete.[/green]")
console.print("\n⬇️ [bold blue]Installing Chromium browser...[/bold blue]")
with Progress(
SpinnerColumn(), TextColumn("[progress.description]{task.description}"), transient=True, console=console
) as progress:
progress.add_task("[bold blue]Downloading Chromium, this may take a moment...", total=None)
subprocess.run(["playwright", "install", "chromium"], check=True)
console.print("✅ [green]Chromium installation complete.[/green]")