techprotrade's picture
Deploy ATOM FastAPI command center runtime (part 3)
92c4ae6 verified
Raw
History Blame Contribute Delete
8.32 kB
"""
Atom CLI - Init command for Personal Edition setup.
Creates initial configuration for Personal Edition:
- .env file with Personal defaults (SQLite)
- data/ directory for local storage
- Database initialization
- First run wizard
"""
import os
import sys
import click
import logging
from pathlib import Path
from datetime import datetime
# Add backend to path for imports
sys.path.insert(0, str(Path(__file__).parent.parent))
logger = logging.getLogger(__name__)
@click.command()
@click.option('--force', is_flag=True, help='Overwrite existing configuration')
@click.option('--edition', type=click.Choice(['personal', 'enterprise']), default='personal',
help='Edition to initialize (default: personal)')
@click.option('--database-url', help='Custom database URL (default: SQLite for personal)')
@click.option('--no-input', is_flag=True, help='Run non-interactively')
def init(force: bool, edition: str, database_url: str, no_input: bool):
"""
Initialize Atom Personal Edition configuration.
Creates .env file with Personal Edition defaults:
- SQLite database (./data/atom.db)
- Local filesystem storage
- Minimal feature set
**Examples:**
atom init # Interactive setup
atom init --edition personal # Personal Edition
atom init --edition enterprise # Enterprise Edition
atom init --force # Overwrite existing
atom init --no-input # Use all defaults
**Enterprise Edition:**
atom init --edition enterprise \\
--database-url "postgresql://user:pass@localhost/atom"
"""
click.echo(click.style("Atom Initialization", bold=True))
click.echo("=" * 50)
# Check if already initialized
env_file = Path(".env")
if env_file.exists() and not force:
click.echo(click.style("Configuration already exists!", fg="yellow"))
click.echo("Use --force to overwrite")
# Show current status
from core.package_feature_service import get_package_feature_service
service = get_package_feature_service()
click.echo("")
click.echo(f"Current Edition: {service.edition.value}")
click.echo(f"Database: {os.getenv('DATABASE_URL', 'Not configured')}")
raise SystemExit(1)
# Edition-specific defaults
if edition == "personal":
_init_personal_edition(database_url, no_input)
else:
_init_enterprise_edition(database_url, no_input, force)
# Success message
click.echo("")
click.echo(click.style("Initialization complete!", fg="green", bold=True))
click.echo("")
click.echo("Next steps:")
click.echo(" 1. Edit .env and add your API keys:")
click.echo(" OPENAI_API_KEY=sk-...")
click.echo(" ANTHROPIC_API_KEY=sk-ant-...")
click.echo("")
click.echo(" 2. Start Atom:")
click.echo(" atom start")
click.echo("")
click.echo(f" 3. Open dashboard:")
click.echo(" http://localhost:8000")
def _init_personal_edition(database_url: str, no_input: bool) -> None:
"""Initialize Personal Edition configuration."""
click.echo("")
click.echo(click.style("Setting up Personal Edition...", fg="blue"))
# Create data directory
data_dir = Path("data")
data_dir.mkdir(exist_ok=True)
click.echo(f" Created data directory: {data_dir}")
# Generate encryption keys
import secrets
encryption_key = secrets.token_urlsafe(32)
jwt_secret = secrets.token_urlsafe(32)
# Set Personal Edition defaults
env_content = f"""# Atom Personal Edition Configuration
# Generated: {datetime.now().isoformat()}
# Edition
ATOM_EDITION=personal
# Server
PORT=8000
HOST=0.0.0.0
WORKERS=1
# Database (SQLite - Personal Edition default)
DATABASE_URL=sqlite:///./data/atom.db
# Encryption Keys (auto-generated)
BYOK_ENCRYPTION_KEY={encryption_key}
JWT_SECRET_KEY={jwt_secret}
# LLM Providers (add your keys)
OPENAI_API_KEY=
ANTHROPIC_API_KEY=
DEEPSEEK_API_KEY=
# Vector Embeddings (local - Personal Edition)
EMBEDDING_PROVIDER=fastembed
FASTEMBED_MODEL=BAAI/bge-small-en-v1.5
LANCEDB_PATH=./data/lancedb
# Agent Governance
AGENT_MATURITY_DEFAULT=STUDENT
MAX_CONCURRENT_AGENTS=3
# Logging
LOG_LEVEL=INFO
STRUCTLOG_LEVEL=INFO
# Feature Flags (Personal Edition)
ATOM_MULTI_USER_ENABLED=false
ATOM_MONITORING_ENABLED=false
ATOM_SSO_ENABLED=false
"""
# Use custom database URL if provided
if database_url:
env_content = env_content.replace(
"DATABASE_URL=sqlite:///./data/atom.db",
f"DATABASE_URL={database_url}"
)
# Write .env file
env_file = Path(".env")
env_file.write_text(env_content)
click.echo(f" Created .env file (Personal Edition)")
# Create subdirectories
(data_dir / "lancedb").mkdir(exist_ok=True)
(data_dir / "uploads").mkdir(exist_ok=True)
click.echo(f" Created storage directories")
# Show database info
db_url = database_url or "sqlite:///./data/atom.db"
click.echo(f" Database: {db_url}")
def _init_enterprise_edition(database_url: str, no_input: bool, force: bool) -> None:
"""Initialize Enterprise Edition configuration."""
click.echo("")
click.echo(click.style("Setting up Enterprise Edition...", fg="blue"))
# Prompt for database URL if not provided
if not database_url and not no_input:
click.echo("")
click.echo("Enterprise Edition requires PostgreSQL.")
database_url = click.prompt(
"Enter PostgreSQL database URL",
default="postgresql://atom:atom@localhost:5432/atom"
)
if not database_url:
click.echo(click.style("Error: Database URL required for Enterprise", fg="red"), err=True)
raise SystemExit(1)
# Create data directory
data_dir = Path("data")
data_dir.mkdir(exist_ok=True)
click.echo(f" Created data directory: {data_dir}")
# Generate encryption keys
import secrets
encryption_key = secrets.token_urlsafe(32)
jwt_secret = secrets.token_urlsafe(32)
# Set Enterprise Edition defaults
env_content = f"""# Atom Enterprise Edition Configuration
# Generated: {datetime.now().isoformat()}
# Edition
ATOM_EDITION=enterprise
# Server
PORT=8000
HOST=0.0.0.0
WORKERS=4
# Database (PostgreSQL - Enterprise Edition required)
DATABASE_URL={database_url}
# Encryption Keys (auto-generated)
BYOK_ENCRYPTION_KEY={encryption_key}
JWT_SECRET_KEY={jwt_secret}
# LLM Providers
OPENAI_API_KEY=
ANTHROPIC_API_KEY=
DEEPSEEK_API_KEY=
# Vector Embeddings (OpenAI for Enterprise)
EMBEDDING_PROVIDER=openai
OPENAI_EMBEDDING_MODEL=text-embedding-3-small
LANCEDB_PATH=./data/lancedb
# Agent Governance
AGENT_MATURITY_DEFAULT=STUDENT
MAX_CONCURRENT_AGENTS=10
# Multi-User (Enterprise)
ATOM_MULTI_USER_ENABLED=true
ATOM_WORKSPACE_ISOLATION=true
# SSO (Enterprise)
ATOM_SSO_ENABLED=false
# SSO_PROVIDER=okta|auth0|saml
# OKTA_DOMAIN=
# OKTA_CLIENT_ID=
# AUTH0_DOMAIN=
# AUTH0_CLIENT_ID=
# Monitoring (Enterprise)
ATOM_MONITORING_ENABLED=true
PROMETHEUS_ENABLED=true
PROMETHEUS_PORT=9090
# Logging
LOG_LEVEL=INFO
STRUCTLOG_LEVEL=INFO
STRUCTLOG_JSON=true
# Redis (Enterprise - for multi-user pub/sub)
REDIS_URL=redis://localhost:6379/0
# Audit Trail (Enterprise)
ATOM_AUDIT_TRAIL_ENABLED=true
AUDIT_LOG_RETENTION_DAYS=90
# Rate Limiting (Enterprise)
ATOM_RATE_LIMITING_ENABLED=true
RATE_LIMIT_PER_MINUTE=60
"""
# Write .env file
env_file = Path(".env")
env_file.write_text(env_content)
click.echo(f" Created .env file (Enterprise Edition)")
# Create subdirectories
(data_dir / "lancedb").mkdir(exist_ok=True)
(data_dir / "uploads").mkdir(exist_ok=True)
(data_dir / "audit").mkdir(exist_ok=True)
click.echo(f" Created storage directories")
# Warning about PostgreSQL
click.echo("")
click.echo(click.style("PostgreSQL Setup Required:", fg="yellow"))
click.echo(" 1. Ensure PostgreSQL is installed and running")
click.echo(" 2. Create database: createdb atom")
click.echo(" 3. Or use connection string to existing database")
click.echo("")
click.echo("Current DATABASE_URL:")
click.echo(f" {database_url}")
def register_init_command(cli_group):
"""Register init command with CLI group."""
cli_group.add_command(init)