MetaList 0.18.0__tar.gz → 0.20.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {metalist-0.18.0/metalist.egg-info → metalist-0.20.0}/PKG-INFO +21 -1
- {metalist-0.18.0 → metalist-0.20.0}/README.md +20 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/api/note_requests.py +43 -3
- {metalist-0.18.0 → metalist-0.20.0}/app/api/routes/ai.py +275 -21
- {metalist-0.18.0 → metalist-0.20.0}/app/api/routes/notes.py +157 -18
- {metalist-0.18.0 → metalist-0.20.0}/app/exception_boundaries.py +1 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/presentation/render/note_renderer.py +1 -1
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/cloud_privacy.py +52 -19
- metalist-0.20.0/app/services/agent/export_title_suggestions.py +187 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/failure_explanations.py +1 -0
- metalist-0.20.0/app/services/agent/note_tag_suggestions.py +318 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/scope.py +4 -2
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/skills/help-ai.md +32 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/skills/help-data.md +9 -2
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/skills/help-formatting.md +22 -6
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/skills/help-menus.md +2 -1
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/skills/help-notes.md +4 -3
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/skills/help-privacy.md +6 -4
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/skills/help-releases.md +20 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/skills/help-search.md +2 -1
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/skills/help-tags.md +14 -9
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/structured_inference.py +2 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/tagging_run.py +43 -25
- {metalist-0.18.0 → metalist-0.20.0}/app/services/ai_chat_rendering.py +2 -2
- metalist-0.20.0/app/services/ai_setup.py +84 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/code_rendering.py +28 -2
- {metalist-0.18.0 → metalist-0.20.0}/app/services/content_formatting.py +40 -20
- {metalist-0.18.0 → metalist-0.20.0}/app/services/diagnostics.py +7 -1
- {metalist-0.18.0 → metalist-0.20.0}/app/services/embedded_references.py +51 -49
- metalist-0.20.0/app/services/html_export.py +652 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/markdown_rendering.py +5 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/note_fullscreen.py +1 -1
- {metalist-0.18.0 → metalist-0.20.0}/app/services/note_store.py +21 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/search_history.py +25 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/search_index.py +61 -17
- {metalist-0.18.0 → metalist-0.20.0}/app/services/snapshot.py +23 -20
- metalist-0.20.0/app/services/tag_details.py +224 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/tag_suggestion_reasons.py +130 -66
- {metalist-0.18.0 → metalist-0.20.0}/app/services/tag_suggestions.py +19 -6
- {metalist-0.18.0 → metalist-0.20.0}/app/services/tag_term_matching.py +57 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/undo_state.py +88 -1
- {metalist-0.18.0 → metalist-0.20.0}/app/services/windows_process_control.py +6 -2
- {metalist-0.18.0 → metalist-0.20.0}/app/startup_sanity_config.py +2 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/config/agent-menu-actions.json +6 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/config/command_palette_tags.json +4 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/css/main.css +322 -33
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/ai-chat/ai-chat-api.js +157 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/api-client.js +172 -23
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/command-palette/command-palette-controller.js +12 -65
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/command-palette/endpoint-registry.js +7 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/config.js +10 -1
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/context-menu/context-menu-registry.js +80 -19
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/context-menu/context-menu-service.js +24 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/context-menu/input-caret-service.js +15 -3
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/error-handler.js +3 -1
- metalist-0.20.0/app/static/js/modules/modals/export-options-modal.js +314 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/actions/content-actions.js +3 -1
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/actions/note-actions.js +2 -1
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/actions/ui-actions.js +15 -1
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/events/context-menu-events.js +460 -299
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/events/keyboard-events.js +168 -10
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/events/mouse-events.js +92 -6
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/command-gate-service.js +12 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/differential-view-service.js +10 -0
- metalist-0.20.0/app/static/js/modules/mode-manager/services/export-service.js +64 -0
- metalist-0.20.0/app/static/js/modules/mode-manager/services/export-title-service.js +59 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/paste-format-detection-service.js +127 -1
- metalist-0.20.0/app/static/js/modules/mode-manager/services/paste-format-guess-service.js +317 -0
- metalist-0.20.0/app/static/js/modules/mode-manager/services/paste-format-offer-service.js +185 -0
- metalist-0.20.0/app/static/js/modules/mode-manager/services/print-service.js +82 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/tag-bar-service.js +34 -1
- metalist-0.20.0/app/static/js/modules/mode-manager/services/tag-proposal-service.js +359 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/viewport-hold-service.js +72 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/prefetch_link_titles.py +1 -1
- metalist-0.20.0/app/usecases/tag_proposals.py +390 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/version.py +1 -1
- {metalist-0.18.0 → metalist-0.20.0}/main.py +24 -1
- {metalist-0.18.0 → metalist-0.20.0/metalist.egg-info}/PKG-INFO +21 -1
- {metalist-0.18.0 → metalist-0.20.0}/metalist.egg-info/SOURCES.txt +10 -0
- metalist-0.18.0/app/services/html_export.py +0 -327
- metalist-0.18.0/app/static/js/modules/mode-manager/services/tag-proposal-service.js +0 -141
- metalist-0.18.0/app/usecases/tag_proposals.py +0 -236
- {metalist-0.18.0 → metalist-0.20.0}/MANIFEST.in +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/__init__.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/api/__init__.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/api/deps.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/api/dev.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/api/middleware/auth.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/api/request_auth.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/api/routes/app_updates.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/api/routes/auth.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/api/routes/backups.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/api/routes/files.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/api/routes/ontology.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/api/routes/reminders.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/api/routes/remote_images.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/api/routes/test.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/api/transactions.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/api/upload_limits.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/config.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/data_directory.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/__init__.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/backup_settings_sql.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/editable_files_migration.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/engine.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/file_schema.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/file_session.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/files_sql.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/link_titles_sql.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/live_recovery.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/migrations.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/notes_sql.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/ontology_rules_sql.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/reminders_sql.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/retire_sounds.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/schema.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/search_history_sql.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/session.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/settings_sql.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/tab_state_sql.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/db/version.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/encryption_audit.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/https_proxy.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/main.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/models/commands.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/models/database.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/models/entities.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/models/enums.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/models/linked_list.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/models/list_operations.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/models/list_traversal.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/models/note_crud.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/models/utils.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/network_settings.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/presentation/__init__.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/presentation/login_page.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/presentation/render/__init__.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/presentation/templates.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/security/authenticated_logging.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/security/encryption.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/security/http_error_diagnostics.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/security/http_headers.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/security/note_html.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/security/request_boundary.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/security/request_hosts.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/security/sensitive_cache.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/security/sensitive_logging.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/security/shell_execution.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/security/validation_errors.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/server_runtime.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/__init__.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/__init__.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/action_log.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/agent_loop.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/agent_tools.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/citation_tokens.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/context.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/evidence_serialization.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/execution_errors.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/help_catalog.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/history.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/inference.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/investigation.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/judging.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/menu_actions.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/model_policy.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/note_aliases.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/openai_cost_tracking.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/openai_inference.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/prompt_settings.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/prompts/__init__.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/prompts/agent.md +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/prompts/final-response.md +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/prompts/system.md +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/release_notes.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/retrieval_settings.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/runtime.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/skill_settings.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/skills/__init__.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/skills/help-dictation.md +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/skills/help-references.md +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/skills/help-reminders.md +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/skills/staged-summary.md +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/skills/tag-proposals.md +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/skills/web-browsing.md +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/staged_summary.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/strict_structured_outputs.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/summary_batch_store.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/tagging.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/token_estimation.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/tool_calling.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/trace.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/web_actions.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/web_capabilities.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/web_evidence.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/web_fetch.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/agent/web_settings.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/ai_chat.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/ai_chat_stream.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/app_update_worker.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/app_updates.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/auth.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/auth_cache_state.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/auth_service.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/backlink_index.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/backlinks.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/backup_service.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/backup_settings_service.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/bulk_operation.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/chess_rendering.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/client_state_service.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/content_cache.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/dictation_cleanup.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/diff_rendering.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/encryption.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/exception_capture.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/file_edit_sessions.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/file_registry.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/file_storage.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/file_text_preview.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/footnote_layout.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/footnote_rendering.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/hierarchy.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/html_unformatting.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/hydration_state.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/image_size_formatting.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/inline_image_dimensions.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/inline_image_occurrences.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/input_errors.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/integrity.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/latex_rendering.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/link_title_retry.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/link_titles.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/login_rate_limit.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/maintenance_mode.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/mermaid_note_rendering.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/namespace_deletion_jobs.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/namespace_deletion_worker.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/namespace_rename_jobs.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/namespace_rename_worker.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/namespace_runtime_guard.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/namespace_switcher.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/note_image_tags.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/note_ordering.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/ontology_rules_store.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/openai_credentials.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/password_note_fields.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/public_http.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/reference_presentation.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/reminders.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/remote_image_proxy.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/request_recovery.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/resource_limits.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/root_sorting.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/runtime_generation.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/runtime_hardening.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/runtime_lock.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/search_history_storage.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/search_query.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/search_text.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/selected_text_tag.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/self_update.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/session_timeout_service.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/shell_session_service.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/store.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/structured_note_renderers.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/sync.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/sync_state.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/tab_state.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/tag_case.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/tag_ontology.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/tag_rename.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/test_reset.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/tokens.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/update_backups.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/update_installer.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/update_preflight.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/view_cache.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/view_diff.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/services/view_state.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/startup_console.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/startup_environment.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/startup_js_sanity.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/startup_sanity.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/css/floating-notes.css +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/css/forms.css +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/img/favicon.ico +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/locked.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/main.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/activity-tracker.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/ai-chat/agent-menu-actions.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/ai-chat/agent-retrieval-settings.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/ai-chat/agent-web-settings.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/ai-chat/ai-agent-debug-view.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/ai-chat/ai-chat-message-placement.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/ai-chat/ai-chat-panel-controller.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/ai-chat/ai-chat-panel-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/ai-chat/ai-thinking-level-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/ai-chat/bulk-elapsed-clock.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/ai-chat/bulk-proposal-ui.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/ai-chat/bulk-scope-question.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/ai-chat/cloud-privacy-policy.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/ai-chat/confirmation-card.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/ai-chat/confirmation-question.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/ai-chat/proposal-menu.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/ai-chat/summary-batch-preview.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/api-error-diagnostics.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/api-failure-classification-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/app-update-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/application-state.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/async-result.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/auth.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/client-state-api.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/client-state-migration.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/command-palette/activation-auth-policy.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/command-palette/backup-command-availability.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/command-palette/click-activation-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/command-palette/note-layout-preferences.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/command-palette/preferences-store.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/command-palette/tag-config-loader.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/command-palette/usage-store.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/connectivity-monitor.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/context-menu/context-menu-target-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/disconnect-editing-state-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/dom-utils-fixed.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/dom-utils.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/editor-commands.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/editor-selection.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/editor-toolbar.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/elapsed-time.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/error-overlay.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/excalidraw/excalidraw-actions.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/excalidraw/excalidraw-autosave.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/excalidraw/excalidraw-editor-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/excalidraw/excalidraw-editor-state.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/excalidraw/excalidraw-loader.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/excalidraw/excalidraw-preview-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/excalidraw/excalidraw-scene.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/expected-errors.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/location-flags.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/login-namespace-picker.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/maintenance.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/ai-agent-settings-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/alphabetize-root-notes-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/backup-restore-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/backup-result-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/backup-retention-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/backup-settings-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/base-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/confirmation-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/delete-namespace-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/delete-namespace-validation.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/dictation-settings-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/help-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/link-title-retry-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/namespace-loading-page.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/namespace-modals.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/namespace-ports-profile.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/namespace-rename-validation.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/note-layout-appearance-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/ontology-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/password-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/prioritize-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/random-password-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/reminder-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/reset-updated-at-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/search-suggestion-statistics-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/session-timeout-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/tag-suggestion-settings-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/version-info-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/modals/visual-cues-modal.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/actions/history-actions.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/actions/search-actions.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/actions/selection-actions.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/events/focus-events.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/events/inactivity-events.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/events/input-events.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/events/search-events.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/mode-context.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/mode-logger.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/mode-manager-controller.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/add-style-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/animated-scroll-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/backlinks-navigation-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/backlinks-panel-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/clipboard-shortcut-policy-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/collapse-affordance-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/collapse-editing-policy-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/context-menu-target-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/deselect-selection-state-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/dictation-note-paste.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/dictation-paste-padding.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/dictation-paste-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/dropped-file-preview-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/edit-session-collapse-policy-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/edit-session-collapse-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/embedded-image-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/file-drop-policy-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/file-image-preview-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/file-reference-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/filtered-refresh-selection-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/floating-note-dom.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/floating-note-layout.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/floating-note-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/footnote-navigation-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/history-selection-policy-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/history-shortcut-policy-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/html-paste-sanitizer-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/image-context-menu-action-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/image-file-insert-choice-modal-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/infinite-scroll-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/link-context-menu-action-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/link-title-prefetch-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/markdown-render-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/mermaid-render-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/note-click-target-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/note-clipboard-write-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/note-collapse-animation-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/note-context-menu-action-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/note-delete-shortcut-policy-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/note-drag-indicator-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/note-drag-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/note-fullscreen-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/note-reposition-animation-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/note-split-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/note-timestamp-hover-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/password-clipboard-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/polling-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/reference-source-navigation-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/remote-image-proxy-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/remove-formatting-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/root-date-separator-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/root-note-creation-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/root-sort-indicator-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/root-sort-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/scroll-anchor-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/scroll-restoration-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/scroll-to-top-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/search-contexts-overlay-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/search-debounce-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/search-input-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/search-interaction-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/search-redaction-reveal-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/search-suggestion-statistics-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/search-suggestion-window-labels-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/search-suggestion-windows-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/search-suggestions-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/search-syntax-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/selected-formatting-removal-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/selected-text-tag-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/shell-output-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/tab-dom-cache-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/tab-drag-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/tab-duplication-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/tab-state-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/tag-input-selection-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/tag-suggestions-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/tag-syntax-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/todo-toggle-editing-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/untagged-view-indicator-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/mode-manager/services/view-mode-search-shortcut-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/note-html-sanitizer.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/password-generator.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/password-operation-response.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/password-policy.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/password-strength.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/reminder-store.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/reminder-surface-service.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/selection-markers.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/session-auth.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/tag-token.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/modules/uuid.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/namespace-deleted.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/namespace-renamed.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/dompurify-3.4.16.LICENSE.txt +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/dompurify-3.4.16.min.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/excalidraw.css +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Bold.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Medium.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Regular.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-SemiBold.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Cascadia/CascadiaCode-Regular.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Virgil/Virgil-Regular.woff2 +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1.LICENSE.txt +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/excalidraw-0.18.1.min.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/markdown-it-14.3.2.LICENSE.txt +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/markdown-it-14.3.2.min.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/mermaid-11.16.1.LICENSE.txt +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/mermaid-11.16.1.min.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/zxcvbn-4.4.2.LICENSE.txt +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/js/vendor/zxcvbn-4.4.2.js +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/static/note-html-policy.json +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/templates/_logo_mark.html +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/templates/base.html +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/templates/index.html +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/templates/locked.html +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/templates/maintenance.html +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/templates/namespace_deleted.html +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/templates/namespace_renamed.html +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/templates/notes_list.html +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/upload_limits.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/__init__.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/add_selected_text_tag.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/alphabetize_root_notes.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/base.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/bulk_tag_proposals.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/collapse.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/copy_note.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/create_child.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/create_file_preview_child.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/create_note.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/create_sibling.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/delete_subtree.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/delete_tag.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/expand.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/file_edit_session.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/indent.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/lock.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/move.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/move_to_top.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/outdent.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/paste_child.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/paste_sibling.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/prioritize.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/redo.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/rename_tag.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/reset_updated_at.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/resize_image.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/run_shell.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/search_comment_autofill.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/search_context_tags.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/set_collapse_bulk.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/set_collapse_in_context.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/split_note.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/toggle_reference_mode.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/toggle_todo_done.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/undo.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/unformat_content.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/update_content.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/usecases/view.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/utils/__init__.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/utils/encryption.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/app/utils/text_utils.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/convert-from-legacy.py +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/metalist.egg-info/dependency_links.txt +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/metalist.egg-info/entry_points.txt +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/metalist.egg-info/requires.txt +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/metalist.egg-info/top_level.txt +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/pyproject.toml +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/scripts/generate-lan-cert.sh +0 -0
- {metalist-0.18.0 → metalist-0.20.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: metalist
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.20.0
|
|
4
4
|
Summary: A minimalist single-user note-taking app with SSR, fast in-memory tree operations, and efficient sync.
|
|
5
5
|
Project-URL: Homepage, https://github.com/evolvingstuff/metalist
|
|
6
6
|
Project-URL: Repository, https://github.com/evolvingstuff/metalist
|
|
@@ -51,6 +51,26 @@ A minimalist single-user note-taking app focused on server-side rendering (SSR),
|
|
|
51
51
|
- Multi-tab search contexts with server-persisted scroll/search state (survives browser restarts)
|
|
52
52
|
- Manual namespace backups/restores to a user-selected backup folder with retention controls
|
|
53
53
|
|
|
54
|
+
## Changes in 0.20.0
|
|
55
|
+
|
|
56
|
+
- **Suggest Tags with AI** for the note being edited: right-click the note, or its tag bar past the tags, and choose 🤖 Suggest Tags with AI (for a note with children: This Note, or This Note and Its Children). The proposals appear under the tag bar for `+`/`−`, tags not yet in use marked **new** and grouped on the right; adding them can be undone. It shows only when an AI is set up and may see the note.
|
|
57
|
+
- The robot count (🤖 N) next to a note: click it to open every collapsed note on the way to its proposals and edit the highest one that has some; right-click it to Accept All or Reject All, one undo step.
|
|
58
|
+
- **Print**: the note menu's Print ▸ Note / View, the background menu's Print View, or the palette's Print view, through the browser's print dialog (Save as PDF included). Always light, fully expanded, without arrows, using the page's full width with its own margins, so the browser prints no header or footer.
|
|
59
|
+
- Export as HTML and Print open one dialog: a title with a smart default (the note's first line, or MetaList with the view's search), which heads the page unless the first note already says it and names an exported file; 🤖 Suggest with AI for the title, asked only when you press it, which never sees private notes, usernames, passwords or the search; and, when some would show, an Include Unredacted Passwords / Usernames checkbox (unchecked: each shows `••••••••`, whatever its length).
|
|
60
|
+
- Exported HTML files show the view as it is shown (its search, sort order, Untagged view; notes a search leaves out are absent), start fully expanded with MetaList's collapse arrows working in the file, and copy usernames, included passwords and `@copyable` values on click. Collapsing no longer shifts the page sideways.
|
|
61
|
+
- `@username` notes are private like `@password`: never sent to the AI. Username, password and email rows show just their icon, named on hover, and the value.
|
|
62
|
+
- Text never runs out of its note: a word too long for the line (a token, a hash, a long URL) breaks at the note's edge, and code, `@json`, `@diff`, CSV and Markdown code blocks wrap. Images shrink to fit their note or embedded note, and `@size` scales them only up to that width.
|
|
63
|
+
- The light theme's header bar is black again, with white icons and count, and the AI chat header now lines up with the search bar.
|
|
64
|
+
|
|
65
|
+
## Changes in 0.19.0
|
|
66
|
+
|
|
67
|
+
- Paste formats: pasting a fenced code block that names its language tags the note `@markdown`, and `@markdown` now colours that code like `@code=<language>` (with its label). Code copied from VS Code is tagged `@code=<its language>`, and cells copied from Excel, Google Sheets or Numbers become CSV text tagged `@csv`.
|
|
68
|
+
- Text that only looks like a format is offered, not applied: after pasting CSV-like, Markdown-like or code-like text, a small card says "Apply as CSV" / "Apply as Markdown" / "Apply as Python" (up to three close languages for code) with "Skip". The card moves nothing and never takes the keyboard; typing on, Escape or a click elsewhere closes it. It also appears when the paste makes a new note.
|
|
69
|
+
- Right-click a tag already in the tag bar or the search box for **About this tag**: whether the note names it, the notes it shares with your other tags, whether a parent or a rule already gives it, its synonyms and implications, how many notes have it ("Only on this note" hints at a typo); in the search box, what it finds and what leaving it out removes. Edit Tag Relationships now comes first in the tag menu, at a fixed place under the pointer.
|
|
70
|
+
- Tag suggestions: a web address in a note counts only by its site's name, so a YouTube link no longer suggests `HTTPS` or `V-neuron`; one letter alone no longer names a tag with longer words. A suggestion without evidence now says only what is true (what you typed matches, which part of its name the note has) instead of "Nothing in this note points to it".
|
|
71
|
+
- Fixed: accepting a Grammarly suggestion while editing could undo itself and end editing, when Grammarly drew its card in an element MetaList did not recognise.
|
|
72
|
+
- Removed the "Make pseudo-suggestions" test item from the note menu.
|
|
73
|
+
|
|
54
74
|
## Changes in 0.18.0
|
|
55
75
|
|
|
56
76
|
- Right-click a tag suggestion, in the tag bar or the search bar, to see why it is suggested. The menu starts with **Why suggested**: the words of the note that name the tag (or a synonym), the tags it goes with and on how many notes, notes sharing this note's tags, whether it already applies through a parent or a rule, or that nothing in the note points to it; then how often the tag is used. Search suggestions also say how often you worked with a tag lately (when that put it first), what your search so far finds, or what leaving it out removes. The reasons are MetaList's own ranking, not the AI's, and appear instantly.
|
|
@@ -12,6 +12,26 @@ 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.20.0
|
|
16
|
+
|
|
17
|
+
- **Suggest Tags with AI** for the note being edited: right-click the note, or its tag bar past the tags, and choose 🤖 Suggest Tags with AI (for a note with children: This Note, or This Note and Its Children). The proposals appear under the tag bar for `+`/`−`, tags not yet in use marked **new** and grouped on the right; adding them can be undone. It shows only when an AI is set up and may see the note.
|
|
18
|
+
- The robot count (🤖 N) next to a note: click it to open every collapsed note on the way to its proposals and edit the highest one that has some; right-click it to Accept All or Reject All, one undo step.
|
|
19
|
+
- **Print**: the note menu's Print ▸ Note / View, the background menu's Print View, or the palette's Print view, through the browser's print dialog (Save as PDF included). Always light, fully expanded, without arrows, using the page's full width with its own margins, so the browser prints no header or footer.
|
|
20
|
+
- Export as HTML and Print open one dialog: a title with a smart default (the note's first line, or MetaList with the view's search), which heads the page unless the first note already says it and names an exported file; 🤖 Suggest with AI for the title, asked only when you press it, which never sees private notes, usernames, passwords or the search; and, when some would show, an Include Unredacted Passwords / Usernames checkbox (unchecked: each shows `••••••••`, whatever its length).
|
|
21
|
+
- Exported HTML files show the view as it is shown (its search, sort order, Untagged view; notes a search leaves out are absent), start fully expanded with MetaList's collapse arrows working in the file, and copy usernames, included passwords and `@copyable` values on click. Collapsing no longer shifts the page sideways.
|
|
22
|
+
- `@username` notes are private like `@password`: never sent to the AI. Username, password and email rows show just their icon, named on hover, and the value.
|
|
23
|
+
- Text never runs out of its note: a word too long for the line (a token, a hash, a long URL) breaks at the note's edge, and code, `@json`, `@diff`, CSV and Markdown code blocks wrap. Images shrink to fit their note or embedded note, and `@size` scales them only up to that width.
|
|
24
|
+
- The light theme's header bar is black again, with white icons and count, and the AI chat header now lines up with the search bar.
|
|
25
|
+
|
|
26
|
+
## Changes in 0.19.0
|
|
27
|
+
|
|
28
|
+
- Paste formats: pasting a fenced code block that names its language tags the note `@markdown`, and `@markdown` now colours that code like `@code=<language>` (with its label). Code copied from VS Code is tagged `@code=<its language>`, and cells copied from Excel, Google Sheets or Numbers become CSV text tagged `@csv`.
|
|
29
|
+
- Text that only looks like a format is offered, not applied: after pasting CSV-like, Markdown-like or code-like text, a small card says "Apply as CSV" / "Apply as Markdown" / "Apply as Python" (up to three close languages for code) with "Skip". The card moves nothing and never takes the keyboard; typing on, Escape or a click elsewhere closes it. It also appears when the paste makes a new note.
|
|
30
|
+
- Right-click a tag already in the tag bar or the search box for **About this tag**: whether the note names it, the notes it shares with your other tags, whether a parent or a rule already gives it, its synonyms and implications, how many notes have it ("Only on this note" hints at a typo); in the search box, what it finds and what leaving it out removes. Edit Tag Relationships now comes first in the tag menu, at a fixed place under the pointer.
|
|
31
|
+
- Tag suggestions: a web address in a note counts only by its site's name, so a YouTube link no longer suggests `HTTPS` or `V-neuron`; one letter alone no longer names a tag with longer words. A suggestion without evidence now says only what is true (what you typed matches, which part of its name the note has) instead of "Nothing in this note points to it".
|
|
32
|
+
- Fixed: accepting a Grammarly suggestion while editing could undo itself and end editing, when Grammarly drew its card in an element MetaList did not recognise.
|
|
33
|
+
- Removed the "Make pseudo-suggestions" test item from the note menu.
|
|
34
|
+
|
|
15
35
|
## Changes in 0.18.0
|
|
16
36
|
|
|
17
37
|
- Right-click a tag suggestion, in the tag bar or the search bar, to see why it is suggested. The menu starts with **Why suggested**: the words of the note that name the tag (or a synonym), the tags it goes with and on how many notes, notes sharing this note's tags, whether it already applies through a parent or a rule, or that nothing in the note points to it; then how often the tag is used. Search suggestions also say how often you worked with a tag lately (when that put it first), what your search so far finds, or what leaving it out removes. The reasons are MetaList's own ranking, not the AI's, and appear instantly.
|
|
@@ -127,6 +127,22 @@ class TagSuggestionsRequest(TypedDict):
|
|
|
127
127
|
prefix: Text
|
|
128
128
|
content_html: Content
|
|
129
129
|
|
|
130
|
+
@with_config(ConfigDict(strict=True))
|
|
131
|
+
class TagDetailsRequest(TypedDict):
|
|
132
|
+
note_id: Identifier
|
|
133
|
+
tag: Identifier
|
|
134
|
+
tags_text: Text
|
|
135
|
+
content_html: Content
|
|
136
|
+
|
|
137
|
+
@with_config(ConfigDict(strict=True))
|
|
138
|
+
class SearchTagDetailsRequest(TypedDict):
|
|
139
|
+
query: Text
|
|
140
|
+
tag: Identifier
|
|
141
|
+
start: Nonnegative
|
|
142
|
+
end: Nonnegative
|
|
143
|
+
excluded: bool
|
|
144
|
+
windowDays: WindowDays
|
|
145
|
+
|
|
130
146
|
@with_config(ConfigDict(strict=True))
|
|
131
147
|
class CreateNoteTopRequest(TypedDict):
|
|
132
148
|
first_visible_note_id: Text | None
|
|
@@ -181,14 +197,38 @@ class AddSelectedTextTagRequest(TypedDict):
|
|
|
181
197
|
viewport: Viewport
|
|
182
198
|
|
|
183
199
|
@with_config(ConfigDict(strict=True))
|
|
184
|
-
class
|
|
200
|
+
class AcceptTagProposalRequest(TypedDict):
|
|
201
|
+
proposal: Identifier
|
|
185
202
|
clientId: Identifier
|
|
186
203
|
undoContext: UndoContext
|
|
187
204
|
viewport: Viewport
|
|
188
205
|
|
|
189
206
|
@with_config(ConfigDict(strict=True))
|
|
190
|
-
class
|
|
191
|
-
|
|
207
|
+
class AddTagProposalsRequest(TypedDict):
|
|
208
|
+
# note id -> the AI's tags for it: the edited note and maybe notes below it.
|
|
209
|
+
proposals: Annotated[dict[Identifier, Annotated[list[Identifier], Field(min_length=1, max_length=12)]],
|
|
210
|
+
Field(min_length=1, max_length=20_000)]
|
|
211
|
+
clientId: Identifier
|
|
212
|
+
undoContext: UndoContext
|
|
213
|
+
viewport: Viewport
|
|
214
|
+
|
|
215
|
+
# The view a robot count (🤖 N) was shown in: its tab, search ('' for none) and kind.
|
|
216
|
+
@with_config(ConfigDict(strict=True))
|
|
217
|
+
class OpenToTagProposalsRequest(TypedDict):
|
|
218
|
+
search: Text
|
|
219
|
+
tabId: Identifier
|
|
220
|
+
isUntaggedView: bool
|
|
221
|
+
clientId: Identifier
|
|
222
|
+
undoContext: UndoContext
|
|
223
|
+
viewport: Viewport
|
|
224
|
+
|
|
225
|
+
@with_config(ConfigDict(strict=True))
|
|
226
|
+
class ResolveRobotProposalsRequest(TypedDict):
|
|
227
|
+
action: Literal["accept", "reject"]
|
|
228
|
+
includesHiddenChildren: bool
|
|
229
|
+
search: Text
|
|
230
|
+
tabId: Identifier
|
|
231
|
+
isUntaggedView: bool
|
|
192
232
|
clientId: Identifier
|
|
193
233
|
undoContext: UndoContext
|
|
194
234
|
viewport: Viewport
|
|
@@ -18,6 +18,10 @@ from app.api.transactions import transactional_route
|
|
|
18
18
|
from app.models.utils import note_data_to_html
|
|
19
19
|
from app.models.utils import render_note_data_read_only
|
|
20
20
|
from app.services.ai_chat_stream import ChatTurnStream
|
|
21
|
+
from app.services.ai_setup import AiConnection
|
|
22
|
+
from app.services.ai_setup import AiNotSetUp
|
|
23
|
+
from app.services.ai_setup import AiProvider
|
|
24
|
+
from app.services.ai_setup import connect_to_ai
|
|
21
25
|
from app.services.ai_chat import ai_chat_store
|
|
22
26
|
from app.services.ai_chat_rendering import find_note_citation_ids
|
|
23
27
|
from app.services.ai_chat_rendering import find_web_citation_ids
|
|
@@ -27,9 +31,7 @@ from app.services.agent.cloud_privacy import cloud_privacy_evaluator
|
|
|
27
31
|
from app.services.agent.cloud_privacy import resolve_cloud_privacy_boundary
|
|
28
32
|
from app.services.agent.inference import InferenceAdapter
|
|
29
33
|
from app.services.agent.model_policy import SingleModelPolicy
|
|
30
|
-
from app.services.agent.openai_inference import OPENAI_API_BASE_URL
|
|
31
34
|
from app.services.agent.openai_inference import OPENAI_MODELS
|
|
32
|
-
from app.services.agent.openai_inference import OpenAIInferenceAdapter
|
|
33
35
|
from app.services.agent.openai_inference import validate_openai_model
|
|
34
36
|
from app.services.agent.openai_cost_tracking import OpenAICostSnapshot
|
|
35
37
|
from app.services.agent.openai_cost_tracking import openai_cost_tracker
|
|
@@ -64,6 +66,19 @@ from app.usecases.bulk_tag_proposals import apply_bulk_proposals, prepare_propos
|
|
|
64
66
|
from app.services.bulk_operation import bulk_operation_guard
|
|
65
67
|
from app.services.tab_state import tab_state_store
|
|
66
68
|
from app.services.tokens import token_service
|
|
69
|
+
from app.services.agent.inference import InferenceProviderError
|
|
70
|
+
from app.services.agent.note_tag_suggestions import build_note_tag_request
|
|
71
|
+
from app.services.agent.export_title_suggestions import MAX_PREVIOUS_TITLES
|
|
72
|
+
from app.services.agent.export_title_suggestions import ExportTitleRequest
|
|
73
|
+
from app.services.agent.export_title_suggestions import build_export_title_request
|
|
74
|
+
from app.services.agent.export_title_suggestions import suggest_export_title
|
|
75
|
+
from app.services.agent.note_tag_suggestions import NoteTagRequest
|
|
76
|
+
from app.services.agent.note_tag_suggestions import suggest_note_tags
|
|
77
|
+
from app.services.snapshot import resolve_view_scope_membership
|
|
78
|
+
from app.services.html_export import resolve_export_scope
|
|
79
|
+
from app.services.ai_setup import describe_ai_setup
|
|
80
|
+
from app.services.input_errors import InputRejected
|
|
81
|
+
from app.utils.text_utils import strip_html
|
|
67
82
|
|
|
68
83
|
|
|
69
84
|
router = APIRouter(prefix="/ai", tags=["ai"])
|
|
@@ -71,6 +86,15 @@ router = APIRouter(prefix="/ai", tags=["ai"])
|
|
|
71
86
|
agent_context_builder = AgentContextBuilder()
|
|
72
87
|
|
|
73
88
|
|
|
89
|
+
def _require_ai_connection(*, provider: AiProvider, token: str, session_key: str) -> AiConnection:
|
|
90
|
+
# lint: allow-PY001 rationale="the user removed or never added the AI's key: an expected 409, not a defect"
|
|
91
|
+
try:
|
|
92
|
+
return connect_to_ai(provider=provider, token=token, session_key=session_key)
|
|
93
|
+
# lint: allow-PY001 rationale="the user removed or never added the AI's key: an expected 409, not a defect"
|
|
94
|
+
except AiNotSetUp as exc:
|
|
95
|
+
raise HTTPException(status_code=409, detail="The AI is not set up: add its API key in AI settings") from exc
|
|
96
|
+
|
|
97
|
+
|
|
74
98
|
def _agent_runtime(*, inference: InferenceAdapter) -> AgentRuntime:
|
|
75
99
|
return AgentRuntime(
|
|
76
100
|
context_builder=agent_context_builder,
|
|
@@ -163,6 +187,76 @@ class AiChatRequest(BaseModel):
|
|
|
163
187
|
return self
|
|
164
188
|
|
|
165
189
|
|
|
190
|
+
class NoteTagSuggestionAvailabilityRequest(BaseModel):
|
|
191
|
+
model_config = ConfigDict(extra="forbid")
|
|
192
|
+
|
|
193
|
+
provider: AiProvider
|
|
194
|
+
# The note as it is being edited, unsaved changes included.
|
|
195
|
+
tags: str = Field(..., max_length=1024 * 1024)
|
|
196
|
+
content_html: str = Field(..., max_length=16 * 1024 * 1024)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
class NoteTagSuggestionAvailabilityResponse(BaseModel):
|
|
200
|
+
is_available: bool
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
class NoteTagSuggestionRequest(BaseModel):
|
|
204
|
+
model_config = ConfigDict(extra="forbid")
|
|
205
|
+
|
|
206
|
+
provider: AiProvider
|
|
207
|
+
model: str
|
|
208
|
+
thinking_level: Literal["off", "low", "medium", "high"]
|
|
209
|
+
# The note alone, or it and the notes below it the view shows.
|
|
210
|
+
include_children: bool
|
|
211
|
+
# The view the note is in ('' for no search).
|
|
212
|
+
search: str = Field(..., max_length=1024 * 1024)
|
|
213
|
+
tab_id: str = Field(..., min_length=1, max_length=256)
|
|
214
|
+
is_untagged_view: bool
|
|
215
|
+
|
|
216
|
+
@model_validator(mode="after")
|
|
217
|
+
def validate_model_for_provider(self) -> Self:
|
|
218
|
+
assert self.provider == "openai"
|
|
219
|
+
validate_openai_model(self.model)
|
|
220
|
+
return self
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
class ExportTitleScope(BaseModel):
|
|
224
|
+
model_config = ConfigDict(extra="forbid")
|
|
225
|
+
|
|
226
|
+
provider: AiProvider
|
|
227
|
+
# The view exported or printed, or the one its note is in ('' for no search).
|
|
228
|
+
search: str = Field(..., max_length=1024 * 1024)
|
|
229
|
+
tab_id: str = Field(..., min_length=1, max_length=256)
|
|
230
|
+
is_untagged_view: bool
|
|
231
|
+
# A note with its children ("note"), or the view as it is shown ("view", note_id '').
|
|
232
|
+
exported: Literal["note", "view"]
|
|
233
|
+
note_id: str = Field(..., max_length=256)
|
|
234
|
+
|
|
235
|
+
@model_validator(mode="after")
|
|
236
|
+
def validate_exported_note(self) -> Self:
|
|
237
|
+
if (self.exported == "note") != (self.note_id != ""):
|
|
238
|
+
raise ValueError("A note's export names the note; the view's export names none")
|
|
239
|
+
return self
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
class ExportTitleAvailabilityResponse(BaseModel):
|
|
243
|
+
# "unavailable": no AI is set up (no button); then as ExportTitleAvailability.
|
|
244
|
+
availability: Literal["unavailable", "nothing", "private", "partial", "ready"]
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class ExportTitleSuggestionRequest(ExportTitleScope):
|
|
248
|
+
model: str
|
|
249
|
+
thinking_level: Literal["off", "low", "medium", "high"]
|
|
250
|
+
# Titles the AI gave in this dialog: it gives another.
|
|
251
|
+
previous_titles: list[str] = Field(..., max_length=MAX_PREVIOUS_TITLES)
|
|
252
|
+
|
|
253
|
+
@model_validator(mode="after")
|
|
254
|
+
def validate_model_for_provider(self) -> Self:
|
|
255
|
+
assert self.provider == "openai"
|
|
256
|
+
validate_openai_model(self.model)
|
|
257
|
+
return self
|
|
258
|
+
|
|
259
|
+
|
|
166
260
|
class AiChatActivity(BaseModel):
|
|
167
261
|
sequence: int = Field(..., ge=1)
|
|
168
262
|
action: str
|
|
@@ -330,6 +424,178 @@ def delete_openai_credential(
|
|
|
330
424
|
)
|
|
331
425
|
|
|
332
426
|
|
|
427
|
+
@router.post(
|
|
428
|
+
"/notes/{note_id}/tag-suggestions/availability",
|
|
429
|
+
response_model=NoteTagSuggestionAvailabilityResponse,
|
|
430
|
+
)
|
|
431
|
+
@transactional_route
|
|
432
|
+
def note_tag_suggestion_availability(
|
|
433
|
+
note_id: str,
|
|
434
|
+
payload: NoteTagSuggestionAvailabilityRequest,
|
|
435
|
+
response: Response,
|
|
436
|
+
token: Annotated[str, Depends(require_request_auth_token)],
|
|
437
|
+
) -> NoteTagSuggestionAvailabilityResponse:
|
|
438
|
+
"""Whether "Suggest Tags with AI" applies: an AI is set up and may see the note as edited."""
|
|
439
|
+
response.headers["Cache-Control"] = "no-store"
|
|
440
|
+
if not note_store.has_note(note_id):
|
|
441
|
+
raise HTTPException(status_code=404, detail=f"Note not found: {note_id}")
|
|
442
|
+
session_key = token_service.get_session_key(token)
|
|
443
|
+
if not describe_ai_setup(token=token, session_key=session_key).is_ready_for(payload.provider):
|
|
444
|
+
return NoteTagSuggestionAvailabilityResponse(is_available=False)
|
|
445
|
+
boundary = resolve_cloud_privacy_boundary(
|
|
446
|
+
preferences=load_client_preferences(token=token),
|
|
447
|
+
provider=payload.provider,
|
|
448
|
+
)
|
|
449
|
+
draft_effective_tags = note_store.draft_effective_tag_terms(
|
|
450
|
+
note_id=note_id, tags=payload.tags, plaintext=strip_html(payload.content_html),
|
|
451
|
+
)
|
|
452
|
+
reason = cloud_privacy_evaluator.draft_exclusion_reason(
|
|
453
|
+
note_id=note_id, draft_effective_tags=draft_effective_tags,
|
|
454
|
+
draft_content_html=payload.content_html, boundary=boundary,
|
|
455
|
+
)
|
|
456
|
+
return NoteTagSuggestionAvailabilityResponse(is_available=reason == "")
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
@router.post("/notes/{note_id}/tag-suggestions")
|
|
460
|
+
@transactional_route
|
|
461
|
+
def suggest_tags_for_note_with_ai(
|
|
462
|
+
note_id: str,
|
|
463
|
+
payload: NoteTagSuggestionRequest,
|
|
464
|
+
token: Annotated[str, Depends(require_request_auth_token)],
|
|
465
|
+
) -> StreamingResponse:
|
|
466
|
+
"""Ask the AI for the saved note's tags (and its children's): streams {"type": "progress"}
|
|
467
|
+
lines, then one {"type": "proposals"} or {"type": "failed"} line.
|
|
468
|
+
|
|
469
|
+
Nothing is written: the client adds what it gets back as proposals
|
|
470
|
+
(POST /notes/{id}/tag-proposals/add), one undo step.
|
|
471
|
+
"""
|
|
472
|
+
if not note_store.has_note(note_id):
|
|
473
|
+
raise HTTPException(status_code=404, detail=f"Note not found: {note_id}")
|
|
474
|
+
session_key = token_service.get_session_key(token)
|
|
475
|
+
connection = _require_ai_connection(provider=payload.provider, token=token, session_key=session_key)
|
|
476
|
+
preferences = load_client_preferences(token=token)
|
|
477
|
+
boundary = resolve_cloud_privacy_boundary(preferences=preferences, provider=payload.provider)
|
|
478
|
+
if cloud_privacy_evaluator.exclusion_reason(note_id=note_id, boundary=boundary) != "":
|
|
479
|
+
raise InputRejected(
|
|
480
|
+
"Your AI privacy settings hide this note from the AI, so it can't suggest tags for it"
|
|
481
|
+
)
|
|
482
|
+
scope = resolve_view_scope_membership(
|
|
483
|
+
search=payload.search,
|
|
484
|
+
sort_mode=tab_state_store.get_sort_mode(tab_id=payload.tab_id),
|
|
485
|
+
is_untagged_view=payload.is_untagged_view,
|
|
486
|
+
)
|
|
487
|
+
if note_id not in scope.allowed_note_ids:
|
|
488
|
+
raise HTTPException(status_code=409, detail="The note is not in this view any more")
|
|
489
|
+
request = build_note_tag_request(
|
|
490
|
+
note_id=note_id, include_children=payload.include_children, boundary=boundary,
|
|
491
|
+
tag_skill=DEFAULT_AGENT_SKILLS.for_action("tag_proposals"), scope_note_ids=scope.allowed_note_ids,
|
|
492
|
+
batch_tokens=resolve_tagging_batch_tokens(preferences, payload.provider),
|
|
493
|
+
)
|
|
494
|
+
events = _note_tag_suggestion_events(
|
|
495
|
+
request=request, connection=connection, payload=payload,
|
|
496
|
+
web_settings=resolve_agent_web_settings(preferences=preferences), session_key=session_key,
|
|
497
|
+
)
|
|
498
|
+
return StreamingResponse(
|
|
499
|
+
events,
|
|
500
|
+
media_type="application/x-ndjson",
|
|
501
|
+
headers={"X-Accel-Buffering": "no", "Cache-Control": "no-store", "Content-Encoding": "identity"},
|
|
502
|
+
)
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
async def _note_tag_suggestion_events(
|
|
506
|
+
*, request: NoteTagRequest, connection: AiConnection, payload: NoteTagSuggestionRequest,
|
|
507
|
+
web_settings: AgentWebSettings, session_key: str,
|
|
508
|
+
) -> AsyncIterator[str]:
|
|
509
|
+
events = suggest_note_tags(
|
|
510
|
+
request=request, inference=connection.inference, base_url=connection.base_url,
|
|
511
|
+
model=payload.model, thinking_level=payload.thinking_level,
|
|
512
|
+
web_settings=web_settings, session_key=session_key,
|
|
513
|
+
)
|
|
514
|
+
# lint: allow-PY001 rationale="the AI provider failed or kept answering unusably: the client shows why"
|
|
515
|
+
try:
|
|
516
|
+
async for event in events:
|
|
517
|
+
yield json.dumps(event) + "\n"
|
|
518
|
+
# lint: allow-PY001 rationale="the AI provider failed or kept answering unusably: the client shows why"
|
|
519
|
+
except InferenceProviderError as exc:
|
|
520
|
+
yield json.dumps({"type": "failed", "message": str(exc)}) + "\n"
|
|
521
|
+
finally:
|
|
522
|
+
await events.aclose()
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
def _export_title_request(scope: ExportTitleScope, token: str) -> ExportTitleRequest:
|
|
526
|
+
"""What the AI may read of the export or print: the notes the AI privacy settings let it see."""
|
|
527
|
+
note_id = None
|
|
528
|
+
if scope.exported == "note":
|
|
529
|
+
note_id = scope.note_id
|
|
530
|
+
if not note_store.has_note(note_id):
|
|
531
|
+
raise HTTPException(status_code=404, detail=f"Note not found: {note_id}")
|
|
532
|
+
search = None
|
|
533
|
+
if scope.search != "":
|
|
534
|
+
search = scope.search
|
|
535
|
+
root_ids, allowed_note_ids = resolve_export_scope(
|
|
536
|
+
search=search,
|
|
537
|
+
sort_mode=tab_state_store.get_sort_mode(tab_id=scope.tab_id),
|
|
538
|
+
is_untagged_view=scope.is_untagged_view, root_note_id=note_id,
|
|
539
|
+
)
|
|
540
|
+
boundary = resolve_cloud_privacy_boundary(preferences=load_client_preferences(token=token), provider=scope.provider)
|
|
541
|
+
return build_export_title_request(root_ids=root_ids, allowed_note_ids=allowed_note_ids, boundary=boundary)
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
@router.post("/export-title/availability", response_model=ExportTitleAvailabilityResponse)
|
|
545
|
+
@transactional_route
|
|
546
|
+
def export_title_availability(
|
|
547
|
+
payload: ExportTitleScope,
|
|
548
|
+
response: Response,
|
|
549
|
+
token: Annotated[str, Depends(require_request_auth_token)],
|
|
550
|
+
) -> ExportTitleAvailabilityResponse:
|
|
551
|
+
"""Whether the Export and Print dialog's "Suggest with AI" can ask, and what it says about private notes."""
|
|
552
|
+
response.headers["Cache-Control"] = "no-store"
|
|
553
|
+
session_key = token_service.get_session_key(token)
|
|
554
|
+
if not describe_ai_setup(token=token, session_key=session_key).is_ready_for(payload.provider):
|
|
555
|
+
return ExportTitleAvailabilityResponse(availability="unavailable")
|
|
556
|
+
return ExportTitleAvailabilityResponse(availability=_export_title_request(payload, token).availability)
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
@router.post("/export-title")
|
|
560
|
+
@transactional_route
|
|
561
|
+
def suggest_export_title_with_ai(
|
|
562
|
+
payload: ExportTitleSuggestionRequest,
|
|
563
|
+
token: Annotated[str, Depends(require_request_auth_token)],
|
|
564
|
+
) -> StreamingResponse:
|
|
565
|
+
"""Ask the AI for an export's or print's title: one {"type": "title"} or {"type": "failed"} line.
|
|
566
|
+
Streamed, so Stop (the client going away) ends the request."""
|
|
567
|
+
session_key = token_service.get_session_key(token)
|
|
568
|
+
connection = _require_ai_connection(provider=payload.provider, token=token, session_key=session_key)
|
|
569
|
+
request = _export_title_request(payload, token)
|
|
570
|
+
if not request.notes:
|
|
571
|
+
raise InputRejected("These notes are private, so the AI can't suggest a title")
|
|
572
|
+
web_mode = resolve_agent_web_settings(preferences=load_client_preferences(token=token)).mode
|
|
573
|
+
return StreamingResponse(
|
|
574
|
+
_export_title_events(
|
|
575
|
+
request=request, payload=payload, connection=connection, web_mode=web_mode, session_key=session_key,
|
|
576
|
+
),
|
|
577
|
+
media_type="application/x-ndjson",
|
|
578
|
+
headers={"X-Accel-Buffering": "no", "Cache-Control": "no-store", "Content-Encoding": "identity"},
|
|
579
|
+
)
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
async def _export_title_events(
|
|
583
|
+
*, request: ExportTitleRequest, payload: ExportTitleSuggestionRequest, connection: AiConnection,
|
|
584
|
+
web_mode: str, session_key: str,
|
|
585
|
+
) -> AsyncIterator[str]:
|
|
586
|
+
# lint: allow-PY001 rationale="the AI provider failed or answered without a title: the dialog shows why"
|
|
587
|
+
try:
|
|
588
|
+
title = await suggest_export_title(
|
|
589
|
+
request=request, previous_titles=tuple(payload.previous_titles), inference=connection.inference,
|
|
590
|
+
base_url=connection.base_url, model=payload.model, thinking_level=payload.thinking_level,
|
|
591
|
+
web_mode=web_mode, session_key=session_key,
|
|
592
|
+
)
|
|
593
|
+
yield json.dumps({"type": "title", "title": title}) + "\n"
|
|
594
|
+
# lint: allow-PY001 rationale="the AI provider failed or answered without a title: the dialog shows why"
|
|
595
|
+
except InferenceProviderError as exc:
|
|
596
|
+
yield json.dumps({"type": "failed", "message": str(exc)}) + "\n"
|
|
597
|
+
|
|
598
|
+
|
|
333
599
|
def _openai_cost_response(snapshot: OpenAICostSnapshot) -> OpenAICostResponse:
|
|
334
600
|
return OpenAICostResponse(
|
|
335
601
|
estimated_cost_usd=float(snapshot.estimated_cost_usd),
|
|
@@ -576,19 +842,7 @@ def stream_ai_chat(
|
|
|
576
842
|
token: Annotated[str, Depends(require_request_auth_token)],
|
|
577
843
|
) -> StreamingResponse:
|
|
578
844
|
session_key = token_service.get_session_key(token)
|
|
579
|
-
|
|
580
|
-
token=token,
|
|
581
|
-
session_key=session_key,
|
|
582
|
-
)
|
|
583
|
-
if not credential_status.configured:
|
|
584
|
-
raise HTTPException(
|
|
585
|
-
status_code=409,
|
|
586
|
-
detail="OpenAI API key is not configured",
|
|
587
|
-
)
|
|
588
|
-
openai_api_key = openai_credential_store.resolve(
|
|
589
|
-
token=token,
|
|
590
|
-
session_key=session_key,
|
|
591
|
-
)
|
|
845
|
+
connection = _require_ai_connection(provider=payload.provider, token=token, session_key=session_key)
|
|
592
846
|
preferences = load_client_preferences(token=token)
|
|
593
847
|
prompts = DEFAULT_AGENT_PROMPTS
|
|
594
848
|
skills = DEFAULT_AGENT_SKILLS
|
|
@@ -655,7 +909,7 @@ def stream_ai_chat(
|
|
|
655
909
|
turn_stream = ChatTurnStream(store=ai_chat_store, notes=note_store,
|
|
656
910
|
web_evidence_store=web_evidence_store, session_key=session_key,
|
|
657
911
|
turn_id=turn_id, initial_input_tokens=initial_approx_input_tokens)
|
|
658
|
-
events = _stream_runtime_events(payload=payload,
|
|
912
|
+
events = _stream_runtime_events(payload=payload, connection=connection,
|
|
659
913
|
session_key=session_key, provider_messages=provider_messages, prompts=prompts, skills=skills,
|
|
660
914
|
retrieval_settings=retrieval_settings, frozen_scope=frozen_scope, tagging_run=tagging_run,
|
|
661
915
|
web_settings=web_settings, earlier_actions=earlier_actions,
|
|
@@ -673,16 +927,16 @@ def stream_ai_chat(
|
|
|
673
927
|
|
|
674
928
|
|
|
675
929
|
async def _stream_runtime_events(
|
|
676
|
-
*, payload: AiChatRequest,
|
|
930
|
+
*, payload: AiChatRequest, connection: AiConnection, session_key: str,
|
|
677
931
|
provider_messages: list[dict[str, str]], prompts: AgentPromptSet, skills: AgentSkillSet,
|
|
678
932
|
retrieval_settings: AgentRetrievalSettings, frozen_scope: ScopedSearchSnapshot,
|
|
679
933
|
tagging_run: TaggingRun, initial_input_tokens: int, web_settings: AgentWebSettings,
|
|
680
934
|
earlier_actions: list[dict[str, object]],
|
|
681
935
|
) -> AsyncIterator[dict[str, object]]:
|
|
682
|
-
action, start_label = 'provider_runtime', 'Connecting to
|
|
683
|
-
ready_label =
|
|
684
|
-
base_url =
|
|
685
|
-
runtime = _agent_runtime(inference=
|
|
936
|
+
action, start_label = 'provider_runtime', f'Connecting to {connection.label} API'
|
|
937
|
+
ready_label = connection.ready_label
|
|
938
|
+
base_url = connection.base_url
|
|
939
|
+
runtime = _agent_runtime(inference=connection.inference)
|
|
686
940
|
yield dict(type='action_status', action=action, status='started', label=start_label,
|
|
687
941
|
approx_input_tokens=initial_input_tokens, output_tokens_received=0, duration_ms=0.0)
|
|
688
942
|
yield dict(type='action_status', action=action, status='completed', label=ready_label,
|