54 lines
1.7 KiB
Python
54 lines
1.7 KiB
Python
import sys
|
|
from contextlib import asynccontextmanager
|
|
from collections.abc import AsyncIterator
|
|
|
|
import uvicorn
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
# Direct IDE runs should not leave Python bytecode caches in the project tree.
|
|
sys.dont_write_bytecode = True
|
|
|
|
from app.agent.scheduler import build_scheduler # noqa: E402
|
|
from app.api.routes import router # noqa: E402
|
|
from app.core.config import get_settings # noqa: E402
|
|
from app.core.log_setup import configure_logging # noqa: E402
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
|
# The scheduler lives with the web process for the demo deployment profile.
|
|
settings = get_settings()
|
|
scheduler = build_scheduler(settings)
|
|
scheduler.start()
|
|
app.state.scheduler = scheduler
|
|
try:
|
|
yield
|
|
finally:
|
|
scheduler.shutdown(wait=False)
|
|
|
|
|
|
def create_app() -> FastAPI:
|
|
# App factory keeps tests and production startup on the same initialization path.
|
|
settings = get_settings()
|
|
configure_logging(settings.log_file)
|
|
app = FastAPI(title=settings.app_name, lifespan=lifespan)
|
|
# The separate Vite frontend runs on 5173 during local development.
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["http://127.0.0.1:5173", "http://localhost:5173"],
|
|
allow_credentials=False,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
app.include_router(router)
|
|
return app
|
|
|
|
|
|
app = create_app()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# Direct execution is for IDE/local development; deployment can still call uvicorn explicitly.
|
|
uvicorn.run("app.main:app", host="127.0.0.1", port=8010, reload=False)
|