feat: add API endpoints

This commit is contained in:
Albert
2025-08-17 01:53:57 +00:00
parent af7362df3d
commit e59d5eea73

180
app/main.py Normal file
View File

@@ -0,0 +1,180 @@
import uuid
import logging
from contextlib import asynccontextmanager
from typing import Annotated
from fastapi import FastAPI, Depends, HTTPException, BackgroundTasks
from fastapi.middleware.cors import CORSMiddleware
from app.core.config import settings
from app.data.database import init_db
from app.data.models import (
StartSessionRequest,
SendMessageRequest,
SessionResponse,
SessionStatusResponse
)
from app.services.session_service import SessionService
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Initialize database on startup."""
logger.info("Initializing database...")
await init_db()
logger.info("Database initialized successfully")
yield
logger.info("Shutting down...")
app = FastAPI(
title="SkyTalk API",
description="AI-powered backend service for conversational idea exploration and knowledge synthesis",
version="1.0.0",
lifespan=lifespan
)
# Add CORS middleware for development
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Configure appropriately for production
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
def get_session_service() -> SessionService:
"""Dependency to get SessionService instance."""
return SessionService()
@app.post("/sessions/start", response_model=SessionResponse)
async def start_session(
request: StartSessionRequest,
session_service: Annotated[SessionService, Depends(get_session_service)]
) -> SessionResponse:
"""Start a new interview session.
Args:
request: StartSessionRequest containing the topic
session_service: Injected SessionService instance
Returns:
SessionResponse with session_id, status, and initial message
"""
try:
result = await session_service.start_session(request.topic)
return SessionResponse(
session_id=result["session_id"],
status=result["status"],
message=result["message"]
)
except Exception as e:
logger.error(f"Error starting session: {e}")
raise HTTPException(status_code=500, detail="Failed to start session")
@app.post("/sessions/sendMessage", response_model=SessionResponse)
async def send_message(
request: SendMessageRequest,
background_tasks: BackgroundTasks,
session_service: Annotated[SessionService, Depends(get_session_service)]
) -> SessionResponse:
"""Send a message to an active session.
Args:
request: SendMessageRequest containing session_id and message
background_tasks: FastAPI background tasks for async processing
session_service: Injected SessionService instance
Returns:
SessionResponse with the AI's response
"""
try:
result = await session_service.handle_message(
session_id=request.session_id,
message=request.message
)
# If session is ending, trigger background synthesis
if result.get("session_ending", False):
background_tasks.add_task(
session_service.process_session_background_task,
request.session_id
)
logger.info(f"Triggered background synthesis for session {request.session_id}")
return SessionResponse(
session_id=result["session_id"],
status=result["status"],
message=result["message"]
)
except ValueError as e:
logger.error(f"Session error: {e}")
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
logger.error(f"Error handling message: {e}")
raise HTTPException(status_code=500, detail="Failed to process message")
@app.get("/sessions/getStatus", response_model=SessionStatusResponse)
async def get_session_status(
session_id: uuid.UUID,
session_service: Annotated[SessionService, Depends(get_session_service)]
) -> SessionStatusResponse:
"""Get the current status of a session.
Args:
session_id: UUID of the session
session_service: Injected SessionService instance
Returns:
SessionStatusResponse with session status and metadata
"""
try:
result = await session_service.get_session_status(session_id)
return SessionStatusResponse(
session_id=result["session_id"],
status=result["status"],
notes_count=result["notes_count"],
created_at=result["created_at"]
)
except ValueError as e:
logger.error(f"Session not found: {e}")
raise HTTPException(status_code=404, detail=str(e))
except Exception as e:
logger.error(f"Error getting session status: {e}")
raise HTTPException(status_code=500, detail="Failed to get session status")
@app.get("/health")
async def health_check():
"""Health check endpoint."""
return {"status": "healthy", "service": "SkyTalk API"}
@app.get("/")
async def root():
"""Root endpoint with API information."""
return {
"message": "Welcome to SkyTalk API",
"description": "AI-powered conversational idea exploration and knowledge synthesis",
"version": "1.0.0",
"docs": "/docs"
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"app.main:app",
host=settings.API_HOST,
port=settings.API_PORT,
reload=True
)