This repository has been archived on 2026-03-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Timmy-time-dashboard/src/dashboard/routes/memory.py

123 lines
3.3 KiB
Python

"""Memory (vector store) routes for browsing and searching memories."""
from fastapi import APIRouter, Form, HTTPException, Request
from fastapi.responses import HTMLResponse, JSONResponse
from dashboard.templating import templates
from timmy.memory_system import (
delete_memory,
get_memory_stats,
recall_personal_facts_with_ids,
search_memories,
store_personal_fact,
update_personal_fact,
)
router = APIRouter(prefix="/memory", tags=["memory"])
@router.get("", response_class=HTMLResponse)
async def memory_page(
request: Request,
query: str | None = None,
context_type: str | None = None,
agent_id: str | None = None,
):
"""Memory browser and search page."""
results = []
if query:
results = search_memories(
query=query,
context_type=context_type,
agent_id=agent_id,
limit=20,
)
stats = get_memory_stats()
facts = recall_personal_facts_with_ids()[:10]
return templates.TemplateResponse(
request,
"memory.html",
{
"page_title": "Memory Browser",
"query": query,
"results": results,
"stats": stats,
"facts": facts,
"filter_type": context_type,
"filter_agent": agent_id,
},
)
@router.post("/search", response_class=HTMLResponse)
async def memory_search(
request: Request,
query: str = Form(...),
context_type: str | None = Form(None),
):
"""Search memories (form submission)."""
query = query.strip()
if not query:
raise HTTPException(status_code=400, detail="Search query cannot be empty")
results = search_memories(
query=query,
context_type=context_type,
limit=20,
)
# Return partial for HTMX
return templates.TemplateResponse(
request,
"partials/memory_results.html",
{
"query": query,
"results": results,
},
)
@router.post("/fact", response_class=HTMLResponse)
async def add_fact(
request: Request,
fact: str = Form(...),
agent_id: str | None = Form(None),
):
"""Add a personal fact to memory."""
fact = fact.strip()
if not fact:
raise HTTPException(status_code=400, detail="Fact content cannot be empty")
store_personal_fact(fact, agent_id=agent_id)
facts = recall_personal_facts_with_ids()[:10]
return templates.TemplateResponse(
request,
"partials/memory_facts.html",
{"facts": facts},
)
@router.put("/fact/{fact_id}", response_class=JSONResponse)
async def edit_fact(fact_id: str, request: Request):
"""Update a personal fact."""
body = await request.json()
new_content = body.get("content", "").strip()
if not new_content:
raise HTTPException(400, "Content cannot be empty")
ok = update_personal_fact(fact_id, new_content)
if not ok:
raise HTTPException(404, "Fact not found")
return {"success": True, "id": fact_id, "content": new_content}
@router.delete("/fact/{fact_id}", response_class=JSONResponse)
async def delete_fact(fact_id: str):
"""Delete a personal fact."""
ok = delete_memory(fact_id)
if not ok:
raise HTTPException(404, "Fact not found")
return {"success": True, "id": fact_id}