Files
grimlock/backend/main.py
JA d9a7c016b1 Backend MVP: FastAPI + Claude integration
Core components:
- FastAPI server with health endpoints
- AI client (Anthropic Claude integration)
- Context manager (loads company knowledge)
- Chat API (non-streaming and streaming)
- Requirements and environment setup

Ready to run: python backend/main.py
2026-02-12 21:16:38 +00:00

107 lines
2.8 KiB
Python

"""
Grimlock - AI-Native Company Operating System
Main FastAPI Application
"""
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager
import logging
from dotenv import load_dotenv
import os
from api.chat import router as chat_router
from core.context_manager import ContextManager
from core.ai_client import AIClient
# Load environment variables
load_dotenv()
# Configure logging
logging.basicConfig(
level=os.getenv("LOG_LEVEL", "INFO"),
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# Global state
context_manager = None
ai_client = None
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Startup and shutdown events"""
global context_manager, ai_client
logger.info("Starting Grimlock backend...")
# Initialize context manager
context_path = os.getenv("CONTEXT_PATH", "./context")
context_manager = ContextManager(context_path)
context_manager.load_all_context()
logger.info(f"Loaded context from {context_path}")
# Initialize AI client
api_key = os.getenv("ANTHROPIC_API_KEY")
if not api_key:
logger.error("ANTHROPIC_API_KEY not set!")
raise ValueError("ANTHROPIC_API_KEY environment variable is required")
ai_client = AIClient(api_key=api_key)
logger.info("AI client initialized")
yield
# Cleanup
logger.info("Shutting down Grimlock backend...")
# Create FastAPI app
app = FastAPI(
title="Grimlock",
description="AI-Native Company Operating System",
version="0.1.0",
lifespan=lifespan
)
# CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Configure appropriately for production
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Include routers
app.include_router(chat_router, prefix="/api/chat", tags=["chat"])
@app.get("/")
async def root():
"""Health check endpoint"""
return {
"status": "online",
"service": "Grimlock",
"version": "0.1.0"
}
@app.get("/api/health")
async def health():
"""Detailed health check"""
return {
"status": "healthy",
"context_loaded": context_manager is not None and context_manager.is_loaded(),
"ai_client_ready": ai_client is not None
}
def get_context_manager() -> ContextManager:
"""Dependency to get context manager"""
if context_manager is None:
raise HTTPException(status_code=500, detail="Context manager not initialized")
return context_manager
def get_ai_client() -> AIClient:
"""Dependency to get AI client"""
if ai_client is None:
raise HTTPException(status_code=500, detail="AI client not initialized")
return ai_client