"""Run the build API with Uvicorn.""" from __future__ import annotations import os from pathlib import Path import uvicorn from .app import create_application REPO_ROOT = Path(__file__).resolve().parent.parent def _load_env_file(path: Path) -> None: """Load KEY=VALUE lines into os.environ. Existing non-empty process env wins. Empty/missing keys are filled from the file so panel "load from file" stubs cannot block a real project .env. """ if not path.is_file(): return for raw in path.read_text(encoding="utf-8").splitlines(): line = raw.strip() if not line or line.startswith("#"): continue if line.startswith("export "): line = line[7:].strip() if "=" not in line: continue key, _, value = line.partition("=") key = key.strip() if not key: continue value = value.strip() if len(value) >= 2 and value[0] == value[-1] and value[0] in {'"', "'"}: value = value[1:-1] current = os.environ.get(key) if current is not None and current.strip(): continue os.environ[key] = value def main() -> None: # Always read project .env; also honor an explicit path from the panel. _load_env_file(REPO_ROOT / ".env") env_file = os.environ.get("BUILD_API_ENV_FILE", "").strip() if env_file: _load_env_file(Path(env_file)) token = os.environ.get("BUILD_API_TOKEN", "").strip() if not token: raise SystemExit( "BUILD_API_TOKEN is missing or empty. " f"Put it in {REPO_ROOT / '.env'} (KEY=value, no spaces around =)." ) host = os.environ.get("BUILD_API_HOST", "127.0.0.1") port = int(os.environ.get("BUILD_API_PORT", "8081")) application = create_application() print(f"build API listening on http://{host}:{port}", flush=True) uvicorn.run(application, host=host, port=port, log_level="info") if __name__ == "__main__": main()