MetaList 0.3.8__tar.gz → 0.3.10__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.3.8/metalist.egg-info → metalist-0.3.10}/PKG-INFO +10 -4
- {metalist-0.3.8 → metalist-0.3.10}/README.md +9 -3
- {metalist-0.3.8 → metalist-0.3.10}/app/services/namespace_switcher.py +61 -5
- metalist-0.3.10/app/services/self_update.py +167 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/version.py +1 -1
- {metalist-0.3.8 → metalist-0.3.10}/main.py +31 -1
- {metalist-0.3.8 → metalist-0.3.10/metalist.egg-info}/PKG-INFO +10 -4
- {metalist-0.3.8 → metalist-0.3.10}/metalist.egg-info/SOURCES.txt +1 -0
- {metalist-0.3.8 → metalist-0.3.10}/MANIFEST.in +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/__init__.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/api/__init__.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/api/deps.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/api/dev.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/api/middleware/auth.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/api/request_auth.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/api/routes/auth.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/api/routes/backups.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/api/routes/files.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/api/routes/mcp.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/api/routes/memory.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/api/routes/notes.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/api/routes/ontology.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/api/routes/reminders.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/api/routes/sounds.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/api/routes/test.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/api/transactions.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/config.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/db/__init__.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/db/backup_settings_sql.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/db/engine.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/db/file_schema.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/db/file_session.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/db/files_sql.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/db/link_titles_sql.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/db/migrations.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/db/notes_sql.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/db/ontology_rules_sql.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/db/reminders_sql.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/db/schema.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/db/search_history_sql.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/db/session.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/db/settings_sql.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/db/sounds_sql.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/db/tab_state_sql.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/encryption_audit.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/main.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/mcp/__init__.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/mcp/__main__.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/mcp/errors.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/mcp/policy.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/mcp/read_service.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/mcp/server.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/mcp/tools.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/models/commands.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/models/database.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/models/entities.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/models/enums.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/models/linked_list.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/models/list_operations.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/models/list_traversal.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/models/note_crud.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/models/utils.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/presentation/__init__.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/presentation/render/__init__.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/presentation/render/note_renderer.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/presentation/templates.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/security/encryption.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/server_runtime.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/__init__.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/auth.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/auth_cache_state.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/auth_service.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/backlinks.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/backup_service.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/backup_settings_service.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/base_service.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/client_state_service.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/content_cache.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/content_formatting.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/date_filtering.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/dependencies.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/diagnostics.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/embedded_references.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/encryption.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/exception_capture.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/file_registry.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/file_storage.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/html_export.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/html_unformatting.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/hydration_state.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/integrity.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/latex_rendering.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/link_titles.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/login_rate_limit.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/maintenance_mode.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/markdown_rendering.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/memory.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/memory_service.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/namespace_deletion_jobs.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/namespace_deletion_worker.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/namespace_rename_jobs.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/namespace_rename_worker.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/note_image_tags.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/note_service.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/note_store.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/ontology_rules_store.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/query_service.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/reminders.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/root_sorting.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/runtime_hardening.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/search_history.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/search_index.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/search_query.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/search_text.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/session_timeout_service.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/shell_session_service.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/snapshot.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/sound_storage.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/store.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/sync.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/sync_state.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/tab_state.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/tag_case.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/tag_ontology.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/tag_rename.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/tag_suggestions.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/tag_term_matching.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/test_reset.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/tokens.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/transaction_manager.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/undo_service.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/undo_state.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/view_cache.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/view_diff.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/view_state.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/services/windows_process_control.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/startup_js_sanity.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/startup_sanity.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/startup_sanity_config.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/config/command_palette_tags.json +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/css/forms.css +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/css/main.css +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/img/favicon.ico +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/locked.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/main.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/activity-tracker.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/api-client.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/async-result.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/auth.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/client-state-api.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/client-state-migration.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/command-palette/click-activation-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/command-palette/command-palette-controller.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/command-palette/endpoint-registry.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/command-palette/preferences-store.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/command-palette/tag-config-loader.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/command-palette/usage-store.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/config.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/connectivity-monitor.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/context-menu/context-menu-registry.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/context-menu/context-menu-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/context-menu/input-caret-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/dom-utils-fixed.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/dom-utils.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/editor-commands.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/editor-selection.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/editor-toolbar.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/error-handler.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/error-overlay.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/location-flags.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/login-namespace-picker.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/alphabetize-root-notes-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/backup-restore-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/backup-result-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/backup-retention-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/backup-settings-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/base-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/delete-namespace-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/delete-namespace-validation.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/help-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/memory-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/namespace-loading-page.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/namespace-modals.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/namespace-ports-profile.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/namespace-rename-validation.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/ontology-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/password-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/prioritize-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/random-password-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/reminder-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/reset-updated-at-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/session-timeout-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/sound-manager-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/modals/version-info-modal.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/actions/content-actions.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/actions/history-actions.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/actions/note-actions.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/actions/search-actions.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/actions/selection-actions.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/actions/ui-actions.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/events/context-menu-events.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/events/focus-events.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/events/inactivity-events.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/events/input-events.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/events/keyboard-events.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/events/mouse-events.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/events/search-events.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/mode-context.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/mode-logger.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/mode-manager-controller.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/animated-scroll-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/backlinks-panel-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/clipboard-shortcut-policy-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/collapse-affordance-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/collapse-editing-policy-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/command-gate-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/context-menu-target-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/date-filter-indicator-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/date-filter-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/differential-view-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/edit-session-collapse-policy-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/edit-session-collapse-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/embedded-image-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/file-image-preview-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/file-reference-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/filtered-refresh-selection-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/html-paste-sanitizer-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/image-context-menu-action-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/image-file-insert-choice-modal-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/infinite-scroll-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/link-context-menu-action-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/markdown-render-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/note-click-target-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/note-clipboard-write-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/note-collapse-animation-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/note-context-menu-action-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/note-drag-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/note-reposition-animation-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/note-split-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/password-clipboard-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/polling-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/rhs-panel-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/root-date-separator-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/root-sort-indicator-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/root-sort-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/scroll-anchor-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/scroll-restoration-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/scroll-to-top-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/search-contexts-overlay-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/search-debounce-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/search-input-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/search-interaction-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/search-redaction-reveal-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/search-suggestions-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/search-syntax-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/shell-output-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/tab-dom-cache-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/tab-duplication-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/tab-state-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/tag-bar-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/tag-suggestions-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/tag-syntax-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/todo-toggle-editing-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/mode-manager/services/view-mode-search-shortcut-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/password-generator.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/reminder-store.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/reminder-surface-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/selection-markers.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/session-auth.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/sound-service.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/tag-token.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/modules/uuid.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/namespace-deleted.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/namespace-renamed.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/js/vendor/markdown-it.min.js +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/static/video/login-startup.mp4 +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/templates/base.html +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/templates/index.html +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/templates/locked.html +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/templates/maintenance.html +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/templates/namespace_deleted.html +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/templates/namespace_renamed.html +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/templates/notes_list.html +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/__init__.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/alphabetize_root_notes.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/base.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/collapse.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/copy_note.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/create_child.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/create_note.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/create_sibling.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/delete_subtree.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/expand.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/indent.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/lock.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/move.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/move_to_top.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/outdent.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/paste_child.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/paste_sibling.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/prioritize.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/record_edit_mode.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/redo.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/rename_tag.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/reset_updated_at.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/run_shell.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/search_comment_autofill.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/search_context_tags.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/set_collapse_bulk.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/set_collapse_in_context.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/split_note.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/toggle_reference_mode.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/toggle_todo_done.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/undo.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/unformat_content.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/update_content.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/usecases/view.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/utils/__init__.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/utils/encryption.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/app/utils/text_utils.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/convert-from-legacy.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/mcp_client.py +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/metalist.egg-info/dependency_links.txt +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/metalist.egg-info/entry_points.txt +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/metalist.egg-info/requires.txt +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/metalist.egg-info/top_level.txt +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/pyproject.toml +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/scripts/generate-lan-cert.sh +0 -0
- {metalist-0.3.8 → metalist-0.3.10}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: metalist
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.10
|
|
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
|
|
@@ -76,6 +76,12 @@ uv tool install metalist
|
|
|
76
76
|
metalist
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
+
After the first installation, update and restart MetaList with one cross-platform command:
|
|
80
|
+
```bash
|
|
81
|
+
metalist update
|
|
82
|
+
```
|
|
83
|
+
The updater stops running namespaces, hands off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock, runs the forced cache-refreshed uv update, and launches MetaList again.
|
|
84
|
+
|
|
79
85
|
For pip, users can run `pip install metalist`. For a non-editable local install from this checkout, use `uv pip install .` or `pip install .` instead of the editable command below.
|
|
80
86
|
|
|
81
87
|
```bash
|
|
@@ -87,11 +93,11 @@ npm install
|
|
|
87
93
|
```
|
|
88
94
|
|
|
89
95
|
### Run
|
|
90
|
-
The installed entrypoint starts
|
|
96
|
+
The installed entrypoint starts or restarts every known namespace, prints their URLs, and exits:
|
|
91
97
|
```bash
|
|
92
98
|
metalist
|
|
93
99
|
```
|
|
94
|
-
For source-checkout compatibility, `python main.py`
|
|
100
|
+
For source-checkout compatibility, `python main.py` performs the same orchestration. Use `metalist work`, `python main.py --namespace work`, or `python main.py work` when you want one foreground namespace process.
|
|
95
101
|
|
|
96
102
|
`metalist` and explicit single-namespace source runs bind HTTP on `0.0.0.0:8000` by default, matching the old MetaList LAN-friendly behavior.
|
|
97
103
|
On first startup, MetaList also auto-generates a self-signed TLS pair at `~/MetaList/certs/metalist-cert.pem` and `~/MetaList/certs/metalist-key.pem`, then enables HTTPS on `0.0.0.0:8443`. If you already have real PEM files, point `METALIST_TLS_CERT` and `METALIST_TLS_KEY` at them instead. Set `METALIST_AUTO_GENERATE_TLS=0` only if you explicitly want HTTP-only startup.
|
|
@@ -104,7 +110,7 @@ Database selection:
|
|
|
104
110
|
- Launch precedence is: explicit CLI flags > env vars > saved namespace profile; if a namespace has no saved profile, launch it once with explicit ports or configure ports from the UI
|
|
105
111
|
- Backups stay beside the namespace data under `~/MetaList/namespaces/work/backups/` and use one archive per snapshot with filenames like `work-<timestamp>.metalist-backup.tar.gz`
|
|
106
112
|
- The Backup Settings modal targets one user-selected backup folder and can include multiple namespaces in a single run
|
|
107
|
-
- Restoring `work` into `work` is the normal overwrite path; importing a backup under a different namespace name
|
|
113
|
+
- Restoring `work` into `work` is the normal overwrite path; importing a backup under a different namespace name can create a new target namespace with automatically selected conflict-free ports.
|
|
108
114
|
|
|
109
115
|
Useful env flags:
|
|
110
116
|
- `CRASH_SERVER_ON_FAIL=1` (default): fail-fast on validation errors
|
|
@@ -47,6 +47,12 @@ uv tool install metalist
|
|
|
47
47
|
metalist
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
+
After the first installation, update and restart MetaList with one cross-platform command:
|
|
51
|
+
```bash
|
|
52
|
+
metalist update
|
|
53
|
+
```
|
|
54
|
+
The updater stops running namespaces, hands off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock, runs the forced cache-refreshed uv update, and launches MetaList again.
|
|
55
|
+
|
|
50
56
|
For pip, users can run `pip install metalist`. For a non-editable local install from this checkout, use `uv pip install .` or `pip install .` instead of the editable command below.
|
|
51
57
|
|
|
52
58
|
```bash
|
|
@@ -58,11 +64,11 @@ npm install
|
|
|
58
64
|
```
|
|
59
65
|
|
|
60
66
|
### Run
|
|
61
|
-
The installed entrypoint starts
|
|
67
|
+
The installed entrypoint starts or restarts every known namespace, prints their URLs, and exits:
|
|
62
68
|
```bash
|
|
63
69
|
metalist
|
|
64
70
|
```
|
|
65
|
-
For source-checkout compatibility, `python main.py`
|
|
71
|
+
For source-checkout compatibility, `python main.py` performs the same orchestration. Use `metalist work`, `python main.py --namespace work`, or `python main.py work` when you want one foreground namespace process.
|
|
66
72
|
|
|
67
73
|
`metalist` and explicit single-namespace source runs bind HTTP on `0.0.0.0:8000` by default, matching the old MetaList LAN-friendly behavior.
|
|
68
74
|
On first startup, MetaList also auto-generates a self-signed TLS pair at `~/MetaList/certs/metalist-cert.pem` and `~/MetaList/certs/metalist-key.pem`, then enables HTTPS on `0.0.0.0:8443`. If you already have real PEM files, point `METALIST_TLS_CERT` and `METALIST_TLS_KEY` at them instead. Set `METALIST_AUTO_GENERATE_TLS=0` only if you explicitly want HTTP-only startup.
|
|
@@ -75,7 +81,7 @@ Database selection:
|
|
|
75
81
|
- Launch precedence is: explicit CLI flags > env vars > saved namespace profile; if a namespace has no saved profile, launch it once with explicit ports or configure ports from the UI
|
|
76
82
|
- Backups stay beside the namespace data under `~/MetaList/namespaces/work/backups/` and use one archive per snapshot with filenames like `work-<timestamp>.metalist-backup.tar.gz`
|
|
77
83
|
- The Backup Settings modal targets one user-selected backup folder and can include multiple namespaces in a single run
|
|
78
|
-
- Restoring `work` into `work` is the normal overwrite path; importing a backup under a different namespace name
|
|
84
|
+
- Restoring `work` into `work` is the normal overwrite path; importing a backup under a different namespace name can create a new target namespace with automatically selected conflict-free ports.
|
|
79
85
|
|
|
80
86
|
Useful env flags:
|
|
81
87
|
- `CRASH_SERVER_ON_FAIL=1` (default): fail-fast on validation errors
|
|
@@ -45,6 +45,8 @@ _PROCESS_WAIT_POLL_INTERVAL_SECONDS = 0.25
|
|
|
45
45
|
_TERMINATE_GRACE_SECONDS = 5.0
|
|
46
46
|
_KILL_GRACE_SECONDS = 5.0
|
|
47
47
|
_PROBE_TAB_ID = "namespace-switcher-probe"
|
|
48
|
+
_LAUNCH_LOG_TAIL_BYTES = 16 * 1024
|
|
49
|
+
ORCHESTRATED_CHILD_ENV_NAME = "METALIST_ORCHESTRATED_CHILD"
|
|
48
50
|
|
|
49
51
|
|
|
50
52
|
@dataclass(frozen=True)
|
|
@@ -75,6 +77,12 @@ class NamespaceOpenResult:
|
|
|
75
77
|
message: str
|
|
76
78
|
|
|
77
79
|
|
|
80
|
+
@dataclass(frozen=True)
|
|
81
|
+
class NamespaceLaunchProcess:
|
|
82
|
+
process: subprocess.Popen[bytes]
|
|
83
|
+
log_path: Path
|
|
84
|
+
|
|
85
|
+
|
|
78
86
|
@dataclass(frozen=True)
|
|
79
87
|
class NamespaceDeleteResult:
|
|
80
88
|
deleted_namespace: str
|
|
@@ -301,7 +309,7 @@ def open_or_launch_namespace(
|
|
|
301
309
|
chosen_profile=chosen_profile,
|
|
302
310
|
allowed_listener_pids=frozenset(),
|
|
303
311
|
)
|
|
304
|
-
_launch_namespace_process(
|
|
312
|
+
launched_process = _launch_namespace_process(
|
|
305
313
|
environ=environ,
|
|
306
314
|
chosen_profile=chosen_profile,
|
|
307
315
|
)
|
|
@@ -309,6 +317,7 @@ def open_or_launch_namespace(
|
|
|
309
317
|
environ=environ,
|
|
310
318
|
namespace=normalized_namespace,
|
|
311
319
|
port=chosen_profile.port,
|
|
320
|
+
launched_process=launched_process,
|
|
312
321
|
)
|
|
313
322
|
launched_url = _build_browser_url(environ=environ, port=chosen_profile.port)
|
|
314
323
|
assert launched_url is not None
|
|
@@ -388,6 +397,23 @@ def open_or_launch_all_namespaces(
|
|
|
388
397
|
return results
|
|
389
398
|
|
|
390
399
|
|
|
400
|
+
def stop_all_namespace_processes_for_update() -> int:
|
|
401
|
+
profiles = _load_saved_profiles_by_namespace()
|
|
402
|
+
reserved_ports: set[int] = set()
|
|
403
|
+
for profile in profiles.values():
|
|
404
|
+
for _, port in _profile_service_ports(profile=profile):
|
|
405
|
+
reserved_ports.add(port)
|
|
406
|
+
|
|
407
|
+
listener_pids: set[int] = set()
|
|
408
|
+
for port in sorted(reserved_ports):
|
|
409
|
+
listener_pids.update(_find_listening_pids_for_port(port=port))
|
|
410
|
+
current_pid = os.getpid()
|
|
411
|
+
listener_pids.discard(current_pid)
|
|
412
|
+
for pid in sorted(listener_pids):
|
|
413
|
+
_stop_process(pid=pid)
|
|
414
|
+
return len(listener_pids)
|
|
415
|
+
|
|
416
|
+
|
|
391
417
|
def _resolve_conflict_free_profiles_for_all_namespaces(
|
|
392
418
|
*,
|
|
393
419
|
raw_namespaces: Sequence[object],
|
|
@@ -1500,7 +1526,7 @@ def _launch_namespace_process(
|
|
|
1500
1526
|
*,
|
|
1501
1527
|
environ: Mapping[str, str],
|
|
1502
1528
|
chosen_profile: NamespaceLaunchProfile,
|
|
1503
|
-
) ->
|
|
1529
|
+
) -> NamespaceLaunchProcess:
|
|
1504
1530
|
child_environ = dict(environ)
|
|
1505
1531
|
for name in (
|
|
1506
1532
|
"METALIST_NAMESPACE",
|
|
@@ -1510,6 +1536,7 @@ def _launch_namespace_process(
|
|
|
1510
1536
|
):
|
|
1511
1537
|
if name in child_environ:
|
|
1512
1538
|
del child_environ[name]
|
|
1539
|
+
child_environ[ORCHESTRATED_CHILD_ENV_NAME] = "1"
|
|
1513
1540
|
command = _resolve_main_launch_command(environ=child_environ)
|
|
1514
1541
|
command.extend(
|
|
1515
1542
|
[
|
|
@@ -1529,7 +1556,7 @@ def _launch_namespace_process(
|
|
|
1529
1556
|
recycle_direct_append_log_file(path=log_path)
|
|
1530
1557
|
log_handle = open(log_path, "ab")
|
|
1531
1558
|
try:
|
|
1532
|
-
subprocess.Popen(
|
|
1559
|
+
process = subprocess.Popen(
|
|
1533
1560
|
command,
|
|
1534
1561
|
env=child_environ,
|
|
1535
1562
|
stdout=log_handle,
|
|
@@ -1538,6 +1565,7 @@ def _launch_namespace_process(
|
|
|
1538
1565
|
)
|
|
1539
1566
|
finally:
|
|
1540
1567
|
log_handle.close()
|
|
1568
|
+
return NamespaceLaunchProcess(process=process, log_path=log_path)
|
|
1541
1569
|
|
|
1542
1570
|
|
|
1543
1571
|
def _stop_processes_listening_on_port(*, port: int) -> None:
|
|
@@ -1567,7 +1595,7 @@ def _restart_running_namespace_process(
|
|
|
1567
1595
|
allowed_listener_pids=allowed_listener_pids,
|
|
1568
1596
|
)
|
|
1569
1597
|
_stop_processes_listening_on_port(port=running_port)
|
|
1570
|
-
_launch_namespace_process(
|
|
1598
|
+
launched_process = _launch_namespace_process(
|
|
1571
1599
|
environ=environ,
|
|
1572
1600
|
chosen_profile=chosen_profile,
|
|
1573
1601
|
)
|
|
@@ -1575,20 +1603,44 @@ def _restart_running_namespace_process(
|
|
|
1575
1603
|
environ=environ,
|
|
1576
1604
|
namespace=namespace,
|
|
1577
1605
|
port=chosen_profile.port,
|
|
1606
|
+
launched_process=launched_process,
|
|
1578
1607
|
)
|
|
1579
1608
|
|
|
1580
1609
|
|
|
1610
|
+
def _read_namespace_launch_log_tail(*, log_path: Path) -> str:
|
|
1611
|
+
read_capture = CapturedExceptionContext(OSError)
|
|
1612
|
+
log_bytes: bytes | None = None
|
|
1613
|
+
with read_capture:
|
|
1614
|
+
log_bytes = log_path.read_bytes()
|
|
1615
|
+
if read_capture.captured_exception is not None:
|
|
1616
|
+
return f"<unable to read child log: {read_capture.captured_exception}>"
|
|
1617
|
+
if log_bytes is None:
|
|
1618
|
+
raise RuntimeError("Namespace child log read produced no bytes")
|
|
1619
|
+
tail = log_bytes[-_LAUNCH_LOG_TAIL_BYTES:].decode("utf-8", errors="replace").strip()
|
|
1620
|
+
if tail == "":
|
|
1621
|
+
return "<child log is empty>"
|
|
1622
|
+
return tail
|
|
1623
|
+
|
|
1624
|
+
|
|
1581
1625
|
def _wait_for_namespace_ready(
|
|
1582
1626
|
*,
|
|
1583
1627
|
environ: Mapping[str, str],
|
|
1584
1628
|
namespace: str,
|
|
1585
1629
|
port: int,
|
|
1630
|
+
launched_process: NamespaceLaunchProcess,
|
|
1586
1631
|
) -> None:
|
|
1587
1632
|
main_server_config = resolve_main_server_config(environ=environ)
|
|
1588
1633
|
connect_host = resolve_backend_connect_host(host=main_server_config.host)
|
|
1589
1634
|
api_prefix = resolve_api_prefix(environ=environ)
|
|
1590
1635
|
deadline = time.monotonic() + _LAUNCH_READY_TIMEOUT_SECONDS
|
|
1591
1636
|
while time.monotonic() < deadline:
|
|
1637
|
+
exit_code = launched_process.process.poll()
|
|
1638
|
+
if exit_code is not None:
|
|
1639
|
+
log_tail = _read_namespace_launch_log_tail(log_path=launched_process.log_path)
|
|
1640
|
+
raise RuntimeError(
|
|
1641
|
+
f"Namespace {namespace} process exited with code {exit_code}. "
|
|
1642
|
+
f"Child log: {launched_process.log_path}\n{log_tail}"
|
|
1643
|
+
)
|
|
1592
1644
|
status_payload = _probe_namespace_status(
|
|
1593
1645
|
host=connect_host,
|
|
1594
1646
|
port=port,
|
|
@@ -1597,7 +1649,11 @@ def _wait_for_namespace_ready(
|
|
|
1597
1649
|
if status_payload is not None and status_payload.get("namespace") == namespace:
|
|
1598
1650
|
return
|
|
1599
1651
|
time.sleep(_READY_POLL_INTERVAL_SECONDS)
|
|
1600
|
-
|
|
1652
|
+
log_tail = _read_namespace_launch_log_tail(log_path=launched_process.log_path)
|
|
1653
|
+
raise RuntimeError(
|
|
1654
|
+
f"Timed out waiting for namespace {namespace} on port {port}. "
|
|
1655
|
+
f"Child log: {launched_process.log_path}\n{log_tail}"
|
|
1656
|
+
)
|
|
1601
1657
|
|
|
1602
1658
|
|
|
1603
1659
|
def _probe_namespace_status(
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
import os
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
import shlex
|
|
8
|
+
import shutil
|
|
9
|
+
import subprocess
|
|
10
|
+
|
|
11
|
+
from app.services.namespace_switcher import stop_all_namespace_processes_for_update
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
_WINDOWS_CREATE_NEW_CONSOLE = 0x00000010
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True)
|
|
18
|
+
class SelfUpdateScheduleResult:
|
|
19
|
+
stopped_process_count: int
|
|
20
|
+
platform_name: str
|
|
21
|
+
message: str
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def schedule_self_update(
|
|
25
|
+
*,
|
|
26
|
+
metalist_executable: str,
|
|
27
|
+
current_pid: int,
|
|
28
|
+
platform_name: str,
|
|
29
|
+
environ: Mapping[str, str],
|
|
30
|
+
) -> SelfUpdateScheduleResult:
|
|
31
|
+
_validate_schedule_inputs(
|
|
32
|
+
metalist_executable=metalist_executable,
|
|
33
|
+
current_pid=current_pid,
|
|
34
|
+
platform_name=platform_name,
|
|
35
|
+
)
|
|
36
|
+
uv_executable = shutil.which("uv")
|
|
37
|
+
if uv_executable is None:
|
|
38
|
+
raise RuntimeError("uv executable was not found on PATH; MetaList was not stopped")
|
|
39
|
+
|
|
40
|
+
updater_command: list[str]
|
|
41
|
+
updater_options: dict[str, object]
|
|
42
|
+
if platform_name == "win32":
|
|
43
|
+
powershell_executable = _resolve_windows_powershell()
|
|
44
|
+
updater_command = _build_windows_updater_command(
|
|
45
|
+
powershell_executable=powershell_executable,
|
|
46
|
+
uv_executable=uv_executable,
|
|
47
|
+
metalist_executable=metalist_executable,
|
|
48
|
+
current_pid=current_pid,
|
|
49
|
+
)
|
|
50
|
+
updater_options = {
|
|
51
|
+
"creationflags": _WINDOWS_CREATE_NEW_CONSOLE,
|
|
52
|
+
"cwd": str(Path.home()),
|
|
53
|
+
"env": dict(environ),
|
|
54
|
+
}
|
|
55
|
+
else:
|
|
56
|
+
shell_path = Path("/bin/sh")
|
|
57
|
+
if not shell_path.is_file():
|
|
58
|
+
raise RuntimeError("/bin/sh is required for MetaList self-update; MetaList was not stopped")
|
|
59
|
+
updater_command = _build_posix_updater_command(
|
|
60
|
+
shell_executable=str(shell_path),
|
|
61
|
+
uv_executable=uv_executable,
|
|
62
|
+
metalist_executable=metalist_executable,
|
|
63
|
+
current_pid=current_pid,
|
|
64
|
+
)
|
|
65
|
+
updater_options = {
|
|
66
|
+
"start_new_session": True,
|
|
67
|
+
"cwd": str(Path.home()),
|
|
68
|
+
"env": dict(environ),
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
stopped_process_count = stop_all_namespace_processes_for_update()
|
|
72
|
+
subprocess.Popen(updater_command, **updater_options)
|
|
73
|
+
return SelfUpdateScheduleResult(
|
|
74
|
+
stopped_process_count=stopped_process_count,
|
|
75
|
+
platform_name=platform_name,
|
|
76
|
+
message=(
|
|
77
|
+
f"Stopped {stopped_process_count} MetaList process(es). "
|
|
78
|
+
"The updater will install the latest release and restart MetaList."
|
|
79
|
+
),
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _validate_schedule_inputs(
|
|
84
|
+
*,
|
|
85
|
+
metalist_executable: str,
|
|
86
|
+
current_pid: int,
|
|
87
|
+
platform_name: str,
|
|
88
|
+
) -> None:
|
|
89
|
+
if not isinstance(metalist_executable, str) or metalist_executable.strip() == "":
|
|
90
|
+
raise ValueError("metalist_executable must be a non-empty string")
|
|
91
|
+
if not isinstance(current_pid, int) or current_pid <= 0:
|
|
92
|
+
raise ValueError("current_pid must be a positive integer")
|
|
93
|
+
if platform_name not in {"darwin", "linux", "win32"}:
|
|
94
|
+
raise RuntimeError(f"MetaList self-update does not support platform: {platform_name}")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _resolve_windows_powershell() -> str:
|
|
98
|
+
powershell_executable = shutil.which("powershell.exe")
|
|
99
|
+
if powershell_executable is not None:
|
|
100
|
+
return powershell_executable
|
|
101
|
+
pwsh_executable = shutil.which("pwsh.exe")
|
|
102
|
+
if pwsh_executable is not None:
|
|
103
|
+
return pwsh_executable
|
|
104
|
+
raise RuntimeError("PowerShell is required for MetaList self-update; MetaList was not stopped")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _quote_powershell_literal(value: str) -> str:
|
|
108
|
+
return "'" + value.replace("'", "''") + "'"
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _build_windows_updater_command(
|
|
112
|
+
*,
|
|
113
|
+
powershell_executable: str,
|
|
114
|
+
uv_executable: str,
|
|
115
|
+
metalist_executable: str,
|
|
116
|
+
current_pid: int,
|
|
117
|
+
) -> list[str]:
|
|
118
|
+
quoted_uv = _quote_powershell_literal(uv_executable)
|
|
119
|
+
quoted_metalist = _quote_powershell_literal(metalist_executable)
|
|
120
|
+
script = (
|
|
121
|
+
f"while (Get-Process -Id {current_pid} -ErrorAction SilentlyContinue) "
|
|
122
|
+
"{ Start-Sleep -Milliseconds 100 }; "
|
|
123
|
+
f"& {quoted_uv} tool install --force --reinstall --refresh metalist; "
|
|
124
|
+
"if ($LASTEXITCODE -ne 0) { "
|
|
125
|
+
"Write-Host 'MetaList update failed. Review the uv output above.' -ForegroundColor Red; "
|
|
126
|
+
"Start-Sleep -Seconds 10; exit $LASTEXITCODE }; "
|
|
127
|
+
f"& {quoted_metalist}; "
|
|
128
|
+
"if ($LASTEXITCODE -ne 0) { "
|
|
129
|
+
"Write-Host 'MetaList updated, but restart failed.' -ForegroundColor Red; "
|
|
130
|
+
"Start-Sleep -Seconds 10; exit $LASTEXITCODE }; "
|
|
131
|
+
"Write-Host 'MetaList update complete.' -ForegroundColor Green; "
|
|
132
|
+
"Start-Sleep -Seconds 3"
|
|
133
|
+
)
|
|
134
|
+
return [
|
|
135
|
+
powershell_executable,
|
|
136
|
+
"-NoLogo",
|
|
137
|
+
"-NoProfile",
|
|
138
|
+
"-NonInteractive",
|
|
139
|
+
"-Command",
|
|
140
|
+
script,
|
|
141
|
+
]
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _build_posix_updater_command(
|
|
145
|
+
*,
|
|
146
|
+
shell_executable: str,
|
|
147
|
+
uv_executable: str,
|
|
148
|
+
metalist_executable: str,
|
|
149
|
+
current_pid: int,
|
|
150
|
+
) -> list[str]:
|
|
151
|
+
uv_command = shlex.join(
|
|
152
|
+
[uv_executable, "tool", "install", "--force", "--reinstall", "--refresh", "metalist"]
|
|
153
|
+
)
|
|
154
|
+
metalist_command = shlex.join([metalist_executable])
|
|
155
|
+
script = (
|
|
156
|
+
f"while kill -0 {current_pid} 2>/dev/null; do sleep 0.1; done\n"
|
|
157
|
+
f"if ! {uv_command}; then\n"
|
|
158
|
+
" echo 'MetaList update failed. Review the uv output above.' >&2\n"
|
|
159
|
+
" exit 1\n"
|
|
160
|
+
"fi\n"
|
|
161
|
+
f"if ! {metalist_command}; then\n"
|
|
162
|
+
" echo 'MetaList updated, but restart failed.' >&2\n"
|
|
163
|
+
" exit 1\n"
|
|
164
|
+
"fi\n"
|
|
165
|
+
"echo 'MetaList update complete.'\n"
|
|
166
|
+
)
|
|
167
|
+
return [shell_executable, "-c", script]
|
|
@@ -33,7 +33,9 @@ from app.startup_sanity import assert_startup_sanity
|
|
|
33
33
|
from app.services.exception_capture import CapturedExceptionContext
|
|
34
34
|
from app.services.namespace_switcher import build_namespace_catalog
|
|
35
35
|
from app.services.namespace_switcher import NamespaceOpenResult
|
|
36
|
+
from app.services.namespace_switcher import ORCHESTRATED_CHILD_ENV_NAME
|
|
36
37
|
from app.services.namespace_switcher import open_or_launch_all_namespaces
|
|
38
|
+
from app.services.self_update import schedule_self_update
|
|
37
39
|
from app.services.windows_process_control import find_listening_pids_for_port as find_windows_listening_pids_for_port
|
|
38
40
|
from app.services.windows_process_control import is_process_running as is_windows_process_running
|
|
39
41
|
from app.services.windows_process_control import stop_process as stop_windows_process
|
|
@@ -775,7 +777,29 @@ def main(argv: list[str]) -> None:
|
|
|
775
777
|
|
|
776
778
|
|
|
777
779
|
def cli() -> None:
|
|
778
|
-
|
|
780
|
+
argv = sys.argv[1:]
|
|
781
|
+
if ORCHESTRATED_CHILD_ENV_NAME in os.environ:
|
|
782
|
+
orchestrated_child = os.environ[ORCHESTRATED_CHILD_ENV_NAME]
|
|
783
|
+
if orchestrated_child != "1":
|
|
784
|
+
raise RuntimeError(f"{ORCHESTRATED_CHILD_ENV_NAME} must be '1' when set")
|
|
785
|
+
del os.environ[ORCHESTRATED_CHILD_ENV_NAME]
|
|
786
|
+
run_orchestrated_namespace_server(argv)
|
|
787
|
+
return
|
|
788
|
+
if len(argv) != 0 and argv[0] == "update":
|
|
789
|
+
if argv != ["update"]:
|
|
790
|
+
raise RuntimeError("Usage: metalist update")
|
|
791
|
+
metalist_executable = _resolve_current_entrypoint()
|
|
792
|
+
if metalist_executable is None:
|
|
793
|
+
raise RuntimeError("Could not resolve the installed MetaList executable")
|
|
794
|
+
result = schedule_self_update(
|
|
795
|
+
metalist_executable=metalist_executable,
|
|
796
|
+
current_pid=os.getpid(),
|
|
797
|
+
platform_name=sys.platform,
|
|
798
|
+
environ=os.environ,
|
|
799
|
+
)
|
|
800
|
+
print(result.message)
|
|
801
|
+
return
|
|
802
|
+
main(argv)
|
|
779
803
|
|
|
780
804
|
|
|
781
805
|
def run_namespace_server(argv: list[str]) -> None:
|
|
@@ -787,6 +811,12 @@ def run_namespace_server(argv: list[str]) -> None:
|
|
|
787
811
|
_run_namespace_server_for_current_env(argv=argv)
|
|
788
812
|
|
|
789
813
|
|
|
814
|
+
def run_orchestrated_namespace_server(argv: list[str]) -> None:
|
|
815
|
+
logging.getLogger("uvicorn.access").addFilter(FilterCheckUpdates())
|
|
816
|
+
apply_main_cli_args_to_environ(argv=argv, environ=os.environ)
|
|
817
|
+
_run_namespace_server_for_current_env(argv=argv)
|
|
818
|
+
|
|
819
|
+
|
|
790
820
|
def _run_namespace_server_for_current_env(*, argv: list[str]) -> None:
|
|
791
821
|
database_runtime_config = resolve_database_runtime_config(
|
|
792
822
|
environ=os.environ,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: metalist
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.10
|
|
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
|
|
@@ -76,6 +76,12 @@ uv tool install metalist
|
|
|
76
76
|
metalist
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
+
After the first installation, update and restart MetaList with one cross-platform command:
|
|
80
|
+
```bash
|
|
81
|
+
metalist update
|
|
82
|
+
```
|
|
83
|
+
The updater stops running namespaces, hands off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock, runs the forced cache-refreshed uv update, and launches MetaList again.
|
|
84
|
+
|
|
79
85
|
For pip, users can run `pip install metalist`. For a non-editable local install from this checkout, use `uv pip install .` or `pip install .` instead of the editable command below.
|
|
80
86
|
|
|
81
87
|
```bash
|
|
@@ -87,11 +93,11 @@ npm install
|
|
|
87
93
|
```
|
|
88
94
|
|
|
89
95
|
### Run
|
|
90
|
-
The installed entrypoint starts
|
|
96
|
+
The installed entrypoint starts or restarts every known namespace, prints their URLs, and exits:
|
|
91
97
|
```bash
|
|
92
98
|
metalist
|
|
93
99
|
```
|
|
94
|
-
For source-checkout compatibility, `python main.py`
|
|
100
|
+
For source-checkout compatibility, `python main.py` performs the same orchestration. Use `metalist work`, `python main.py --namespace work`, or `python main.py work` when you want one foreground namespace process.
|
|
95
101
|
|
|
96
102
|
`metalist` and explicit single-namespace source runs bind HTTP on `0.0.0.0:8000` by default, matching the old MetaList LAN-friendly behavior.
|
|
97
103
|
On first startup, MetaList also auto-generates a self-signed TLS pair at `~/MetaList/certs/metalist-cert.pem` and `~/MetaList/certs/metalist-key.pem`, then enables HTTPS on `0.0.0.0:8443`. If you already have real PEM files, point `METALIST_TLS_CERT` and `METALIST_TLS_KEY` at them instead. Set `METALIST_AUTO_GENERATE_TLS=0` only if you explicitly want HTTP-only startup.
|
|
@@ -104,7 +110,7 @@ Database selection:
|
|
|
104
110
|
- Launch precedence is: explicit CLI flags > env vars > saved namespace profile; if a namespace has no saved profile, launch it once with explicit ports or configure ports from the UI
|
|
105
111
|
- Backups stay beside the namespace data under `~/MetaList/namespaces/work/backups/` and use one archive per snapshot with filenames like `work-<timestamp>.metalist-backup.tar.gz`
|
|
106
112
|
- The Backup Settings modal targets one user-selected backup folder and can include multiple namespaces in a single run
|
|
107
|
-
- Restoring `work` into `work` is the normal overwrite path; importing a backup under a different namespace name
|
|
113
|
+
- Restoring `work` into `work` is the normal overwrite path; importing a backup under a different namespace name can create a new target namespace with automatically selected conflict-free ports.
|
|
108
114
|
|
|
109
115
|
Useful env flags:
|
|
110
116
|
- `CRASH_SERVER_ON_FAIL=1` (default): fail-fast on validation errors
|
|
@@ -114,6 +114,7 @@ app/services/search_history.py
|
|
|
114
114
|
app/services/search_index.py
|
|
115
115
|
app/services/search_query.py
|
|
116
116
|
app/services/search_text.py
|
|
117
|
+
app/services/self_update.py
|
|
117
118
|
app/services/session_timeout_service.py
|
|
118
119
|
app/services/shell_session_service.py
|
|
119
120
|
app/services/snapshot.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|