MetaList 0.12.0__tar.gz → 0.13.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.12.0 → metalist-0.13.0}/PKG-INFO +9 -1
- {metalist-0.12.0 → metalist-0.13.0}/README.md +8 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/api/note_requests.py +20 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/api/routes/ai.py +4 -2
- {metalist-0.12.0 → metalist-0.13.0}/app/api/routes/notes.py +42 -0
- metalist-0.13.0/app/services/agent/action_log.py +59 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/agent_loop.py +16 -1
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/context.py +18 -2
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/help_catalog.py +1 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/prompts/agent.md +7 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/runtime.py +6 -2
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/skills/help-ai.md +1 -1
- metalist-0.13.0/app/services/agent/skills/help-dictation.md +92 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/skills/help-menus.md +1 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/skills/help-notes.md +1 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/skills/help-references.md +3 -2
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/skills/help-releases.md +8 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/skills/help-search.md +9 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/skills/help-tags.md +3 -2
- {metalist-0.12.0 → metalist-0.13.0}/app/services/ai_chat.py +37 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/ai_chat_stream.py +8 -1
- {metalist-0.12.0 → metalist-0.13.0}/app/services/client_state_service.py +10 -0
- metalist-0.13.0/app/services/dictation_cleanup.py +469 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/embedded_references.py +13 -2
- metalist-0.13.0/app/services/file_text_preview.py +83 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/search_index.py +3 -3
- {metalist-0.12.0 → metalist-0.13.0}/app/services/search_query.py +5 -1
- {metalist-0.12.0 → metalist-0.13.0}/app/services/search_text.py +35 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/tag_suggestions.py +104 -23
- {metalist-0.12.0 → metalist-0.13.0}/app/static/config/agent-menu-actions.json +6 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/config/command_palette_tags.json +4 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/ai-chat/proposal-menu.js +5 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/api-client.js +8 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/command-palette/command-palette-controller.js +60 -1
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/command-palette/endpoint-registry.js +7 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/config.js +2 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/ai-agent-settings-modal.js +4 -0
- metalist-0.13.0/app/static/js/modules/modals/dictation-settings-modal.js +130 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/ontology-modal.js +20 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/prioritize-modal.js +3 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/visual-cues-modal.js +1 -1
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/events/input-events.js +14 -1
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/events/keyboard-events.js +23 -1
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/events/search-events.js +7 -0
- metalist-0.13.0/app/static/js/modules/mode-manager/services/dictation-note-paste.js +48 -0
- metalist-0.13.0/app/static/js/modules/mode-manager/services/dictation-paste-padding.js +21 -0
- metalist-0.13.0/app/static/js/modules/mode-manager/services/dictation-paste-service.js +236 -0
- metalist-0.13.0/app/static/js/modules/mode-manager/services/dropped-file-preview-service.js +47 -0
- metalist-0.13.0/app/usecases/create_file_preview_child.py +68 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/search_comment_autofill.py +4 -3
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/search_context_tags.py +4 -3
- {metalist-0.12.0 → metalist-0.13.0}/app/version.py +1 -1
- {metalist-0.12.0 → metalist-0.13.0}/metalist.egg-info/PKG-INFO +9 -1
- {metalist-0.12.0 → metalist-0.13.0}/metalist.egg-info/SOURCES.txt +10 -0
- {metalist-0.12.0 → metalist-0.13.0}/MANIFEST.in +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/__init__.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/api/__init__.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/api/deps.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/api/dev.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/api/middleware/auth.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/api/request_auth.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/api/routes/app_updates.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/api/routes/auth.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/api/routes/backups.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/api/routes/files.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/api/routes/ontology.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/api/routes/reminders.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/api/routes/remote_images.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/api/routes/test.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/api/transactions.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/api/upload_limits.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/config.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/data_directory.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/__init__.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/backup_settings_sql.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/editable_files_migration.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/engine.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/file_schema.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/file_session.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/files_sql.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/link_titles_sql.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/live_recovery.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/migrations.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/notes_sql.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/ontology_rules_sql.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/reminders_sql.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/retire_sounds.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/schema.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/search_history_sql.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/session.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/settings_sql.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/tab_state_sql.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/db/version.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/encryption_audit.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/exception_boundaries.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/https_proxy.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/main.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/models/commands.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/models/database.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/models/entities.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/models/enums.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/models/linked_list.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/models/list_operations.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/models/list_traversal.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/models/note_crud.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/models/utils.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/network_settings.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/presentation/__init__.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/presentation/render/__init__.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/presentation/render/note_renderer.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/presentation/templates.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/security/authenticated_logging.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/security/encryption.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/security/http_error_diagnostics.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/security/http_headers.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/security/note_html.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/security/request_boundary.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/security/request_hosts.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/security/sensitive_cache.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/security/sensitive_logging.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/security/shell_execution.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/security/validation_errors.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/server_runtime.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/__init__.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/__init__.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/agent_tools.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/citation_tokens.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/cloud_privacy.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/evidence_serialization.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/execution_errors.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/failure_explanations.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/history.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/inference.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/investigation.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/judging.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/menu_actions.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/model_policy.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/note_aliases.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/openai_cost_tracking.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/openai_inference.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/prompt_settings.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/prompts/__init__.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/prompts/final-response.md +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/prompts/system.md +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/release_notes.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/retrieval_settings.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/scope.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/skill_settings.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/skills/__init__.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/skills/help-data.md +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/skills/help-formatting.md +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/skills/help-privacy.md +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/skills/help-reminders.md +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/skills/staged-summary.md +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/skills/tag-proposals.md +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/skills/web-browsing.md +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/staged_summary.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/structured_inference.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/tagging.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/tagging_run.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/token_estimation.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/tool_calling.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/trace.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/web_actions.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/web_capabilities.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/web_evidence.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/web_fetch.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/agent/web_settings.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/ai_chat_rendering.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/app_update_worker.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/app_updates.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/auth.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/auth_cache_state.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/auth_service.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/backlink_index.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/backlinks.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/backup_service.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/backup_settings_service.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/bulk_operation.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/content_cache.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/content_formatting.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/diagnostics.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/encryption.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/exception_capture.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/file_edit_sessions.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/file_registry.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/file_storage.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/footnote_layout.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/footnote_rendering.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/hierarchy.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/html_export.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/html_unformatting.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/hydration_state.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/image_size_formatting.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/inline_image_dimensions.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/inline_image_occurrences.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/input_errors.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/integrity.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/latex_rendering.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/link_titles.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/login_rate_limit.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/maintenance_mode.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/markdown_rendering.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/namespace_deletion_jobs.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/namespace_deletion_worker.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/namespace_rename_jobs.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/namespace_rename_worker.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/namespace_runtime_guard.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/namespace_switcher.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/note_fullscreen.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/note_image_tags.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/note_ordering.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/note_store.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/ontology_rules_store.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/openai_credentials.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/password_note_fields.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/public_http.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/reference_presentation.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/reminders.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/remote_image_proxy.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/request_recovery.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/resource_limits.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/root_sorting.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/runtime_generation.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/runtime_hardening.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/runtime_lock.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/search_history.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/search_history_storage.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/selected_text_tag.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/self_update.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/session_timeout_service.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/shell_session_service.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/snapshot.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/store.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/structured_note_renderers.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/sync.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/sync_state.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/tab_state.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/tag_case.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/tag_ontology.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/tag_rename.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/tag_term_matching.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/test_reset.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/tokens.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/undo_state.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/update_backups.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/update_installer.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/update_preflight.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/view_cache.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/view_diff.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/view_state.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/services/windows_process_control.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/startup_environment.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/startup_js_sanity.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/startup_sanity.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/startup_sanity_config.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/css/floating-notes.css +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/css/forms.css +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/css/main.css +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/img/favicon.ico +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/locked.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/main.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/activity-tracker.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/ai-chat/agent-menu-actions.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/ai-chat/agent-retrieval-settings.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/ai-chat/agent-web-settings.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/ai-chat/ai-agent-debug-view.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/ai-chat/ai-chat-api.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/ai-chat/ai-chat-message-placement.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/ai-chat/ai-chat-panel-controller.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/ai-chat/ai-chat-panel-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/ai-chat/ai-thinking-level-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/ai-chat/bulk-elapsed-clock.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/ai-chat/bulk-proposal-ui.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/ai-chat/bulk-scope-question.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/ai-chat/cloud-privacy-policy.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/ai-chat/confirmation-card.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/ai-chat/confirmation-question.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/ai-chat/summary-batch-preview.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/api-error-diagnostics.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/api-failure-classification-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/app-update-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/application-state.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/async-result.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/auth.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/client-state-api.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/client-state-migration.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/command-palette/activation-auth-policy.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/command-palette/backup-command-availability.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/command-palette/click-activation-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/command-palette/note-layout-preferences.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/command-palette/preferences-store.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/command-palette/tag-config-loader.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/command-palette/usage-store.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/connectivity-monitor.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/context-menu/context-menu-registry.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/context-menu/context-menu-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/context-menu/context-menu-target-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/context-menu/input-caret-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/disconnect-editing-state-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/dom-utils-fixed.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/dom-utils.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/editor-commands.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/editor-selection.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/editor-toolbar.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/elapsed-time.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/error-handler.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/error-overlay.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/excalidraw/excalidraw-actions.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/excalidraw/excalidraw-autosave.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/excalidraw/excalidraw-editor-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/excalidraw/excalidraw-editor-state.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/excalidraw/excalidraw-loader.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/excalidraw/excalidraw-preview-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/excalidraw/excalidraw-scene.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/expected-errors.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/location-flags.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/login-namespace-picker.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/maintenance.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/alphabetize-root-notes-modal.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/backup-restore-modal.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/backup-result-modal.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/backup-retention-modal.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/backup-settings-modal.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/base-modal.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/confirmation-modal.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/delete-namespace-modal.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/delete-namespace-validation.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/help-modal.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/namespace-loading-page.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/namespace-modals.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/namespace-ports-profile.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/namespace-rename-validation.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/note-layout-appearance-modal.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/password-modal.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/random-password-modal.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/reminder-modal.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/reset-updated-at-modal.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/search-suggestion-statistics-modal.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/session-timeout-modal.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/modals/version-info-modal.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/actions/content-actions.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/actions/history-actions.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/actions/note-actions.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/actions/search-actions.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/actions/selection-actions.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/actions/ui-actions.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/events/context-menu-events.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/events/focus-events.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/events/inactivity-events.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/events/mouse-events.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/mode-context.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/mode-logger.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/mode-manager-controller.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/add-style-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/animated-scroll-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/backlinks-navigation-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/backlinks-panel-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/clipboard-shortcut-policy-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/collapse-affordance-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/collapse-editing-policy-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/command-gate-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/context-menu-target-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/deselect-selection-state-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/differential-view-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/edit-session-collapse-policy-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/edit-session-collapse-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/embedded-image-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/file-drop-policy-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/file-image-preview-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/file-reference-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/filtered-refresh-selection-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/floating-note-dom.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/floating-note-layout.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/floating-note-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/footnote-navigation-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/history-selection-policy-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/history-shortcut-policy-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/html-paste-sanitizer-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/image-context-menu-action-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/image-file-insert-choice-modal-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/infinite-scroll-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/link-context-menu-action-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/link-title-prefetch-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/markdown-render-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/mermaid-render-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/note-click-target-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/note-clipboard-write-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/note-collapse-animation-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/note-context-menu-action-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/note-delete-shortcut-policy-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/note-drag-indicator-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/note-drag-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/note-fullscreen-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/note-reposition-animation-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/note-split-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/note-timestamp-hover-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/password-clipboard-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/polling-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/reference-source-navigation-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/remote-image-proxy-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/remove-formatting-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/root-date-separator-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/root-note-creation-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/root-sort-indicator-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/root-sort-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/scroll-anchor-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/scroll-restoration-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/scroll-to-top-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/search-contexts-overlay-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/search-debounce-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/search-input-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/search-interaction-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/search-redaction-reveal-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/search-suggestion-statistics-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/search-suggestion-window-labels-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/search-suggestion-windows-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/search-suggestions-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/search-syntax-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/selected-formatting-removal-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/selected-text-tag-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/shell-output-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/tab-dom-cache-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/tab-drag-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/tab-duplication-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/tab-state-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/tag-bar-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/tag-input-selection-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/tag-proposal-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/tag-suggestions-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/tag-syntax-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/todo-toggle-editing-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/untagged-view-indicator-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/view-mode-search-shortcut-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/mode-manager/services/viewport-hold-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/note-html-sanitizer.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/password-generator.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/password-operation-response.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/password-policy.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/password-strength.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/reminder-store.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/reminder-surface-service.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/selection-markers.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/session-auth.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/tag-token.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/modules/uuid.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/namespace-deleted.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/namespace-renamed.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/dompurify-3.4.16.LICENSE.txt +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/dompurify-3.4.16.min.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/excalidraw.css +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Bold.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Medium.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Regular.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-SemiBold.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Cascadia/CascadiaCode-Regular.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Virgil/Virgil-Regular.woff2 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1.LICENSE.txt +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/excalidraw-0.18.1.min.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/markdown-it-14.3.2.LICENSE.txt +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/markdown-it-14.3.2.min.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/mermaid-11.16.1.LICENSE.txt +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/mermaid-11.16.1.min.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/zxcvbn-4.4.2.LICENSE.txt +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/js/vendor/zxcvbn-4.4.2.js +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/note-html-policy.json +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/static/video/login-startup.mp4 +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/templates/base.html +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/templates/index.html +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/templates/locked.html +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/templates/maintenance.html +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/templates/namespace_deleted.html +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/templates/namespace_renamed.html +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/templates/notes_list.html +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/upload_limits.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/__init__.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/add_selected_text_tag.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/alphabetize_root_notes.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/base.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/bulk_tag_proposals.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/collapse.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/copy_note.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/create_child.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/create_note.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/create_sibling.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/delete_subtree.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/delete_tag.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/expand.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/file_edit_session.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/indent.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/lock.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/move.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/move_to_top.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/outdent.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/paste_child.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/paste_sibling.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/prefetch_link_titles.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/prioritize.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/redo.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/rename_tag.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/reset_updated_at.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/resize_image.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/run_shell.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/set_collapse_bulk.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/set_collapse_in_context.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/split_note.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/tag_proposals.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/toggle_reference_mode.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/toggle_todo_done.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/undo.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/unformat_content.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/update_content.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/usecases/view.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/utils/__init__.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/utils/encryption.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/app/utils/text_utils.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/convert-from-legacy.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/main.py +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/metalist.egg-info/dependency_links.txt +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/metalist.egg-info/entry_points.txt +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/metalist.egg-info/requires.txt +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/metalist.egg-info/top_level.txt +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/pyproject.toml +0 -0
- {metalist-0.12.0 → metalist-0.13.0}/scripts/generate-lan-cert.sh +0 -0
- {metalist-0.12.0 → metalist-0.13.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.13.0
|
|
4
4
|
Summary: A minimalist single-user note-taking app with SSR, fast in-memory tree operations, and efficient sync.
|
|
5
5
|
Project-URL: Homepage, https://github.com/evolvingstuff/metalist
|
|
6
6
|
Project-URL: Repository, https://github.com/evolvingstuff/metalist
|
|
@@ -49,6 +49,14 @@ A minimalist single-user note-taking app focused on server-side rendering (SSR),
|
|
|
49
49
|
- Multi-tab search contexts with server-persisted scroll/search state (survives browser restarts)
|
|
50
50
|
- Manual namespace backups/restores to a user-selected backup folder with retention controls
|
|
51
51
|
|
|
52
|
+
## Changes in 0.13.0
|
|
53
|
+
|
|
54
|
+
- Dictation: text from speech-to-text tools such as Superwhisper, pasted into the search bar or any tag field, becomes your existing tags ("neural network" gives `neural-network`). Say "quote … end quote" for text, "minus" to exclude, "at" before meta tags such as `@todo`. In a note, the words after "start tags" go to its tag bar. The phrases are set in Dictation Settings, and one undo restores what was pasted.
|
|
55
|
+
- A quoted search with a space at its edge matches whole words: `" fat"` no longer finds "father".
|
|
56
|
+
- The AI keeps a record of what it did for each answer (notes read, searches, web pages opened), so questions like "did you search the web for that?" are answered from what actually happened.
|
|
57
|
+
- Dropping a `.txt`, `.md`, `.csv` or `.json` file stores it as before and adds its text as a child note, shown as Markdown, a table or formatted JSON. File pills show the extension (`.MD`, `.CSV`, …), and hovering a pill says that clicking downloads the file.
|
|
58
|
+
- Typing one letter in the tag bar now narrows the suggestions you were already shown instead of reordering them, so the tag you want is in the top five far more often.
|
|
59
|
+
|
|
52
60
|
## Changes in 0.12.0
|
|
53
61
|
|
|
54
62
|
- AI chat is now a tool-using agent: in one answer it can look up MetaList help, read and search the notes in your view, open web pages, and open menus, instead of picking a single route up front. Answers cite notes and web pages with clickable references, including each item listed from a web page.
|
|
@@ -12,6 +12,14 @@ 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.13.0
|
|
16
|
+
|
|
17
|
+
- Dictation: text from speech-to-text tools such as Superwhisper, pasted into the search bar or any tag field, becomes your existing tags ("neural network" gives `neural-network`). Say "quote … end quote" for text, "minus" to exclude, "at" before meta tags such as `@todo`. In a note, the words after "start tags" go to its tag bar. The phrases are set in Dictation Settings, and one undo restores what was pasted.
|
|
18
|
+
- A quoted search with a space at its edge matches whole words: `" fat"` no longer finds "father".
|
|
19
|
+
- The AI keeps a record of what it did for each answer (notes read, searches, web pages opened), so questions like "did you search the web for that?" are answered from what actually happened.
|
|
20
|
+
- Dropping a `.txt`, `.md`, `.csv` or `.json` file stores it as before and adds its text as a child note, shown as Markdown, a table or formatted JSON. File pills show the extension (`.MD`, `.CSV`, …), and hovering a pill says that clicking downloads the file.
|
|
21
|
+
- Typing one letter in the tag bar now narrows the suggestions you were already shown instead of reordering them, so the tag you want is in the top five far more often.
|
|
22
|
+
|
|
15
23
|
## Changes in 0.12.0
|
|
16
24
|
|
|
17
25
|
- AI chat is now a tool-using agent: in one answer it can look up MetaList help, read and search the notes in your view, open web pages, and open menus, instead of picking a single route up front. Answers cite notes and web pages with clickable references, including each item listed from a web page.
|
|
@@ -106,6 +106,18 @@ class SearchSuggestionInteractionRequest(TypedDict):
|
|
|
106
106
|
class TabSearchInteractionRequest(TypedDict):
|
|
107
107
|
searchQuery: Text
|
|
108
108
|
|
|
109
|
+
@with_config(ConfigDict(strict=True))
|
|
110
|
+
class DictationPasteRequest(TypedDict):
|
|
111
|
+
"""Text pasted into the search bar or the tag bar, and the field's current value."""
|
|
112
|
+
text: Text
|
|
113
|
+
target: Literal["search", "tags", "tag", "condition"]
|
|
114
|
+
current_value: Text
|
|
115
|
+
# The spoken phrases around a quoted phrase (Dictation Settings).
|
|
116
|
+
quote_open: Identifier
|
|
117
|
+
quote_close: Identifier
|
|
118
|
+
# Spoken before a search term to exclude it (Dictation Settings).
|
|
119
|
+
negate_phrase: Identifier
|
|
120
|
+
|
|
109
121
|
@with_config(ConfigDict(strict=True))
|
|
110
122
|
class TagSuggestionsRequest(TypedDict):
|
|
111
123
|
note_id: Identifier
|
|
@@ -136,6 +148,14 @@ class CreateChildRequest(TypedDict):
|
|
|
136
148
|
undoContext: UndoContext
|
|
137
149
|
viewport: Viewport
|
|
138
150
|
|
|
151
|
+
@with_config(ConfigDict(strict=True))
|
|
152
|
+
class CreateFilePreviewChildRequest(TypedDict):
|
|
153
|
+
fileId: Identifier
|
|
154
|
+
search_query: Text | None
|
|
155
|
+
clientId: Identifier
|
|
156
|
+
undoContext: UndoContext
|
|
157
|
+
viewport: Viewport
|
|
158
|
+
|
|
139
159
|
@with_config(ConfigDict(strict=True))
|
|
140
160
|
class UpdateNoteRequest(TypedDict):
|
|
141
161
|
clientId: Identifier
|
|
@@ -642,6 +642,7 @@ def stream_ai_chat(
|
|
|
642
642
|
model=payload.model,
|
|
643
643
|
)
|
|
644
644
|
provider_messages = ai_chat_store.provider_messages(session_key=session_key)
|
|
645
|
+
earlier_actions = ai_chat_store.earlier_actions(session_key=session_key)
|
|
645
646
|
initial_messages = agent_context_builder.build_initial_messages(
|
|
646
647
|
canonical_messages=provider_messages,
|
|
647
648
|
prompts=prompts,
|
|
@@ -654,7 +655,7 @@ def stream_ai_chat(
|
|
|
654
655
|
events = _stream_runtime_events(payload=payload, openai_api_key=openai_api_key,
|
|
655
656
|
session_key=session_key, provider_messages=provider_messages, prompts=prompts, skills=skills,
|
|
656
657
|
retrieval_settings=retrieval_settings, frozen_scope=frozen_scope, tagging_run=tagging_run,
|
|
657
|
-
web_settings=web_settings,
|
|
658
|
+
web_settings=web_settings, earlier_actions=earlier_actions,
|
|
658
659
|
initial_input_tokens=initial_approx_input_tokens)
|
|
659
660
|
|
|
660
661
|
return StreamingResponse(
|
|
@@ -673,6 +674,7 @@ async def _stream_runtime_events(
|
|
|
673
674
|
provider_messages: list[dict[str, str]], prompts: AgentPromptSet, skills: AgentSkillSet,
|
|
674
675
|
retrieval_settings: AgentRetrievalSettings, frozen_scope: ScopedSearchSnapshot,
|
|
675
676
|
tagging_run: TaggingRun, initial_input_tokens: int, web_settings: AgentWebSettings,
|
|
677
|
+
earlier_actions: list[dict[str, object]],
|
|
676
678
|
) -> AsyncIterator[dict[str, object]]:
|
|
677
679
|
action, start_label = 'provider_runtime', 'Connecting to OpenAI API'
|
|
678
680
|
ready_label = 'OpenAI API ready · 1,050,000-token context'
|
|
@@ -686,7 +688,7 @@ async def _stream_runtime_events(
|
|
|
686
688
|
selected_model=payload.model, thinking_level=payload.thinking_level,
|
|
687
689
|
canonical_messages=provider_messages, prompts=prompts, skills=skills,
|
|
688
690
|
retrieval_settings=retrieval_settings, web_settings=web_settings,
|
|
689
|
-
frozen_scope=frozen_scope, tagging_run=tagging_run)
|
|
691
|
+
frozen_scope=frozen_scope, tagging_run=tagging_run, earlier_actions=earlier_actions)
|
|
690
692
|
try:
|
|
691
693
|
async for event in events:
|
|
692
694
|
yield event
|
|
@@ -20,9 +20,11 @@ from app.api.note_requests import (
|
|
|
20
20
|
SearchSuggestionInteractionRequest,
|
|
21
21
|
TabSearchInteractionRequest,
|
|
22
22
|
TagSuggestionsRequest,
|
|
23
|
+
DictationPasteRequest,
|
|
23
24
|
CreateNoteTopRequest,
|
|
24
25
|
CreateSiblingRequest,
|
|
25
26
|
CreateChildRequest,
|
|
27
|
+
CreateFilePreviewChildRequest,
|
|
26
28
|
UpdateNoteRequest,
|
|
27
29
|
SaveNoteRequest,
|
|
28
30
|
AddSelectedTextTagRequest,
|
|
@@ -61,7 +63,9 @@ from app.services.exception_capture import CapturedExceptionContext
|
|
|
61
63
|
from app.usecases.create_note import CmdCreateNote
|
|
62
64
|
from app.usecases.base import QueryCommand
|
|
63
65
|
from app.usecases.create_sibling import CmdCreateSibling
|
|
66
|
+
from app.services.file_registry import file_registry
|
|
64
67
|
from app.usecases.create_child import CmdCreateChild
|
|
68
|
+
from app.usecases.create_file_preview_child import CmdCreateFilePreviewChild
|
|
65
69
|
from app.usecases.update_content import CmdUpdateContent
|
|
66
70
|
from app.usecases.prefetch_link_titles import CmdPrefetchLinkTitles
|
|
67
71
|
from app.usecases.add_selected_text_tag import CmdAddSelectedTextTag
|
|
@@ -127,6 +131,7 @@ from app.services.html_export import build_notes_export_filename
|
|
|
127
131
|
from app.services.note_fullscreen import build_note_fullscreen_markup
|
|
128
132
|
from app.services.link_titles import link_title_store
|
|
129
133
|
from app.services.search_index import search_index
|
|
134
|
+
from app.services.dictation_cleanup import clean_dictated_paste
|
|
130
135
|
from app.services.tag_suggestions import suggest_tags_for_note
|
|
131
136
|
from app.services.undo_state import reset_undo_stack
|
|
132
137
|
from app.usecases.prioritize import list_prioritize_tag_suggestions
|
|
@@ -551,6 +556,22 @@ def delete_tag_interactions(request: Request) -> Dict[str, object]:
|
|
|
551
556
|
return {"deletedCount": deleted_count}
|
|
552
557
|
|
|
553
558
|
|
|
559
|
+
@router.post("/notes/dictation-paste")
|
|
560
|
+
@transactional_route
|
|
561
|
+
def dictation_paste(payload: DictationPasteRequest) -> Dict[str, object]:
|
|
562
|
+
"""Read-only: the cleaned-up text to insert for a paste (docs/ui/dictation-paste.md)."""
|
|
563
|
+
text = clean_dictated_paste(
|
|
564
|
+
text=payload["text"],
|
|
565
|
+
target=payload["target"],
|
|
566
|
+
existing_tag_frequencies=search_index.list_explicit_tag_frequencies(),
|
|
567
|
+
current_value=payload["current_value"],
|
|
568
|
+
quote_open=payload["quote_open"],
|
|
569
|
+
quote_close=payload["quote_close"],
|
|
570
|
+
negate_phrase=payload["negate_phrase"],
|
|
571
|
+
)
|
|
572
|
+
return {"text": text}
|
|
573
|
+
|
|
574
|
+
|
|
554
575
|
@router.post("/notes/tag-suggestions")
|
|
555
576
|
@transactional_route
|
|
556
577
|
def tag_suggestions(payload: TagSuggestionsRequest) -> Dict[str, object]:
|
|
@@ -750,6 +771,27 @@ def create_child(request: Request, note_id: str, body: CreateChildRequest):
|
|
|
750
771
|
return cmd.execute()
|
|
751
772
|
|
|
752
773
|
|
|
774
|
+
@router.post("/notes/file-preview-child/{note_id}")
|
|
775
|
+
@transactional_route
|
|
776
|
+
def create_file_preview_child(request: Request, note_id: str, body: CreateFilePreviewChildRequest):
|
|
777
|
+
token = _require_bearer_token(request)
|
|
778
|
+
viewport = _require_viewport(body)
|
|
779
|
+
_require_note_present(note_id, context="notes.file-preview-child")
|
|
780
|
+
file_id = body["fileId"]
|
|
781
|
+
if not file_registry.has_file(file_id):
|
|
782
|
+
raise HTTPException(status_code=404, detail=f"File not found: {file_id}")
|
|
783
|
+
cmd = CmdCreateFilePreviewChild(
|
|
784
|
+
parent_note_id=note_id,
|
|
785
|
+
file_id=file_id,
|
|
786
|
+
search_query=body["search_query"],
|
|
787
|
+
token=token,
|
|
788
|
+
client_id=body["clientId"],
|
|
789
|
+
undo_context=body["undoContext"],
|
|
790
|
+
viewport=viewport,
|
|
791
|
+
)
|
|
792
|
+
return cmd.execute()
|
|
793
|
+
|
|
794
|
+
|
|
753
795
|
@router.put("/notes/{note_id}")
|
|
754
796
|
@transactional_route
|
|
755
797
|
def update_note(request: Request, note_id: str, body: UpdateNoteRequest):
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""The agent's own record of what it did for an answer.
|
|
2
|
+
|
|
3
|
+
Each tool call becomes one short entry: what was asked and what came of it,
|
|
4
|
+
never the content a tool returned (page text and notes can be huge, and the
|
|
5
|
+
model can read them again). The entries are kept with the answer for the rest of
|
|
6
|
+
the chat and given to the model on later turns, so a question such as "did you
|
|
7
|
+
search the web for that?" is answered from what actually happened. Only the
|
|
8
|
+
model sees them.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import json
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
_NOTE_READ_TOOLS = frozenset({"read_view_notes", "search_view_notes"})
|
|
17
|
+
_OPERATION_TOOLS = frozenset({"summarize_view", "propose_tag_generation", "propose_tag_review"})
|
|
18
|
+
_KNOWN_TOOLS = _NOTE_READ_TOOLS | _OPERATION_TOOLS | {
|
|
19
|
+
"lookup_metalist_help", "view_overview", "open_web_pages", "open_menu",
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def describe_action(*, name: str, arguments: str, result_content: str, is_error: bool) -> dict[str, object]:
|
|
24
|
+
"""One log entry for a tool call, from its JSON arguments and JSON result."""
|
|
25
|
+
# A rejected call may name a tool that does not exist: it is still recorded.
|
|
26
|
+
if is_error:
|
|
27
|
+
return {"tool": name, "rejected": True}
|
|
28
|
+
if name not in _KNOWN_TOOLS:
|
|
29
|
+
raise ValueError(f"No action log entry for unknown tool: {name!r}")
|
|
30
|
+
parsed_arguments = json.loads(arguments)
|
|
31
|
+
assert isinstance(parsed_arguments, dict), "Tool arguments are a JSON object"
|
|
32
|
+
if name in _OPERATION_TOOLS:
|
|
33
|
+
return {"tool": name, "arguments": parsed_arguments}
|
|
34
|
+
result = json.loads(result_content)
|
|
35
|
+
assert isinstance(result, dict), "Tool results are a JSON object"
|
|
36
|
+
if name == "lookup_metalist_help":
|
|
37
|
+
return {"tool": name, "topics": list(parsed_arguments["topics"])}
|
|
38
|
+
if name == "view_overview":
|
|
39
|
+
return {"tool": name, "notes_in_view": result["note_count"], "trees_in_view": result["tree_count"]}
|
|
40
|
+
if name == "open_menu":
|
|
41
|
+
return {"tool": name, "menu": result["label"], "status": result["status"]}
|
|
42
|
+
if name == "open_web_pages":
|
|
43
|
+
return {"tool": name, "pages": [_page_entry(page) for page in result["pages"]]}
|
|
44
|
+
entry: dict[str, object] = {"tool": name}
|
|
45
|
+
if name == "search_view_notes":
|
|
46
|
+
entry["query"] = parsed_arguments["query"]
|
|
47
|
+
entry["matching_notes"] = result["matching_note_count"]
|
|
48
|
+
entry["trees_read"] = len(result["trees"])
|
|
49
|
+
entry["trees_left_unread"] = len(result["unread_root_ids"])
|
|
50
|
+
entry["trees_too_large"] = len(result["too_large_root_ids"])
|
|
51
|
+
return entry
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _page_entry(page: dict[str, object]) -> dict[str, object]:
|
|
55
|
+
"""The address as asked, whether it opened, and its title when it did."""
|
|
56
|
+
title = ""
|
|
57
|
+
if page["status"] == "ok":
|
|
58
|
+
title = page["title"]
|
|
59
|
+
return {"url": page["requested_url"], "status": page["status"], "title": title}
|
|
@@ -52,6 +52,7 @@ from app.services.bulk_operation import bulk_operation_guard
|
|
|
52
52
|
from app.services.agent.citation_tokens import ShortCitationTranslator
|
|
53
53
|
from app.services.agent.note_aliases import NoteAliases
|
|
54
54
|
from app.services.agent.execution_errors import AgentExecutionError
|
|
55
|
+
from app.services.agent.action_log import describe_action
|
|
55
56
|
|
|
56
57
|
|
|
57
58
|
MAX_AGENT_TURNS = 8
|
|
@@ -82,6 +83,8 @@ class AgentLoopState:
|
|
|
82
83
|
self.web_evidence: list[WebPageEvidence] = []
|
|
83
84
|
self.capabilities = capabilities
|
|
84
85
|
self.content = ""
|
|
86
|
+
# What this answer did, for later turns (action_log.py).
|
|
87
|
+
self.actions: list[dict[str, object]] = []
|
|
85
88
|
# Note text shown to the model, and full-mode addresses the user approved.
|
|
86
89
|
self.note_text_parts: list[str] = [selected_note_text]
|
|
87
90
|
self.approved_urls: set[str] = set()
|
|
@@ -129,14 +132,19 @@ class AgentLoopState:
|
|
|
129
132
|
"reference_note_ids": list(self.reference_note_ids),
|
|
130
133
|
"reference_web_ids": self.reference_web_ids()}
|
|
131
134
|
|
|
135
|
+
def record_action(self, *, call: dict[str, str], result_content: str, is_error: bool) -> None:
|
|
136
|
+
self.actions.append(describe_action(name=call["name"], arguments=call["arguments"],
|
|
137
|
+
result_content=result_content, is_error=is_error))
|
|
138
|
+
|
|
132
139
|
def done_event(self) -> dict[str, object]:
|
|
133
140
|
return {"type": "done", "reference_note_ids": list(self.reference_note_ids),
|
|
134
|
-
"reference_web_ids": self.reference_web_ids()}
|
|
141
|
+
"reference_web_ids": self.reference_web_ids(), "actions": list(self.actions)}
|
|
135
142
|
|
|
136
143
|
|
|
137
144
|
class AgentLoopMixin:
|
|
138
145
|
async def _run_agent_loop(
|
|
139
146
|
self, *, run, canonical_messages: list[dict[str, str]], frozen_scope: ScopedSearchSnapshot, tagging_run,
|
|
147
|
+
earlier_actions: list[dict[str, object]],
|
|
140
148
|
) -> AsyncIterator[dict[str, object]]:
|
|
141
149
|
if not isinstance(frozen_scope, ScopedSearchSnapshot):
|
|
142
150
|
raise TypeError("frozen_scope must be ScopedSearchSnapshot")
|
|
@@ -167,6 +175,7 @@ class AgentLoopMixin:
|
|
|
167
175
|
messages = self._context_builder.build_agent_messages(
|
|
168
176
|
canonical_messages=canonical_messages, skills=run.skills, web_settings=run.web_settings,
|
|
169
177
|
snapshot=snapshot, available_urls=capabilities.normalized_urls, note_aliases=note_aliases,
|
|
178
|
+
earlier_actions=earlier_actions,
|
|
170
179
|
)
|
|
171
180
|
self._trace_store.append_event(
|
|
172
181
|
session_key=run.session_key, run_id=run.run_id, event_type="FROZEN_SCOPE",
|
|
@@ -238,16 +247,21 @@ class AgentLoopMixin:
|
|
|
238
247
|
result = tool_message_result({"summary": "not started",
|
|
239
248
|
"reason": "The current view has no notes to summarize."})
|
|
240
249
|
self._record_tool_call(run=run, call=operation, result_text=result.content)
|
|
250
|
+
state.record_action(call=operation, result_content=result.content, is_error=False)
|
|
241
251
|
messages.append({"role": "tool", "tool_call_id": operation["id"], "name": operation["name"],
|
|
242
252
|
"content": result.content})
|
|
243
253
|
answered_without_operation = True
|
|
244
254
|
elif not isinstance(parsed, ToolResult):
|
|
245
255
|
self._record_tool_call(run=run, call=operation, result_text="(operation started)")
|
|
256
|
+
state.record_action(call=operation, result_content="{}", is_error=False)
|
|
246
257
|
async with aclosing(self._stream_agent_operation(
|
|
247
258
|
run=run, canonical_messages=canonical_messages, snapshot=snapshot,
|
|
248
259
|
tagging_run=tagging_run, arguments=parsed, state=state,
|
|
249
260
|
)) as operation_events:
|
|
250
261
|
async for event in operation_events:
|
|
262
|
+
# The operation ends the answer: its completion carries the log.
|
|
263
|
+
if event["type"] == "done":
|
|
264
|
+
event = {**event, "actions": list(state.actions)}
|
|
251
265
|
yield event
|
|
252
266
|
return
|
|
253
267
|
if answered_without_operation:
|
|
@@ -266,6 +280,7 @@ class AgentLoopMixin:
|
|
|
266
280
|
result = result_holder[0]
|
|
267
281
|
results.append(result)
|
|
268
282
|
state.add_tool_result(result)
|
|
283
|
+
state.record_action(call=call, result_content=result.content, is_error=result.is_error)
|
|
269
284
|
self._record_tool_call(run=run, call=call, result_text=result.content)
|
|
270
285
|
messages.append({"role": "tool", "tool_call_id": call["id"], "name": call["name"],
|
|
271
286
|
"content": result.content})
|
|
@@ -78,7 +78,8 @@ class AgentContextBuilder:
|
|
|
78
78
|
"none": (
|
|
79
79
|
"Web access is disabled. You cannot search or open pages. If the "
|
|
80
80
|
"request requires the web, state that limitation and tell the user "
|
|
81
|
-
"they can enable contextual or full web access in AI Agent Settings."
|
|
81
|
+
"they can enable contextual or full web access in AI Agent Settings. Label "
|
|
82
|
+
"anything you suggest from your own knowledge as not looked up."
|
|
82
83
|
),
|
|
83
84
|
"contextual": (
|
|
84
85
|
"You may open only exact URLs in available_urls, plus addresses written in "
|
|
@@ -86,7 +87,11 @@ class AgentContextBuilder:
|
|
|
86
87
|
"A #fragment is ignored "
|
|
87
88
|
"when comparing, so https://a.example/page#part is the same address as "
|
|
88
89
|
"https://a.example/page. You cannot search, and links discovered inside "
|
|
89
|
-
"opened pages do not become available."
|
|
90
|
+
"opened pages do not become available. When a request needs a search (for "
|
|
91
|
+
"example newer or recent papers, releases or news), say plainly that this mode "
|
|
92
|
+
"only opens links already in the notes or chat, that 'Open any public web page' "
|
|
93
|
+
"in AI Agent Settings allows searching, and label anything you suggest from your "
|
|
94
|
+
"own knowledge as not looked up."
|
|
90
95
|
),
|
|
91
96
|
"full": (
|
|
92
97
|
"You may open any direct public HTTP(S) page, including Google "
|
|
@@ -158,6 +163,7 @@ class AgentContextBuilder:
|
|
|
158
163
|
snapshot: ScopedSearchSnapshot,
|
|
159
164
|
available_urls: tuple[str, ...],
|
|
160
165
|
note_aliases: NoteAliases,
|
|
166
|
+
earlier_actions: list[dict[str, object]],
|
|
161
167
|
) -> list[dict[str, object]]:
|
|
162
168
|
"""The tool-using agent's opening conversation.
|
|
163
169
|
|
|
@@ -189,6 +195,16 @@ class AgentContextBuilder:
|
|
|
189
195
|
{"role": "user", "content": "SELECTED_NOTE_CONTEXT\n" + json.dumps(view_context, sort_keys=True, separators=(",", ":"))},
|
|
190
196
|
*self.append_web_access_context(messages=[], settings=web_settings, available_urls=available_urls),
|
|
191
197
|
]
|
|
198
|
+
if earlier_actions:
|
|
199
|
+
context_messages.append({"role": "user", "content": "EARLIER_ACTIONS\n" + json.dumps({
|
|
200
|
+
"instruction": (
|
|
201
|
+
"Your own record of what you did for each earlier answer in this chat, oldest first: "
|
|
202
|
+
"the tools you called, what you asked for, and what came of them (page text and note "
|
|
203
|
+
"content are not repeated here). Answer questions about how an earlier answer was made "
|
|
204
|
+
"only from this record. If it does not show something, say you cannot tell."
|
|
205
|
+
),
|
|
206
|
+
"answers": earlier_actions,
|
|
207
|
+
}, sort_keys=True, separators=(",", ":"))})
|
|
192
208
|
return [
|
|
193
209
|
*system_messages,
|
|
194
210
|
*[dict(message) for message in canonical_messages[:-1]],
|
|
@@ -16,6 +16,7 @@ HELP_TOPICS = {
|
|
|
16
16
|
'ai': ('AI and tag proposals', 'OpenAI settings, context limits, prompts/skills, history export, and AI tag proposals: generation, acceptance, rejection/removal and bulk undo limits. This topic alone covers proposal workflow explanations.'),
|
|
17
17
|
'privacy': ('Privacy and security', 'Cloud disclosure, gray notes when hovering chat, password exclusion, encryption and credentials.'),
|
|
18
18
|
'data': ('Namespaces and backups', 'Namespaces, backup/restore, HTML export, ports and updates.'),
|
|
19
|
+
'dictation': ('Dictation (speech to text)', 'Pasting dictated text from speech-to-text tools such as Superwhisper into the search bar, tag bar or a note: how words become tags, spoken dash/quote/or/not, "at to do" meta tags, the "start tags" phrase in notes, undo, and Dictation Settings.'),
|
|
19
20
|
'releases': ('Release notes', 'What changed in each MetaList version (what is new, when a feature or fix arrived).'),
|
|
20
21
|
}
|
|
21
22
|
HelpTopic = Literal[tuple(HELP_TOPICS)]
|
|
@@ -103,6 +103,13 @@ last tool call. Answer the user's exact current question. Use the conversation t
|
|
|
103
103
|
resolve follow-ups such as "try again"; earlier answers are not evidence about the
|
|
104
104
|
current view, and earlier citations must not be reused.
|
|
105
105
|
|
|
106
|
+
`EARLIER_ACTIONS` is your own record of what you did for each earlier answer in
|
|
107
|
+
this chat: the tools you called and what came of them. When asked how an earlier
|
|
108
|
+
answer was made (did you search the web, which pages, did you read the notes),
|
|
109
|
+
answer from that record, including the searches and pages it lists. If the record
|
|
110
|
+
does not show something, say you cannot tell; never deny or claim an action
|
|
111
|
+
otherwise.
|
|
112
|
+
|
|
106
113
|
Notes are identified by short ids such as `n12`. Cite every claim drawn from a note
|
|
107
114
|
with its id in double brackets, copying the `note_id` of the note whose
|
|
108
115
|
`content_text` supports it (a child, not merely its root), directly after the
|
|
@@ -160,8 +160,12 @@ class AgentRuntime(AgentLoopMixin):
|
|
|
160
160
|
web_settings: AgentWebSettings,
|
|
161
161
|
frozen_scope: ScopedSearchSnapshot,
|
|
162
162
|
tagging_run,
|
|
163
|
+
earlier_actions: list[dict[str, object]],
|
|
163
164
|
) -> AsyncIterator[dict[str, object]]:
|
|
164
|
-
"""Answer with the tool-using agent loop (see agent_loop.py).
|
|
165
|
+
"""Answer with the tool-using agent loop (see agent_loop.py).
|
|
166
|
+
|
|
167
|
+
`earlier_actions` is the agent's own record of what each earlier answer in
|
|
168
|
+
the history did (AiChatSessionStore.earlier_actions, action_log.py)."""
|
|
165
169
|
run, _initial_messages = self._start_run(
|
|
166
170
|
session_key=session_key, base_url=base_url, selected_model=selected_model,
|
|
167
171
|
thinking_level=thinking_level, canonical_messages=canonical_messages, prompts=prompts,
|
|
@@ -172,7 +176,7 @@ class AgentRuntime(AgentLoopMixin):
|
|
|
172
176
|
try:
|
|
173
177
|
async with aclosing(self._run_agent_loop(
|
|
174
178
|
run=run, canonical_messages=canonical_messages, frozen_scope=frozen_scope,
|
|
175
|
-
tagging_run=tagging_run,
|
|
179
|
+
tagging_run=tagging_run, earlier_actions=earlier_actions,
|
|
176
180
|
)) as steps:
|
|
177
181
|
async for event in steps:
|
|
178
182
|
self._trace_store.append_event(
|
|
@@ -39,7 +39,7 @@ a word search (every word must appear in a note's text or tags), and reading who
|
|
|
39
39
|
result trees in visible order. Each read returns as many whole trees as fit the
|
|
40
40
|
evidence limit; a tree is never divided, trees left unread can be read in a later
|
|
41
41
|
step, and a tree too large for the limit on its own is reported instead of read.
|
|
42
|
-
Notes within returned trees are complete. A whole-view summary packs trees in
|
|
42
|
+
The AI keeps a private record of what it did for each answer in the chat (help it looked up, notes it read, searches and pages it opened), so it can say truthfully how an earlier answer was made; the record is cleared with the chat. Notes within returned trees are complete. A whole-view summary packs trees in
|
|
43
43
|
visible order and asks before using several batches. The limit estimates
|
|
44
44
|
serialized evidence, not the entire conversation/model context. Raising it can
|
|
45
45
|
include more evidence and increase cost. A reference-source view
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Dictation (speech to text)
|
|
2
|
+
|
|
3
|
+
Use this reference to explain MetaList accurately. It describes user capabilities,
|
|
4
|
+
not permission or tools for you to execute every operation. You can answer and
|
|
5
|
+
request one supported menu/dialog opening. You cannot submit a form, change
|
|
6
|
+
settings, run a shell command, or mutate notes through this help response. Do not
|
|
7
|
+
claim that you inspected current notes or settings: none are supplied here.
|
|
8
|
+
Prefer user-facing steps over implementation details. If the reference does not
|
|
9
|
+
answer a question, say what is unknown; do not invent syntax or controls.
|
|
10
|
+
|
|
11
|
+
Sources: docs/ui/dictation-paste.md
|
|
12
|
+
|
|
13
|
+
## What it is for
|
|
14
|
+
|
|
15
|
+
Speech-to-text tools such as Superwhisper paste sentences, not tags: saying
|
|
16
|
+
"neural network" can arrive as `Neural network, neural network. Neural-Dash
|
|
17
|
+
Network.` MetaList cleans up such text when it is **pasted** into the search bar, a
|
|
18
|
+
note's tag bar, or a note being edited, and turns it into the user's tags. It uses
|
|
19
|
+
fixed rules, no AI, and it only reacts to pasting: typed text is never changed.
|
|
20
|
+
|
|
21
|
+
## How dictated words become tags
|
|
22
|
+
|
|
23
|
+
- Sentence punctuation (`, . ? ! ; :`) is dropped.
|
|
24
|
+
- Spoken joiners join words: "dash" or "hyphen" gives `-`, "underscore" `_`,
|
|
25
|
+
"slash" `/`. Superwhisper's `foo-Dash bar` gives `foo-bar`.
|
|
26
|
+
- The longest run of words matching one of the user's existing tags becomes that
|
|
27
|
+
tag, ignoring capitals and treating spaces, `-`, `_`, `.` and `/` alike, spelled
|
|
28
|
+
the way the user uses it most. "neural network" gives `neural-network`.
|
|
29
|
+
- Words also match a tag written as one word: "to do" gives `todo`, "scratch pad"
|
|
30
|
+
gives `scratchpad`.
|
|
31
|
+
- "at" before the name of a built-in meta tag gives that meta tag: "at to do" gives
|
|
32
|
+
`@todo`, "at done" `@done`, "at list bulleted" `@list-bulleted`. Otherwise "at"
|
|
33
|
+
is ignored. One "at" covers a run of meta tags: "at green bold" gives
|
|
34
|
+
`@green @bold` (Superwhisper drops a repeated "at" anyway), even if the user also
|
|
35
|
+
has a plain tag such as `bold`.
|
|
36
|
+
- "quote … end quote" (the default quote phrases) or quote marks mark a phrase, in
|
|
37
|
+
the search bar and tag relationship conditions only; in tag fields the quote
|
|
38
|
+
phrases are dropped.
|
|
39
|
+
- Filler words (a, an, and, at, the, tag, tags, comma, period, um, uh) are ignored,
|
|
40
|
+
unless the word is itself one of the user's tags. A spoken word that is a tag
|
|
41
|
+
always stays that tag.
|
|
42
|
+
- Repeats count once, and tags already in the field are not added again.
|
|
43
|
+
|
|
44
|
+
## Where to paste
|
|
45
|
+
|
|
46
|
+
- **Search bar:** words matching no tag are dropped. "or" becomes `OR`, the
|
|
47
|
+
exclusion phrase ("minus" by default) excludes the next term ("neural network
|
|
48
|
+
minus python" gives `neural-network -python`), and a quoted phrase becomes a text
|
|
49
|
+
search. "not" is an ordinary word unless it is set as the exclusion phrase.
|
|
50
|
+
- **Tag bar:** words matching no tag become new tags, lowercased unless they look
|
|
51
|
+
like an acronym (`GPT`). Each word is its own tag unless the words together match
|
|
52
|
+
one of the user's tags; a new multi-word tag has to be typed.
|
|
53
|
+
- **Other one-tag fields** (Edit Tag Relationships' search box, Add tag, Implied
|
|
54
|
+
tag, Synonym tag, Rename tag; Prioritize Tag; Manage tag proposals' tag filter):
|
|
55
|
+
the whole paste becomes one tag, "Machine learning" gives `machine-learning`.
|
|
56
|
+
- **Tag relationship conditions:** existing tags and quoted text; no regular
|
|
57
|
+
expressions by voice.
|
|
58
|
+
- **AI privacy tag lists:** tags, one per line.
|
|
59
|
+
- **A note being edited:** say the tag phrase, **"start tags"** by default, then the
|
|
60
|
+
tags. The text before the phrase goes into the note; the words after it are added
|
|
61
|
+
to the note's tags with the tag-bar rules. "Here is my content. Start tags. Neural
|
|
62
|
+
network, at to do." adds the content and the tags `neural-network @todo`. Saying
|
|
63
|
+
only "Start tags, scratch pad." adds just the tag. Only the first phrase counts.
|
|
64
|
+
Words that together match no existing tag become separate tags: "spring planning"
|
|
65
|
+
gives `spring` and `planning`, never `spring-planning` (type a new multi-word tag).
|
|
66
|
+
Without the phrase, a paste into a note is an ordinary paste.
|
|
67
|
+
|
|
68
|
+
It is a phrase rather than a repeated word because Superwhisper drops a word said
|
|
69
|
+
twice in a row.
|
|
70
|
+
|
|
71
|
+
## Undo
|
|
72
|
+
|
|
73
|
+
One undo (Cmd/Ctrl+Z) right after the paste brings back what was pasted in the
|
|
74
|
+
search bar or tag bar (in the tag bar without commas, which tags cannot contain).
|
|
75
|
+
After a paste into a note, one undo removes both the pasted text and the added tags.
|
|
76
|
+
|
|
77
|
+
## Dictation Settings
|
|
78
|
+
|
|
79
|
+
The command palette's **Dictation Settings** dialog sets four phrases, each words of
|
|
80
|
+
letters (2 to 64 characters): the phrase that starts tags in a note ("start tags"),
|
|
81
|
+
the phrases that start and end a quote ("quote", "end quote"), and the phrase that
|
|
82
|
+
excludes the next search term ("minus"). One unusual word such as "armadillo" also
|
|
83
|
+
works. The quote and exclusion phrases must differ. Save applies them.
|
|
84
|
+
|
|
85
|
+
## Tips and limits
|
|
86
|
+
|
|
87
|
+
- Plurals do not match: "transformers" is not the tag `transformer`. In search it
|
|
88
|
+
is dropped; in the tag bar it becomes a new tag.
|
|
89
|
+
- In the tag bar, a new multi-word tag has to be typed: dictated words become
|
|
90
|
+
separate tags unless together they match an existing tag.
|
|
91
|
+
- Saying "dash" in its ordinary sense ("100 meter dash") joins the words around it.
|
|
92
|
+
- `@size=…` and other values cannot be dictated; type them.
|
|
@@ -62,6 +62,7 @@ Opening or dismissing the command palette does not clear undo/redo. Global actio
|
|
|
62
62
|
- Endpoint definitions (behavior/labels) live in code.
|
|
63
63
|
- Palette preferences (`pref.*`) and command usage history are persisted per namespace in the main SQLite DB via `/api2/auth/client-state*`, not in browser `localStorage`.
|
|
64
64
|
- `Animated transitions` is on by default and controls UI motion such as tag-bar edit transitions and note expand/collapse transitions.
|
|
65
|
+
- `Dictation Settings` sets the spoken phrases for pasted dictated text: the phrase that starts tags in a note (`start tags`), the phrases that start and end a quote (`quote`, `end quote`), and the phrase that excludes the next search term (`minus`). Each is words of letters, 2 to 64 characters; the quote and exclusion phrases must differ. Save applies them, Escape or a click outside closes without saving.
|
|
65
66
|
- `Visual Cues` opens one window of independent checkboxes, all on by default and saved immediately. Under Drag and drop: `Drag ghost` (a dashed outline of the dragged note and its visible children follows the pointer), `Drop indicator` (a grey landing line plus a faint outline on the note it lands beside or under), and `Direction cursor` (the mouse cursor itself becomes an up, down, indent or outdent icon for a possible move; impossible moves and the option turned off keep the usual grabbing hand). They change only what is shown; dragging works the same. Close the window with Escape or by clicking outside it.
|
|
66
67
|
- `Note Layout & Appearance` stores namespace-scoped presets for top-level note size, child indentation, vertical spacing, note corners, and tag style. The defaults are `Larger`, `Standard`, `Comfortable`, `Round`, and `Pills` respectively. Note corners can be `Subtle`, `Rounded`, or `Round`; tag style shows visible note tags as outlined `Pills` or `Plain text` in both themes.
|
|
67
68
|
- `Search suggestion stats & settings` is the single suggestion-personalization control surface. Its ordered 1–365 day slots and default-on time-window-label and one-credit-per-note-per-search-context toggles save immediately when changed. The modal also displays retained daily tag-credit statistics and provides the confirmed activity reset. An empty slot list disables personalization; the default slots are 1, 7, and 30 days.
|
|
@@ -39,6 +39,7 @@ Sources: docs/ui/controls.md
|
|
|
39
39
|
| `⇧ + ⌘ + Z` or `⌘ + Y` | Redo text/tag edits locally, or redo the latest saved mutation when the active editor has no local edit history |
|
|
40
40
|
|
|
41
41
|
- If note clipboard conditions are **not** met and edit mode is active, `⌘ + V` uses browser clipboard paste and runs external HTML sanitization before insertion.
|
|
42
|
+
- Dictated text pasted into a note can end with tags: everything after the phrase "start tags" (set in `Dictation Settings`) is added to the note's tags. The full rules are in the dictation help topic.
|
|
42
43
|
- When note paste replaces an empty target, the target keeps its search-context tags and merges in copied root tags with case-insensitive dedupe.
|
|
43
44
|
- A saved whole-note paste resets the local editor history baseline so the next Undo reaches application history.
|
|
44
45
|
- If the clipboard value came from `Generate random password…`, pasting into an empty note also adds `@password` automatically when that tag is not already present.
|
|
@@ -36,12 +36,12 @@ Sources: docs/ui/references.md
|
|
|
36
36
|
- when that compact source preview is a standalone URL with a cached link title, it displays the same `title · domain` treatment as the source note instead of the raw URL. Inline/prose URLs remain raw.
|
|
37
37
|
- right-click anywhere inside a rendered reference and choose **Go to Source** to open that source note with the same navigation behavior.
|
|
38
38
|
- File targets:
|
|
39
|
-
- non-image files render a file card/link row with a deterministic type badge (`PDF`, `IMG`, `VID`, `TXT`, etc.) and the file title.
|
|
39
|
+
- non-image files render a file card/link row with a deterministic type badge (`PDF`, `IMG`, `VID`, `TXT`, etc.) and the file title. `.txt`, `.md`, `.csv` and `.json` files are labelled by their extension: `.TXT`, `.MD`, `.CSV`, `.JSON`.
|
|
40
40
|
- embedded image files (`![[UUID]]`) render an authenticated image preview with a `download image` control beneath it.
|
|
41
41
|
- right-clicking the rendered image preview also offers image actions (`Copy Image`, `Save Image`, `Zoom Image`, `Open Image in New Tab`).
|
|
42
42
|
- link-mode image files (`[[UUID]]`) keep the generic compact file card/link row.
|
|
43
43
|
- embedded Excalidraw diagrams (`.excalidraw` files, badge `DRAW`) render their stored light or dark SVG preview; double-click or right-click **Edit Diagram** to open the full-screen editor (see Excalidraw Diagrams below).
|
|
44
|
-
- clicking the rendered file reference downloads the decrypted file from the server.
|
|
44
|
+
- clicking the rendered file reference downloads the decrypted file from the server; hovering it shows the tooltip "Click to download <file name>".
|
|
45
45
|
- when the host note is collapsed, non-image file references stay visible as a single compact row showing the badge and a truncated title.
|
|
46
46
|
- when the host note is collapsed and the first visible line is an embedded image file or diagram, the note collapses to a compact thumbnail-only version of that preview.
|
|
47
47
|
- Rendered references have no internal expand/collapse or embed/link controls; edit the raw token to change between `![[...]]` and `[[...]]`.
|
|
@@ -60,6 +60,7 @@ Sources: docs/ui/references.md
|
|
|
60
60
|
- Drag/drop follows the same attachment path for non-image files.
|
|
61
61
|
- Dropping onto the actively edited note inserts into that note.
|
|
62
62
|
- Dropping anywhere else creates a new top note first, then inserts there.
|
|
63
|
+
- Dropping a `.txt`, `.md`, `.csv` or `.json` file also copies its text into a new child note under the note holding its pill, shown expanded. Markdown is tagged `@markdown`, CSV `@csv` and JSON `@json`, so they render as formatted text, a table and pretty-printed JSON. The child is the last child, one per file in drop order. It is an ordinary note: edit or delete it freely; the stored file is unchanged and clicking the pill still downloads it. Files over 200 KB or not in UTF-8 get only the pill, with a banner saying why. `Attach file…` adds no child.
|
|
63
64
|
- Named image files dropped or pasted into the editor prompt for one of two paths:
|
|
64
65
|
- `Paste Inline`: embed the image into note HTML as compressed `data:image/...`.
|
|
65
66
|
- `Save as File`: upload the original file without recompression and insert its `![[UUID]]` token.
|
|
@@ -5,6 +5,14 @@ README. Changes made after the newest listed version are not described here.
|
|
|
5
5
|
Compare with installed_version from the help lookup to tell the user whether
|
|
6
6
|
they already have a release. Version info offers updates (see the data topic).
|
|
7
7
|
|
|
8
|
+
## 0.13.0
|
|
9
|
+
|
|
10
|
+
- Dictation: text from speech-to-text tools such as Superwhisper, pasted into the search bar or any tag field, becomes your existing tags ("neural network" gives `neural-network`). Say "quote … end quote" for text, "minus" to exclude, "at" before meta tags such as `@todo`. In a note, the words after "start tags" go to its tag bar. The phrases are set in Dictation Settings, and one undo restores what was pasted.
|
|
11
|
+
- A quoted search with a space at its edge matches whole words: `" fat"` no longer finds "father".
|
|
12
|
+
- The AI keeps a record of what it did for each answer (notes read, searches, web pages opened), so questions like "did you search the web for that?" are answered from what actually happened.
|
|
13
|
+
- Dropping a `.txt`, `.md`, `.csv` or `.json` file stores it as before and adds its text as a child note, shown as Markdown, a table or formatted JSON. File pills show the extension (`.MD`, `.CSV`, …), and hovering a pill says that clicking downloads the file.
|
|
14
|
+
- Typing one letter in the tag bar now narrows the suggestions you were already shown instead of reordering them, so the tag you want is in the top five far more often.
|
|
15
|
+
|
|
8
16
|
## 0.12.0
|
|
9
17
|
|
|
10
18
|
- AI chat is now a tool-using agent: in one answer it can look up MetaList help, read and search the notes in your view, open web pages, and open menus, instead of picking a single route up front. Answers cite notes and web pages with clickable references, including each item listed from a web page.
|
|
@@ -71,6 +71,9 @@ Searching for quote characters without escaping:
|
|
|
71
71
|
- Leading/trailing whitespace is trimmed.
|
|
72
72
|
- The verifier actively rewrites the input while typing (cursor/selection is preserved).
|
|
73
73
|
|
|
74
|
+
## Pasting Dictated Text
|
|
75
|
+
- Pasting (never typing) dictated text, for example from Superwhisper, turns it into tags: "neural network minus python" becomes `neural-network -python`. The full rules are in the dictation help topic.
|
|
76
|
+
|
|
74
77
|
## Completeness + Warnings
|
|
75
78
|
The verifier produces:
|
|
76
79
|
- `normalizedText`: the normalized query string.
|
|
@@ -135,6 +138,7 @@ Ontology rules also add **inferred tags** before search matching:
|
|
|
135
138
|
- Prefix matching happens against the complete candidate set before the visible suggestion limit is applied, so an interacted `shortcut` cannot be discarded merely because 50 unrelated tags rank above it globally and leave frequency-ranked `short-story` first.
|
|
136
139
|
- Case-equivalent tags are collapsed in suggestions, and the most-used spelling is shown.
|
|
137
140
|
- Searches themselves never earn credit. Intentional note engagements—edit selection, manual expansion, full-screen view, shell/todo command execution—increment the note's raw explicit/inherited searchable tags once per active tab/search flow. Leaving for another tab or executed search and later returning starts a new flow, so a later shell run can count again. Successfully adding explicit tags separately credits only those newly added tags; removals and case-only changes are neutral. Accepting a search suggestion by mouse or keyboard credits that selected tag once, with no engagement-flow deduplication. Clicking a search-context tab credits each known positive tag term in its executed query once; excluded tags and quoted text are ignored. Programmatic tab restoration/switching, collapse, search execution, hover, render, and scroll are neutral.
|
|
141
|
+
- After one or more completed tags, the remaining suggestions (only tags that still leave results) are ordered by how closely their notes overlap with the notes matching the tags already typed, so specific companions come before tags that are common everywhere.
|
|
138
142
|
- Activity uses sparse per-calendar-day counts. A window sums the relevant daily buckets, selects its highest-count matching tag, and excludes tags chosen by earlier windows. No decay calculation or all-time score exists. The latest 365 populated days are retained, so unused calendar days consume no buckets.
|
|
139
143
|
- In password-protected namespaces, all retained daily buckets live together in one authenticated encrypted payload. The database exposes only one random row UUID, ciphertext, nonce, and authentication tag—never dates, tag names, counts, queries, or changed-tag metadata.
|
|
140
144
|
- A typed prefix can match either the start of the full tag or the start of any connector-separated segment.
|
|
@@ -158,6 +162,11 @@ Text matching is:
|
|
|
158
162
|
- Case-insensitive (`casefold`).
|
|
159
163
|
- Against **visible text**, extracted by stripping HTML (scripts/styles ignored).
|
|
160
164
|
- Also against tag-bar `/* ... */` comment text (whitespace-normalized).
|
|
165
|
+
- A space at the edge of the quotes marks a word boundary on that side: `"fat "` needs
|
|
166
|
+
the word to end there (a space, punctuation or the end of the text follows), so it
|
|
167
|
+
matches "fat cat" and "fat." but not "father"; `" fat"` needs it to start there, so
|
|
168
|
+
it does not match "sulfate"; `" fat "` matches only the word "fat". Without edge
|
|
169
|
+
spaces a term matches anywhere, also inside words (`"fat"` matches "father").
|
|
161
170
|
|
|
162
171
|
### UUID Terms
|
|
163
172
|
- UUIDs in positive terms are treated as direct note targets (including when pasted as `[[UUID]]`).
|