Phase 4: Documents & Memory — upload, FTS, AI tools, context injection
Backend:
- Document + MemoryEntry models with Alembic migration (GIN FTS index)
- File upload endpoint with path traversal protection (sanitized filenames)
- Background document text extraction (PyMuPDF)
- Full-text search on extracted_text via PostgreSQL tsvector/tsquery
- Memory CRUD with enum-validated categories/importance, field allow-list
- AI tools: save_memory, search_documents, get_memory (Claude function calling)
- Tool execution loop in stream_ai_response (multi-turn tool use)
- Context assembly: injects critical memory + relevant doc excerpts
- File storage abstraction (local filesystem, S3-swappable)
- Secure file deletion (DB flush before disk delete)
Frontend:
- Document upload dialog (drag-and-drop + file picker)
- Document list with status badges, search, download (via authenticated blob)
- Document viewer with extracted text preview
- Memory list grouped by category with importance color coding
- Memory editor with category/importance dropdowns
- Documents + Memory pages with full CRUD
- Enabled sidebar navigation for both sections
Review fixes applied:
- Sanitized upload filenames (path traversal prevention)
- Download via axios blob (not bare <a href>, preserves auth)
- Route ordering: /search before /{id}/reindex
- Memory update allows is_active=False + field allow-list
- MemoryEditor form resets on mode switch
- Literal enum validation on category/importance schemas
- DB flush before file deletion for data integrity
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -90,6 +90,55 @@
|
||||
"subtitle": "This context is added to all your AI conversations",
|
||||
"placeholder": "Add personal information that the AI should know about you..."
|
||||
},
|
||||
"documents": {
|
||||
"upload": "Upload",
|
||||
"drop_or_click": "Drop a file here or click to browse",
|
||||
"doc_type": "Document Type",
|
||||
"no_documents": "No documents uploaded yet.",
|
||||
"download": "Download",
|
||||
"reindex": "Re-extract text",
|
||||
"extracted_text": "Extracted Text",
|
||||
"search_placeholder": "Search documents...",
|
||||
"clear_search": "Clear",
|
||||
"types": {
|
||||
"other": "Other",
|
||||
"lab_result": "Lab Result",
|
||||
"consultation": "Consultation",
|
||||
"prescription": "Prescription",
|
||||
"imaging": "Imaging"
|
||||
},
|
||||
"status": {
|
||||
"pending": "Pending",
|
||||
"processing": "Processing",
|
||||
"completed": "Completed",
|
||||
"failed": "Failed"
|
||||
}
|
||||
},
|
||||
"memory": {
|
||||
"create": "Add Memory Entry",
|
||||
"edit": "Edit Memory Entry",
|
||||
"no_entries": "No memory entries yet. The AI will save important health information here.",
|
||||
"category": "Category",
|
||||
"importance": "Importance",
|
||||
"title_field": "Title",
|
||||
"title_placeholder": "e.g. Diabetes Type 2",
|
||||
"content_field": "Content",
|
||||
"content_placeholder": "Detailed information...",
|
||||
"categories": {
|
||||
"condition": "Condition",
|
||||
"medication": "Medication",
|
||||
"allergy": "Allergy",
|
||||
"vital": "Vital Sign",
|
||||
"document_summary": "Document Summary",
|
||||
"other": "Other"
|
||||
},
|
||||
"importance_levels": {
|
||||
"critical": "Critical",
|
||||
"high": "High",
|
||||
"medium": "Medium",
|
||||
"low": "Low"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"loading": "Loading...",
|
||||
"error": "An error occurred",
|
||||
|
||||
Reference in New Issue
Block a user