MetaList 0.9.0__tar.gz → 0.11.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {metalist-0.9.0 → metalist-0.11.0}/PKG-INFO +18 -1
- {metalist-0.9.0 → metalist-0.11.0}/README.md +17 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/api/middleware/auth.py +0 -16
- {metalist-0.9.0 → metalist-0.11.0}/app/api/note_requests.py +17 -2
- {metalist-0.9.0 → metalist-0.11.0}/app/api/routes/auth.py +2 -1
- metalist-0.11.0/app/api/routes/files.py +244 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/api/routes/notes.py +41 -152
- {metalist-0.9.0 → metalist-0.11.0}/app/api/routes/ontology.py +0 -4
- {metalist-0.9.0 → metalist-0.11.0}/app/api/upload_limits.py +13 -1
- metalist-0.11.0/app/db/editable_files_migration.py +50 -0
- metalist-0.11.0/app/db/file_schema.py +58 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/db/files_sql.py +161 -2
- {metalist-0.9.0 → metalist-0.11.0}/app/db/migrations.py +2 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/db/notes_sql.py +9 -8
- {metalist-0.9.0 → metalist-0.11.0}/app/db/version.py +1 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/encryption_audit.py +74 -10
- {metalist-0.9.0 → metalist-0.11.0}/app/main.py +27 -0
- metalist-0.11.0/app/security/sensitive_cache.py +116 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/help_catalog.py +4 -2
- metalist-0.11.0/app/services/agent/markdown_validation.py +35 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/skills/help-formatting.md +3 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/skills/help-menus.md +2 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/skills/help-notes.md +1 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/skills/help-references.md +14 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/services/backlinks.py +2 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/services/backup_service.py +3 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/services/client_state_service.py +2 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/content_formatting.py +44 -2
- {metalist-0.9.0 → metalist-0.11.0}/app/services/embedded_references.py +251 -29
- {metalist-0.9.0 → metalist-0.11.0}/app/services/encryption.py +29 -12
- metalist-0.11.0/app/services/file_edit_sessions.py +81 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/file_registry.py +7 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/file_storage.py +403 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/services/html_export.py +9 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/services/image_size_formatting.py +1 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/services/link_titles.py +16 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/note_image_tags.py +11 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/note_store.py +193 -48
- {metalist-0.9.0 → metalist-0.11.0}/app/services/request_recovery.py +4 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/root_sorting.py +125 -59
- {metalist-0.9.0 → metalist-0.11.0}/app/services/search_history.py +84 -35
- {metalist-0.9.0 → metalist-0.11.0}/app/services/search_index.py +105 -48
- {metalist-0.9.0 → metalist-0.11.0}/app/services/snapshot.py +336 -176
- {metalist-0.9.0 → metalist-0.11.0}/app/services/store.py +3 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/services/sync.py +7 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/services/tab_state.py +8 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/tag_suggestions.py +24 -31
- {metalist-0.9.0 → metalist-0.11.0}/app/services/tag_term_matching.py +35 -33
- {metalist-0.9.0 → metalist-0.11.0}/app/services/undo_state.py +72 -3
- metalist-0.11.0/app/services/view_cache.py +99 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/config/agent-menu-actions.json +6 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/config/command_palette_tags.json +5 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/static/css/main.css +516 -117
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/api-client.js +202 -6
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/command-palette/command-palette-controller.js +30 -75
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/command-palette/endpoint-registry.js +8 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/command-palette/note-layout-preferences.js +19 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/command-palette/tag-config-loader.js +94 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/config.js +8 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/context-menu/context-menu-registry.js +78 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/context-menu/context-menu-service.js +6 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/editor-selection.js +2 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/editor-toolbar.js +2 -1
- metalist-0.11.0/app/static/js/modules/excalidraw/excalidraw-actions.js +93 -0
- metalist-0.11.0/app/static/js/modules/excalidraw/excalidraw-autosave.js +159 -0
- metalist-0.11.0/app/static/js/modules/excalidraw/excalidraw-editor-service.js +388 -0
- metalist-0.11.0/app/static/js/modules/excalidraw/excalidraw-editor-state.js +35 -0
- metalist-0.11.0/app/static/js/modules/excalidraw/excalidraw-loader.js +50 -0
- metalist-0.11.0/app/static/js/modules/excalidraw/excalidraw-preview-service.js +163 -0
- metalist-0.11.0/app/static/js/modules/excalidraw/excalidraw-scene.js +89 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/expected-errors.js +20 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/note-layout-appearance-modal.js +18 -4
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/actions/note-actions.js +6 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/actions/ui-actions.js +76 -29
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/events/context-menu-events.js +17 -2
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/events/focus-events.js +3 -2
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/events/input-events.js +0 -3
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/events/keyboard-events.js +30 -10
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/events/mouse-events.js +41 -15
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/mode-context.js +93 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/mode-manager-controller.js +8 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/collapse-affordance-service.js +50 -21
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/differential-view-service.js +25 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/floating-note-service.js +4 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/html-paste-sanitizer-service.js +4 -2
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/image-context-menu-action-service.js +6 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/infinite-scroll-service.js +41 -52
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/note-fullscreen-service.js +2 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/polling-service.js +42 -6
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/root-date-separator-service.js +1 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/root-sort-service.js +7 -2
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/scroll-to-top-service.js +13 -2
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/tab-state-service.js +17 -4
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/tag-suggestions-service.js +5 -4
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/tag-syntax-service.js +28 -0
- metalist-0.11.0/app/static/js/modules/mode-manager/services/viewport-hold-service.js +75 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/excalidraw.css +1 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Bold.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Medium.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Regular.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-SemiBold.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Cascadia/CascadiaCode-Regular.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Virgil/Virgil-Regular.woff2 +0 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1.LICENSE.txt +3135 -0
- metalist-0.11.0/app/static/js/vendor/excalidraw-0.18.1.min.js +208 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/bulk_tag_proposals.py +9 -5
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/delete_subtree.py +3 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/delete_tag.py +10 -7
- metalist-0.11.0/app/usecases/file_edit_session.py +110 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/rename_tag.py +6 -5
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/resize_image.py +1 -1
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/view.py +3 -3
- {metalist-0.9.0 → metalist-0.11.0}/app/utils/text_utils.py +3 -4
- {metalist-0.9.0 → metalist-0.11.0}/app/version.py +1 -1
- {metalist-0.9.0 → metalist-0.11.0}/metalist.egg-info/PKG-INFO +18 -1
- {metalist-0.9.0 → metalist-0.11.0}/metalist.egg-info/SOURCES.txt +39 -0
- metalist-0.9.0/app/api/routes/files.py +0 -95
- metalist-0.9.0/app/db/file_schema.py +0 -28
- metalist-0.9.0/app/security/sensitive_cache.py +0 -78
- metalist-0.9.0/app/services/view_cache.py +0 -122
- {metalist-0.9.0 → metalist-0.11.0}/MANIFEST.in +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/__init__.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/api/__init__.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/api/deps.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/api/dev.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/api/request_auth.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/api/routes/ai.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/api/routes/app_updates.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/api/routes/backups.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/api/routes/reminders.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/api/routes/remote_images.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/api/routes/test.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/api/transactions.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/config.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/data_directory.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/db/__init__.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/db/backup_settings_sql.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/db/engine.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/db/file_session.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/db/link_titles_sql.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/db/live_recovery.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/db/ontology_rules_sql.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/db/reminders_sql.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/db/retire_sounds.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/db/schema.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/db/search_history_sql.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/db/session.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/db/settings_sql.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/db/tab_state_sql.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/exception_boundaries.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/https_proxy.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/models/commands.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/models/database.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/models/entities.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/models/enums.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/models/linked_list.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/models/list_operations.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/models/list_traversal.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/models/note_crud.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/models/utils.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/network_settings.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/presentation/__init__.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/presentation/render/__init__.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/presentation/render/note_renderer.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/presentation/templates.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/security/authenticated_logging.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/security/encryption.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/security/http_error_diagnostics.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/security/http_headers.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/security/note_html.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/security/request_boundary.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/security/request_hosts.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/security/sensitive_logging.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/security/shell_execution.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/security/validation_errors.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/server_runtime.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/__init__.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/__init__.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/actions.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/cloud_privacy.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/context.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/evidence_serialization.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/history.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/inference.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/investigation.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/judging.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/menu_actions.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/model_policy.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/openai_cost_tracking.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/openai_inference.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/permissions.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/prompt_settings.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/prompts/__init__.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/prompts/final-response.md +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/prompts/help-response.md +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/prompts/system.md +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/prompts/tool-result.md +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/retrieval_settings.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/runtime.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/scope.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/skill_settings.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/skills/__init__.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/skills/help-ai.md +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/skills/help-data.md +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/skills/help-privacy.md +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/skills/help-reminders.md +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/skills/help-search.md +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/skills/help-tags.md +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/skills/scoped-investigation.md +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/skills/staged-summary.md +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/skills/tag-proposals.md +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/skills/web-browsing.md +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/staged_summary.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/structured_inference.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/tagging.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/tagging_run.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/token_estimation.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/tools.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/trace.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/web_capabilities.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/web_evidence.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/web_fetch.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/agent/web_settings.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/ai_chat.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/ai_chat_rendering.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/ai_chat_stream.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/app_update_worker.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/app_updates.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/auth.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/auth_cache_state.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/auth_service.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/backlink_index.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/backup_settings_service.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/bulk_operation.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/content_cache.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/diagnostics.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/exception_capture.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/footnote_layout.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/footnote_rendering.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/hierarchy.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/html_unformatting.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/hydration_state.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/inline_image_occurrences.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/input_errors.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/integrity.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/latex_rendering.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/login_rate_limit.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/maintenance_mode.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/markdown_rendering.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/namespace_deletion_jobs.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/namespace_deletion_worker.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/namespace_rename_jobs.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/namespace_rename_worker.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/namespace_runtime_guard.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/namespace_switcher.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/note_fullscreen.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/note_ordering.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/ontology_rules_store.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/openai_credentials.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/password_note_fields.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/public_http.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/reference_presentation.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/reminders.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/remote_image_proxy.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/resource_limits.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/runtime_generation.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/runtime_hardening.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/runtime_lock.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/search_history_storage.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/search_query.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/search_text.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/selected_text_tag.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/self_update.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/session_timeout_service.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/shell_session_service.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/structured_note_renderers.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/sync_state.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/tag_case.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/tag_ontology.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/tag_rename.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/test_reset.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/tokens.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/update_backups.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/update_installer.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/update_preflight.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/view_diff.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/view_state.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/services/windows_process_control.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/startup_environment.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/startup_js_sanity.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/startup_sanity.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/startup_sanity_config.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/css/floating-notes.css +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/css/forms.css +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/img/favicon.ico +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/locked.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/main.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/activity-tracker.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/ai-chat/agent-menu-actions.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/ai-chat/agent-prompt-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/ai-chat/agent-retrieval-settings.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/ai-chat/agent-web-settings.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/ai-chat/ai-agent-debug-view.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/ai-chat/ai-chat-api.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/ai-chat/ai-chat-message-placement.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/ai-chat/ai-chat-panel-controller.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/ai-chat/ai-chat-panel-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/ai-chat/ai-thinking-level-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/ai-chat/bulk-elapsed-clock.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/ai-chat/bulk-proposal-ui.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/ai-chat/bulk-scope-question.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/ai-chat/cloud-privacy-policy.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/ai-chat/proposal-menu.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/ai-chat/summary-batch-preview.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/api-error-diagnostics.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/api-failure-classification-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/app-update-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/application-state.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/async-result.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/auth.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/client-state-api.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/client-state-migration.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/command-palette/activation-auth-policy.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/command-palette/backup-command-availability.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/command-palette/click-activation-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/command-palette/preferences-store.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/command-palette/usage-store.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/connectivity-monitor.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/context-menu/context-menu-target-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/context-menu/input-caret-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/disconnect-editing-state-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/dom-utils-fixed.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/dom-utils.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/editor-commands.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/elapsed-time.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/error-handler.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/error-overlay.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/location-flags.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/login-namespace-picker.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/maintenance.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/agent-prompt-editor-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/ai-agent-settings-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/alphabetize-root-notes-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/backup-restore-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/backup-result-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/backup-retention-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/backup-settings-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/base-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/confirmation-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/delete-namespace-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/delete-namespace-validation.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/help-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/namespace-loading-page.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/namespace-modals.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/namespace-ports-profile.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/namespace-rename-validation.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/ontology-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/password-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/prioritize-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/random-password-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/reminder-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/reset-updated-at-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/search-suggestion-statistics-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/session-timeout-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/modals/version-info-modal.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/actions/content-actions.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/actions/history-actions.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/actions/search-actions.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/actions/selection-actions.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/events/inactivity-events.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/events/search-events.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/mode-logger.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/add-style-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/animated-scroll-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/backlinks-navigation-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/backlinks-panel-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/clipboard-shortcut-policy-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/collapse-editing-policy-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/command-gate-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/context-menu-target-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/deselect-selection-state-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/edit-session-collapse-policy-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/edit-session-collapse-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/embedded-image-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/file-drop-policy-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/file-image-preview-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/file-reference-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/filtered-refresh-selection-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/floating-note-dom.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/floating-note-layout.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/footnote-navigation-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/history-selection-policy-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/history-shortcut-policy-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/image-file-insert-choice-modal-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/link-context-menu-action-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/link-title-prefetch-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/markdown-render-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/mermaid-render-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/note-click-target-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/note-clipboard-write-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/note-collapse-animation-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/note-context-menu-action-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/note-delete-shortcut-policy-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/note-drag-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/note-reposition-animation-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/note-split-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/note-timestamp-hover-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/password-clipboard-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/reference-source-navigation-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/remote-image-proxy-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/remove-formatting-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/root-sort-indicator-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/scroll-anchor-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/scroll-restoration-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/search-contexts-overlay-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/search-debounce-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/search-input-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/search-interaction-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/search-redaction-reveal-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/search-suggestion-statistics-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/search-suggestion-window-labels-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/search-suggestion-windows-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/search-suggestions-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/search-syntax-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/selected-formatting-removal-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/selected-text-tag-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/shell-output-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/tab-dom-cache-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/tab-drag-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/tab-duplication-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/tag-bar-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/tag-input-selection-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/tag-proposal-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/todo-toggle-editing-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/untagged-view-indicator-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/mode-manager/services/view-mode-search-shortcut-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/note-html-sanitizer.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/password-generator.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/password-operation-response.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/password-policy.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/password-strength.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/reminder-store.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/reminder-surface-service.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/selection-markers.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/session-auth.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/tag-token.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/modules/uuid.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/namespace-deleted.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/namespace-renamed.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/vendor/dompurify-3.4.13.LICENSE.txt +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/vendor/dompurify-3.4.13.min.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/vendor/markdown-it-14.3.2.LICENSE.txt +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/vendor/markdown-it-14.3.2.min.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/vendor/mermaid-11.16.1.LICENSE.txt +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/vendor/mermaid-11.16.1.min.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/vendor/zxcvbn-4.4.2.LICENSE.txt +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/js/vendor/zxcvbn-4.4.2.js +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/note-html-policy.json +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/static/video/login-startup.mp4 +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/templates/base.html +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/templates/index.html +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/templates/locked.html +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/templates/maintenance.html +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/templates/namespace_deleted.html +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/templates/namespace_renamed.html +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/templates/notes_list.html +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/upload_limits.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/__init__.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/add_selected_text_tag.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/alphabetize_root_notes.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/base.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/collapse.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/copy_note.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/create_child.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/create_note.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/create_sibling.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/expand.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/indent.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/lock.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/move.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/move_to_top.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/outdent.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/paste_child.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/paste_sibling.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/prefetch_link_titles.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/prioritize.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/redo.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/reset_updated_at.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/run_shell.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/search_comment_autofill.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/search_context_tags.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/set_collapse_bulk.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/set_collapse_in_context.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/split_note.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/tag_proposals.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/toggle_reference_mode.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/toggle_todo_done.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/undo.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/unformat_content.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/usecases/update_content.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/utils/__init__.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/app/utils/encryption.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/convert-from-legacy.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/main.py +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/metalist.egg-info/dependency_links.txt +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/metalist.egg-info/entry_points.txt +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/metalist.egg-info/requires.txt +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/metalist.egg-info/top_level.txt +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/pyproject.toml +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/scripts/generate-lan-cert.sh +0 -0
- {metalist-0.9.0 → metalist-0.11.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: metalist
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.0
|
|
4
4
|
Summary: A minimalist single-user note-taking app with SSR, fast in-memory tree operations, and efficient sync.
|
|
5
5
|
Project-URL: Homepage, https://github.com/evolvingstuff/metalist
|
|
6
6
|
Project-URL: Repository, https://github.com/evolvingstuff/metalist
|
|
@@ -49,6 +49,23 @@ A minimalist single-user note-taking app focused on server-side rendering (SSR),
|
|
|
49
49
|
- Multi-tab search contexts with server-persisted scroll/search state (survives browser restarts)
|
|
50
50
|
- Manual namespace backups/restores to a user-selected backup folder with retention controls
|
|
51
51
|
|
|
52
|
+
## Changes in 0.11.0
|
|
53
|
+
|
|
54
|
+
- Large namespaces stay fast while scrolling: only a band of root notes around the viewport is loaded, the server remembers what each tab shows so the browser no longer sends note hashes, and rendered notes are cached.
|
|
55
|
+
- Tag suggestions, searches with only exclusions (`-tag`), and the updated/content-volume sort orders respond much faster on large namespaces.
|
|
56
|
+
- Accepting or removing tag proposals in bulk, renaming or deleting a tag, and undoing a large delete no longer rebuild every note's inherited tags.
|
|
57
|
+
- Unlocking an encrypted namespace is faster, and the startup encryption audit no longer loads every attachment into memory.
|
|
58
|
+
- Fixed undo of deleting a note whose children have several children, and "accept all" failing on tag bars with leading or trailing spaces.
|
|
59
|
+
- Fixed crashes in the status check after returning to a tab and in scroll-position saving.
|
|
60
|
+
|
|
61
|
+
## Changes in 0.10.0
|
|
62
|
+
|
|
63
|
+
- Excalidraw diagrams: add one from the note's right-click menu or the command palette, and double-click a diagram to edit it full screen. Diagrams autosave, show light and dark previews, resize like images, and each editing session is one undo step. The editor is bundled locally and needs no Node server.
|
|
64
|
+
- The dark theme uses neutral greys with a brighter accent, the light theme header is darker, and Note Layout & Appearance adds note corner and tag style settings.
|
|
65
|
+
- References to a note that starts with an image or diagram show its thumbnail. Collapsed notes, reference titles, and backlink previews show only the first line.
|
|
66
|
+
- Fixed a command palette crash on queries with no matches.
|
|
67
|
+
- The database schema moves to version 10. Password-protected namespaces migrate after unlock, with the usual automatic backup first.
|
|
68
|
+
|
|
52
69
|
## Changes in 0.9.0
|
|
53
70
|
|
|
54
71
|
- AI chat can browse the web in disabled, contextual, or unrestricted mode, fetch multiple pages concurrently, and cite the specific pages used as evidence.
|
|
@@ -12,6 +12,23 @@ A minimalist single-user note-taking app focused on server-side rendering (SSR),
|
|
|
12
12
|
- Multi-tab search contexts with server-persisted scroll/search state (survives browser restarts)
|
|
13
13
|
- Manual namespace backups/restores to a user-selected backup folder with retention controls
|
|
14
14
|
|
|
15
|
+
## Changes in 0.11.0
|
|
16
|
+
|
|
17
|
+
- Large namespaces stay fast while scrolling: only a band of root notes around the viewport is loaded, the server remembers what each tab shows so the browser no longer sends note hashes, and rendered notes are cached.
|
|
18
|
+
- Tag suggestions, searches with only exclusions (`-tag`), and the updated/content-volume sort orders respond much faster on large namespaces.
|
|
19
|
+
- Accepting or removing tag proposals in bulk, renaming or deleting a tag, and undoing a large delete no longer rebuild every note's inherited tags.
|
|
20
|
+
- Unlocking an encrypted namespace is faster, and the startup encryption audit no longer loads every attachment into memory.
|
|
21
|
+
- Fixed undo of deleting a note whose children have several children, and "accept all" failing on tag bars with leading or trailing spaces.
|
|
22
|
+
- Fixed crashes in the status check after returning to a tab and in scroll-position saving.
|
|
23
|
+
|
|
24
|
+
## Changes in 0.10.0
|
|
25
|
+
|
|
26
|
+
- Excalidraw diagrams: add one from the note's right-click menu or the command palette, and double-click a diagram to edit it full screen. Diagrams autosave, show light and dark previews, resize like images, and each editing session is one undo step. The editor is bundled locally and needs no Node server.
|
|
27
|
+
- The dark theme uses neutral greys with a brighter accent, the light theme header is darker, and Note Layout & Appearance adds note corner and tag style settings.
|
|
28
|
+
- References to a note that starts with an image or diagram show its thumbnail. Collapsed notes, reference titles, and backlink previews show only the first line.
|
|
29
|
+
- Fixed a command palette crash on queries with no matches.
|
|
30
|
+
- The database schema moves to version 10. Password-protected namespaces migrate after unlock, with the usual automatic backup first.
|
|
31
|
+
|
|
15
32
|
## Changes in 0.9.0
|
|
16
33
|
|
|
17
34
|
- AI chat can browse the web in disabled, contextual, or unrestricted mode, fetch multiple pages concurrently, and cite the specific pages used as evidence.
|
|
@@ -37,11 +37,6 @@ class AuthMiddleware(BaseHTTPMiddleware):
|
|
|
37
37
|
)
|
|
38
38
|
assert all(path.endswith("/") for path in PUBLIC_PREFIX_PATHS)
|
|
39
39
|
|
|
40
|
-
# Paths to suppress verbose logging for (frequent polling endpoints)
|
|
41
|
-
QUIET_PATHS = [
|
|
42
|
-
f"{API_PREFIX}/auth/status",
|
|
43
|
-
]
|
|
44
|
-
|
|
45
40
|
# Background/automated paths that should NOT refresh tokens (not user activity)
|
|
46
41
|
NO_TOKEN_REFRESH_PATHS = [
|
|
47
42
|
f"{API_PREFIX}/auth/status", # Polling service pings this for connectivity
|
|
@@ -75,20 +70,9 @@ class AuthMiddleware(BaseHTTPMiddleware):
|
|
|
75
70
|
# Redirect all other requests to maintenance page
|
|
76
71
|
return RedirectResponse(url="/maintenance", status_code=302)
|
|
77
72
|
|
|
78
|
-
# Check if this is a quiet path (suppress verbose logging)
|
|
79
|
-
is_quiet = any(path.startswith(quiet) for quiet in self.QUIET_PATHS)
|
|
80
|
-
|
|
81
|
-
if not is_quiet:
|
|
82
|
-
print(f"Middleware checking path: {path}")
|
|
83
|
-
|
|
84
73
|
if self.is_public_path(path=path):
|
|
85
|
-
if not is_quiet:
|
|
86
|
-
print(f"Path {path} is explicitly public, skipping auth")
|
|
87
74
|
return await call_next(request)
|
|
88
75
|
|
|
89
|
-
if not is_quiet:
|
|
90
|
-
print(f"Path {path} is NOT public, checking auth")
|
|
91
|
-
|
|
92
76
|
# Startup and recoverable password transitions publish this memory-owned flag.
|
|
93
77
|
if path == f"{API_PREFIX}/auth/settings/password/create" and not is_encryption_required():
|
|
94
78
|
return await call_next(request)
|
|
@@ -56,8 +56,9 @@ class ViewDiffRequest(TypedDict):
|
|
|
56
56
|
search: Text | None
|
|
57
57
|
tabId: Identifier
|
|
58
58
|
undoContext: UndoContext
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
tabViewEmpty: bool
|
|
60
|
+
visibleTopRootId: Text | None
|
|
61
|
+
visibleBottomRootId: Text | None
|
|
61
62
|
isUntaggedView: bool
|
|
62
63
|
|
|
63
64
|
@with_config(ConfigDict(strict=True))
|
|
@@ -76,6 +77,7 @@ class UpdateTabSortModeRequest(TypedDict):
|
|
|
76
77
|
@with_config(ConfigDict(strict=True))
|
|
77
78
|
class CreateNewTabRequest(TypedDict):
|
|
78
79
|
copyFromTabId: Identifier
|
|
80
|
+
clientId: Identifier
|
|
79
81
|
|
|
80
82
|
@with_config(ConfigDict(strict=True))
|
|
81
83
|
class DeleteTabRequest(TypedDict):
|
|
@@ -206,6 +208,19 @@ class ResizeNoteImageRequest(TypedDict):
|
|
|
206
208
|
undoContext: UndoContext
|
|
207
209
|
viewport: Viewport
|
|
208
210
|
|
|
211
|
+
@with_config(ConfigDict(strict=True))
|
|
212
|
+
class FinishFileEditSessionRequest(TypedDict):
|
|
213
|
+
clientId: Identifier
|
|
214
|
+
hostNoteId: Identifier
|
|
215
|
+
contentRevision: Annotated[int, Field(ge=1)]
|
|
216
|
+
isNewDiagram: bool
|
|
217
|
+
undoContext: UndoContext
|
|
218
|
+
viewport: Viewport
|
|
219
|
+
|
|
220
|
+
@with_config(ConfigDict(strict=True))
|
|
221
|
+
class DiscardFileEditSessionRequest(TypedDict):
|
|
222
|
+
contentRevision: Annotated[int, Field(ge=1)]
|
|
223
|
+
|
|
209
224
|
@with_config(ConfigDict(strict=True))
|
|
210
225
|
class RunShellEndpointRequest(TypedDict):
|
|
211
226
|
timeoutSeconds: Annotated[int, Field(ge=0, le=SHELL_SECONDS)]
|
|
@@ -713,7 +713,8 @@ def auth_status(
|
|
|
713
713
|
"version": VERSION,
|
|
714
714
|
"database_user_version": database_user_version,
|
|
715
715
|
"authenticated": token is not None,
|
|
716
|
-
|
|
716
|
+
# Same answer as AuthService.has_password(), from the row already read.
|
|
717
|
+
"has_password": settings is not None and bool(settings.encryption_enabled),
|
|
717
718
|
"encryption_enabled": settings.encryption_enabled if settings else False,
|
|
718
719
|
"encryption_algorithm": settings.encryption_algorithm if settings else None,
|
|
719
720
|
"vault_version": settings.vault_version if settings else None,
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from io import BytesIO
|
|
4
|
+
from typing import Annotated
|
|
5
|
+
from urllib.parse import quote
|
|
6
|
+
|
|
7
|
+
from fastapi import APIRouter, File, Form, HTTPException, Request, UploadFile
|
|
8
|
+
from fastapi.responses import Response, StreamingResponse
|
|
9
|
+
from pydantic import BaseModel
|
|
10
|
+
|
|
11
|
+
from app.api.note_requests import DiscardFileEditSessionRequest, FinishFileEditSessionRequest
|
|
12
|
+
from app.api.transactions import transactional_route
|
|
13
|
+
from app.api.upload_limits import read_attachment
|
|
14
|
+
from app.api.request_auth import require_request_auth_token
|
|
15
|
+
from app.services.file_registry import file_registry
|
|
16
|
+
from app.services.note_store import store as note_store
|
|
17
|
+
from app.db.file_schema import FILE_PREVIEW_VARIANTS
|
|
18
|
+
from app.services.file_storage import (
|
|
19
|
+
create_file,
|
|
20
|
+
download_file,
|
|
21
|
+
get_file_preview,
|
|
22
|
+
replace_file_content,
|
|
23
|
+
store_file_previews,
|
|
24
|
+
trim_unused_files,
|
|
25
|
+
)
|
|
26
|
+
from app.usecases.file_edit_session import (
|
|
27
|
+
CmdDiscardFileEditSession,
|
|
28
|
+
CmdFinishFileEditSession,
|
|
29
|
+
CmdStartFileEditSession,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
router = APIRouter(prefix="/files", tags=["files"])
|
|
33
|
+
|
|
34
|
+
FILE_REVISION_HEADER = "X-MetaList-File-Revision"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class UploadedFileResponse(BaseModel):
|
|
38
|
+
file_id: str
|
|
39
|
+
reference_token: str
|
|
40
|
+
title: str
|
|
41
|
+
original_filename: str
|
|
42
|
+
mime_type: str
|
|
43
|
+
size_bytes: int
|
|
44
|
+
thumbnail_kind: str
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class FileContentUpdatedResponse(BaseModel):
|
|
48
|
+
file_id: str
|
|
49
|
+
content_revision: int
|
|
50
|
+
size_bytes: int
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class FilePreviewsStoredResponse(BaseModel):
|
|
54
|
+
file_id: str
|
|
55
|
+
content_revision: int
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class TrimUnusedFilesResponse(BaseModel):
|
|
59
|
+
deleted_count: int
|
|
60
|
+
deleted_file_ids: list[str]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _require_bearer_token(request: Request) -> str:
|
|
64
|
+
return require_request_auth_token(request)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _require_known_file(file_id: str) -> None:
|
|
68
|
+
if not file_registry.has_file(file_id):
|
|
69
|
+
raise HTTPException(status_code=404, detail=f"File not found: {file_id}")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@router.post("/upload", response_model=UploadedFileResponse)
|
|
73
|
+
@transactional_route
|
|
74
|
+
async def upload_file_endpoint(
|
|
75
|
+
request: Request,
|
|
76
|
+
file: Annotated[UploadFile, File()],
|
|
77
|
+
):
|
|
78
|
+
token = _require_bearer_token(request)
|
|
79
|
+
if not isinstance(file.filename, str) or file.filename == "":
|
|
80
|
+
raise HTTPException(status_code=400, detail="Uploaded file must include a filename")
|
|
81
|
+
if not isinstance(file.content_type, str) or file.content_type == "":
|
|
82
|
+
raise HTTPException(status_code=400, detail="Uploaded file must include a non-empty MIME type")
|
|
83
|
+
|
|
84
|
+
content_bytes = await read_attachment(file)
|
|
85
|
+
|
|
86
|
+
record = create_file(
|
|
87
|
+
original_filename=file.filename,
|
|
88
|
+
mime_type=file.content_type,
|
|
89
|
+
content_bytes=content_bytes,
|
|
90
|
+
token=token,
|
|
91
|
+
)
|
|
92
|
+
return UploadedFileResponse(
|
|
93
|
+
file_id=record.id,
|
|
94
|
+
reference_token=f"![[{record.id}]]",
|
|
95
|
+
title=record.title,
|
|
96
|
+
original_filename=record.original_filename,
|
|
97
|
+
mime_type=record.mime_type,
|
|
98
|
+
size_bytes=record.size_bytes,
|
|
99
|
+
thumbnail_kind=record.thumbnail_kind,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@router.get("/{file_id}/download")
|
|
104
|
+
def download_file_endpoint(request: Request, file_id: str):
|
|
105
|
+
token = _require_bearer_token(request)
|
|
106
|
+
if not file_registry.has_file(file_id):
|
|
107
|
+
raise HTTPException(status_code=404, detail=f"File not found: {file_id}")
|
|
108
|
+
|
|
109
|
+
downloaded = download_file(file_id, token)
|
|
110
|
+
quoted_filename = quote(downloaded.record.original_filename, safe="")
|
|
111
|
+
return StreamingResponse(
|
|
112
|
+
BytesIO(downloaded.content_bytes),
|
|
113
|
+
media_type=downloaded.record.mime_type,
|
|
114
|
+
headers={
|
|
115
|
+
"Content-Disposition": f"attachment; filename*=UTF-8''{quoted_filename}",
|
|
116
|
+
FILE_REVISION_HEADER: str(downloaded.record.content_revision),
|
|
117
|
+
},
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@router.put("/{file_id}/content", response_model=FileContentUpdatedResponse)
|
|
122
|
+
@transactional_route
|
|
123
|
+
async def replace_file_content_endpoint(
|
|
124
|
+
request: Request,
|
|
125
|
+
file_id: str,
|
|
126
|
+
file: Annotated[UploadFile, File()],
|
|
127
|
+
expected_revision: Annotated[int, Form()],
|
|
128
|
+
):
|
|
129
|
+
token = _require_bearer_token(request)
|
|
130
|
+
_require_known_file(file_id)
|
|
131
|
+
content_bytes = await read_attachment(file)
|
|
132
|
+
record = replace_file_content(
|
|
133
|
+
file_id=file_id,
|
|
134
|
+
content_bytes=content_bytes,
|
|
135
|
+
expected_revision=expected_revision,
|
|
136
|
+
token=token,
|
|
137
|
+
)
|
|
138
|
+
return FileContentUpdatedResponse(
|
|
139
|
+
file_id=record.id,
|
|
140
|
+
content_revision=record.content_revision,
|
|
141
|
+
size_bytes=record.size_bytes,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@router.put("/{file_id}/previews", response_model=FilePreviewsStoredResponse)
|
|
146
|
+
@transactional_route
|
|
147
|
+
async def store_file_previews_endpoint(
|
|
148
|
+
request: Request,
|
|
149
|
+
file_id: str,
|
|
150
|
+
light: Annotated[UploadFile, File()],
|
|
151
|
+
dark: Annotated[UploadFile, File()],
|
|
152
|
+
content_revision: Annotated[int, Form()],
|
|
153
|
+
):
|
|
154
|
+
token = _require_bearer_token(request)
|
|
155
|
+
_require_known_file(file_id)
|
|
156
|
+
previews_by_variant = {
|
|
157
|
+
"light": await read_attachment(light),
|
|
158
|
+
"dark": await read_attachment(dark),
|
|
159
|
+
}
|
|
160
|
+
record = store_file_previews(
|
|
161
|
+
file_id=file_id,
|
|
162
|
+
previews_by_variant=previews_by_variant,
|
|
163
|
+
content_revision=content_revision,
|
|
164
|
+
token=token,
|
|
165
|
+
)
|
|
166
|
+
return FilePreviewsStoredResponse(file_id=record.id, content_revision=record.content_revision)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
@router.get("/{file_id}/previews/{variant}")
|
|
170
|
+
def download_file_preview_endpoint(request: Request, file_id: str, variant: str):
|
|
171
|
+
token = _require_bearer_token(request)
|
|
172
|
+
_require_known_file(file_id)
|
|
173
|
+
if variant not in FILE_PREVIEW_VARIANTS:
|
|
174
|
+
raise HTTPException(status_code=404, detail=f"Unknown preview variant: {variant}")
|
|
175
|
+
preview = get_file_preview(file_id=file_id, variant=variant, token=token)
|
|
176
|
+
return Response(
|
|
177
|
+
content=preview.content_bytes,
|
|
178
|
+
media_type=preview.mime_type,
|
|
179
|
+
headers={FILE_REVISION_HEADER: str(preview.content_revision)},
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
# A diagram editing session: opened with the editor, finished by Done (one undo step), or discarded.
|
|
184
|
+
@router.post("/{file_id}/edit-sessions")
|
|
185
|
+
@transactional_route
|
|
186
|
+
def start_file_edit_session_endpoint(request: Request, file_id: str) -> dict[str, object]:
|
|
187
|
+
token = _require_bearer_token(request)
|
|
188
|
+
_require_known_file(file_id)
|
|
189
|
+
return CmdStartFileEditSession(file_id=file_id, token=token).execute()
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
@router.post("/{file_id}/edit-sessions/{session_id}/finish")
|
|
193
|
+
@transactional_route
|
|
194
|
+
def finish_file_edit_session_endpoint(
|
|
195
|
+
request: Request,
|
|
196
|
+
file_id: str,
|
|
197
|
+
session_id: str,
|
|
198
|
+
body: FinishFileEditSessionRequest,
|
|
199
|
+
) -> dict[str, object]:
|
|
200
|
+
token = _require_bearer_token(request)
|
|
201
|
+
_require_known_file(file_id)
|
|
202
|
+
host_note_id = body["hostNoteId"]
|
|
203
|
+
if not note_store.has_note(host_note_id):
|
|
204
|
+
raise HTTPException(status_code=404, detail=f"Note not found: {host_note_id}")
|
|
205
|
+
return CmdFinishFileEditSession(
|
|
206
|
+
file_id=file_id,
|
|
207
|
+
session_id=session_id,
|
|
208
|
+
host_note_id=host_note_id,
|
|
209
|
+
content_revision=body["contentRevision"],
|
|
210
|
+
is_new_diagram=body["isNewDiagram"],
|
|
211
|
+
token=token,
|
|
212
|
+
client_id=body["clientId"],
|
|
213
|
+
undo_context=body["undoContext"],
|
|
214
|
+
viewport=body["viewport"],
|
|
215
|
+
).execute()
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
@router.post("/{file_id}/edit-sessions/{session_id}/discard")
|
|
219
|
+
@transactional_route
|
|
220
|
+
def discard_file_edit_session_endpoint(
|
|
221
|
+
request: Request,
|
|
222
|
+
file_id: str,
|
|
223
|
+
session_id: str,
|
|
224
|
+
body: DiscardFileEditSessionRequest,
|
|
225
|
+
) -> dict[str, object]:
|
|
226
|
+
token = _require_bearer_token(request)
|
|
227
|
+
_require_known_file(file_id)
|
|
228
|
+
return CmdDiscardFileEditSession(
|
|
229
|
+
file_id=file_id,
|
|
230
|
+
session_id=session_id,
|
|
231
|
+
content_revision=body["contentRevision"],
|
|
232
|
+
token=token,
|
|
233
|
+
).execute()
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
@router.post("/trim-unused", response_model=TrimUnusedFilesResponse)
|
|
237
|
+
@transactional_route
|
|
238
|
+
def trim_unused_files_endpoint(request: Request):
|
|
239
|
+
_require_bearer_token(request)
|
|
240
|
+
result = trim_unused_files()
|
|
241
|
+
return TrimUnusedFilesResponse(
|
|
242
|
+
deleted_count=result.deleted_count,
|
|
243
|
+
deleted_file_ids=result.deleted_file_ids,
|
|
244
|
+
)
|
|
@@ -241,16 +241,16 @@ def view_diff(payload: ViewDiffRequest):
|
|
|
241
241
|
search = payload["search"]
|
|
242
242
|
tab_id = payload["tabId"]
|
|
243
243
|
undo_context = payload["undoContext"]
|
|
244
|
-
|
|
245
|
-
|
|
244
|
+
tab_view_empty = payload["tabViewEmpty"]
|
|
245
|
+
visible_top_root_id = payload["visibleTopRootId"]
|
|
246
|
+
visible_bottom_root_id = payload["visibleBottomRootId"]
|
|
246
247
|
is_untagged_view = payload["isUntaggedView"]
|
|
247
248
|
if not isinstance(is_untagged_view, bool):
|
|
248
249
|
raise TypeError("isUntaggedView must be a boolean")
|
|
250
|
+
if not isinstance(tab_view_empty, bool):
|
|
251
|
+
raise TypeError("tabViewEmpty must be a boolean")
|
|
249
252
|
|
|
250
253
|
sort_mode = _resolve_tab_sort_mode(tab_id)
|
|
251
|
-
if not isinstance(client_note_uuid_hashes, dict):
|
|
252
|
-
raise TypeError("clientNoteUuidHashes must be an object")
|
|
253
|
-
|
|
254
254
|
normalized_search = search
|
|
255
255
|
if isinstance(normalized_search, str) and normalized_search == "":
|
|
256
256
|
normalized_search = None
|
|
@@ -278,164 +278,58 @@ def view_diff(payload: ViewDiffRequest):
|
|
|
278
278
|
if not note_store.has_note(normalized_editing_note_id):
|
|
279
279
|
normalized_editing_note_id = None
|
|
280
280
|
|
|
281
|
-
#
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
"sort_mode": sort_mode,
|
|
291
|
-
"is_untagged_view": is_untagged_view,
|
|
292
|
-
}
|
|
293
|
-
cached_state = view_cache.get(**cache_key)
|
|
294
|
-
if not anchor_root_id and cached_state and client_hashes:
|
|
295
|
-
last_roots = list(cached_state.children_by_parent.get(None, []))
|
|
296
|
-
if last_roots:
|
|
297
|
-
anchor_root_id = last_roots[-1]
|
|
281
|
+
# The server keeps each tab's warm view (what that browser tab displays),
|
|
282
|
+
# so the browser sends only where it is. A tab with no warm view, or one
|
|
283
|
+
# whose browser shows nothing for it, gets its initial window.
|
|
284
|
+
warm_view = view_cache.get(client_id=client_id, tab_id=tab_id)
|
|
285
|
+
if tab_view_empty:
|
|
286
|
+
warm_view = None
|
|
287
|
+
client_known_note_ids: set[str] = set()
|
|
288
|
+
if warm_view is not None:
|
|
289
|
+
client_known_note_ids = set(warm_view.hash_by_id)
|
|
298
290
|
|
|
299
291
|
state = build_view_state(
|
|
300
292
|
editing_note_id=normalized_editing_note_id,
|
|
301
293
|
search=normalized_search,
|
|
302
294
|
sort_mode=sort_mode,
|
|
303
|
-
client_known_note_ids=
|
|
304
|
-
|
|
305
|
-
|
|
295
|
+
client_known_note_ids=client_known_note_ids,
|
|
296
|
+
visible_top_root_id=visible_top_root_id,
|
|
297
|
+
visible_bottom_root_id=visible_bottom_root_id,
|
|
306
298
|
is_untagged_view=is_untagged_view,
|
|
307
299
|
)
|
|
308
300
|
update_uuid = get_current_sync_uuid()
|
|
309
301
|
root_ids = list(state.children_by_parent.get(None, []))
|
|
310
|
-
|
|
311
|
-
search_root_count_total = state.metadata["searchRootCountTotal"]
|
|
312
|
-
|
|
313
|
-
client_note_ids = set(client_hashes.keys())
|
|
314
|
-
current_note_ids = set(state.hash_by_id.keys())
|
|
315
|
-
if cached_state is None:
|
|
316
|
-
cached_note_ids = set()
|
|
317
|
-
else:
|
|
318
|
-
cached_note_ids = set(cached_state.hash_by_id.keys())
|
|
319
|
-
extra_client_ids = _unknown_client_note_ids(
|
|
320
|
-
client_note_ids=client_note_ids,
|
|
321
|
-
current_note_ids=current_note_ids,
|
|
322
|
-
cached_note_ids=cached_note_ids,
|
|
323
|
-
)
|
|
324
|
-
force_full_snapshot = bool(extra_client_ids)
|
|
325
|
-
if force_full_snapshot:
|
|
326
|
-
logger.info(
|
|
327
|
-
"notes.view forcing full snapshot (client has unknown ids): extra_count=%s",
|
|
328
|
-
len(extra_client_ids),
|
|
329
|
-
)
|
|
330
|
-
|
|
331
|
-
client_has_state = bool(client_hashes)
|
|
332
|
-
|
|
333
|
-
if not cached_state or force_full_snapshot:
|
|
334
|
-
view_cache.set(state=state, **cache_key)
|
|
335
|
-
if force_full_snapshot:
|
|
336
|
-
filtered_notes = dict(state.payloads)
|
|
337
|
-
else:
|
|
338
|
-
filtered_notes = {
|
|
339
|
-
note_id: data
|
|
340
|
-
for note_id, data in state.payloads.items()
|
|
341
|
-
if client_hashes.get(note_id) != data.get("hash")
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
# Optimization: when the server cache is cold but the client already has a
|
|
345
|
-
# complete, matching hash map for the visible window, avoid resending the
|
|
346
|
-
# full structure + note payloads. This is common when a new tab is created
|
|
347
|
-
# by cloning the existing DOM.
|
|
348
|
-
if client_has_state and not filtered_notes and not force_full_snapshot:
|
|
349
|
-
response_snapshot = {
|
|
350
|
-
"diffOps": [],
|
|
351
|
-
"notes": {},
|
|
352
|
-
"locks": state.locks,
|
|
353
|
-
"rootIds": root_ids,
|
|
354
|
-
"lockDiffs": {},
|
|
355
|
-
"updateUUID": update_uuid,
|
|
356
|
-
"version": VERSION,
|
|
357
|
-
"currentClientId": client_id,
|
|
358
|
-
"searchQuery": search,
|
|
359
|
-
"sortMode": sort_mode,
|
|
360
|
-
"isUntaggedView": is_untagged_view,
|
|
361
|
-
"rootCountTotal": root_count_total,
|
|
362
|
-
"searchRootCountTotal": search_root_count_total,
|
|
363
|
-
"rootSortBuckets": state.metadata["rootSortBuckets"],
|
|
364
|
-
"editingNoteId": normalized_editing_note_id,
|
|
365
|
-
}
|
|
366
|
-
return {"snapshot": response_snapshot, "updateUUID": update_uuid}
|
|
367
|
-
|
|
368
|
-
response_snapshot = {
|
|
369
|
-
"structure": state.structure,
|
|
370
|
-
"notes": filtered_notes,
|
|
371
|
-
"locks": state.locks,
|
|
372
|
-
"rootIds": root_ids,
|
|
373
|
-
"updateUUID": update_uuid,
|
|
374
|
-
"version": VERSION,
|
|
375
|
-
"currentClientId": client_id,
|
|
376
|
-
"searchQuery": search,
|
|
377
|
-
"sortMode": sort_mode,
|
|
378
|
-
"isUntaggedView": is_untagged_view,
|
|
379
|
-
"rootCountTotal": root_count_total,
|
|
380
|
-
"searchRootCountTotal": search_root_count_total,
|
|
381
|
-
"rootSortBuckets": state.metadata["rootSortBuckets"],
|
|
382
|
-
"editingNoteId": normalized_editing_note_id,
|
|
383
|
-
}
|
|
384
|
-
return {"snapshot": response_snapshot, "updateUUID": update_uuid}
|
|
385
|
-
|
|
386
|
-
if not client_has_state:
|
|
387
|
-
view_cache.set(state=state, **cache_key)
|
|
388
|
-
filtered_notes = {
|
|
389
|
-
note_id: data
|
|
390
|
-
for note_id, data in state.payloads.items()
|
|
391
|
-
if client_hashes.get(note_id) != data.get("hash")
|
|
392
|
-
}
|
|
393
|
-
response_snapshot = {
|
|
394
|
-
"structure": state.structure,
|
|
395
|
-
"notes": filtered_notes,
|
|
396
|
-
"locks": state.locks,
|
|
397
|
-
"rootIds": root_ids,
|
|
398
|
-
"updateUUID": update_uuid,
|
|
399
|
-
"version": VERSION,
|
|
400
|
-
"currentClientId": client_id,
|
|
401
|
-
"searchQuery": search,
|
|
402
|
-
"sortMode": sort_mode,
|
|
403
|
-
"isUntaggedView": is_untagged_view,
|
|
404
|
-
"rootCountTotal": root_count_total,
|
|
405
|
-
"searchRootCountTotal": search_root_count_total,
|
|
406
|
-
"rootSortBuckets": state.metadata["rootSortBuckets"],
|
|
407
|
-
"editingNoteId": normalized_editing_note_id,
|
|
408
|
-
}
|
|
409
|
-
return {"snapshot": response_snapshot, "updateUUID": update_uuid}
|
|
410
|
-
|
|
411
|
-
diff_ops = generate_diff_ops(cached_state, state)
|
|
412
|
-
note_updates = {
|
|
413
|
-
note_id: payload
|
|
414
|
-
for note_id, payload in state.payloads.items()
|
|
415
|
-
if cached_state.hash_by_id.get(note_id) != payload["hash"]
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
view_cache.set(state=state, **cache_key)
|
|
419
|
-
|
|
420
|
-
lock_diff = _compute_lock_diff(cached_state.locks, state.locks)
|
|
421
|
-
|
|
302
|
+
view_cache.set(client_id=client_id, tab_id=tab_id, state=state)
|
|
422
303
|
response_snapshot = {
|
|
423
|
-
"
|
|
424
|
-
"notes": note_updates,
|
|
304
|
+
"notes": {},
|
|
425
305
|
"locks": state.locks,
|
|
426
306
|
"rootIds": root_ids,
|
|
427
|
-
"lockDiffs": lock_diff,
|
|
428
307
|
"updateUUID": update_uuid,
|
|
429
308
|
"version": VERSION,
|
|
430
309
|
"currentClientId": client_id,
|
|
431
310
|
"searchQuery": search,
|
|
432
311
|
"sortMode": sort_mode,
|
|
433
312
|
"isUntaggedView": is_untagged_view,
|
|
434
|
-
"rootCountTotal":
|
|
435
|
-
"searchRootCountTotal":
|
|
313
|
+
"rootCountTotal": state.metadata["rootCountTotal"],
|
|
314
|
+
"searchRootCountTotal": state.metadata["searchRootCountTotal"],
|
|
436
315
|
"rootSortBuckets": state.metadata["rootSortBuckets"],
|
|
316
|
+
"rootWindowStart": state.metadata["rootWindowStart"],
|
|
317
|
+
"rootBandMargin": state.metadata["rootBandMargin"],
|
|
318
|
+
"rootSortKeyBeforeWindow": state.metadata["rootSortKeyBeforeWindow"],
|
|
437
319
|
"editingNoteId": normalized_editing_note_id,
|
|
438
320
|
}
|
|
321
|
+
if warm_view is None:
|
|
322
|
+
response_snapshot["structure"] = state.structure
|
|
323
|
+
response_snapshot["notes"] = dict(state.payloads)
|
|
324
|
+
return {"snapshot": response_snapshot, "updateUUID": update_uuid}
|
|
325
|
+
|
|
326
|
+
response_snapshot["diffOps"] = generate_diff_ops(warm_view, state)
|
|
327
|
+
response_snapshot["notes"] = {
|
|
328
|
+
note_id: note_payload
|
|
329
|
+
for note_id, note_payload in state.payloads.items()
|
|
330
|
+
if note_id not in warm_view.hash_by_id or warm_view.hash_by_id[note_id] != note_payload["hash"]
|
|
331
|
+
}
|
|
332
|
+
response_snapshot["lockDiffs"] = _compute_lock_diff(warm_view.locks, state.locks)
|
|
439
333
|
return {"snapshot": response_snapshot, "updateUUID": update_uuid}
|
|
440
334
|
|
|
441
335
|
|
|
@@ -501,6 +395,11 @@ def create_new_tab(payload: CreateNewTabRequest) -> Dict[str, object]:
|
|
|
501
395
|
response = tab_state_store.create_tab(copy_from_tab_id=copy_from_tab_id)
|
|
502
396
|
if capture.captured_exception is not None:
|
|
503
397
|
raise HTTPException(status_code=400, detail="Invalid or stale tab state") from capture.captured_exception
|
|
398
|
+
# The browser clones the source tab's DOM into the new tab, so the new tab
|
|
399
|
+
# starts from the source tab's warm view.
|
|
400
|
+
view_cache.copy_tab(
|
|
401
|
+
client_id=payload["clientId"], source_tab_id=copy_from_tab_id, target_tab_id=response["newTabId"],
|
|
402
|
+
)
|
|
504
403
|
return response
|
|
505
404
|
|
|
506
405
|
|
|
@@ -790,16 +689,6 @@ def _compute_lock_diff(previous: Dict[str, str], current: Dict[str, str]) -> Dic
|
|
|
790
689
|
return diff
|
|
791
690
|
|
|
792
691
|
|
|
793
|
-
def _unknown_client_note_ids(
|
|
794
|
-
*,
|
|
795
|
-
client_note_ids: set[str],
|
|
796
|
-
current_note_ids: set[str],
|
|
797
|
-
cached_note_ids: set[str],
|
|
798
|
-
) -> set[str]:
|
|
799
|
-
stale_deleted_ids = client_note_ids - current_note_ids
|
|
800
|
-
return stale_deleted_ids - cached_note_ids
|
|
801
|
-
|
|
802
|
-
|
|
803
692
|
# Stub endpoints for the rest of the notes API (501 Not Implemented)
|
|
804
693
|
|
|
805
694
|
def _not_impl(exc: Exception) -> None:
|
|
@@ -11,7 +11,6 @@ from app.api.transactions import transactional_route
|
|
|
11
11
|
from app.services.search_index import search_index
|
|
12
12
|
from app.services.note_store import store as note_store
|
|
13
13
|
from app.services.sync import generate_new_uuid
|
|
14
|
-
from app.services.view_cache import view_cache
|
|
15
14
|
from app.services.tag_ontology import RegexAtom, TagAtom, TextAtom, parse_rules_text
|
|
16
15
|
from app.services.ontology_rules_store import (
|
|
17
16
|
build_direct_edge_rule_map,
|
|
@@ -155,7 +154,6 @@ def create_rule(request: Request, payload: RuleTextRequest) -> dict:
|
|
|
155
154
|
rule_id, normalized = create_rule_line(text=text, token=token)
|
|
156
155
|
if note_store.loaded:
|
|
157
156
|
note_store.rebuild_search_index_tag_terms_for_notes(candidate_note_ids)
|
|
158
|
-
view_cache.clear()
|
|
159
157
|
update_uuid = generate_new_uuid()
|
|
160
158
|
return {"id": rule_id, "text": normalized, "updateUUID": update_uuid}
|
|
161
159
|
return {"id": rule_id, "text": normalized}
|
|
@@ -193,7 +191,6 @@ def update_rule(request: Request, rule_id: int, payload: RuleTextRequest) -> dic
|
|
|
193
191
|
updated_id, normalized = update_rule_line(rule_id=rule_id, text=text, token=token)
|
|
194
192
|
if note_store.loaded:
|
|
195
193
|
note_store.rebuild_search_index_tag_terms_for_notes(candidate_note_ids)
|
|
196
|
-
view_cache.clear()
|
|
197
194
|
update_uuid = generate_new_uuid()
|
|
198
195
|
return {"id": updated_id, "text": normalized, "updateUUID": update_uuid}
|
|
199
196
|
return {"id": updated_id, "text": normalized}
|
|
@@ -224,7 +221,6 @@ def delete_rule(rule_id: int) -> dict:
|
|
|
224
221
|
delete_rule_line(rule_id=rule_id)
|
|
225
222
|
if note_store.loaded:
|
|
226
223
|
note_store.rebuild_search_index_tag_terms_for_notes(candidate_note_ids)
|
|
227
|
-
view_cache.clear()
|
|
228
224
|
update_uuid = generate_new_uuid()
|
|
229
225
|
return {"ok": True, "updateUUID": update_uuid}
|
|
230
226
|
return {"ok": True}
|