Files
grimlock/backend/main.py
JA 6d6b1d0fbb Session fixes: auth working, frontend files created, running locally
- Fixed circular imports in API files
- Created missing frontend lib files (api.ts, socket.ts, types.ts)
- Fixed register endpoint to return token instead of user
- Updated Anthropic client version
- Backend running locally on port 8000
- Frontend running on port 3000
- Authentication working
- Still need: channel response fix, WebSocket auth fix
2026-02-14 04:45:39 +00:00

134 lines
4.0 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
import socketio
# Remove circular import - comment out chat router
# from api.chat import router as chat_router
from api.auth import router as auth_router
from api.channels import router as channels_router
from api.messages import router as messages_router
from api.direct_messages import router as dm_router
from api.files import router as files_router
from core.context_manager import ContextManager
from core.ai_client import AIClient
from core.database import engine
from core.models import Base
from core.websocket import sio, broadcast_new_message
# 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...")
# Create database tables
Base.metadata.create_all(bind=engine)
logger.info("Database tables created/verified")
# 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")
logger.info("WebSocket server ready")
yield
# Cleanup
logger.info("Shutting down Grimlock backend...")
# Create FastAPI app
app = FastAPI(
title="Grimlock",
description="AI-Native Company Operating System",
version="0.3.0",
lifespan=lifespan
)
# Mount Socket.IO
socket_app = socketio.ASGIApp(sio, app)
# CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Configure appropriately for production
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Include routers (chat router removed to fix circular import)
app.include_router(auth_router, prefix="/api/auth", tags=["auth"])
app.include_router(channels_router, prefix="/api/channels", tags=["channels"])
app.include_router(messages_router, prefix="/api/channels", tags=["messages"])
app.include_router(dm_router, prefix="/api/dms", tags=["direct-messages"])
app.include_router(files_router, prefix="/api/files", tags=["files"])
# app.include_router(chat_router, prefix="/api/chat", tags=["chat"]) # Commented out - circular import
@app.get("/")
async def root():
"""Health check endpoint"""
return {
"status": "online",
"service": "Grimlock",
"version": "0.3.0",
"features": ["auth", "channels", "messages", "dms", "files", "websocket", "ai"]
}
@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,
"database": "connected",
"websocket": "ready"
}
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