# app.py import os from fastapi import FastAPI, Request, HTTPException from fastapi.middleware.cors import CORSMiddleware from jose import jwt, JWTError from supabase_ie import load_history_for_display from datetime import datetime from routes_utils import router as utils_router from routes_stt import router as stt_router from routes_wizard import router as wizard_router from translate_query_response import ( detect_language_code, translate_to_english, translate_from_english, ) from app_nn import run_chat_app # your Socrates logic APP = FastAPI(title="Socrates API", version="1.0") APP.include_router(utils_router) APP.include_router(stt_router) APP.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) APP.include_router(wizard_router) # --- Supabase JWT secret (HS256) --- JWT_SECRET = os.environ.get("SUPABASE_JWT_SECRET") if not JWT_SECRET: raise RuntimeError("SUPABASE_JWT_SECRET not set in environment") async def verify_jwt(auth_header: str) -> str: """ Verify Supabase access token using shared JWT secret. Return user_id (sub). """ if not auth_header or not auth_header.startswith("Bearer "): raise HTTPException(status_code=401, detail="Missing Authorization header") token = auth_header.split(" ", 1)[1] try: claims = jwt.decode( token, JWT_SECRET, algorithms=["HS256"], # Supabase default options={"verify_aud": False}, ) except JWTError as e: print("JWT decode error:", repr(e)) raise HTTPException(status_code=401, detail=f"Invalid JWT: {e}") user_id = claims.get("sub") if not user_id: raise HTTPException(status_code=401, detail="JWT has no sub (user id)") return user_id @APP.post("/chat/send") async def chat_send(req: Request): user_id = await verify_jwt(req.headers.get("authorization")) data = await req.json() message = data.get("message", "") username = data.get("username") or "Anonymous" profile = data.get("profile") or {} ui_lang = data.get("ui_lang", "en") reply = run_chat_app( user_id=user_id, username=username, profile=profile, ui_lang=ui_lang, user_msg=message, ) if isinstance(reply, dict): news = reply.get("news_fetch") if isinstance(news, dict): news.pop("faiss_object", None) return {"reply": reply, "user_id": user_id} @APP.post("/chat/history") async def chat_history(req: Request): auth_header = req.headers.get("authorization", "") try: user_id = await verify_jwt(auth_header) except Exception: raise HTTPException(status_code=401, detail="Invalid JWT") if not user_id: raise HTTPException(status_code=401, detail="Invalid JWT") msgs = load_history_for_display(user_id=user_id) or [] safe_messages = [] for i, m in enumerate(msgs): safe_messages.append({ "id": m.get("id") or f"{i}-{m.get('role','assistant')}", "role": m.get("role", "assistant"), "content": m.get("content", ""), "time": ( m.get("time") or m.get("timestamp") or datetime.utcnow().isoformat() ), }) return {"messages": safe_messages}