MetaList 0.7.1__tar.gz → 0.7.3__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.7.1 → metalist-0.7.3}/MANIFEST.in +2 -0
- {metalist-0.7.1/metalist.egg-info → metalist-0.7.3}/PKG-INFO +16 -1
- {metalist-0.7.1 → metalist-0.7.3}/README.md +15 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/ai.py +53 -104
- {metalist-0.7.1 → metalist-0.7.3}/app/config.py +2 -2
- {metalist-0.7.1 → metalist-0.7.3}/app/db/live_recovery.py +4 -1
- {metalist-0.7.1 → metalist-0.7.3}/app/exception_boundaries.py +0 -10
- {metalist-0.7.1 → metalist-0.7.3}/app/models/database.py +3 -18
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/actions.py +14 -77
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/cloud_privacy.py +33 -9
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/context.py +67 -22
- metalist-0.7.3/app/services/agent/help_catalog.py +43 -0
- metalist-0.7.3/app/services/agent/history.py +106 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/investigation.py +5 -3
- metalist-0.7.3/app/services/agent/judging.py +15 -0
- metalist-0.7.3/app/services/agent/menu_actions.py +63 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/openai_inference.py +16 -6
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/prompts/final-response.md +14 -0
- metalist-0.7.3/app/services/agent/prompts/help-response.md +25 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/prompts/system.md +24 -7
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/retrieval_settings.py +7 -31
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/runtime.py +128 -137
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/scope.py +109 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/skill_settings.py +8 -1
- metalist-0.7.3/app/services/agent/skills/help-ai.md +79 -0
- metalist-0.7.3/app/services/agent/skills/help-data.md +40 -0
- metalist-0.7.3/app/services/agent/skills/help-formatting.md +176 -0
- metalist-0.7.3/app/services/agent/skills/help-menus.md +116 -0
- metalist-0.7.3/app/services/agent/skills/help-notes.md +200 -0
- metalist-0.7.3/app/services/agent/skills/help-privacy.md +135 -0
- metalist-0.7.3/app/services/agent/skills/help-references.md +106 -0
- metalist-0.7.3/app/services/agent/skills/help-reminders.md +152 -0
- metalist-0.7.3/app/services/agent/skills/help-search.md +214 -0
- metalist-0.7.3/app/services/agent/skills/help-tags.md +354 -0
- metalist-0.7.1/app/services/agent/ollama_inference.py → metalist-0.7.3/app/services/agent/structured_inference.py +22 -151
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/trace.py +82 -7
- {metalist-0.7.1 → metalist-0.7.3}/app/services/ai_chat_stream.py +2 -3
- {metalist-0.7.1 → metalist-0.7.3}/app/services/app_updates.py +18 -15
- {metalist-0.7.1 → metalist-0.7.3}/app/services/client_state_service.py +10 -17
- {metalist-0.7.1 → metalist-0.7.3}/app/services/content_formatting.py +51 -2
- {metalist-0.7.1 → metalist-0.7.3}/app/services/search_index.py +52 -11
- {metalist-0.7.1 → metalist-0.7.3}/app/services/snapshot.py +3 -1
- metalist-0.7.3/app/services/update_installer.py +122 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/update_preflight.py +4 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/startup_js_sanity.py +1 -1
- {metalist-0.7.1 → metalist-0.7.3}/app/startup_sanity.py +1 -1
- {metalist-0.7.1 → metalist-0.7.3}/app/startup_sanity_config.py +0 -5
- metalist-0.7.3/app/static/config/agent-menu-actions.json +326 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/config/command_palette_tags.json +3 -3
- {metalist-0.7.1 → metalist-0.7.3}/app/static/css/main.css +24 -22
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/main.js +1 -0
- metalist-0.7.3/app/static/js/modules/ai-chat/agent-menu-actions.js +43 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/agent-retrieval-settings.js +2 -22
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/ai-agent-debug-view.js +16 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/ai-chat-api.js +30 -101
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/ai-chat-panel-controller.js +37 -9
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/ai-chat-panel-service.js +8 -12
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/ai-thinking-level-service.js +4 -15
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/auth.js +8 -20
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/command-palette-controller.js +51 -54
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/config.js +2 -1
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/ai-agent-settings-modal.js +48 -236
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/backup-restore-modal.js +2 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/base-modal.js +8 -3
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/delete-namespace-modal.js +3 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/namespace-modals.js +12 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/password-modal.js +6 -3
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/session-timeout-modal.js +3 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/actions/content-actions.js +33 -10
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/events/context-menu-events.js +6 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/events/keyboard-events.js +1 -1
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/events/mouse-events.js +20 -0
- metalist-0.7.3/app/static/js/modules/session-auth.js +43 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/templates/index.html +3 -2
- {metalist-0.7.1 → metalist-0.7.3}/app/version.py +1 -1
- {metalist-0.7.1 → metalist-0.7.3/metalist.egg-info}/PKG-INFO +16 -1
- {metalist-0.7.1 → metalist-0.7.3}/metalist.egg-info/SOURCES.txt +19 -3
- metalist-0.7.1/app/services/managed_ollama_runtime.py +0 -499
- metalist-0.7.1/app/services/ollama_provider.py +0 -519
- metalist-0.7.1/app/static/js/modules/session-auth.js +0 -22
- {metalist-0.7.1 → metalist-0.7.3}/app/__init__.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/__init__.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/deps.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/dev.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/middleware/auth.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/note_requests.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/request_auth.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/app_updates.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/auth.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/backups.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/files.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/notes.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/ontology.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/reminders.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/remote_images.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/test.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/transactions.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/api/upload_limits.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/data_directory.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/__init__.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/backup_settings_sql.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/engine.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/file_schema.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/file_session.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/files_sql.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/link_titles_sql.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/migrations.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/notes_sql.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/ontology_rules_sql.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/reminders_sql.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/retire_sounds.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/schema.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/search_history_sql.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/session.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/settings_sql.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/tab_state_sql.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/db/version.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/encryption_audit.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/https_proxy.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/main.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/models/commands.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/models/entities.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/models/enums.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/models/linked_list.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/models/list_operations.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/models/list_traversal.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/models/note_crud.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/models/utils.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/network_settings.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/presentation/__init__.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/presentation/render/__init__.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/presentation/render/note_renderer.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/presentation/templates.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/security/authenticated_logging.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/security/encryption.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/security/http_headers.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/security/note_html.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/security/request_boundary.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/security/request_hosts.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/security/sensitive_cache.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/security/sensitive_logging.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/security/shell_execution.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/security/validation_errors.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/server_runtime.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/__init__.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/__init__.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/evidence_serialization.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/inference.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/model_policy.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/openai_cost_tracking.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/permissions.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/prompt_settings.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/prompts/__init__.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/prompts/tool-result.md +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/skills/__init__.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/skills/scoped-investigation.md +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/tagging.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/tagging_run.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/token_estimation.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/tools.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/ai_chat.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/ai_chat_rendering.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/app_update_worker.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/auth.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/auth_cache_state.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/auth_service.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/backlink_index.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/backlinks.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/backup_service.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/backup_settings_service.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/bulk_operation.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/content_cache.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/diagnostics.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/embedded_references.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/encryption.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/exception_capture.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/file_registry.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/file_storage.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/footnote_layout.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/footnote_rendering.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/hierarchy.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/html_export.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/html_unformatting.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/hydration_state.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/image_size_formatting.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/inline_image_occurrences.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/input_errors.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/integrity.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/latex_rendering.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/link_titles.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/login_rate_limit.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/maintenance_mode.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/markdown_rendering.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/namespace_deletion_jobs.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/namespace_deletion_worker.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/namespace_rename_jobs.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/namespace_rename_worker.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/namespace_runtime_guard.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/namespace_switcher.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/note_fullscreen.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/note_image_tags.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/note_ordering.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/note_store.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/ontology_rules_store.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/openai_credentials.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/password_note_fields.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/reference_presentation.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/reminders.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/remote_image_proxy.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/request_recovery.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/resource_limits.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/root_sorting.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/runtime_generation.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/runtime_hardening.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/runtime_lock.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/search_history.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/search_history_storage.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/search_query.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/search_text.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/selected_text_tag.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/self_update.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/session_timeout_service.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/shell_session_service.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/store.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/structured_note_renderers.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/sync.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/sync_state.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/tab_state.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/tag_case.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/tag_ontology.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/tag_rename.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/tag_suggestions.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/tag_term_matching.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/test_reset.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/tokens.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/undo_state.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/update_backups.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/view_cache.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/view_diff.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/view_state.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/services/windows_process_control.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/startup_environment.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/css/floating-notes.css +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/css/forms.css +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/img/favicon.ico +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/locked.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/activity-tracker.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/agent-prompt-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/bulk-elapsed-clock.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/bulk-proposal-ui.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/cloud-privacy-policy.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/proposal-menu.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/api-client.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/api-failure-classification-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/app-update-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/application-state.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/async-result.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/client-state-api.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/client-state-migration.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/activation-auth-policy.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/backup-command-availability.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/click-activation-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/endpoint-registry.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/note-layout-preferences.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/preferences-store.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/tag-config-loader.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/usage-store.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/connectivity-monitor.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/context-menu/context-menu-registry.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/context-menu/context-menu-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/context-menu/context-menu-target-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/context-menu/input-caret-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/disconnect-editing-state-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/dom-utils-fixed.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/dom-utils.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/editor-commands.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/editor-selection.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/editor-toolbar.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/elapsed-time.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/error-handler.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/error-overlay.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/expected-errors.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/location-flags.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/login-namespace-picker.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/maintenance.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/agent-prompt-editor-modal.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/alphabetize-root-notes-modal.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/backup-result-modal.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/backup-retention-modal.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/backup-settings-modal.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/confirmation-modal.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/delete-namespace-validation.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/help-modal.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/namespace-loading-page.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/namespace-ports-profile.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/namespace-rename-validation.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/note-layout-appearance-modal.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/ontology-modal.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/prioritize-modal.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/random-password-modal.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/reminder-modal.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/reset-updated-at-modal.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/search-suggestion-statistics-modal.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/version-info-modal.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/actions/history-actions.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/actions/note-actions.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/actions/search-actions.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/actions/selection-actions.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/actions/ui-actions.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/events/focus-events.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/events/inactivity-events.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/events/input-events.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/events/search-events.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/mode-context.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/mode-logger.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/mode-manager-controller.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/add-style-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/animated-scroll-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/backlinks-navigation-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/backlinks-panel-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/clipboard-shortcut-policy-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/collapse-affordance-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/collapse-editing-policy-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/command-gate-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/context-menu-target-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/deselect-selection-state-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/differential-view-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/edit-session-collapse-policy-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/edit-session-collapse-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/embedded-image-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/file-drop-policy-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/file-image-preview-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/file-reference-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/filtered-refresh-selection-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/floating-note-dom.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/floating-note-layout.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/floating-note-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/footnote-navigation-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/history-selection-policy-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/history-shortcut-policy-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/html-paste-sanitizer-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/image-context-menu-action-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/image-file-insert-choice-modal-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/infinite-scroll-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/link-context-menu-action-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/link-title-prefetch-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/markdown-render-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/mermaid-render-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-click-target-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-clipboard-write-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-collapse-animation-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-context-menu-action-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-delete-shortcut-policy-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-drag-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-fullscreen-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-reposition-animation-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-split-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-timestamp-hover-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/password-clipboard-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/polling-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/reference-source-navigation-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/remote-image-proxy-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/remove-formatting-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/root-date-separator-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/root-sort-indicator-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/root-sort-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/scroll-anchor-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/scroll-restoration-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/scroll-to-top-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-contexts-overlay-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-debounce-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-input-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-interaction-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-redaction-reveal-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-suggestion-statistics-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-suggestion-window-labels-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-suggestion-windows-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-suggestions-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-syntax-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/selected-formatting-removal-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/selected-text-tag-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/shell-output-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tab-dom-cache-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tab-drag-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tab-duplication-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tab-state-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tag-bar-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tag-input-selection-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tag-proposal-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tag-suggestions-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tag-syntax-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/todo-toggle-editing-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/untagged-view-indicator-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/view-mode-search-shortcut-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/note-html-sanitizer.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/password-generator.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/password-operation-response.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/password-policy.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/password-strength.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/reminder-store.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/reminder-surface-service.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/selection-markers.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/tag-token.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/uuid.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/namespace-deleted.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/namespace-renamed.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/vendor/dompurify-3.4.13.LICENSE.txt +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/vendor/dompurify-3.4.13.min.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/vendor/markdown-it-14.3.2.LICENSE.txt +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/vendor/markdown-it-14.3.2.min.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/vendor/mermaid-11.16.1.LICENSE.txt +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/vendor/mermaid-11.16.1.min.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/vendor/zxcvbn-4.4.2.LICENSE.txt +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/js/vendor/zxcvbn-4.4.2.js +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/note-html-policy.json +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/static/video/login-startup.mp4 +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/templates/base.html +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/templates/locked.html +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/templates/maintenance.html +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/templates/namespace_deleted.html +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/templates/namespace_renamed.html +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/templates/notes_list.html +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/upload_limits.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/__init__.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/add_selected_text_tag.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/alphabetize_root_notes.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/base.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/bulk_tag_proposals.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/collapse.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/copy_note.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/create_child.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/create_note.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/create_sibling.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/delete_subtree.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/delete_tag.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/expand.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/indent.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/lock.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/move.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/move_to_top.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/outdent.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/paste_child.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/paste_sibling.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/prefetch_link_titles.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/prioritize.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/redo.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/rename_tag.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/reset_updated_at.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/resize_image.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/run_shell.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/search_comment_autofill.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/search_context_tags.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/set_collapse_bulk.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/set_collapse_in_context.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/split_note.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/tag_proposals.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/toggle_reference_mode.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/toggle_todo_done.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/undo.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/unformat_content.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/update_content.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/usecases/view.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/utils/__init__.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/utils/encryption.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/app/utils/text_utils.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/convert-from-legacy.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/main.py +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/metalist.egg-info/dependency_links.txt +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/metalist.egg-info/entry_points.txt +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/metalist.egg-info/requires.txt +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/metalist.egg-info/top_level.txt +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/pyproject.toml +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/scripts/generate-lan-cert.sh +0 -0
- {metalist-0.7.1 → metalist-0.7.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: metalist
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.3
|
|
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
|
|
@@ -48,6 +48,19 @@ A minimalist single-user note-taking app focused on server-side rendering (SSR),
|
|
|
48
48
|
- Multi-tab search contexts with server-persisted scroll/search state (survives browser restarts)
|
|
49
49
|
- Manual namespace backups/restores to a user-selected backup folder with retention controls
|
|
50
50
|
|
|
51
|
+
## Changes in 0.7.3
|
|
52
|
+
|
|
53
|
+
- Windows updates use a private verified uv release when an older installer is vulnerable to the reported PE-resource access-denied failure. A standalone repair ZIP can bootstrap installations whose existing updater cannot update itself.
|
|
54
|
+
- Release candidates now run the complete test and installed-package matrix on Windows, macOS, and Linux across Python 3.10–3.14. Real Chrome and Firefox exercise repeated cold loads and encrypted login on every operating system; Windows also checks Edge over verified LAN HTTPS and the repair path from a published older release.
|
|
55
|
+
|
|
56
|
+
## Changes in 0.7.2
|
|
57
|
+
|
|
58
|
+
- Login, hydration, and workspace requests share one initialized browser-tab identity. Losing the `sessionStorage` copy while opening the workspace no longer causes the reported missing-tab-ID crash. The external trigger for that storage loss remains unconfirmed.
|
|
59
|
+
- AI chat preserves the edited note and includes its permitted tree, tags, and cached URL titles. Search redaction and cloud privacy restrictions apply to every node; blocked selections expose only their availability reason.
|
|
60
|
+
- Added on-demand AI help and menu actions, privacy previews, and Copy Response throughout assistant message bubbles. OpenAI is the supported inference provider.
|
|
61
|
+
- LLM regressions use current production prompts, default to five trials with cache-aware parallel scheduling, and can run only cases affected by prompt or skill changes.
|
|
62
|
+
- Improved Grammarly edit preservation and search suggestions that match the complete active clause.
|
|
63
|
+
|
|
51
64
|
## Changes in 0.6.3
|
|
52
65
|
|
|
53
66
|
- Restored HTTPS connection reuse and aligned the pending accept queue with the existing worker capacity, so a browser’s six-connection startup burst is admitted.
|
|
@@ -139,6 +152,8 @@ metalist update
|
|
|
139
152
|
```
|
|
140
153
|
The updater checks the installed version against the latest PyPI release first. If MetaList is already current, it reports the installed version and leaves all running namespaces untouched. When an update is available, it checks installer prerequisites and uses uv to install the candidate into a disposable tool environment with the current base Python interpreter. It checks dependencies and starts a temporary namespace to verify HTTP readiness, version, and runtime assets. A failed preflight leaves the current installation and running namespaces unchanged. After preflight succeeds, it stops running namespaces, and creates and verifies a new backup of every namespace before installation can begin. Each archive includes the complete notes/settings database, the attachments database when present, and any legacy search-history database. Locked namespaces are backed up with their encrypted data and key metadata intact, without requiring a password.
|
|
141
154
|
|
|
155
|
+
On Windows, the updater checks uv before installing packages. Versions older than 0.12.13 use a temporary PE-resource editing operation that can fail with `uv-trampoline.exe: Access is denied`. This checkout selects a private, checksum-verified uv 0.12.17 for those installations, keeping the same installer through preflight and final installation. It does not replace global uv. Already-installed MetaList releases retain their own updater code; the standalone repair launcher described in [recovery](docs/security/recovery.md#windows-updater-pe-resource-failure) supplies the compatible installer to that existing updater.
|
|
156
|
+
|
|
142
157
|
Backups are saved to `~/MetaList/namespaces/<namespace>/backups/<namespace>-<timestamp>.metalist-backup.tar.gz`; the updater prints each verified path. Existing backups remain unchanged and are not pruned. If any backup fails, the update aborts with the current installation intact; run `metalist` to restart the stopped servers after resolving the failure.
|
|
143
158
|
|
|
144
159
|
Only after all backups pass does the updater hand off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock. It delegates installation to uv, pinning the current base interpreter and the exact tested package/dependency versions, using the cache populated during preflight with network access disabled. It then launches MetaList again, and reports the installed version (for example, `MetaList updated to v0.5.0.`). This protection requires an installed version containing the backup safeguard and applies to `metalist update` and the in-app update action; direct pip/uv install commands do not run it.
|
|
@@ -12,6 +12,19 @@ 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.7.3
|
|
16
|
+
|
|
17
|
+
- Windows updates use a private verified uv release when an older installer is vulnerable to the reported PE-resource access-denied failure. A standalone repair ZIP can bootstrap installations whose existing updater cannot update itself.
|
|
18
|
+
- Release candidates now run the complete test and installed-package matrix on Windows, macOS, and Linux across Python 3.10–3.14. Real Chrome and Firefox exercise repeated cold loads and encrypted login on every operating system; Windows also checks Edge over verified LAN HTTPS and the repair path from a published older release.
|
|
19
|
+
|
|
20
|
+
## Changes in 0.7.2
|
|
21
|
+
|
|
22
|
+
- Login, hydration, and workspace requests share one initialized browser-tab identity. Losing the `sessionStorage` copy while opening the workspace no longer causes the reported missing-tab-ID crash. The external trigger for that storage loss remains unconfirmed.
|
|
23
|
+
- AI chat preserves the edited note and includes its permitted tree, tags, and cached URL titles. Search redaction and cloud privacy restrictions apply to every node; blocked selections expose only their availability reason.
|
|
24
|
+
- Added on-demand AI help and menu actions, privacy previews, and Copy Response throughout assistant message bubbles. OpenAI is the supported inference provider.
|
|
25
|
+
- LLM regressions use current production prompts, default to five trials with cache-aware parallel scheduling, and can run only cases affected by prompt or skill changes.
|
|
26
|
+
- Improved Grammarly edit preservation and search suggestions that match the complete active clause.
|
|
27
|
+
|
|
15
28
|
## Changes in 0.6.3
|
|
16
29
|
|
|
17
30
|
- Restored HTTPS connection reuse and aligned the pending accept queue with the existing worker capacity, so a browser’s six-connection startup burst is admitted.
|
|
@@ -103,6 +116,8 @@ metalist update
|
|
|
103
116
|
```
|
|
104
117
|
The updater checks the installed version against the latest PyPI release first. If MetaList is already current, it reports the installed version and leaves all running namespaces untouched. When an update is available, it checks installer prerequisites and uses uv to install the candidate into a disposable tool environment with the current base Python interpreter. It checks dependencies and starts a temporary namespace to verify HTTP readiness, version, and runtime assets. A failed preflight leaves the current installation and running namespaces unchanged. After preflight succeeds, it stops running namespaces, and creates and verifies a new backup of every namespace before installation can begin. Each archive includes the complete notes/settings database, the attachments database when present, and any legacy search-history database. Locked namespaces are backed up with their encrypted data and key metadata intact, without requiring a password.
|
|
105
118
|
|
|
119
|
+
On Windows, the updater checks uv before installing packages. Versions older than 0.12.13 use a temporary PE-resource editing operation that can fail with `uv-trampoline.exe: Access is denied`. This checkout selects a private, checksum-verified uv 0.12.17 for those installations, keeping the same installer through preflight and final installation. It does not replace global uv. Already-installed MetaList releases retain their own updater code; the standalone repair launcher described in [recovery](docs/security/recovery.md#windows-updater-pe-resource-failure) supplies the compatible installer to that existing updater.
|
|
120
|
+
|
|
106
121
|
Backups are saved to `~/MetaList/namespaces/<namespace>/backups/<namespace>-<timestamp>.metalist-backup.tar.gz`; the updater prints each verified path. Existing backups remain unchanged and are not pruned. If any backup fails, the update aborts with the current installation intact; run `metalist` to restart the stopped servers after resolving the failure.
|
|
107
122
|
|
|
108
123
|
Only after all backups pass does the updater hand off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock. It delegates installation to uv, pinning the current base interpreter and the exact tested package/dependency versions, using the cache populated during preflight with network access disabled. It then launches MetaList again, and reports the installed version (for example, `MetaList updated to v0.5.0.`). This protection requires an installed version containing the backup safeguard and applies to `metalist update` and the in-app update action; direct pip/uv install commands do not run it.
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import asyncio
|
|
6
5
|
import json
|
|
7
6
|
import math
|
|
8
7
|
from collections.abc import AsyncIterator
|
|
@@ -27,7 +26,6 @@ from app.services.agent.cloud_privacy import cloud_privacy_evaluator
|
|
|
27
26
|
from app.services.agent.cloud_privacy import resolve_cloud_privacy_boundary
|
|
28
27
|
from app.services.agent.inference import InferenceAdapter
|
|
29
28
|
from app.services.agent.model_policy import SingleModelPolicy
|
|
30
|
-
from app.services.agent.ollama_inference import OllamaInferenceAdapter
|
|
31
29
|
from app.services.agent.openai_inference import OPENAI_API_BASE_URL
|
|
32
30
|
from app.services.agent.openai_inference import OPENAI_MODELS
|
|
33
31
|
from app.services.agent.openai_inference import OpenAIInferenceAdapter
|
|
@@ -50,15 +48,10 @@ from app.services.agent.skill_settings import resolve_agent_skill_set
|
|
|
50
48
|
from app.services.agent.token_estimation import estimate_input_tokens
|
|
51
49
|
from app.services.agent.tools import read_only_agent_tools
|
|
52
50
|
from app.services.agent.trace import agent_trace_store
|
|
51
|
+
from app.services.agent.menu_actions import MenuResult, menu_action_store
|
|
53
52
|
from app.services.client_state_service import load_client_preferences
|
|
54
53
|
from app.services.markdown_rendering import render_markdown_to_html
|
|
55
|
-
from app.services.managed_ollama_runtime import ManagedOllamaRuntimeError
|
|
56
|
-
from app.services.managed_ollama_runtime import managed_ollama_runtime
|
|
57
54
|
from app.services.note_store import store as note_store
|
|
58
|
-
from app.services.ollama_provider import OllamaProviderError
|
|
59
|
-
from app.services.ollama_provider import ollama_provider
|
|
60
|
-
from app.services.ollama_provider import resolve_ollama_think_value
|
|
61
|
-
from app.services.ollama_provider import validate_ollama_model
|
|
62
55
|
from app.services.openai_credentials import OpenAICredentialInputError
|
|
63
56
|
from app.services.openai_credentials import openai_credential_store
|
|
64
57
|
from app.services.openai_credentials import validate_openai_api_key
|
|
@@ -89,17 +82,10 @@ def _agent_runtime(*, inference: InferenceAdapter) -> AgentRuntime:
|
|
|
89
82
|
)
|
|
90
83
|
|
|
91
84
|
|
|
92
|
-
agent_runtime = _agent_runtime(
|
|
93
|
-
inference=OllamaInferenceAdapter(provider=ollama_provider)
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
85
|
class AiModelsRequest(BaseModel):
|
|
100
86
|
model_config = ConfigDict(extra="forbid")
|
|
101
87
|
|
|
102
|
-
provider: Literal["
|
|
88
|
+
provider: Literal["openai"]
|
|
103
89
|
|
|
104
90
|
|
|
105
91
|
class AiModelsResponse(BaseModel):
|
|
@@ -128,7 +114,7 @@ class OpenAICostResponse(BaseModel):
|
|
|
128
114
|
class CloudPrivacyPreviewRequest(BaseModel):
|
|
129
115
|
model_config = ConfigDict(extra="forbid")
|
|
130
116
|
|
|
131
|
-
provider: Literal["
|
|
117
|
+
provider: Literal["openai"]
|
|
132
118
|
note_ids: list[str] = Field(..., max_length=20_000)
|
|
133
119
|
|
|
134
120
|
@field_validator("note_ids")
|
|
@@ -163,27 +149,16 @@ class AiPromptDefaultsResponse(BaseModel):
|
|
|
163
149
|
skills: list[AiSkillDefaultResponse]
|
|
164
150
|
|
|
165
151
|
|
|
166
|
-
class AiModelPullRequest(BaseModel):
|
|
167
|
-
model_config = ConfigDict(extra="forbid")
|
|
168
|
-
|
|
169
|
-
provider: Literal["ollama"]
|
|
170
|
-
model: str
|
|
171
|
-
|
|
172
|
-
@field_validator("model")
|
|
173
|
-
@classmethod
|
|
174
|
-
def validate_model(cls, value: str) -> str:
|
|
175
|
-
return validate_ollama_model(value)
|
|
176
|
-
|
|
177
|
-
|
|
178
152
|
class AiChatRequest(BaseModel):
|
|
179
153
|
model_config = ConfigDict(extra="forbid")
|
|
180
154
|
|
|
181
|
-
provider: Literal["
|
|
155
|
+
provider: Literal["openai"]
|
|
182
156
|
model: str
|
|
183
157
|
thinking_level: Literal["off", "low", "medium", "high"]
|
|
184
158
|
show_diagnostics: bool
|
|
185
159
|
message: str = Field(..., max_length=32_000)
|
|
186
160
|
scope: AgentScopeDescriptor
|
|
161
|
+
selected_note_id: str = Field(..., max_length=128, pattern=r"^(?:\S+)?$")
|
|
187
162
|
|
|
188
163
|
@field_validator("model")
|
|
189
164
|
@classmethod
|
|
@@ -202,14 +177,7 @@ class AiChatRequest(BaseModel):
|
|
|
202
177
|
|
|
203
178
|
@model_validator(mode="after")
|
|
204
179
|
def validate_thinking_level_for_model(self) -> Self:
|
|
205
|
-
|
|
206
|
-
validate_ollama_model(self.model)
|
|
207
|
-
resolve_ollama_think_value(
|
|
208
|
-
model=self.model,
|
|
209
|
-
thinking_level=self.thinking_level,
|
|
210
|
-
)
|
|
211
|
-
else:
|
|
212
|
-
validate_openai_model(self.model)
|
|
180
|
+
validate_openai_model(self.model)
|
|
213
181
|
return self
|
|
214
182
|
|
|
215
183
|
|
|
@@ -239,7 +207,7 @@ class AiChatMessage(BaseModel):
|
|
|
239
207
|
rendered_thinking: str
|
|
240
208
|
status: Literal["complete", "streaming", "error"]
|
|
241
209
|
error: str
|
|
242
|
-
provider: Literal["
|
|
210
|
+
provider: Literal["openai"]
|
|
243
211
|
model: str
|
|
244
212
|
activities: list[AiChatActivity]
|
|
245
213
|
|
|
@@ -308,15 +276,8 @@ async def list_ai_models(
|
|
|
308
276
|
payload: AiModelsRequest,
|
|
309
277
|
token: Annotated[str, Depends(require_request_auth_token)],
|
|
310
278
|
) -> AiModelsResponse:
|
|
311
|
-
del token
|
|
312
|
-
|
|
313
|
-
return AiModelsResponse(models=list(OPENAI_MODELS))
|
|
314
|
-
try:
|
|
315
|
-
runtime_info = await asyncio.to_thread(managed_ollama_runtime.ensure_running)
|
|
316
|
-
models = await ollama_provider.list_models(base_url=runtime_info.base_url)
|
|
317
|
-
except (ManagedOllamaRuntimeError, OllamaProviderError) as exc:
|
|
318
|
-
raise HTTPException(status_code=502, detail=str(exc)) from exc
|
|
319
|
-
return AiModelsResponse(models=models)
|
|
279
|
+
del token, payload
|
|
280
|
+
return AiModelsResponse(models=list(OPENAI_MODELS))
|
|
320
281
|
|
|
321
282
|
|
|
322
283
|
@router.get(
|
|
@@ -476,38 +437,6 @@ def preview_cloud_privacy(
|
|
|
476
437
|
)
|
|
477
438
|
|
|
478
439
|
|
|
479
|
-
@router.post("/models/pull")
|
|
480
|
-
@transactional_route
|
|
481
|
-
def pull_ai_model(
|
|
482
|
-
payload: AiModelPullRequest,
|
|
483
|
-
token: Annotated[str, Depends(require_request_auth_token)],
|
|
484
|
-
) -> StreamingResponse:
|
|
485
|
-
del token
|
|
486
|
-
|
|
487
|
-
async def stream_events() -> AsyncIterator[str]:
|
|
488
|
-
try:
|
|
489
|
-
runtime_info = await asyncio.to_thread(managed_ollama_runtime.ensure_running)
|
|
490
|
-
async for event in ollama_provider.stream_pull(
|
|
491
|
-
base_url=runtime_info.base_url,
|
|
492
|
-
model=payload.model,
|
|
493
|
-
):
|
|
494
|
-
yield f"{json.dumps(event, separators=(',', ':'))}\n"
|
|
495
|
-
# lint: allow-PY001 rationale="pull errors must be delivered after response headers are sent"
|
|
496
|
-
except (ManagedOllamaRuntimeError, OllamaProviderError) as exc:
|
|
497
|
-
error_event = {"type": "error", "message": str(exc)}
|
|
498
|
-
yield f"{json.dumps(error_event, separators=(',', ':'))}\n"
|
|
499
|
-
|
|
500
|
-
return StreamingResponse(
|
|
501
|
-
stream_events(),
|
|
502
|
-
media_type="application/x-ndjson",
|
|
503
|
-
headers={
|
|
504
|
-
"X-Accel-Buffering": "no",
|
|
505
|
-
"Cache-Control": "no-store",
|
|
506
|
-
"Content-Encoding": "identity",
|
|
507
|
-
},
|
|
508
|
-
)
|
|
509
|
-
|
|
510
|
-
|
|
511
440
|
@router.get("/session", response_model=AiSessionResponse)
|
|
512
441
|
def get_ai_session(
|
|
513
442
|
response: Response,
|
|
@@ -589,6 +518,17 @@ def get_ai_debug_snapshot(
|
|
|
589
518
|
)
|
|
590
519
|
|
|
591
520
|
|
|
521
|
+
@router.get("/history")
|
|
522
|
+
def get_ai_history(
|
|
523
|
+
response: Response,
|
|
524
|
+
token: Annotated[str, Depends(require_request_auth_token)],
|
|
525
|
+
) -> list:
|
|
526
|
+
response.headers["Cache-Control"] = "no-store"
|
|
527
|
+
return agent_trace_store.export_history(
|
|
528
|
+
session_key=token_service.get_session_key(token)
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
|
|
592
532
|
@router.put("/debug", response_model=AiDebugSnapshotResponse)
|
|
593
533
|
@transactional_route
|
|
594
534
|
def put_ai_debug_details(
|
|
@@ -666,21 +606,19 @@ def stream_ai_chat(
|
|
|
666
606
|
token: Annotated[str, Depends(require_request_auth_token)],
|
|
667
607
|
) -> StreamingResponse:
|
|
668
608
|
session_key = token_service.get_session_key(token)
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
status_code=409,
|
|
678
|
-
detail="OpenAI API key is not configured",
|
|
679
|
-
)
|
|
680
|
-
openai_api_key = openai_credential_store.resolve(
|
|
681
|
-
token=token,
|
|
682
|
-
session_key=session_key,
|
|
609
|
+
credential_status = openai_credential_store.status(
|
|
610
|
+
token=token,
|
|
611
|
+
session_key=session_key,
|
|
612
|
+
)
|
|
613
|
+
if not credential_status.configured:
|
|
614
|
+
raise HTTPException(
|
|
615
|
+
status_code=409,
|
|
616
|
+
detail="OpenAI API key is not configured",
|
|
683
617
|
)
|
|
618
|
+
openai_api_key = openai_credential_store.resolve(
|
|
619
|
+
token=token,
|
|
620
|
+
session_key=session_key,
|
|
621
|
+
)
|
|
684
622
|
preferences = load_client_preferences(token=token)
|
|
685
623
|
prompts = resolve_agent_prompt_set(preferences=preferences)
|
|
686
624
|
skills = resolve_agent_skill_set(preferences=preferences)
|
|
@@ -704,6 +642,11 @@ def stream_ai_chat(
|
|
|
704
642
|
authoritative_sort_mode = tab_state_store.get_sort_mode(
|
|
705
643
|
tab_id=payload.scope.scope_tab_id
|
|
706
644
|
)
|
|
645
|
+
active_search_query = authoritative_search_query
|
|
646
|
+
active_sort_mode = authoritative_sort_mode
|
|
647
|
+
if payload.selected_note_id and payload.scope.active_tab_id != payload.scope.scope_tab_id:
|
|
648
|
+
active_search_query = tab_state_store.get_search_query(tab_id=authoritative_active_tab_id)
|
|
649
|
+
active_sort_mode = tab_state_store.get_sort_mode(tab_id=authoritative_active_tab_id)
|
|
707
650
|
frozen_scope = scoped_search_snapshot_factory.freeze(
|
|
708
651
|
descriptor=payload.scope,
|
|
709
652
|
authoritative_search_query=authoritative_search_query,
|
|
@@ -711,6 +654,9 @@ def stream_ai_chat(
|
|
|
711
654
|
run_id=str(uuid4()),
|
|
712
655
|
session_key=session_key,
|
|
713
656
|
privacy_boundary=privacy_boundary,
|
|
657
|
+
selected_note_id=payload.selected_note_id,
|
|
658
|
+
authoritative_active_search_query=active_search_query,
|
|
659
|
+
authoritative_active_sort_mode=active_sort_mode,
|
|
714
660
|
)
|
|
715
661
|
tagging_run = TaggingRun(token=token, snapshot=frozen_scope, preferences=preferences, sync_uuid=get_current_sync_uuid(),
|
|
716
662
|
batch_tokens=resolve_tagging_batch_tokens(preferences, payload.provider))
|
|
@@ -758,18 +704,9 @@ async def _stream_runtime_events(
|
|
|
758
704
|
action, start_label = 'provider_runtime', 'Connecting to OpenAI API'
|
|
759
705
|
ready_label = 'OpenAI API ready · 1,050,000-token context'
|
|
760
706
|
base_url = OPENAI_API_BASE_URL
|
|
761
|
-
|
|
762
|
-
action = 'ollama_runtime'
|
|
763
|
-
start_label = 'Starting MetaList-managed Ollama · 32,768-token context'
|
|
764
|
-
runtime = agent_runtime
|
|
765
|
-
else:
|
|
766
|
-
runtime = _agent_runtime(inference=OpenAIInferenceAdapter(api_key=openai_api_key, cost_tracker=openai_cost_tracker))
|
|
707
|
+
runtime = _agent_runtime(inference=OpenAIInferenceAdapter(api_key=openai_api_key, cost_tracker=openai_cost_tracker))
|
|
767
708
|
yield dict(type='action_status', action=action, status='started', label=start_label,
|
|
768
709
|
approx_input_tokens=initial_input_tokens, output_tokens_received=0, duration_ms=0.0)
|
|
769
|
-
if payload.provider == 'ollama':
|
|
770
|
-
runtime_info = await asyncio.to_thread(managed_ollama_runtime.ensure_running)
|
|
771
|
-
base_url = runtime_info.base_url
|
|
772
|
-
ready_label = f'MetaList-managed Ollama ready · {runtime_info.context_tokens:,}-token context'
|
|
773
710
|
yield dict(type='action_status', action=action, status='completed', label=ready_label,
|
|
774
711
|
approx_input_tokens=initial_input_tokens, output_tokens_received=0, duration_ms=0.0)
|
|
775
712
|
events = runtime.stream_scoped(session_key=session_key, base_url=base_url,
|
|
@@ -783,6 +720,18 @@ async def _stream_runtime_events(
|
|
|
783
720
|
await events.aclose()
|
|
784
721
|
|
|
785
722
|
|
|
723
|
+
@router.post("/menu-result")
|
|
724
|
+
@transactional_route
|
|
725
|
+
async def acknowledge_menu_result(payload: MenuResult, token: Annotated[str, Depends(require_request_auth_token)]):
|
|
726
|
+
# lint: allow-PY001 rationale="browser acknowledgments can be stale or belong to another session"
|
|
727
|
+
try:
|
|
728
|
+
menu_action_store.acknowledge(session_key=token_service.get_session_key(token), result=payload)
|
|
729
|
+
# lint: allow-PY001 rationale="reject invalid external menu acknowledgment with a conflict response"
|
|
730
|
+
except ValueError as exc:
|
|
731
|
+
raise HTTPException(status_code=409, detail=str(exc)) from exc
|
|
732
|
+
return {"acknowledged": True}
|
|
733
|
+
|
|
734
|
+
|
|
786
735
|
class BulkAnswerRequest(BaseModel):
|
|
787
736
|
model_config = ConfigDict(extra="forbid")
|
|
788
737
|
question_id: str = Field(..., min_length=1)
|
|
@@ -114,9 +114,9 @@ if TEST_MODE:
|
|
|
114
114
|
# Delete existing test.db if it exists
|
|
115
115
|
if test_database_path.exists():
|
|
116
116
|
test_database_path.unlink()
|
|
117
|
-
print("
|
|
117
|
+
print("Deleted existing test.db")
|
|
118
118
|
|
|
119
|
-
print("
|
|
119
|
+
print("Running in TEST MODE - using test.db")
|
|
120
120
|
else:
|
|
121
121
|
# Use production database
|
|
122
122
|
DEFAULT_DB_PATH = str(resolve_default_database_path())
|
|
@@ -44,7 +44,10 @@ def _sync_directory(path: Path) -> None:
|
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
def _sync_file(path: Path) -> None:
|
|
47
|
-
|
|
47
|
+
# Windows' CRT rejects fsync/_commit on a read-only descriptor with EBADF.
|
|
48
|
+
# These are live or recovery files owned by this transaction, so open them
|
|
49
|
+
# without truncation using a descriptor that every supported OS can flush.
|
|
50
|
+
with path.open('r+b') as handle:
|
|
48
51
|
os.fsync(handle.fileno())
|
|
49
52
|
|
|
50
53
|
|
|
@@ -112,16 +112,6 @@ CAPTURE_BOUNDARIES = {
|
|
|
112
112
|
# Handle expected external I/O, provider, image or LaTeX parsing failure.
|
|
113
113
|
'app/services/link_titles.py:fetch_link_title:target_capture': ('_LinkTitleTargetRejected',),
|
|
114
114
|
# Handle expected external I/O, provider, image or LaTeX parsing failure.
|
|
115
|
-
'app/services/managed_ollama_runtime.py:_acquire_startup_lock:lock_capture': ('FileExistsError',),
|
|
116
|
-
# Handle expected external I/O, provider, image or LaTeX parsing failure.
|
|
117
|
-
'app/services/managed_ollama_runtime.py:_is_process_running:process_capture': ('ProcessLookupError', 'PermissionError'),
|
|
118
|
-
# Handle expected external I/O, provider, image or LaTeX parsing failure.
|
|
119
|
-
'app/services/managed_ollama_runtime.py:_probe_ollama_version:probe_capture': ('HTTPError', 'JSONDecodeError'),
|
|
120
|
-
# Handle expected external I/O, provider, image or LaTeX parsing failure.
|
|
121
|
-
'app/services/managed_ollama_runtime.py:_remove_stale_lock:missing_capture': ('FileNotFoundError',),
|
|
122
|
-
# Handle expected external I/O, provider, image or LaTeX parsing failure.
|
|
123
|
-
'app/services/managed_ollama_runtime.py:_remove_stale_lock:read_capture': ('FileNotFoundError',),
|
|
124
|
-
# Handle expected external I/O, provider, image or LaTeX parsing failure.
|
|
125
115
|
'app/services/namespace_deletion_worker.py:_is_process_running:kill_capture': ('ProcessLookupError', 'PermissionError'),
|
|
126
116
|
# Handle expected external I/O, provider, image or LaTeX parsing failure.
|
|
127
117
|
'app/services/namespace_deletion_worker.py:_send_signal_if_running:signal_capture': ('ProcessLookupError',),
|
|
@@ -124,15 +124,8 @@ class SafeSession:
|
|
|
124
124
|
_configure_sql_logging(anchor)
|
|
125
125
|
cls._memory_anchor = anchor
|
|
126
126
|
print("\n" + "=" * 50)
|
|
127
|
-
print(
|
|
128
|
-
|
|
129
|
-
🧪 SWITCHING TO TEST MODE 🧪
|
|
130
|
-
┌──────────────────────────┐
|
|
131
|
-
│ IN-MEMORY DATABASE │
|
|
132
|
-
│ *All Data is Temporary │
|
|
133
|
-
└──────────────────────────┘
|
|
134
|
-
"""
|
|
135
|
-
)
|
|
127
|
+
print("TEST MODE: IN-MEMORY DATABASE")
|
|
128
|
+
print("All data is temporary")
|
|
136
129
|
print("=" * 50 + "\n")
|
|
137
130
|
return {"status": "ok", "message": "Using in-memory database"}
|
|
138
131
|
|
|
@@ -159,15 +152,7 @@ class SafeSession:
|
|
|
159
152
|
_configure_sql_logging(conn)
|
|
160
153
|
conn.close()
|
|
161
154
|
print("\n" + "=" * 50)
|
|
162
|
-
print(
|
|
163
|
-
"""
|
|
164
|
-
📝 RETURNING TO PRODUCTION MODE 📝
|
|
165
|
-
┌──────────────────────────┐
|
|
166
|
-
│ PROD DATABASE │
|
|
167
|
-
│ │
|
|
168
|
-
└──────────────────────────┘
|
|
169
|
-
"""
|
|
170
|
-
)
|
|
155
|
+
print("PRODUCTION MODE: FILE DATABASE")
|
|
171
156
|
print("=" * 50 + "\n")
|
|
172
157
|
return {"status": "ok", "message": "Using file database"}
|
|
173
158
|
|
|
@@ -2,73 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import re
|
|
6
|
-
from collections.abc import Iterator
|
|
7
|
-
from contextlib import contextmanager
|
|
8
|
-
from contextvars import ContextVar
|
|
9
|
-
from dataclasses import dataclass
|
|
10
5
|
from typing import Annotated, Literal, Union
|
|
11
6
|
|
|
12
7
|
from pydantic import BaseModel, ConfigDict, Field, TypeAdapter, field_validator, model_validator
|
|
13
8
|
from typing_extensions import Self
|
|
14
9
|
|
|
15
10
|
from app.services.search_query import parse_search_query
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@dataclass(frozen=True, slots=True)
|
|
19
|
-
class ScopedRouteConstraints:
|
|
20
|
-
explicit_saved_notes_request: bool
|
|
21
|
-
|
|
22
|
-
def __post_init__(self) -> None:
|
|
23
|
-
if not isinstance(self.explicit_saved_notes_request, bool):
|
|
24
|
-
raise TypeError("explicit_saved_notes_request must be bool")
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
_SCOPED_ROUTE_CONSTRAINTS: ContextVar[ScopedRouteConstraints | None] = ContextVar(
|
|
28
|
-
"scoped_route_constraints",
|
|
29
|
-
default=None,
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
_EXPLICIT_SAVED_NOTES_PATTERNS = (
|
|
33
|
-
re.compile(r"\b(?:my|our)\s+(?:saved\s+)?notes?\b", re.IGNORECASE),
|
|
34
|
-
re.compile(
|
|
35
|
-
r"\b(?:summari[sz]e|search|find|review|read|inspect|analy[sz]e|"
|
|
36
|
-
r"synthesi[sz]e)\b(?:\W+\w+){0,12}\W+notes?\b",
|
|
37
|
-
re.IGNORECASE,
|
|
38
|
-
),
|
|
39
|
-
)
|
|
40
|
-
_SAVED_NOTES_EXCLUSION_PATTERN = re.compile(
|
|
41
|
-
r"\b(?:without|do\s+not|don't|dont)\b.{0,48}"
|
|
42
|
-
r"\b(?:use|using|search|read|consult|reference)\b.{0,48}"
|
|
43
|
-
r"\b(?:my|our)?\s*(?:saved\s+)?notes?\b",
|
|
44
|
-
re.IGNORECASE,
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def request_explicitly_requires_saved_notes(user_message: str) -> bool:
|
|
49
|
-
if not isinstance(user_message, str):
|
|
50
|
-
raise TypeError("user_message must be a string")
|
|
51
|
-
if user_message.strip() == "":
|
|
52
|
-
raise ValueError("user_message must not be blank")
|
|
53
|
-
if _SAVED_NOTES_EXCLUSION_PATTERN.search(user_message) is not None:
|
|
54
|
-
return False
|
|
55
|
-
return any(
|
|
56
|
-
pattern.search(user_message) is not None
|
|
57
|
-
for pattern in _EXPLICIT_SAVED_NOTES_PATTERNS
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
@contextmanager
|
|
62
|
-
def bind_scoped_route_constraints(
|
|
63
|
-
constraints: ScopedRouteConstraints,
|
|
64
|
-
) -> Iterator[None]:
|
|
65
|
-
if not isinstance(constraints, ScopedRouteConstraints):
|
|
66
|
-
raise TypeError("constraints must be ScopedRouteConstraints")
|
|
67
|
-
token = _SCOPED_ROUTE_CONSTRAINTS.set(constraints)
|
|
68
|
-
try:
|
|
69
|
-
yield
|
|
70
|
-
finally:
|
|
71
|
-
_SCOPED_ROUTE_CONSTRAINTS.reset(token)
|
|
11
|
+
from app.services.agent.help_catalog import HelpTopic
|
|
72
12
|
|
|
73
13
|
|
|
74
14
|
def _validate_agent_search_query(value: str) -> str:
|
|
@@ -163,10 +103,11 @@ class ScopedRouteEnvelope(BaseModel):
|
|
|
163
103
|
|
|
164
104
|
model_config = ConfigDict(extra="forbid")
|
|
165
105
|
|
|
166
|
-
kind: Literal["respond", "investigate_current_scope", "tag_proposals"] = Field(
|
|
106
|
+
kind: Literal["respond", "investigate_current_scope", "tag_proposals", "metalist_help"] = Field(
|
|
167
107
|
...,
|
|
168
108
|
description=(
|
|
169
|
-
"
|
|
109
|
+
"metalist_help for MetaList product questions or opening menus, with relevant help_topics; "
|
|
110
|
+
"respond for requests answerable from the supplied selected note tree alone or without note evidence; "
|
|
170
111
|
"investigate_current_scope only when the answer depends on evidence "
|
|
171
112
|
"inside the frozen active MetaList result scope. "
|
|
172
113
|
"tag_proposals ONLY for an explicit current user request to generate, "
|
|
@@ -174,6 +115,16 @@ class ScopedRouteEnvelope(BaseModel):
|
|
|
174
115
|
"hypotheticals, and unrelated requests must never select tag_proposals."
|
|
175
116
|
),
|
|
176
117
|
)
|
|
118
|
+
help_topics: list[HelpTopic] = Field(..., max_length=10, description="Relevant product-help topics for metalist_help; empty for other routes.")
|
|
119
|
+
|
|
120
|
+
@model_validator(mode="after")
|
|
121
|
+
def validate_help_topics(self) -> Self:
|
|
122
|
+
if len(set(self.help_topics)) != len(self.help_topics):
|
|
123
|
+
raise ValueError("Help topics must be unique")
|
|
124
|
+
if (self.kind == "metalist_help") != bool(self.help_topics):
|
|
125
|
+
raise ValueError("Only metalist_help requires nonempty help_topics")
|
|
126
|
+
return self
|
|
127
|
+
|
|
177
128
|
reason: str = Field(..., min_length=1, max_length=4_000)
|
|
178
129
|
|
|
179
130
|
@field_validator("reason")
|
|
@@ -183,20 +134,6 @@ class ScopedRouteEnvelope(BaseModel):
|
|
|
183
134
|
raise ValueError("Scoped route reason must not be blank")
|
|
184
135
|
return value
|
|
185
136
|
|
|
186
|
-
@model_validator(mode="after")
|
|
187
|
-
def enforce_explicit_saved_notes_request(self) -> Self:
|
|
188
|
-
constraints = _SCOPED_ROUTE_CONSTRAINTS.get()
|
|
189
|
-
if (
|
|
190
|
-
constraints is not None
|
|
191
|
-
and constraints.explicit_saved_notes_request
|
|
192
|
-
and self.kind not in {"investigate_current_scope", "tag_proposals"}
|
|
193
|
-
):
|
|
194
|
-
raise ValueError(
|
|
195
|
-
"The user explicitly requests evidence from saved notes; choose "
|
|
196
|
-
"investigate_current_scope, not respond"
|
|
197
|
-
)
|
|
198
|
-
return self
|
|
199
|
-
|
|
200
137
|
|
|
201
138
|
AgentAction = Annotated[
|
|
202
139
|
Union[SearchNotesAction, ReadNotesByIdAction, RespondAction],
|
|
@@ -16,7 +16,7 @@ from app.utils.text_utils import strip_html
|
|
|
16
16
|
|
|
17
17
|
CLOUD_PRIVACY_POLICY_PREFERENCE_KEY = "pref.ai.cloud_privacy_policy"
|
|
18
18
|
_CLOUD_PROVIDERS = frozenset({"openai"})
|
|
19
|
-
_SUPPORTED_PROVIDERS = frozenset({"
|
|
19
|
+
_SUPPORTED_PROVIDERS = frozenset({"openai"})
|
|
20
20
|
_MAX_POLICY_ENTRIES_PER_LIST = 200
|
|
21
21
|
_MAX_POLICY_TAG_LENGTH = 256
|
|
22
22
|
_MAX_POLICY_PHRASE_LENGTH = 500
|
|
@@ -261,16 +261,38 @@ class CloudPrivacyEvaluator:
|
|
|
261
261
|
note_id: str,
|
|
262
262
|
match_plan: _CloudPrivacyMatchPlan,
|
|
263
263
|
) -> bool:
|
|
264
|
+
return self._direct_exclusion_reason(note_id=note_id, match_plan=match_plan) != ""
|
|
265
|
+
|
|
266
|
+
def exclusion_reason(self, *, note_id: str, boundary: CloudPrivacyBoundary) -> str:
|
|
267
|
+
"""Return a content-free reason, including restrictions on ancestors."""
|
|
268
|
+
match_plan = self._match_plan(boundary)
|
|
269
|
+
reasons = set()
|
|
270
|
+
seen = set()
|
|
271
|
+
current_id = note_id
|
|
272
|
+
while True:
|
|
273
|
+
assert current_id not in seen, "Hierarchy cycle in disclosure boundary"
|
|
274
|
+
seen.add(current_id)
|
|
275
|
+
reasons.add(self._direct_exclusion_reason(note_id=current_id, match_plan=match_plan))
|
|
276
|
+
parent_id = self._notes.get_note(current_id).parent_id
|
|
277
|
+
if parent_id is None:
|
|
278
|
+
break
|
|
279
|
+
current_id = parent_id
|
|
280
|
+
for reason in ("password_protected", "blacklisted", "not_whitelisted"):
|
|
281
|
+
if reason in reasons:
|
|
282
|
+
return reason
|
|
283
|
+
return ""
|
|
284
|
+
|
|
285
|
+
def _direct_exclusion_reason(self, *, note_id: str, match_plan: _CloudPrivacyMatchPlan) -> str:
|
|
264
286
|
record = self._notes.get_note(note_id)
|
|
265
287
|
effective_tags_casefold = {
|
|
266
288
|
tag.casefold() for tag in self._effective_tags_provider(note_id)
|
|
267
289
|
}
|
|
268
290
|
if "@password" in effective_tags_casefold:
|
|
269
|
-
return
|
|
291
|
+
return "password_protected"
|
|
270
292
|
if not match_plan.apply_cloud_policy:
|
|
271
|
-
return
|
|
293
|
+
return ""
|
|
272
294
|
if effective_tags_casefold & match_plan.blacklist_tags:
|
|
273
|
-
return
|
|
295
|
+
return "blacklisted"
|
|
274
296
|
needs_plaintext = any(
|
|
275
297
|
(match_plan.blacklist_phrases, match_plan.whitelist_phrases)
|
|
276
298
|
)
|
|
@@ -280,14 +302,16 @@ class CloudPrivacyEvaluator:
|
|
|
280
302
|
if any(
|
|
281
303
|
phrase in plaintext_casefold for phrase in match_plan.blacklist_phrases
|
|
282
304
|
):
|
|
283
|
-
return
|
|
305
|
+
return "blacklisted"
|
|
284
306
|
if not match_plan.has_whitelist:
|
|
285
|
-
return
|
|
307
|
+
return ""
|
|
286
308
|
if effective_tags_casefold & match_plan.whitelist_tags:
|
|
287
|
-
return
|
|
288
|
-
|
|
309
|
+
return ""
|
|
310
|
+
if any(
|
|
289
311
|
phrase in plaintext_casefold for phrase in match_plan.whitelist_phrases
|
|
290
|
-
)
|
|
312
|
+
):
|
|
313
|
+
return ""
|
|
314
|
+
return "not_whitelisted"
|
|
291
315
|
|
|
292
316
|
@staticmethod
|
|
293
317
|
def _match_plan(boundary: CloudPrivacyBoundary) -> _CloudPrivacyMatchPlan:
|