""" Direct HF Spaces deploy script — creates space, uploads all files. """ import os import json import shutil import tempfile from pathlib import Path from huggingface_hub import HfApi, upload_folder api = HfApi() SPACE_ID = "Raunak211006/hale-api" PROJECT_DIR = os.path.dirname(os.path.abspath(__file__)) print("=" * 60) print("HALE API -> Hugging Face Spaces Deploy") print("=" * 60) # 1. Create Space print("\n[1/4] Creating Space...") try: api.create_repo( repo_id=SPACE_ID, repo_type="space", space_sdk="docker", private=False, exist_ok=True, ) print(f" > Space ready: https://huggingface.co/spaces/{SPACE_ID}") except Exception as e: print(f" Space: {e}") # 2. Prepare deploy directory print("\n[2/4] Preparing deploy files...") deploy_dir = os.path.join(tempfile.gettempdir(), "hale-deploy") if os.path.exists(deploy_dir): shutil.rmtree(deploy_dir) os.makedirs(deploy_dir) # Files/dirs to SKIP SKIP = { '.git', '__pycache__', '.pytest_cache', 'hale-frontend', 'node_modules', '.env', 'data', 'logs', '.planning', 'Dockerfile.spaces', 'deploy_hf.py', 'deploy_spaces.py', '.github', '.gitattributes', '.dockerignore', 'docker-compose.yml', 'alembic', 'alembic.ini', 'debug_hale_db.py', 'migrate_db.py', 'seed_test_data.py', 'simulate_e2e.py', '.antigravityignore', } for item in os.listdir(PROJECT_DIR): if item in SKIP: continue src = os.path.join(PROJECT_DIR, item) dst = os.path.join(deploy_dir, item) try: if os.path.isdir(src): shutil.copytree(src, dst, dirs_exist_ok=True, ignore=shutil.ignore_patterns('__pycache__', '*.pyc', '.pytest_cache')) else: shutil.copy2(src, dst) except Exception as e: print(f" Skip {item}: {e}") # Copy Dockerfile.spaces as Dockerfile spaces_dockerfile = os.path.join(PROJECT_DIR, "Dockerfile.spaces") if os.path.exists(spaces_dockerfile): shutil.copy2(spaces_dockerfile, os.path.join(deploy_dir, "Dockerfile")) print(" > Dockerfile.spaces -> Dockerfile") # Create .env for spaces env_content = f"""APP_ENV=production DATABASE_URL=sqlite:///./data/hale.db CORS_ORIGINS=* LOG_LEVEL=INFO GEMINI_API_KEYS={os.environ.get('GEMINI_API_KEYS', '')} SECRET_KEY=hale-production-key-change-me-to-random-64-chars-in-settings """ # Read GEMINI keys from local .env local_env = os.path.join(PROJECT_DIR, ".env") if os.path.exists(local_env): with open(local_env) as f: for line in f: line = line.strip() if line.startswith("GEMINI_API_KEYS="): gemini_keys = line.split("=", 1)[1] env_content = env_content.replace( f"GEMINI_API_KEYS=", f"GEMINI_API_KEYS={gemini_keys}" ) break with open(os.path.join(deploy_dir, ".env"), "w", encoding="utf-8") as f: f.write(env_content) print(" > .env created") # Create README.md with HF Spaces metadata readme = "---\ntitle: HALE - Adaptive Learning Engine API\nemoji: \U0001F9E0\ncolorFrom: purple\ncolorTo: blue\nsdk: docker\napp_port: 7860\npinned: true\n---\n\n# HALE - Adaptive Learning Engine\n\nAI-powered adaptive learning API with Reinforcement Learning behavioral engine.\n\n**API Docs**: [Open Swagger UI](/docs)\n\n## Quick Start\n1. POST /api/auth/register - Register user\n2. POST /api/auth/login - Get JWT token\n3. POST /api/goals/ - Create a learning goal\n4. GET /api/plan - Get todays adaptive plan\n5. POST /api/complete-task - Mark task done\n6. GET /api/stats - View analytics\n\n## Features\n- Contextual Multi-Armed Bandit RL engine (Thompson Sampling)\n- AI-generated curriculum via Gemini\n- Behavioral adaptation (mood, fatigue, stress, sleep)\n- Multi-goal support with priority-weighted scheduling\n- Streak tracking, XP, and leveling system\n- Auto-close at 2 AM IST with next-day preparation\n" with open(os.path.join(deploy_dir, "README.md"), "w", encoding="utf-8") as f: f.write(readme) print(" > README.md created") # Count files file_count = sum(len(files) for _, _, files in os.walk(deploy_dir)) print(f" > {file_count} files ready") # 3. Upload print(f"\n[3/4] Uploading to HF Spaces ({SPACE_ID})...") try: api.upload_folder( folder_path=deploy_dir, repo_id=SPACE_ID, repo_type="space", commit_message="Deploy HALE API v3.1", ) print(" > Upload complete!") except Exception as e: print(f" Upload failed: {e}") raise # 4. Done print("") print("=" * 60) print("DEPLOYMENT COMPLETE!") print("") print("API: https://raunak211006-hale-api.hf.space") print("Docs: https://raunak211006-hale-api.hf.space/docs") print(f"Space: https://huggingface.co/spaces/{SPACE_ID}") print("") print("Building may take 2-3 minutes. Check the Space page for status.") print("=" * 60)