File size: 4,217 Bytes
b0b150b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fb96efc
 
 
 
 
 
 
 
 
 
 
 
b0b150b
 
fb96efc
b0b150b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c87cf42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b0b150b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
"""
MEXAR Core Engine - FastAPI Backend Application
Main entry point for the MEXAR Phase 2 API.

This is a clean, minimal main.py that only includes routers.
All endpoints are handled by the api/ modules.
"""

import os
import logging
from pathlib import Path
from contextlib import asynccontextmanager

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

# Ensure data directories exist
DATA_DIRS = [
    Path("data/storage"),
    Path("data/temp"),
]
for dir_path in DATA_DIRS:
    dir_path.mkdir(parents=True, exist_ok=True)


# Lifespan context manager
@asynccontextmanager
async def lifespan(app: FastAPI):
    """Application lifespan handler - database initialization."""
    logger.info("MEXAR Core Engine starting up...")
    
    # Initialize database tables
    try:
        from core.database import engine, Base
        from models.user import User
        from models.agent import Agent, CompilationJob
        from models.conversation import Conversation, Message
        from models.chunk import DocumentChunk
        from sqlalchemy import text

        # Enable vector extension
        with engine.connect() as conn:
            conn.execute(text("CREATE EXTENSION IF NOT EXISTS vector"))
            conn.commit()

        Base.metadata.create_all(bind=engine)
        logger.info("Database tables created/verified successfully")
    except Exception as e:
        logger.warning(f"Database initialization: {e}")
    
    yield
    logger.info("MEXAR Core Engine shutting down...")


# Create FastAPI app
app = FastAPI(
    title="MEXAR Core Engine",
    description="Multimodal Explainable AI Reasoning Assistant - Phase 2",
    version="2.0.0",
    lifespan=lifespan
)

# Configure CORS
# Configure CORS
# CRITICAL: Configure CORS for Vercel frontend
FRONTEND_URL = os.getenv("FRONTEND_URL", "http://localhost:3000")

allow_origins = [
    "*", 
    FRONTEND_URL, 
    "https://*.vercel.app", 
    "http://localhost:3000",
    "http://localhost:3001"
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=allow_origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Import and include Phase 2 routers
from api import auth, agents, chat, compile, websocket, admin, prompts, diagnostics

app.include_router(auth.router)
app.include_router(agents.router)
app.include_router(chat.router)
app.include_router(compile.router)
app.include_router(websocket.router)
app.include_router(admin.router)
app.include_router(prompts.router)
app.include_router(diagnostics.router)


# ===== CORE UTILITY ENDPOINTS =====

@app.get("/")
async def root():
    """Root endpoint - serves landing page."""
    from fastapi.responses import FileResponse
    from pathlib import Path
    
    html_path = Path(__file__).parent / "static" / "index.html"
    if html_path.exists():
        return FileResponse(html_path, media_type="text/html")
    else:
        # Fallback to JSON if HTML not found
        return {
            "name": "MEXAR Core Engine",
            "version": "2.0.0",
            "status": "operational",
            "docs": "/docs"
        }


@app.get("/api/health")
async def health_check():
    """Health check endpoint."""
    return {
        "status": "healthy",
        "groq_configured": bool(os.getenv("GROQ_API_KEY"))
    }





# ===== ERROR HANDLERS =====

@app.exception_handler(Exception)
async def global_exception_handler(request, exc):
    """Global exception handler."""
    logger.error(f"Unhandled exception: {exc}")
    return JSONResponse(
        status_code=500,
        content={
            "success": False,
            "error": "Internal server error",
            "detail": str(exc)
        }
    )


# ===== MAIN ENTRY POINT =====

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(
        "main:app",
        host="0.0.0.0",
        port=8000,
        reload=True,
        log_level="info"
    )