Spaces:
Running
Running
| # api_server.py | |
| import requests | |
| from fastapi import FastAPI, Request | |
| from pydantic import BaseModel | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import HTMLResponse | |
| from fastapi.staticfiles import StaticFiles | |
| from fastapi.responses import FileResponse | |
| from fastapi import BackgroundTasks | |
| from core.conversation_manager import ConversationState | |
| from core.conversation_engine import handle_turn | |
| from core.agent_orchestrator import run_agents | |
| from core.input_classifier import is_meaningful_input | |
| from core.memory_store import save_state, load_state # session persistence handling | |
| from core.conversation_manager import from_dict # to have the retrieved conversation in DICT/JSON converted to ConversationState Object | |
| from core.command_parser import parse_command | |
| from agents.epistemic_agent import epistemic_response | |
| from core.epistemic.profile_manager import update_global_profile | |
| from core.epistemic.epistemic_cross import cross_session_analysis | |
| # CREATE APP FIRST | |
| app = FastAPI() | |
| # THEN MOUNT STATIC | |
| app.mount("/static", StaticFiles(directory="web"), name="static") | |
| # sessions = {} | |
| # ---- CORS FIX ---- | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], # allow any origin | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| class ChatRequest(BaseModel): | |
| session_id: str | |
| message: str | |
| def serve_ui(): | |
| return FileResponse("web/index.html") | |
| #@app.get("/") | |
| #def root(): | |
| # return {"status": "CGJI01 API running"} | |
| #@app.post("/analyze") | |
| #def analyze(req: Request): | |
| # results = run_agents(req.text) | |
| # return results | |
| def analyze(req: Request): | |
| if not is_meaningful_input(req.text): | |
| return { | |
| "status": "ok", | |
| "message": "Input does not appear to require deep psychological analysis.", | |
| "input": req.text | |
| } | |
| results = run_agents(req.text) | |
| return {"result": results} | |
| """ | |
| sessions = {} | |
| @app.post("/chat") | |
| async def chat(req: Request): | |
| data = await req.json() | |
| session_id = data["session_id"] | |
| message = data["message"] | |
| if session_id not in sessions: | |
| sessions[session_id] = ConversationState() | |
| state = sessions[session_id] | |
| output = handle_turn(state, message) | |
| if output["type"] == "end": | |
| del sessions[session_id] # Clean up session when finished | |
| return output | |
| """ | |
| # HANDLE AGENT SWITCH - FUNCTION | |
| def handle_agent_switch(state, agent_name): | |
| output = run_specific_agent(agent_name, state.initial_query) | |
| # Ensure output is a dict | |
| if not isinstance(output, dict): | |
| output = { | |
| "type": "error", | |
| "content": "Agent returned invalid response" | |
| } | |
| print("🧠 AGENT SWITCH OUTPUT:", output) | |
| # Inject agent identity | |
| output["agent"] = agent_name | |
| return output | |
| #def handle_agent_switch(state, agent_name): | |
| # 🔥 TEMP: route through existing system | |
| # print(f"⚠️ Switching to {agent_name}, but using handle_turn for now") | |
| # return handle_turn(state, state.initial_query) | |
| def run_epistemic_witness(state, session_id): | |
| try: | |
| # Extract full histories | |
| client_history = [ | |
| msg["text"] for msg in state.agent_histories.get("jung", []) | |
| if msg["role"] == "client" | |
| ] | |
| jung_history = [ | |
| msg["text"] for msg in state.agent_histories.get("jung", []) | |
| if msg["role"] == "agent" | |
| ] | |
| # Run epistemic analysis | |
| analysis = epistemic_response(client_history, jung_history) | |
| # Store inside state | |
| if not hasattr(state, "witness_logs"): | |
| state.witness_logs = {} | |
| state.witness_logs["epistemic"] = analysis | |
| print("🧠 EPISTEMIC UPDATED") | |
| except Exception as e: | |
| print("❌ Epistemic error:", e) | |
| sessions = {} | |
| def chat(req: ChatRequest, background_tasks: BackgroundTasks): | |
| print("🔥 CHAT ENDPOINT HIT") | |
| session_id = req.session_id | |
| message = req.message | |
| print("\n🧾 RAW REQUEST BODY:", req) | |
| #if session_id not in sessions: | |
| # sessions[session_id] = ConversationState() | |
| if session_id not in sessions: | |
| saved_data = load_state(session_id) # when user sends a message after loading, backend restores full conversation automatically | |
| if saved_data: | |
| print("♻️ Restored session from disk") | |
| #sessions[session_id] = loaded | |
| print("🔍 SAVED DATA:", saved_data) | |
| try: | |
| state = from_dict(saved_data) | |
| except Exception as e: | |
| print("❌ RESTORE FAILED:", e) | |
| state = ConversationState() | |
| else: | |
| #sessions[session_id] = ConversationState() | |
| state = ConversationState() | |
| sessions[session_id] = state | |
| state = sessions[session_id] | |
| # ✅ Ensure flag exists | |
| if not hasattr(state, "conversation_started"): | |
| state.conversation_started = False | |
| if not state.conversation_started: | |
| state.conversation_started = True | |
| # ✅ Store initial query | |
| if not state.initial_query and not message.startswith("__agent__:"): | |
| #state.initial_query = message | |
| if state.history: | |
| state.initial_query = next( | |
| (m["content"] for m in data.get("history", []) if m["role"] == "client"), | |
| "" | |
| ) # improve initial query restore | |
| else: | |
| state.initial_query = message | |
| print("\n📥 USER MESSAGE:", message) | |
| cmd, cleaned_message = parse_command(message) | |
| if cmd: | |
| if cmd["command"] == "general": | |
| state.mode = "general" | |
| state.role = "client" | |
| elif cmd["command"] == "analysis": | |
| state.mode = "analysis" | |
| if len(cmd["args"]) > 0: | |
| if cmd["args"][0] == "analyst": | |
| state.role = "analyst" | |
| elif cmd["args"][0] == "client": | |
| state.role = "client" | |
| message = cleaned_message | |
| # ----------------------------- | |
| # AGENT SWITCH | |
| # ----------------------------- | |
| if message.startswith("__agent__:"): | |
| selected_agent = message.split(":")[1] | |
| print("🧭 Switching to agent:", selected_agent) | |
| state.current_agent = selected_agent | |
| output = handle_agent_switch(state, selected_agent) | |
| print("\n📤 RESPONSE TO UI:", output) | |
| return output | |
| # ----------------------------- | |
| # NORMAL FLOW (JUNG etc.) | |
| # ----------------------------- | |
| output = handle_turn(state, message) | |
| # ---- (EXPERIMENTAL) LOW-LEVEL CROSS-SESSION EPISTEMIC INTELLIGENCE/ANALYSIS ---- | |
| # ------------------------------- | |
| # UPDATE GLOBAL PROFILE | |
| # ------------------------------- | |
| state.session_id = session_id # ensure attached | |
| session_record = update_global_profile(state) | |
| # ------------------------------- | |
| # EPISTEMIC CROSS-SESSION | |
| # ------------------------------- | |
| epistemic_text = cross_session_analysis(session_record) | |
| # attach to response | |
| output["witness_updates"] = { | |
| "epistemic": epistemic_text | |
| } | |
| # ---- (EXPERIMENTAL) LOW-LEVEL CROSS-SESSION EPISTEMIC INTELLIGENCE/ANALYSIS - End ---- | |
| # ----------------------------------------- | |
| # SAVE STATE AFTER EVERY TURN (PERSISTENCE) | |
| # ----------------------------------------- | |
| save_state(session_id, state) | |
| # ----------------------------- | |
| # 🧠 EPISTEMIC (BACKGROUND) | |
| # ----------------------------- | |
| jung_history_len = len(state.agent_histories.get("jung", [])) | |
| # ✅ Throttle → every 2 turns | |
| if jung_history_len % 2 == 0: | |
| background_tasks.add_task(run_epistemic_witness, state, session_id) | |
| # ----------------------------- | |
| # 📦 ATTACH EPISTEMIC TO RESPONSE | |
| # ----------------------------- | |
| if hasattr(state, "witness_logs"): | |
| output["witness_updates"] = state.witness_logs | |
| print("\n📤 RESPONSE TO UI:", output) | |
| # ----------------------------- | |
| # CLEANUP | |
| # ----------------------------- | |
| if output["type"] == "end": | |
| del sessions[session_id] | |
| return output | |
| # ---- GET SESSION DATA, PAST CONVERSATION ---- | |
| def get_session(session_id: str): | |
| data = load_state(session_id) | |
| if not data: | |
| return {"error": "Session not found"} | |
| return data | |
| def health_check(): | |
| #import requests | |
| ollama_status = False | |
| try: | |
| requests.get("http://127.0.0.1:11434") | |
| ollama_status = True | |
| except: | |
| pass | |
| return { | |
| "api": "running", | |
| "ollama": "connected" if ollama_status else "not running", | |
| "agents": "ready" | |
| } |