from __future__ import annotations import logging import os import socket import sys import threading import time import webbrowser from pathlib import Path from typing import Any import uvicorn logging.basicConfig( level=logging.INFO, format="%(asctime)s | %(levelname)s | %(message)s", ) logger = logging.getLogger("kronos-launcher") DEFAULT_HOST: str = "127.0.0.1" SERVER_BOOT_DELAY_SECONDS: float = 2.5 PROJECT_ROOT: Path = Path(__file__).resolve().parent.parent BANNER = r""" _ ___ _ _ ___ | |/ / | __ ___ _ __ ___ ___ / \ / \ |_ _| | ' /| |/ _` \ \/ / '_ \ / _ \/ __| / _ \ / _ \ | | | . \| | (_| |> <| | | | (_) \__ \/ ___ \ / ___ \ | | |_|\_\_|\__,_/_/\_\_| |_|\___/|___/_/ \_\/_/ \_\___| """ def print_banner() -> None: """Render a clean startup banner in the local console.""" os.system("cls" if os.name == "nt" else "clear") print("\033[96m" + BANNER + "\033[0m") print(" [*] Dang khoi dong he thong phan tich AI...") print(" [*] Dang nap du lieu thi truong...") print(" [*] Trinh duyet se tu dong mo khi server san sang.") print() def load_app() -> Any: """Import the FastAPI app after runtime settings are in place.""" project_root = str(PROJECT_ROOT) if project_root not in sys.path: sys.path.insert(0, project_root) from backend.main import app as fastapi_app return fastapi_app def find_free_port(host: str = DEFAULT_HOST) -> int: """Ask the OS for a currently available local TCP port.""" with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket: server_socket.bind((host, 0)) server_socket.listen(1) return int(server_socket.getsockname()[1]) def resolve_server_port() -> int: """Use PORT when defined, otherwise choose a random free local port.""" raw_port = os.getenv("PORT", "").strip() if raw_port: try: return int(raw_port) except ValueError as exc: raise ValueError(f"Invalid PORT value: {raw_port}") from exc port = find_free_port() os.environ["PORT"] = str(port) return port def open_browser(url: str) -> None: """Wait briefly for the server to start, then open the dashboard.""" time.sleep(SERVER_BOOT_DELAY_SECONDS) logger.info("Dang mo bang dieu khien tai %s", url) webbrowser.open(url) if __name__ == "__main__": print_banner() host = DEFAULT_HOST port = resolve_server_port() url = f"http://{host}:{port}" app = load_app() logger.info("Khoi dong Backend Core tren %s", url) threading.Thread(target=open_browser, args=(url,), daemon=True).start() try: uvicorn.run(app, host=host, port=port, log_level="warning") except Exception as exc: logger.exception("Loi khoi dong he thong: %s", exc) print("\n [!] Co loi xay ra trong qua trinh khoi dong.") print(" [!] Nhan Enter de thoat...") input()