Files
project-lyra/cortex/router.py
2025-11-28 19:29:41 -05:00

107 lines
3.2 KiB
Python

# router.py
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from reasoning.reasoning import reason_check
from reasoning.reflection import reflect_notes
from reasoning.refine import refine_answer
from persona.speak import speak
from persona.identity import load_identity
from ingest.intake_client import IntakeClient
from context import collect_context, update_last_assistant_message
# -----------------------------
# Router (NOT FastAPI app)
# -----------------------------
cortex_router = APIRouter()
# Initialize Intake client once
intake_client = IntakeClient()
# -----------------------------
# Pydantic models
# -----------------------------
class ReasonRequest(BaseModel):
session_id: str
user_prompt: str
temperature: float | None = None
# -----------------------------
# /reason endpoint
# -----------------------------
@cortex_router.post("/reason")
async def run_reason(req: ReasonRequest):
# 0. Collect unified context from all sources
context_state = await collect_context(req.session_id, req.user_prompt)
# 0.5. Load identity block
identity_block = load_identity(req.session_id)
# 1. Extract Intake summary for reflection
# Use L20 (Session Overview) as primary summary for reflection
intake_summary = "(no context available)"
if context_state.get("intake"):
l20_summary = context_state["intake"].get("L20")
if l20_summary and isinstance(l20_summary, dict):
intake_summary = l20_summary.get("summary", "(no context available)")
elif isinstance(l20_summary, str):
intake_summary = l20_summary
# 2. Reflection
try:
reflection = await reflect_notes(intake_summary, identity_block=identity_block)
reflection_notes = reflection.get("notes", [])
except Exception:
reflection_notes = []
# 3. First-pass reasoning draft
draft = await reason_check(
req.user_prompt,
identity_block=identity_block,
rag_block=context_state.get("rag", []),
reflection_notes=reflection_notes,
context=context_state
)
# 4. Refinement
result = await refine_answer(
draft_output=draft,
reflection_notes=reflection_notes,
identity_block=identity_block,
rag_block=context_state.get("rag", []),
)
final_neutral = result["final_output"]
# 5. Persona layer
persona_answer = await speak(final_neutral)
# 6. Update session state with assistant's response
update_last_assistant_message(req.session_id, persona_answer)
# 7. Return full bundle
return {
"draft": draft,
"neutral": final_neutral,
"persona": persona_answer,
"reflection": reflection_notes,
"session_id": req.session_id,
"context_summary": {
"rag_results": len(context_state.get("rag", [])),
"minutes_since_last": context_state.get("minutes_since_last_msg"),
"message_count": context_state.get("message_count"),
"mode": context_state.get("mode"),
}
}
# -----------------------------
# Intake ingest passthrough
# -----------------------------
@cortex_router.post("/ingest")
async def ingest_stub():
return {"status": "ok"}