# -*- coding: utf-8 -*- # [Imperial HF Wrapper v2.8.0 - Sync Blueprint Registration] # Flask 3.x PROHIBITS register_blueprint after first request. # ALL route/blueprint registration MUST happen synchronously before gunicorn serves. # Only heavy AI engine loading is deferred to background thread. import os import sys import threading # ── Path Resolution ───────────────────────────────────────────────────────── current_dir = os.path.dirname(os.path.abspath(__file__)) # Add the root (dist_hf/) so 'shadow_brain_core' package is importable if current_dir not in sys.path: sys.path.insert(0, current_dir) # Add shadow_brain_core itself so inner modules are importable by short name core_path = os.path.join(current_dir, "shadow_brain_core") if os.path.exists(core_path) and core_path not in sys.path: sys.path.insert(0, core_path) # Add scripts/tools so cloud_tool, gdrive_sync, quota_manager etc. resolve tools_path = os.path.join(current_dir, "scripts", "tools") if os.path.exists(tools_path) and tools_path not in sys.path: sys.path.insert(0, tools_path) # ── Minimal Flask Bootstrap ─────────────────────────────────────────────────── from flask import Flask, jsonify, request from flask_cors import CORS print(f"[SYSTEM] [HF] Gunicorn worker starting... v2.8.0 Sync-Blueprint.", flush=True) print(f"[SYSTEM] [HF] Environment PORT: {os.environ.get('PORT', 'Not Set (Default 7860)')}", flush=True) app = Flask(__name__) # [🔱] CORS is handled dynamically in web_server.py via after_request to support credentials. # We initialize it here with minimal settings to avoid conflicts. CORS(app, supports_credentials=True) app.status = "BOOTING" app.boot_error = None @app.before_request def log_request_info(): # [🔱 Imperial] Mute periodic polling logs to keep terminal clean poll_paths = ["/api/logs/shadow-brain", "/api/system/monitor/r2", "/health", "/api/health", "/api/status"] if any(p in request.path for p in poll_paths): return print(f"[DEBUG] [REQUEST] Path: {request.path}, Method: {request.method}", flush=True) @app.route("/", strict_slashes=False) def hf_root(): return jsonify({ "status": app.status, "message": "Imperial Shadow Brain (v2.8.0) — Sync Blueprint Architecture", "boot_error": str(app.boot_error) if app.boot_error else None, "engine": "LinuxCloudEngine", "assigned_port": os.environ.get('PORT', '7860') }) @app.route("/health", strict_slashes=False) @app.route("/api/health", strict_slashes=False) def hf_health(): return jsonify({ "status": app.status, "engine_ready": (app.status in ["RUNNING", "IGNITING"]), "ok": True, "version": "2.8.0", }) # ── [🔱 CRITICAL FIX v2.8.0] Register all blueprints SYNCHRONOUSLY ────────── # Flask 3.x requires ALL blueprints registered BEFORE first request. # The previous background-thread approach caused FATAL errors: blueprints # could not be registered after gunicorn served the first /health request. print("[SYSTEM] [HF] Registering blueprints synchronously (Flask 3.x compliance)...", flush=True) try: from shadow_brain_core.web_server import create_web_server class LinuxCloudEngine: def set_title(self, title): pass def get_status(self): return "Active (Cloud)" # create_web_server registers ALL blueprints onto app synchronously. # It also spawns its own background threads for heavy AI engine loading. create_web_server(current_dir, LinuxCloudEngine(), app_instance=app) app.status = "IGNITING" print("[SYSTEM] [HF] All blueprints registered. Engine igniting in background...", flush=True) # [🔱 Imperial Telegram] 텔레그램 봇은 로컬 전용 정책이므로 HF(클라우드)에서는 점화하지 않는다. # (로컬은 web_server.run_server()에서 telegram_bot.start()로 기동됨) print("[SYSTEM] [HF] ☁️ 텔레그램 봇 미점화 — 로컬 전용 정책.", flush=True) # [🔱 Imperial Discord] HF(클라우드)는 discord.com:443 아웃바운드가 차단되어 게이트웨이 # 연결이 불가하다(Cannot connect to host discord.com:443). 디스코드 봇은 로컬 전용 정책이므로 # HF에서는 점화하지 않는다. print("[SYSTEM] [HF] ☁️ 디스코드 봇 미점화 — 로컬 전용 정책(클라우드 discord.com 아웃바운드 차단).", flush=True) except Exception as e: app.status = "ERROR" app.boot_error = e print(f"[FATAL] [HF] Synchronous blueprint registration failed: {e}", flush=True) import traceback traceback.print_exc() # ── WSGI entry point ───────────────────────────────────────────────────────── # Gunicorn: `gunicorn app:app` if __name__ == "__main__": port = int(os.environ.get("PORT", 7860)) app.run(host="0.0.0.0", port=port, debug=False, use_reloader=False)