MetaList 0.10.0__tar.gz → 0.12.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.10.0 → metalist-0.12.0}/PKG-INFO +20 -1
- {metalist-0.10.0 → metalist-0.12.0}/README.md +19 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/api/middleware/auth.py +0 -16
- {metalist-0.10.0 → metalist-0.12.0}/app/api/note_requests.py +4 -2
- {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/ai.py +8 -57
- {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/auth.py +2 -1
- {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/notes.py +49 -158
- {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/ontology.py +0 -4
- {metalist-0.10.0 → metalist-0.12.0}/app/api/transactions.py +3 -1
- {metalist-0.10.0 → metalist-0.12.0}/app/db/notes_sql.py +9 -8
- {metalist-0.10.0 → metalist-0.12.0}/app/encryption_audit.py +11 -2
- {metalist-0.10.0 → metalist-0.12.0}/app/exception_boundaries.py +3 -1
- {metalist-0.10.0 → metalist-0.12.0}/app/main.py +8 -1
- {metalist-0.10.0 → metalist-0.12.0}/app/models/utils.py +4 -1
- metalist-0.12.0/app/security/sensitive_cache.py +116 -0
- metalist-0.12.0/app/services/agent/agent_loop.py +556 -0
- metalist-0.12.0/app/services/agent/agent_tools.py +464 -0
- metalist-0.12.0/app/services/agent/citation_tokens.py +62 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/context.py +59 -258
- metalist-0.12.0/app/services/agent/execution_errors.py +7 -0
- metalist-0.12.0/app/services/agent/failure_explanations.py +164 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/help_catalog.py +2 -21
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/history.py +19 -1
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/inference.py +29 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/investigation.py +67 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/model_policy.py +1 -2
- metalist-0.12.0/app/services/agent/note_aliases.py +77 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/openai_inference.py +169 -1
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/prompt_settings.py +8 -49
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/prompts/__init__.py +1 -1
- metalist-0.12.0/app/services/agent/prompts/agent.md +125 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/prompts/final-response.md +3 -5
- metalist-0.12.0/app/services/agent/prompts/system.md +28 -0
- metalist-0.12.0/app/services/agent/release_notes.py +50 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/runtime.py +90 -1341
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/scope.py +16 -1
- metalist-0.12.0/app/services/agent/skill_settings.py +130 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/__init__.py +0 -2
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-ai.md +45 -22
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-formatting.md +4 -1
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-menus.md +4 -8
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-notes.md +17 -3
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-privacy.md +1 -1
- metalist-0.12.0/app/services/agent/skills/help-releases.md +100 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-search.md +1 -1
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/structured_inference.py +34 -17
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/tagging.py +0 -15
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/tagging_run.py +49 -37
- metalist-0.12.0/app/services/agent/tool_calling.py +147 -0
- metalist-0.12.0/app/services/agent/web_actions.py +214 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/web_capabilities.py +21 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/web_evidence.py +22 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/web_fetch.py +16 -3
- {metalist-0.10.0 → metalist-0.12.0}/app/services/ai_chat_stream.py +5 -2
- {metalist-0.10.0 → metalist-0.12.0}/app/services/bulk_operation.py +31 -7
- {metalist-0.10.0 → metalist-0.12.0}/app/services/client_state_service.py +9 -22
- {metalist-0.10.0 → metalist-0.12.0}/app/services/content_formatting.py +46 -3
- {metalist-0.10.0 → metalist-0.12.0}/app/services/embedded_references.py +53 -26
- {metalist-0.10.0 → metalist-0.12.0}/app/services/encryption.py +29 -12
- {metalist-0.10.0 → metalist-0.12.0}/app/services/html_export.py +3 -2
- metalist-0.12.0/app/services/inline_image_dimensions.py +140 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/integrity.py +3 -2
- {metalist-0.10.0 → metalist-0.12.0}/app/services/link_titles.py +16 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/markdown_rendering.py +16 -1
- {metalist-0.10.0 → metalist-0.12.0}/app/services/note_image_tags.py +11 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/note_store.py +193 -48
- {metalist-0.10.0 → metalist-0.12.0}/app/services/request_recovery.py +4 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/root_sorting.py +127 -59
- {metalist-0.10.0 → metalist-0.12.0}/app/services/search_history.py +84 -35
- {metalist-0.10.0 → metalist-0.12.0}/app/services/search_index.py +125 -61
- {metalist-0.10.0 → metalist-0.12.0}/app/services/search_query.py +5 -1
- {metalist-0.10.0 → metalist-0.12.0}/app/services/snapshot.py +400 -179
- {metalist-0.10.0 → metalist-0.12.0}/app/services/store.py +3 -1
- {metalist-0.10.0 → metalist-0.12.0}/app/services/sync.py +7 -1
- {metalist-0.10.0 → metalist-0.12.0}/app/services/tab_state.py +8 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/tag_suggestions.py +24 -31
- {metalist-0.10.0 → metalist-0.12.0}/app/services/tag_term_matching.py +35 -33
- {metalist-0.10.0 → metalist-0.12.0}/app/services/undo_state.py +13 -2
- metalist-0.12.0/app/services/view_cache.py +99 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/startup_sanity.py +28 -1
- {metalist-0.10.0 → metalist-0.12.0}/app/static/config/agent-menu-actions.json +9 -9
- {metalist-0.10.0 → metalist-0.12.0}/app/static/config/command_palette_tags.json +6 -6
- {metalist-0.10.0 → metalist-0.12.0}/app/static/css/main.css +182 -143
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/main.js +2 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/ai-chat-api.js +0 -9
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/ai-chat-panel-controller.js +80 -32
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/ai-chat-panel-service.js +0 -66
- metalist-0.12.0/app/static/js/modules/ai-chat/confirmation-card.js +93 -0
- metalist-0.12.0/app/static/js/modules/ai-chat/confirmation-question.js +28 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/proposal-menu.js +6 -7
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/api-client.js +18 -6
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/auth.js +2 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/command-palette-controller.js +44 -79
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/endpoint-registry.js +10 -10
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/config.js +2 -2
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/error-overlay.js +22 -1
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/excalidraw/excalidraw-actions.js +5 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/excalidraw/excalidraw-preview-service.js +29 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/expected-errors.js +9 -0
- metalist-0.12.0/app/static/js/modules/modals/visual-cues-modal.js +138 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/actions/content-actions.js +2 -11
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/actions/note-actions.js +70 -21
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/actions/selection-actions.js +71 -4
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/actions/ui-actions.js +104 -30
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/events/input-events.js +0 -3
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/events/keyboard-events.js +51 -6
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/events/mouse-events.js +253 -30
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/mode-context.js +93 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/mode-manager-controller.js +10 -2
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/animated-scroll-service.js +4 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/collapse-affordance-service.js +50 -21
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/collapse-editing-policy-service.js +8 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/differential-view-service.js +2 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/edit-session-collapse-policy-service.js +3 -1
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/edit-session-collapse-service.js +9 -2
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/file-image-preview-service.js +25 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/file-reference-service.js +3 -2
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/floating-note-service.js +2 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/html-paste-sanitizer-service.js +4 -2
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/infinite-scroll-service.js +41 -52
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/mermaid-render-service.js +49 -0
- metalist-0.12.0/app/static/js/modules/mode-manager/services/note-drag-indicator-service.js +117 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/polling-service.js +42 -6
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/root-date-separator-service.js +1 -1
- metalist-0.12.0/app/static/js/modules/mode-manager/services/root-note-creation-service.js +34 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/root-sort-service.js +31 -2
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/scroll-restoration-service.js +28 -3
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/scroll-to-top-service.js +13 -2
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-syntax-service.js +28 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tab-state-service.js +17 -4
- metalist-0.12.0/app/static/js/modules/mode-manager/services/viewport-hold-service.js +755 -0
- metalist-0.12.0/app/static/js/vendor/dompurify-3.4.16.min.js +7 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/templates/base.html +1 -1
- {metalist-0.10.0 → metalist-0.12.0}/app/templates/index.html +1 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/bulk_tag_proposals.py +9 -5
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/delete_subtree.py +3 -1
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/delete_tag.py +10 -7
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/prioritize.py +5 -4
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/rename_tag.py +6 -5
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/view.py +3 -3
- {metalist-0.10.0 → metalist-0.12.0}/app/utils/text_utils.py +3 -4
- {metalist-0.10.0 → metalist-0.12.0}/app/version.py +1 -1
- {metalist-0.10.0 → metalist-0.12.0}/metalist.egg-info/PKG-INFO +20 -1
- {metalist-0.10.0 → metalist-0.12.0}/metalist.egg-info/SOURCES.txt +20 -10
- metalist-0.10.0/app/security/sensitive_cache.py +0 -78
- metalist-0.10.0/app/services/agent/actions.py +0 -292
- metalist-0.10.0/app/services/agent/permissions.py +0 -30
- metalist-0.10.0/app/services/agent/prompts/help-response.md +0 -25
- metalist-0.10.0/app/services/agent/prompts/system.md +0 -92
- metalist-0.10.0/app/services/agent/prompts/tool-result.md +0 -2
- metalist-0.10.0/app/services/agent/skill_settings.py +0 -219
- metalist-0.10.0/app/services/agent/skills/scoped-investigation.md +0 -27
- metalist-0.10.0/app/services/agent/tools.py +0 -323
- metalist-0.10.0/app/services/view_cache.py +0 -122
- metalist-0.10.0/app/static/js/modules/ai-chat/agent-prompt-service.js +0 -257
- metalist-0.10.0/app/static/js/modules/modals/agent-prompt-editor-modal.js +0 -347
- metalist-0.10.0/app/static/js/vendor/dompurify-3.4.13.min.js +0 -3
- {metalist-0.10.0 → metalist-0.12.0}/MANIFEST.in +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/__init__.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/api/__init__.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/api/deps.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/api/dev.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/api/request_auth.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/app_updates.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/backups.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/files.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/reminders.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/remote_images.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/test.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/api/upload_limits.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/config.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/data_directory.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/__init__.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/backup_settings_sql.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/editable_files_migration.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/engine.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/file_schema.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/file_session.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/files_sql.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/link_titles_sql.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/live_recovery.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/migrations.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/ontology_rules_sql.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/reminders_sql.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/retire_sounds.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/schema.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/search_history_sql.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/session.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/settings_sql.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/tab_state_sql.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/db/version.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/https_proxy.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/models/commands.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/models/database.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/models/entities.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/models/enums.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/models/linked_list.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/models/list_operations.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/models/list_traversal.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/models/note_crud.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/network_settings.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/presentation/__init__.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/presentation/render/__init__.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/presentation/render/note_renderer.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/presentation/templates.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/security/authenticated_logging.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/security/encryption.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/security/http_error_diagnostics.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/security/http_headers.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/security/note_html.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/security/request_boundary.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/security/request_hosts.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/security/sensitive_logging.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/security/shell_execution.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/security/validation_errors.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/server_runtime.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/__init__.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/__init__.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/cloud_privacy.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/evidence_serialization.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/judging.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/menu_actions.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/openai_cost_tracking.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/retrieval_settings.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-data.md +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-references.md +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-reminders.md +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-tags.md +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/staged-summary.md +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/tag-proposals.md +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/web-browsing.md +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/staged_summary.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/token_estimation.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/trace.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/web_settings.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/ai_chat.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/ai_chat_rendering.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/app_update_worker.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/app_updates.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/auth.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/auth_cache_state.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/auth_service.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/backlink_index.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/backlinks.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/backup_service.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/backup_settings_service.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/content_cache.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/diagnostics.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/exception_capture.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/file_edit_sessions.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/file_registry.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/file_storage.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/footnote_layout.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/footnote_rendering.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/hierarchy.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/html_unformatting.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/hydration_state.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/image_size_formatting.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/inline_image_occurrences.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/input_errors.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/latex_rendering.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/login_rate_limit.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/maintenance_mode.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/namespace_deletion_jobs.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/namespace_deletion_worker.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/namespace_rename_jobs.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/namespace_rename_worker.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/namespace_runtime_guard.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/namespace_switcher.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/note_fullscreen.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/note_ordering.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/ontology_rules_store.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/openai_credentials.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/password_note_fields.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/public_http.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/reference_presentation.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/reminders.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/remote_image_proxy.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/resource_limits.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/runtime_generation.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/runtime_hardening.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/runtime_lock.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/search_history_storage.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/search_text.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/selected_text_tag.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/self_update.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/session_timeout_service.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/shell_session_service.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/structured_note_renderers.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/sync_state.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/tag_case.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/tag_ontology.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/tag_rename.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/test_reset.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/tokens.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/update_backups.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/update_installer.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/update_preflight.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/view_diff.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/view_state.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/services/windows_process_control.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/startup_environment.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/startup_js_sanity.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/startup_sanity_config.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/css/floating-notes.css +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/css/forms.css +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/img/favicon.ico +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/locked.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/activity-tracker.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/agent-menu-actions.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/agent-retrieval-settings.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/agent-web-settings.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/ai-agent-debug-view.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/ai-chat-message-placement.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/ai-thinking-level-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/bulk-elapsed-clock.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/bulk-proposal-ui.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/bulk-scope-question.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/cloud-privacy-policy.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/summary-batch-preview.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/api-error-diagnostics.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/api-failure-classification-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/app-update-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/application-state.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/async-result.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/client-state-api.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/client-state-migration.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/activation-auth-policy.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/backup-command-availability.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/click-activation-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/note-layout-preferences.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/preferences-store.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/tag-config-loader.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/usage-store.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/connectivity-monitor.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/context-menu/context-menu-registry.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/context-menu/context-menu-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/context-menu/context-menu-target-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/context-menu/input-caret-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/disconnect-editing-state-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/dom-utils-fixed.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/dom-utils.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/editor-commands.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/editor-selection.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/editor-toolbar.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/elapsed-time.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/error-handler.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/excalidraw/excalidraw-autosave.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/excalidraw/excalidraw-editor-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/excalidraw/excalidraw-editor-state.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/excalidraw/excalidraw-loader.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/excalidraw/excalidraw-scene.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/location-flags.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/login-namespace-picker.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/maintenance.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/ai-agent-settings-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/alphabetize-root-notes-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/backup-restore-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/backup-result-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/backup-retention-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/backup-settings-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/base-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/confirmation-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/delete-namespace-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/delete-namespace-validation.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/help-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/namespace-loading-page.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/namespace-modals.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/namespace-ports-profile.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/namespace-rename-validation.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/note-layout-appearance-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/ontology-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/password-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/prioritize-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/random-password-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/reminder-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/reset-updated-at-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/search-suggestion-statistics-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/session-timeout-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/version-info-modal.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/actions/history-actions.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/actions/search-actions.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/events/context-menu-events.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/events/focus-events.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/events/inactivity-events.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/events/search-events.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/mode-logger.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/add-style-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/backlinks-navigation-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/backlinks-panel-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/clipboard-shortcut-policy-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/command-gate-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/context-menu-target-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/deselect-selection-state-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/embedded-image-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/file-drop-policy-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/filtered-refresh-selection-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/floating-note-dom.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/floating-note-layout.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/footnote-navigation-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/history-selection-policy-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/history-shortcut-policy-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/image-context-menu-action-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/image-file-insert-choice-modal-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/link-context-menu-action-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/link-title-prefetch-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/markdown-render-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-click-target-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-clipboard-write-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-collapse-animation-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-context-menu-action-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-delete-shortcut-policy-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-drag-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-fullscreen-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-reposition-animation-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-split-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-timestamp-hover-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/password-clipboard-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/reference-source-navigation-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/remote-image-proxy-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/remove-formatting-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/root-sort-indicator-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/scroll-anchor-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-contexts-overlay-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-debounce-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-input-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-interaction-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-redaction-reveal-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-suggestion-statistics-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-suggestion-window-labels-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-suggestion-windows-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-suggestions-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/selected-formatting-removal-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/selected-text-tag-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/shell-output-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tab-dom-cache-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tab-drag-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tab-duplication-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tag-bar-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tag-input-selection-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tag-proposal-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tag-suggestions-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tag-syntax-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/todo-toggle-editing-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/untagged-view-indicator-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/view-mode-search-shortcut-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/note-html-sanitizer.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/password-generator.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/password-operation-response.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/password-policy.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/password-strength.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/reminder-store.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/reminder-surface-service.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/selection-markers.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/session-auth.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/tag-token.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/uuid.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/namespace-deleted.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/namespace-renamed.js +0 -0
- /metalist-0.10.0/app/static/js/vendor/dompurify-3.4.13.LICENSE.txt → /metalist-0.12.0/app/static/js/vendor/dompurify-3.4.16.LICENSE.txt +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/excalidraw.css +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Bold.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Medium.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Regular.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-SemiBold.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Cascadia/CascadiaCode-Regular.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Virgil/Virgil-Regular.woff2 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1.LICENSE.txt +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1.min.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/markdown-it-14.3.2.LICENSE.txt +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/markdown-it-14.3.2.min.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/mermaid-11.16.1.LICENSE.txt +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/mermaid-11.16.1.min.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/zxcvbn-4.4.2.LICENSE.txt +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/zxcvbn-4.4.2.js +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/note-html-policy.json +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/static/video/login-startup.mp4 +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/templates/locked.html +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/templates/maintenance.html +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/templates/namespace_deleted.html +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/templates/namespace_renamed.html +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/templates/notes_list.html +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/upload_limits.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/__init__.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/add_selected_text_tag.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/alphabetize_root_notes.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/base.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/collapse.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/copy_note.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/create_child.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/create_note.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/create_sibling.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/expand.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/file_edit_session.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/indent.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/lock.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/move.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/move_to_top.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/outdent.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/paste_child.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/paste_sibling.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/prefetch_link_titles.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/redo.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/reset_updated_at.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/resize_image.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/run_shell.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/search_comment_autofill.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/search_context_tags.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/set_collapse_bulk.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/set_collapse_in_context.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/split_note.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/tag_proposals.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/toggle_reference_mode.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/toggle_todo_done.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/undo.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/unformat_content.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/usecases/update_content.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/utils/__init__.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/app/utils/encryption.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/convert-from-legacy.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/main.py +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/metalist.egg-info/dependency_links.txt +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/metalist.egg-info/entry_points.txt +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/metalist.egg-info/requires.txt +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/metalist.egg-info/top_level.txt +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/pyproject.toml +0 -0
- {metalist-0.10.0 → metalist-0.12.0}/scripts/generate-lan-cert.sh +0 -0
- {metalist-0.10.0 → metalist-0.12.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.12.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,25 @@ 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.12.0
|
|
53
|
+
|
|
54
|
+
- AI chat is now a tool-using agent: in one answer it can look up MetaList help, read and search the notes in your view, open web pages, and open menus, instead of picking a single route up front. Answers cite notes and web pages with clickable references, including each item listed from a web page.
|
|
55
|
+
- Nothing changes without your Yes: tag operations ask first with the exact change, and web addresses that carry words from your notes ask before opening. Summaries that fit in one pass start without a dialog, and summaries never block other edits while they run.
|
|
56
|
+
- "How do I change…" questions open the menu that holds the setting; release notes are part of the help. AI prompts and skills are no longer editable, and a $ button shows or hides the spend estimate.
|
|
57
|
+
- The AI is told only that a note is private, never which privacy setting hides it, and failed AI steps are explained in the chat.
|
|
58
|
+
- Leaving edit mode keeps your place, with no highlight; a collapsed note you changed stays expanded. Clicking into a note keeps the clicked spot under the pointer, including in diagrams and formulas.
|
|
59
|
+
- Dragging a note shows a ghost, a drop line and a direction cursor; the note lands where you dropped it without the page scrolling.
|
|
60
|
+
- Searches that cannot be parsed are explained politely instead of failing.
|
|
61
|
+
|
|
62
|
+
## Changes in 0.11.0
|
|
63
|
+
|
|
64
|
+
- 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.
|
|
65
|
+
- Tag suggestions, searches with only exclusions (`-tag`), and the updated/content-volume sort orders respond much faster on large namespaces.
|
|
66
|
+
- 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.
|
|
67
|
+
- Unlocking an encrypted namespace is faster, and the startup encryption audit no longer loads every attachment into memory.
|
|
68
|
+
- Fixed undo of deleting a note whose children have several children, and "accept all" failing on tag bars with leading or trailing spaces.
|
|
69
|
+
- Fixed crashes in the status check after returning to a tab and in scroll-position saving.
|
|
70
|
+
|
|
52
71
|
## Changes in 0.10.0
|
|
53
72
|
|
|
54
73
|
- 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.
|
|
@@ -12,6 +12,25 @@ 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.12.0
|
|
16
|
+
|
|
17
|
+
- AI chat is now a tool-using agent: in one answer it can look up MetaList help, read and search the notes in your view, open web pages, and open menus, instead of picking a single route up front. Answers cite notes and web pages with clickable references, including each item listed from a web page.
|
|
18
|
+
- Nothing changes without your Yes: tag operations ask first with the exact change, and web addresses that carry words from your notes ask before opening. Summaries that fit in one pass start without a dialog, and summaries never block other edits while they run.
|
|
19
|
+
- "How do I change…" questions open the menu that holds the setting; release notes are part of the help. AI prompts and skills are no longer editable, and a $ button shows or hides the spend estimate.
|
|
20
|
+
- The AI is told only that a note is private, never which privacy setting hides it, and failed AI steps are explained in the chat.
|
|
21
|
+
- Leaving edit mode keeps your place, with no highlight; a collapsed note you changed stays expanded. Clicking into a note keeps the clicked spot under the pointer, including in diagrams and formulas.
|
|
22
|
+
- Dragging a note shows a ghost, a drop line and a direction cursor; the note lands where you dropped it without the page scrolling.
|
|
23
|
+
- Searches that cannot be parsed are explained politely instead of failing.
|
|
24
|
+
|
|
25
|
+
## Changes in 0.11.0
|
|
26
|
+
|
|
27
|
+
- 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.
|
|
28
|
+
- Tag suggestions, searches with only exclusions (`-tag`), and the updated/content-volume sort orders respond much faster on large namespaces.
|
|
29
|
+
- 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.
|
|
30
|
+
- Unlocking an encrypted namespace is faster, and the startup encryption audit no longer loads every attachment into memory.
|
|
31
|
+
- Fixed undo of deleting a note whose children have several children, and "accept all" failing on tag bars with leading or trailing spaces.
|
|
32
|
+
- Fixed crashes in the status check after returning to a tab and in scroll-position saving.
|
|
33
|
+
|
|
15
34
|
## Changes in 0.10.0
|
|
16
35
|
|
|
17
36
|
- 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.
|
|
@@ -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):
|
|
@@ -33,21 +33,17 @@ from app.services.agent.openai_inference import OpenAIInferenceAdapter
|
|
|
33
33
|
from app.services.agent.openai_inference import validate_openai_model
|
|
34
34
|
from app.services.agent.openai_cost_tracking import OpenAICostSnapshot
|
|
35
35
|
from app.services.agent.openai_cost_tracking import openai_cost_tracker
|
|
36
|
-
from app.services.agent.permissions import AgentPermissionPolicy
|
|
37
36
|
from app.services.agent.prompt_settings import AgentPromptSet
|
|
38
37
|
from app.services.agent.skill_settings import AgentSkillSet
|
|
39
38
|
from app.services.agent.retrieval_settings import AgentRetrievalSettings
|
|
40
39
|
from app.services.agent.scope import ScopedSearchSnapshot
|
|
41
40
|
from app.services.agent.prompt_settings import DEFAULT_AGENT_PROMPTS
|
|
42
|
-
from app.services.agent.prompt_settings import resolve_agent_prompt_set
|
|
43
41
|
from app.services.agent.retrieval_settings import resolve_agent_retrieval_settings
|
|
44
42
|
from app.services.agent.scope import AgentScopeDescriptor
|
|
45
43
|
from app.services.agent.scope import scoped_search_snapshot_factory
|
|
46
44
|
from app.services.agent.runtime import AgentRuntime
|
|
47
45
|
from app.services.agent.skill_settings import DEFAULT_AGENT_SKILLS
|
|
48
|
-
from app.services.agent.skill_settings import resolve_agent_skill_set
|
|
49
46
|
from app.services.agent.token_estimation import estimate_input_tokens
|
|
50
|
-
from app.services.agent.tools import read_only_agent_tools
|
|
51
47
|
from app.services.agent.trace import agent_trace_store
|
|
52
48
|
from app.services.agent.menu_actions import MenuResult, menu_action_store
|
|
53
49
|
from app.services.client_state_service import load_client_preferences
|
|
@@ -62,7 +58,7 @@ from app.services.agent.retrieval_settings import resolve_tagging_batch_tokens
|
|
|
62
58
|
from app.services.agent.web_settings import AgentWebSettings
|
|
63
59
|
from app.services.agent.web_settings import resolve_agent_web_settings
|
|
64
60
|
from app.services.agent.web_evidence import web_evidence_store
|
|
65
|
-
from app.services.agent.tagging import
|
|
61
|
+
from app.services.agent.tagging import TAGGING_POLICY_KEY
|
|
66
62
|
from app.usecases.bulk_tag_proposals import apply_bulk_proposals, prepare_proposal_changes
|
|
67
63
|
from app.services.bulk_operation import bulk_operation_guard
|
|
68
64
|
from app.services.tab_state import tab_state_store
|
|
@@ -79,8 +75,6 @@ def _agent_runtime(*, inference: InferenceAdapter) -> AgentRuntime:
|
|
|
79
75
|
context_builder=agent_context_builder,
|
|
80
76
|
inference=inference,
|
|
81
77
|
model_policy=SingleModelPolicy(),
|
|
82
|
-
permission_policy=AgentPermissionPolicy(),
|
|
83
|
-
tool_registry=read_only_agent_tools,
|
|
84
78
|
trace_store=agent_trace_store,
|
|
85
79
|
provider_label=inference.provider_label,
|
|
86
80
|
)
|
|
@@ -136,23 +130,6 @@ class CloudPrivacyPreviewResponse(BaseModel):
|
|
|
136
130
|
hidden_note_ids: list[str]
|
|
137
131
|
|
|
138
132
|
|
|
139
|
-
class AiSkillDefaultResponse(BaseModel):
|
|
140
|
-
skill_id: str
|
|
141
|
-
title: str
|
|
142
|
-
description: str
|
|
143
|
-
trigger_action: str
|
|
144
|
-
preference_key: str
|
|
145
|
-
content: str
|
|
146
|
-
superseded_preference_keys: list[str]
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
class AiPromptDefaultsResponse(BaseModel):
|
|
150
|
-
system_prompt: str
|
|
151
|
-
final_response_prompt: str
|
|
152
|
-
tool_result_prompt: str
|
|
153
|
-
skills: list[AiSkillDefaultResponse]
|
|
154
|
-
|
|
155
|
-
|
|
156
133
|
class AiChatRequest(BaseModel):
|
|
157
134
|
model_config = ConfigDict(extra="forbid")
|
|
158
135
|
|
|
@@ -384,32 +361,6 @@ def reset_openai_cost(
|
|
|
384
361
|
return _openai_cost_response(openai_cost_tracker.snapshot())
|
|
385
362
|
|
|
386
363
|
|
|
387
|
-
@router.get("/prompts/defaults", response_model=AiPromptDefaultsResponse)
|
|
388
|
-
def get_ai_prompt_defaults(
|
|
389
|
-
response: Response,
|
|
390
|
-
token: Annotated[str, Depends(require_request_auth_token)],
|
|
391
|
-
) -> AiPromptDefaultsResponse:
|
|
392
|
-
del token
|
|
393
|
-
response.headers["Cache-Control"] = "no-store"
|
|
394
|
-
return AiPromptDefaultsResponse(
|
|
395
|
-
system_prompt=DEFAULT_AGENT_PROMPTS.system_prompt,
|
|
396
|
-
final_response_prompt=DEFAULT_AGENT_PROMPTS.final_response_prompt,
|
|
397
|
-
tool_result_prompt=DEFAULT_AGENT_PROMPTS.tool_result_prompt,
|
|
398
|
-
skills=[
|
|
399
|
-
AiSkillDefaultResponse(
|
|
400
|
-
skill_id=skill.skill_id,
|
|
401
|
-
title=skill.title,
|
|
402
|
-
description=skill.description,
|
|
403
|
-
trigger_action=skill.trigger_action,
|
|
404
|
-
preference_key=skill.preference_key,
|
|
405
|
-
content=skill.content,
|
|
406
|
-
superseded_preference_keys=list(skill.superseded_preference_keys),
|
|
407
|
-
)
|
|
408
|
-
for skill in DEFAULT_AGENT_SKILLS.skills
|
|
409
|
-
],
|
|
410
|
-
)
|
|
411
|
-
|
|
412
|
-
|
|
413
364
|
@router.post(
|
|
414
365
|
"/cloud-privacy/preview",
|
|
415
366
|
response_model=CloudPrivacyPreviewResponse,
|
|
@@ -637,8 +588,8 @@ def stream_ai_chat(
|
|
|
637
588
|
session_key=session_key,
|
|
638
589
|
)
|
|
639
590
|
preferences = load_client_preferences(token=token)
|
|
640
|
-
prompts =
|
|
641
|
-
skills =
|
|
591
|
+
prompts = DEFAULT_AGENT_PROMPTS
|
|
592
|
+
skills = DEFAULT_AGENT_SKILLS
|
|
642
593
|
retrieval_settings = resolve_agent_retrieval_settings(
|
|
643
594
|
preferences=preferences,
|
|
644
595
|
provider=payload.provider,
|
|
@@ -731,11 +682,11 @@ async def _stream_runtime_events(
|
|
|
731
682
|
approx_input_tokens=initial_input_tokens, output_tokens_received=0, duration_ms=0.0)
|
|
732
683
|
yield dict(type='action_status', action=action, status='completed', label=ready_label,
|
|
733
684
|
approx_input_tokens=initial_input_tokens, output_tokens_received=0, duration_ms=0.0)
|
|
734
|
-
events = runtime.
|
|
685
|
+
events = runtime.stream_agent(session_key=session_key, base_url=base_url,
|
|
735
686
|
selected_model=payload.model, thinking_level=payload.thinking_level,
|
|
736
687
|
canonical_messages=provider_messages, prompts=prompts, skills=skills,
|
|
737
688
|
retrieval_settings=retrieval_settings, web_settings=web_settings,
|
|
738
|
-
frozen_scope=frozen_scope,
|
|
689
|
+
frozen_scope=frozen_scope, tagging_run=tagging_run)
|
|
739
690
|
try:
|
|
740
691
|
async for event in events:
|
|
741
692
|
yield event
|
|
@@ -771,6 +722,8 @@ class BulkAnswerRequest(BaseModel):
|
|
|
771
722
|
"prefix_focus_both",
|
|
772
723
|
"summarize_all",
|
|
773
724
|
"use_prefix",
|
|
725
|
+
"yes",
|
|
726
|
+
"no",
|
|
774
727
|
]
|
|
775
728
|
|
|
776
729
|
|
|
@@ -820,6 +773,4 @@ def manage_bulk_proposals(payload: BulkManageRequest, token: Annotated[str, Depe
|
|
|
820
773
|
@router.get("/proposals/settings")
|
|
821
774
|
def get_tagging_settings(token: Annotated[str, Depends(require_request_auth_token)]):
|
|
822
775
|
preferences = load_client_preferences(token=token)
|
|
823
|
-
return {"policy": preferences.get(TAGGING_POLICY_KEY, "")
|
|
824
|
-
"prompt": preferences.get(TAGGING_PROMPT_KEY, DEFAULT_TAGGING_PROMPT),
|
|
825
|
-
"default_prompt": DEFAULT_TAGGING_PROMPT}
|
|
776
|
+
return {"policy": preferences.get(TAGGING_POLICY_KEY, "")}
|
|
@@ -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,
|
|
@@ -241,28 +241,25 @@ 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
|
|
257
257
|
if normalized_search is not None:
|
|
258
258
|
if not isinstance(normalized_search, str):
|
|
259
259
|
raise HTTPException(status_code=400, detail="search must be a string or null")
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
if capture.captured_exception is not None:
|
|
264
|
-
exc = capture.captured_exception
|
|
265
|
-
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
260
|
+
# Validated before anything changes; a search that does not parse is
|
|
261
|
+
# answered as rejected input (main.py), shown as a polite warning.
|
|
262
|
+
parse_search_query(normalized_search)
|
|
266
263
|
|
|
267
264
|
maybe_reset_on_context(client_id, undo_context)
|
|
268
265
|
|
|
@@ -278,164 +275,63 @@ def view_diff(payload: ViewDiffRequest):
|
|
|
278
275
|
if not note_store.has_note(normalized_editing_note_id):
|
|
279
276
|
normalized_editing_note_id = None
|
|
280
277
|
|
|
281
|
-
#
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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]
|
|
278
|
+
# The server keeps each tab's warm view (what that browser tab displays),
|
|
279
|
+
# so the browser sends only where it is. A tab with no warm view, or one
|
|
280
|
+
# whose browser shows nothing for it, gets its initial window.
|
|
281
|
+
warm_view = view_cache.get(client_id=client_id, tab_id=tab_id)
|
|
282
|
+
if tab_view_empty:
|
|
283
|
+
warm_view = None
|
|
284
|
+
client_known_note_ids: set[str] = set()
|
|
285
|
+
# The tab's previous root order: a sorted tab keeps the edited note's root there.
|
|
286
|
+
previous_root_ids: list[str] = []
|
|
287
|
+
if warm_view is not None:
|
|
288
|
+
client_known_note_ids = set(warm_view.hash_by_id)
|
|
289
|
+
if None in warm_view.children_by_parent:
|
|
290
|
+
previous_root_ids = warm_view.children_by_parent[None]
|
|
298
291
|
|
|
299
292
|
state = build_view_state(
|
|
300
293
|
editing_note_id=normalized_editing_note_id,
|
|
301
294
|
search=normalized_search,
|
|
302
295
|
sort_mode=sort_mode,
|
|
303
|
-
client_known_note_ids=
|
|
304
|
-
|
|
305
|
-
|
|
296
|
+
client_known_note_ids=client_known_note_ids,
|
|
297
|
+
previous_root_ids=previous_root_ids,
|
|
298
|
+
visible_top_root_id=visible_top_root_id,
|
|
299
|
+
visible_bottom_root_id=visible_bottom_root_id,
|
|
306
300
|
is_untagged_view=is_untagged_view,
|
|
307
301
|
)
|
|
308
302
|
update_uuid = get_current_sync_uuid()
|
|
309
303
|
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
|
-
|
|
304
|
+
view_cache.set(client_id=client_id, tab_id=tab_id, state=state)
|
|
422
305
|
response_snapshot = {
|
|
423
|
-
"
|
|
424
|
-
"notes": note_updates,
|
|
306
|
+
"notes": {},
|
|
425
307
|
"locks": state.locks,
|
|
426
308
|
"rootIds": root_ids,
|
|
427
|
-
"lockDiffs": lock_diff,
|
|
428
309
|
"updateUUID": update_uuid,
|
|
429
310
|
"version": VERSION,
|
|
430
311
|
"currentClientId": client_id,
|
|
431
312
|
"searchQuery": search,
|
|
432
313
|
"sortMode": sort_mode,
|
|
433
314
|
"isUntaggedView": is_untagged_view,
|
|
434
|
-
"rootCountTotal":
|
|
435
|
-
"searchRootCountTotal":
|
|
315
|
+
"rootCountTotal": state.metadata["rootCountTotal"],
|
|
316
|
+
"searchRootCountTotal": state.metadata["searchRootCountTotal"],
|
|
436
317
|
"rootSortBuckets": state.metadata["rootSortBuckets"],
|
|
318
|
+
"rootWindowStart": state.metadata["rootWindowStart"],
|
|
319
|
+
"rootBandMargin": state.metadata["rootBandMargin"],
|
|
320
|
+
"rootSortKeyBeforeWindow": state.metadata["rootSortKeyBeforeWindow"],
|
|
437
321
|
"editingNoteId": normalized_editing_note_id,
|
|
438
322
|
}
|
|
323
|
+
if warm_view is None:
|
|
324
|
+
response_snapshot["structure"] = state.structure
|
|
325
|
+
response_snapshot["notes"] = dict(state.payloads)
|
|
326
|
+
return {"snapshot": response_snapshot, "updateUUID": update_uuid}
|
|
327
|
+
|
|
328
|
+
response_snapshot["diffOps"] = generate_diff_ops(warm_view, state)
|
|
329
|
+
response_snapshot["notes"] = {
|
|
330
|
+
note_id: note_payload
|
|
331
|
+
for note_id, note_payload in state.payloads.items()
|
|
332
|
+
if note_id not in warm_view.hash_by_id or warm_view.hash_by_id[note_id] != note_payload["hash"]
|
|
333
|
+
}
|
|
334
|
+
response_snapshot["lockDiffs"] = _compute_lock_diff(warm_view.locks, state.locks)
|
|
439
335
|
return {"snapshot": response_snapshot, "updateUUID": update_uuid}
|
|
440
336
|
|
|
441
337
|
|
|
@@ -501,6 +397,11 @@ def create_new_tab(payload: CreateNewTabRequest) -> Dict[str, object]:
|
|
|
501
397
|
response = tab_state_store.create_tab(copy_from_tab_id=copy_from_tab_id)
|
|
502
398
|
if capture.captured_exception is not None:
|
|
503
399
|
raise HTTPException(status_code=400, detail="Invalid or stale tab state") from capture.captured_exception
|
|
400
|
+
# The browser clones the source tab's DOM into the new tab, so the new tab
|
|
401
|
+
# starts from the source tab's warm view.
|
|
402
|
+
view_cache.copy_tab(
|
|
403
|
+
client_id=payload["clientId"], source_tab_id=copy_from_tab_id, target_tab_id=response["newTabId"],
|
|
404
|
+
)
|
|
504
405
|
return response
|
|
505
406
|
|
|
506
407
|
|
|
@@ -790,16 +691,6 @@ def _compute_lock_diff(previous: Dict[str, str], current: Dict[str, str]) -> Dic
|
|
|
790
691
|
return diff
|
|
791
692
|
|
|
792
693
|
|
|
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
694
|
# Stub endpoints for the rest of the notes API (501 Not Implemented)
|
|
804
695
|
|
|
805
696
|
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}
|
|
@@ -125,6 +125,8 @@ def assert_mutation_routes_wrapped(app: FastAPI) -> None:
|
|
|
125
125
|
def _check_bulk_guard(endpoint_name: str) -> None:
|
|
126
126
|
if endpoint_name in _STORAGE_TRANSITIONS and bulk_operation_guard.active_mutations > 1:
|
|
127
127
|
raise HTTPException(status_code=409, detail="Wait for the current request to finish before changing namespace storage.")
|
|
128
|
-
|
|
128
|
+
# Preferences never touch notes, and every operation reads them once when it
|
|
129
|
+
# starts, so saving them (e.g. the chat panel width) cannot disturb it.
|
|
130
|
+
permitted = {"answer_bulk_question", "preview_cloud_privacy", "put_ai_debug_details", "put_client_preferences"}
|
|
129
131
|
if bulk_operation_guard.operation_id and endpoint_name not in permitted:
|
|
130
132
|
raise HTTPException(status_code=409, detail="A bulk operation is running. Wait or cancel it before changing the app.")
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import sqlite3
|
|
6
|
-
import time
|
|
7
6
|
from datetime import datetime
|
|
8
7
|
from typing import Iterable, Optional, Any
|
|
9
8
|
|
|
@@ -12,6 +11,9 @@ from .schema import NOTES_TABLE
|
|
|
12
11
|
from app.services.hierarchy import validate_database_parent
|
|
13
12
|
|
|
14
13
|
|
|
14
|
+
_DELETE_CHUNK_SIZE = 900
|
|
15
|
+
|
|
16
|
+
|
|
15
17
|
def _conn(connection: GuardedConnection | sqlite3.Connection) -> sqlite3.Connection:
|
|
16
18
|
raw_connection = getattr(connection, "raw_connection", None)
|
|
17
19
|
if isinstance(raw_connection, sqlite3.Connection):
|
|
@@ -403,14 +405,13 @@ def delete_notes(
|
|
|
403
405
|
identifiers = list(note_ids)
|
|
404
406
|
if not identifiers:
|
|
405
407
|
return
|
|
406
|
-
placeholders = ",".join(["?"] * len(identifiers))
|
|
407
|
-
sql = f"DELETE FROM {NOTES_TABLE} WHERE id IN ({placeholders})"
|
|
408
|
-
print('DEBUG CHECKPOINT 1')
|
|
409
|
-
t1 = time.perf_counter()
|
|
410
408
|
conn = _conn(connection)
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
409
|
+
# Chunk below SQLite's bound-variable limit (999 on older builds) so large
|
|
410
|
+
# subtree deletes do not fail; the caller's transaction keeps it atomic.
|
|
411
|
+
for start in range(0, len(identifiers), _DELETE_CHUNK_SIZE):
|
|
412
|
+
chunk = identifiers[start : start + _DELETE_CHUNK_SIZE]
|
|
413
|
+
placeholders = ",".join(["?"] * len(chunk))
|
|
414
|
+
conn.execute(f"DELETE FROM {NOTES_TABLE} WHERE id IN ({placeholders})", tuple(chunk))
|
|
414
415
|
|
|
415
416
|
|
|
416
417
|
def fetch_note(
|
|
@@ -679,9 +679,18 @@ def _audit_payloads(
|
|
|
679
679
|
needed_columns = {spec.value_column, spec.nonce_column, spec.tag_column}
|
|
680
680
|
if not needed_columns.issubset(actual_columns):
|
|
681
681
|
continue
|
|
682
|
+
value_expression = spec.value_column
|
|
683
|
+
if spec.storage_kind == "bytes":
|
|
684
|
+
# Binary checks need only the storage type: stand an empty BLOB in
|
|
685
|
+
# for each BLOB so file contents are never read into memory.
|
|
686
|
+
value_expression = (
|
|
687
|
+
f"CASE WHEN typeof({spec.value_column}) = 'blob' THEN zeroblob(0) "
|
|
688
|
+
f"ELSE {spec.value_column} END AS {spec.value_column}"
|
|
689
|
+
)
|
|
690
|
+
# Stream rows: payload tables can be far larger than memory should hold.
|
|
682
691
|
rows = connection.execute(
|
|
683
|
-
f"SELECT {
|
|
684
|
-
)
|
|
692
|
+
f"SELECT {value_expression}, {spec.nonce_column}, {spec.tag_column} FROM {spec.table}"
|
|
693
|
+
)
|
|
685
694
|
for row in rows:
|
|
686
695
|
_audit_payload_row(
|
|
687
696
|
row=row,
|
|
@@ -14,7 +14,9 @@ CAPTURE_BOUNDARIES = {
|
|
|
14
14
|
'app/services/agent/web_fetch.py:_extract_pdf_content:pdf_capture': ('PyPdfError',),
|
|
15
15
|
'app/services/agent/web_fetch.py:_decode_web_text:encoding_capture': ('LookupError',),
|
|
16
16
|
'app/services/agent/web_fetch.py:handle_starttag:join_capture': ('ValueError',),
|
|
17
|
-
'app/services/agent/
|
|
17
|
+
'app/services/agent/web_actions.py:open_web_pages:evidence_capacity_capture': ('WebEvidenceCapacityError',),
|
|
18
|
+
# A model's tool call is untrusted input; rejected arguments are explained back to the model.
|
|
19
|
+
'app/services/agent/agent_tools.py:parse_tool_call:arguments_capture': ('ValidationError',),
|
|
18
20
|
# In-app updates translate only external transport, installation eligibility and job lookup errors.
|
|
19
21
|
'app/services/app_updates.py:check_for_update:eligibility': ('AppUpdateRejected',),
|
|
20
22
|
'app/services/app_updates.py:job_path:validation': ('ValueError',),
|