"""Memory API router for retrieving and managing global memory data.""" from fastapi import APIRouter from pydantic import BaseModel, Field from deerflow.agents.memory.updater import get_memory_data, reload_memory_data from deerflow.config.memory_config import get_memory_config router = APIRouter(prefix="/api", tags=["memory"]) class ContextSection(BaseModel): """Model for context sections (user and history).""" summary: str = Field(default="", description="Summary content") updatedAt: str = Field(default="", description="Last update timestamp") class UserContext(BaseModel): """Model for user context.""" workContext: ContextSection = Field(default_factory=ContextSection) personalContext: ContextSection = Field(default_factory=ContextSection) topOfMind: ContextSection = Field(default_factory=ContextSection) class HistoryContext(BaseModel): """Model for history context.""" recentMonths: ContextSection = Field(default_factory=ContextSection) earlierContext: ContextSection = Field(default_factory=ContextSection) longTermBackground: ContextSection = Field(default_factory=ContextSection) class Fact(BaseModel): """Model for a memory fact.""" id: str = Field(..., description="Unique identifier for the fact") content: str = Field(..., description="Fact content") category: str = Field(default="context", description="Fact category") confidence: float = Field(default=0.5, description="Confidence score (0-1)") createdAt: str = Field(default="", description="Creation timestamp") source: str = Field(default="unknown", description="Source thread ID") class MemoryResponse(BaseModel): """Response model for memory data.""" version: str = Field(default="1.0", description="Memory schema version") lastUpdated: str = Field(default="", description="Last update timestamp") user: UserContext = Field(default_factory=UserContext) history: HistoryContext = Field(default_factory=HistoryContext) facts: list[Fact] = Field(default_factory=list) class MemoryConfigResponse(BaseModel): """Response model for memory configuration.""" enabled: bool = Field(..., description="Whether memory is enabled") storage_path: str = Field(..., description="Path to memory storage file") debounce_seconds: int = Field(..., description="Debounce time for memory updates") max_facts: int = Field(..., description="Maximum number of facts to store") fact_confidence_threshold: float = Field(..., description="Minimum confidence threshold for facts") injection_enabled: bool = Field(..., description="Whether memory injection is enabled") max_injection_tokens: int = Field(..., description="Maximum tokens for memory injection") class MemoryStatusResponse(BaseModel): """Response model for memory status.""" config: MemoryConfigResponse data: MemoryResponse @router.get( "/memory", response_model=MemoryResponse, summary="Get Memory Data", description="Retrieve the current global memory data including user context, history, and facts.", ) async def get_memory() -> MemoryResponse: """Get the current global memory data. Returns: The current memory data with user context, history, and facts. Example Response: ```json { "version": "1.0", "lastUpdated": "2024-01-15T10:30:00Z", "user": { "workContext": {"summary": "Working on DeerFlow project", "updatedAt": "..."}, "personalContext": {"summary": "Prefers concise responses", "updatedAt": "..."}, "topOfMind": {"summary": "Building memory API", "updatedAt": "..."} }, "history": { "recentMonths": {"summary": "Recent development activities", "updatedAt": "..."}, "earlierContext": {"summary": "", "updatedAt": ""}, "longTermBackground": {"summary": "", "updatedAt": ""} }, "facts": [ { "id": "fact_abc123", "content": "User prefers TypeScript over JavaScript", "category": "preference", "confidence": 0.9, "createdAt": "2024-01-15T10:30:00Z", "source": "thread_xyz" } ] } ``` """ memory_data = get_memory_data() return MemoryResponse(**memory_data) @router.post( "/memory/reload", response_model=MemoryResponse, summary="Reload Memory Data", description="Reload memory data from the storage file, refreshing the in-memory cache.", ) async def reload_memory() -> MemoryResponse: """Reload memory data from file. This forces a reload of the memory data from the storage file, useful when the file has been modified externally. Returns: The reloaded memory data. """ memory_data = reload_memory_data() return MemoryResponse(**memory_data) @router.get( "/memory/config", response_model=MemoryConfigResponse, summary="Get Memory Configuration", description="Retrieve the current memory system configuration.", ) async def get_memory_config_endpoint() -> MemoryConfigResponse: """Get the memory system configuration. Returns: The current memory configuration settings. Example Response: ```json { "enabled": true, "storage_path": ".deer-flow/memory.json", "debounce_seconds": 30, "max_facts": 100, "fact_confidence_threshold": 0.7, "injection_enabled": true, "max_injection_tokens": 2000 } ``` """ config = get_memory_config() return MemoryConfigResponse( enabled=config.enabled, storage_path=config.storage_path, debounce_seconds=config.debounce_seconds, max_facts=config.max_facts, fact_confidence_threshold=config.fact_confidence_threshold, injection_enabled=config.injection_enabled, max_injection_tokens=config.max_injection_tokens, ) @router.get( "/memory/status", response_model=MemoryStatusResponse, summary="Get Memory Status", description="Retrieve both memory configuration and current data in a single request.", ) async def get_memory_status() -> MemoryStatusResponse: """Get the memory system status including configuration and data. Returns: Combined memory configuration and current data. """ config = get_memory_config() memory_data = get_memory_data() return MemoryStatusResponse( config=MemoryConfigResponse( enabled=config.enabled, storage_path=config.storage_path, debounce_seconds=config.debounce_seconds, max_facts=config.max_facts, fact_confidence_threshold=config.fact_confidence_threshold, injection_enabled=config.injection_enabled, max_injection_tokens=config.max_injection_tokens, ), data=MemoryResponse(**memory_data), )