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:
2026-03-19 13:46:59 +03:00
parent 03afb7a075
commit 8b8fe916f0
37 changed files with 1921 additions and 26 deletions

View File

@@ -90,6 +90,55 @@
"subtitle": "Этот контекст добавляется ко всем вашим разговорам с ИИ",
"placeholder": "Добавьте личную информацию, которую ИИ должен знать о вас..."
},
"documents": {
"upload": "Загрузить",
"drop_or_click": "Перетащите файл или нажмите для выбора",
"doc_type": "Тип документа",
"no_documents": "Документы ещё не загружены.",
"download": "Скачать",
"reindex": "Извлечь текст заново",
"extracted_text": "Извлечённый текст",
"search_placeholder": "Поиск по документам...",
"clear_search": "Очистить",
"types": {
"other": "Другое",
"lab_result": "Анализы",
"consultation": "Консультация",
"prescription": "Рецепт",
"imaging": "Снимки"
},
"status": {
"pending": "Ожидание",
"processing": "Обработка",
"completed": "Готово",
"failed": "Ошибка"
}
},
"memory": {
"create": "Добавить запись",
"edit": "Редактировать запись",
"no_entries": "Записей пока нет. ИИ будет сохранять важную информацию о здоровье здесь.",
"category": "Категория",
"importance": "Важность",
"title_field": "Заголовок",
"title_placeholder": "напр. Диабет 2 типа",
"content_field": "Содержание",
"content_placeholder": "Подробная информация...",
"categories": {
"condition": "Заболевание",
"medication": "Лекарство",
"allergy": "Аллергия",
"vital": "Показатели",
"document_summary": "Сводка документа",
"other": "Другое"
},
"importance_levels": {
"critical": "Критическая",
"high": "Высокая",
"medium": "Средняя",
"low": "Низкая"
}
},
"common": {
"loading": "Загрузка...",
"error": "Произошла ошибка",