import os import sys from pathlib import Path from typing import List, Optional from fastapi import FastAPI, HTTPException, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import FileResponse from pydantic import BaseModel # Add parent directory to sys.path to allow importing the brain package sys.path.append(str(Path(__file__).resolve().parents[2])) from brain.paths import get_brains_dir, get_brain_path from brain.config import load_config, save_config from brain.templates.brain_instance import scaffold_brain_instance app = FastAPI(title="Ever Brain API") # Configure CORS app.add_middleware( CORSMiddleware, allow_origins=["*"], # In production, specify the actual frontend URL allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) class BrainCreateRequest(BaseModel): name: str class BrainUseRequest(BaseModel): name: str class BrainStatusResponse(BaseModel): active_brain: Optional[str] brains_path: str brain_count: int @app.get("/status", response_model=BrainStatusResponse) async def get_status(): config = load_config() brains_dir = get_brains_dir() brains = [d.name for d in brains_dir.iterdir() if d.is_dir()] active_path_str = config.get("active_brain") active_brain_name = Path(active_path_str).name if active_path_str else None return { "active_brain": active_brain_name, "brains_path": str(brains_dir), "brain_count": len(brains) } @app.get("/brains", response_model=List[str]) async def list_brains(): brains_dir = get_brains_dir() return [d.name for d in brains_dir.iterdir() if d.is_dir()] @app.post("/brains") async def create_brain(request: BrainCreateRequest): brain_path = get_brain_path(request.name) if brain_path.exists(): raise HTTPException(status_code=400, detail=f"Brain instance '{request.name}' already exists.") try: scaffold_brain_instance(brain_path) return {"message": f"Brain '{request.name}' created successfully.", "path": str(brain_path)} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @app.post("/brains/use") async def use_brain(request: BrainUseRequest): brain_path = get_brain_path(request.name) if not brain_path.exists(): raise HTTPException(status_code=404, detail=f"Brain instance '{request.name}' not found.") from brain.config import set_active_brain set_active_brain(brain_path) return {"message": f"Active brain set to '{request.name}'."} @app.get("/download") async def download_cli(): # Path to the pre-packaged binary binary_path = Path(__file__).resolve().parents[2] / "dist" / "ever-brain.exe" if not binary_path.exists(): raise HTTPException(status_code=404, detail="CLI binary not found. Please run the packaging script.") return FileResponse( path=binary_path, filename="ever-brain.exe", media_type="application/octet-stream" ) @app.get("/download/setup") async def download_setup(): # Path to the GUI installer setup_path = Path(__file__).resolve().parents[2] / "dist" / "EverBrainSetup.exe" if not setup_path.exists(): raise HTTPException(status_code=404, detail="GUI Setup installer not found. Please compile the .iss script.") return FileResponse( path=setup_path, filename="EverBrainSetup.exe", media_type="application/octet-stream" ) @app.get("/install.ps1") async def download_install_script(request: Request): # Path to the web installation script script_path = Path(__file__).resolve().parents[2] / "scripts" / "web_install.ps1" if not script_path.exists(): raise HTTPException(status_code=404, detail="Installation script not found.") # Read script and inject the current host URL content = script_path.read_text(encoding="utf-8") # Hugging Face usually has 'x-forwarded-proto' and 'host' headers protocol = request.headers.get("x-forwarded-proto", "http") host = request.headers.get("host", "localhost:8000") base_url = f"{protocol}://{host}" content = content.replace('http://localhost:8000', base_url) from fastapi.responses import Response return Response( content=content, media_type="text/plain", headers={"Content-Disposition": "attachment; filename=install.ps1"} ) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)