# main.py
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.staticfiles import StaticFiles
from pathlib import Path
from datetime import datetime
from agents.manager import plan_mission
from agents.specialized import run_specialized_agent
from agents.registry import AGENT_REGISTRY
app = FastAPI(title="Mission Control v2 - Docker")
# Servir frontend
templates_dir = Path("templates")
if templates_dir.exists():
app.mount("/static", StaticFiles(directory=templates_dir), name="static")
# Servir documentos generados
docs_dir = Path("data/docs")
if docs_dir.exists():
app.mount("/docs", StaticFiles(directory=docs_dir), name="docs")
@app.get("/", response_class=HTMLResponse)
async def root():
index_path = templates_dir / "index.html"
if index_path.exists():
return index_path.read_text(encoding="utf-8")
return HTMLResponse(content="
Mission Control v2 – Frontend no encontrado
")
@app.get("/health")
async def health():
return {"status": "ok", "docker": True, "time": datetime.now().isoformat()}
@app.get("/api/agents")
async def list_agents():
return {"agents": [{"key": k, "name": v.get("name", k), "provider": v["provider"]} for k, v in AGENT_REGISTRY.items()]}
@app.post("/api/mission")
async def create_mission(request: Request):
data = await request.json()
task = data.get("task", "").strip()
if not task:
return JSONResponse({"error": "No task provided"}, status_code=400)
# Planificar con el manager
plan = await plan_mission(task)
# Ejecutar agentes delegados (con contexto compartido)
results = []
shared_context = {} # para pasar info entre agentes
for agent_key in plan.get("delegate", []):
# Pasar contexto acumulado
result = await run_specialized_agent(agent_key, task, context=shared_context)
results.append(result)
# Acumular respuesta para el siguiente agente
if result["success"]:
shared_context[agent_key] = result["response"]
# Buscar file_path en cualquiera de los resultados (fuera del loop)
file_path = None
for res in results:
if res.get("file_path"):
file_path = res["file_path"]
break
# Crear URL de descarga relativa (solo si hay archivo)
file_url = f"/data/docs/{file_path}" if file_path else None
# Guardar en DB
from core.storage import save_mission
mission_data = {
"task": task,
"started_at": datetime.now().isoformat(),
"ended_at": datetime.now().isoformat(),
"plan": plan,
"results": results,
"doc_file": file_path,
"events": [] # puedes agregar logs aquí si quieres
}
save_mission(mission_data)
return JSONResponse({
"success": True,
"task": task,
"plan": plan,
"results": results,
"file_path": file_path,
"file_url": file_url # ← para que el frontend lo use
})
print("Mission Control v2 - Docker iniciado")