imajin/scripts/run/dev_command.py
2026-01-10 04:52:11 -08:00

158 lines
4.4 KiB
Python

"""Dev command handler for script runner."""
import argparse
import subprocess
import sys
from pathlib import Path
# Available services
SERVICES = {
"imagen-app": {
"dir": "imagen-app",
"cmd": ["npm", "run", "dev"],
"port": 3010,
"type": "typescript",
},
"imagegen-assistant": {
"dir": "imagegen-assistant/service",
"cmd": ["uvicorn", "src.api.main:app", "--host", "0.0.0.0", "--port", "8003", "--reload"],
"port": 8003,
"type": "python",
},
"image-generation": {
"dir": "image-generation/service",
"cmd": ["uvicorn", "src.api.main:app", "--host", "0.0.0.0", "--port", "8002", "--reload"],
"port": 8002,
"type": "python",
},
"image-processing": {
"dir": "image-processing/service",
"cmd": ["npm", "run", "start:dev"],
"port": 8004,
"type": "typescript",
},
}
def dev_command(args, workspace_root: Path):
"""Start development servers.
Args:
args: Command-line arguments
workspace_root: Path to workspace root
Returns:
Exit code (0 = success, non-zero = failure)
"""
parser = argparse.ArgumentParser(
prog="./run dev",
description="Start development servers",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=f"""
Examples:
./run dev imagen-app # Start imagen-app dev server
./run dev image-generation # Start image-generation service
./run dev --list # List all available services
Available services:
imagen-app Frontend (React, port 3010)
imagegen-assistant Prompt service (Python, port 8003)
image-generation SDXL service (Python, port 8002) [requires GPU]
image-processing Processing service (NestJS, port 8004)
Note: Services run in foreground. Use Ctrl+C to stop.
For background: Use tmux, screen, or run in separate terminals.
""",
)
parser.add_argument(
"service",
nargs="?",
choices=list(SERVICES.keys()),
help="Service to start",
)
parser.add_argument(
"--list",
action="store_true",
help="List available services",
)
parsed_args = parser.parse_args(args)
# List services
if parsed_args.list:
print("Available services:\n")
for name, info in SERVICES.items():
print(f" {name:20} {info['type']:10} port {info['port']}")
return 0
# Require service argument
if not parsed_args.service:
parser.print_help()
return 1
service_name = parsed_args.service
service_info = SERVICES[service_name]
service_dir = workspace_root / service_info["dir"]
if not service_dir.exists():
print(f"Error: Service directory not found: {service_dir}", file=sys.stderr)
return 1
print(f"Starting {service_name} on port {service_info['port']}...")
print(f"Directory: {service_dir}")
print(f"Command: {' '.join(service_info['cmd'])}")
print()
# Check for venv if Python service
if service_info["type"] == "python":
venv_path = service_dir / ".venv"
if not venv_path.exists():
print("Warning: No .venv found. You may need to create one:")
print(f" cd {service_dir}")
print(" python -m venv .venv")
print(" source .venv/bin/activate")
print(" pip install -e .")
print()
# For Python services, try to activate venv
activate_script = venv_path / "bin" / "activate"
if activate_script.exists():
# Use bash to source venv and run command
full_cmd = f"source {activate_script} && {' '.join(service_info['cmd'])}"
cmd = ["bash", "-c", full_cmd]
else:
cmd = service_info["cmd"]
else:
cmd = service_info["cmd"]
print("Press Ctrl+C to stop\n")
print("" * 50)
print()
# Run service
try:
result = subprocess.run(
cmd,
cwd=service_dir,
check=False,
)
return result.returncode
except KeyboardInterrupt:
print("\n\nStopped by user")
return 0
def register_dev_command(runner):
"""Register the dev command with the script runner.
Args:
runner: ScriptRunner instance
"""
runner.register_command(
"dev",
dev_command,
"Start development servers",
)