"""Memory API routes""" import asyncio import logging from fastapi import APIRouter, HTTPException, Request logger = logging.getLogger(__name__) router = APIRouter(prefix="/memory", tags=["memory"]) def _get_memory_retriever(request: Request): retriever = getattr(request.app.state, "memory_retriever", None) if retriever is None: raise HTTPException( status_code=503, detail="Memory retriever is not configured", ) return retriever @router.get("/episodic") async def search_episodic_memory( query: str, top_k: int = 5, agent_name: str | None = None, req: Request = None, ): """Search episodic memory.""" retriever = _get_memory_retriever(req) if retriever._episodic is None: raise HTTPException( status_code=503, detail="Episodic memory is not configured", ) try: filters = {} if agent_name: filters["agent_name"] = agent_name items = await retriever._episodic.search(query, top_k=top_k, filters=filters or None) except asyncio.CancelledError: raise except Exception as e: logger.error(f"Failed to search episodic memory: {e}") raise HTTPException(status_code=500, detail="Failed to search episodic memory") results = [] for item in items: results.append({ "key": item.key, "value": item.value, "score": item.score, "metadata": item.metadata, }) return {"query": query, "results": results, "total": len(results)} @router.get("/semantic/search") async def search_semantic_memory( query: str, knowledge_base_ids: str | None = None, top_k: int = 5, req: Request = None, ): """Search semantic memory (knowledge bases).""" retriever = _get_memory_retriever(req) if retriever._semantic is None: raise HTTPException( status_code=503, detail="Semantic memory is not configured", ) try: filters = {} if knowledge_base_ids: filters["knowledge_base_ids"] = [kid.strip() for kid in knowledge_base_ids.split(",")] items = await retriever._semantic.search(query, top_k=top_k, filters=filters or None) except asyncio.CancelledError: raise except Exception as e: logger.error(f"Failed to search semantic memory: {e}") raise HTTPException(status_code=500, detail="Failed to search semantic memory") results = [] for item in items: results.append({ "key": item.key, "value": item.value, "score": item.score, "metadata": item.metadata, }) return {"query": query, "results": results, "total": len(results)} @router.delete("/episodic/{key}") async def delete_episodic_memory(key: str, req: Request = None): """Delete an episodic memory entry.""" retriever = _get_memory_retriever(req) if retriever._episodic is None: raise HTTPException( status_code=503, detail="Episodic memory is not configured", ) try: deleted = await retriever._episodic.delete(key) except asyncio.CancelledError: raise except Exception as e: logger.error(f"Failed to delete episodic memory '{key}': {e}") raise HTTPException(status_code=500, detail="Failed to delete episodic memory") if not deleted: raise HTTPException(status_code=404, detail=f"Episodic memory '{key}' not found") return {"key": key, "deleted": True}