MetaList 0.22.0__tar.gz → 0.23.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.
Files changed (613) hide show
  1. {metalist-0.22.0/metalist.egg-info → metalist-0.23.0}/PKG-INFO +17 -2
  2. {metalist-0.22.0 → metalist-0.23.0}/README.md +15 -0
  3. {metalist-0.22.0 → metalist-0.23.0}/app/api/note_requests.py +37 -3
  4. {metalist-0.22.0 → metalist-0.23.0}/app/api/routes/auth.py +2 -2
  5. {metalist-0.22.0 → metalist-0.23.0}/app/api/routes/backups.py +10 -10
  6. {metalist-0.22.0 → metalist-0.23.0}/app/api/routes/notes.py +53 -3
  7. {metalist-0.22.0 → metalist-0.23.0}/app/api/routes/ontology.py +133 -41
  8. {metalist-0.22.0 → metalist-0.23.0}/app/api/transactions.py +2 -2
  9. {metalist-0.22.0 → metalist-0.23.0}/app/db/engine.py +0 -4
  10. {metalist-0.22.0 → metalist-0.23.0}/app/main.py +15 -15
  11. {metalist-0.22.0 → metalist-0.23.0}/app/security/authenticated_logging.py +5 -3
  12. {metalist-0.22.0 → metalist-0.23.0}/app/server_runtime.py +10 -8
  13. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/agent_tools.py +2 -2
  14. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/help_catalog.py +1 -1
  15. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/help-ai.md +3 -3
  16. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/help-data.md +15 -15
  17. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/help-dictation.md +3 -4
  18. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/help-formatting.md +3 -3
  19. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/help-menus.md +26 -24
  20. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/help-mouse.md +5 -5
  21. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/help-notes.md +13 -5
  22. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/help-ontology.md +6 -2
  23. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/help-privacy.md +17 -17
  24. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/help-references.md +11 -11
  25. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/help-releases.md +15 -0
  26. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/help-reminders.md +3 -3
  27. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/help-search.md +4 -4
  28. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/help-tags.md +1 -1
  29. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/tagging.py +1 -1
  30. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/tagging_run.py +1 -1
  31. {metalist-0.22.0 → metalist-0.23.0}/app/services/app_updates.py +1 -1
  32. {metalist-0.22.0 → metalist-0.23.0}/app/services/auth_service.py +1 -1
  33. {metalist-0.22.0 → metalist-0.23.0}/app/services/backup_service.py +2 -2
  34. {metalist-0.22.0 → metalist-0.23.0}/app/services/bulk_operation.py +1 -1
  35. {metalist-0.22.0 → metalist-0.23.0}/app/services/dictation_cleanup.py +10 -17
  36. {metalist-0.22.0 → metalist-0.23.0}/app/services/embedded_references.py +66 -5
  37. metalist-0.23.0/app/services/find_text.py +119 -0
  38. {metalist-0.22.0 → metalist-0.23.0}/app/services/namespace_deletion_jobs.py +1 -1
  39. {metalist-0.22.0 → metalist-0.23.0}/app/services/namespace_deletion_worker.py +1 -1
  40. {metalist-0.22.0 → metalist-0.23.0}/app/services/namespace_rename_worker.py +1 -1
  41. {metalist-0.22.0 → metalist-0.23.0}/app/services/namespace_runtime_guard.py +5 -5
  42. {metalist-0.22.0 → metalist-0.23.0}/app/services/namespace_switcher.py +42 -42
  43. {metalist-0.22.0 → metalist-0.23.0}/app/services/note_store.py +7 -0
  44. {metalist-0.22.0 → metalist-0.23.0}/app/services/openai_credentials.py +1 -1
  45. {metalist-0.22.0 → metalist-0.23.0}/app/services/root_sorting.py +32 -4
  46. {metalist-0.22.0 → metalist-0.23.0}/app/services/search_index.py +39 -0
  47. {metalist-0.22.0 → metalist-0.23.0}/app/services/self_update.py +2 -2
  48. {metalist-0.22.0 → metalist-0.23.0}/app/services/snapshot.py +256 -46
  49. {metalist-0.22.0 → metalist-0.23.0}/app/services/tab_state.py +98 -1
  50. {metalist-0.22.0 → metalist-0.23.0}/app/services/update_backups.py +1 -1
  51. {metalist-0.22.0 → metalist-0.23.0}/app/services/update_preflight.py +1 -1
  52. {metalist-0.22.0 → metalist-0.23.0}/app/static/config/agent-menu-actions.json +20 -8
  53. {metalist-0.22.0 → metalist-0.23.0}/app/static/config/command_palette_tags.json +13 -5
  54. {metalist-0.22.0 → metalist-0.23.0}/app/static/css/main.css +470 -134
  55. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/proposal-menu.js +1 -1
  56. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/api-client.js +22 -0
  57. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/auth.js +5 -5
  58. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/backup-reminder-schedule.js +1 -1
  59. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/command-palette/command-palette-controller.js +5 -0
  60. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/command-palette/endpoint-registry.js +39 -12
  61. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/command-palette/tag-config-loader.js +25 -0
  62. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/config.js +1 -0
  63. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/context-menu/context-menu-registry.js +38 -14
  64. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/context-menu/context-menu-service.js +11 -0
  65. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/login-namespace-picker.js +1 -1
  66. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/ai-agent-settings-modal.js +3 -3
  67. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/backup-restore-modal.js +12 -12
  68. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/backup-result-modal.js +1 -1
  69. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/backup-settings-modal.js +5 -5
  70. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/delete-namespace-modal.js +22 -22
  71. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/help-modal.js +3 -0
  72. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/memory-usage-modal.js +2 -2
  73. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/namespace-modals.js +46 -46
  74. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/note-layout-appearance-modal.js +1 -1
  75. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/ontology-modal.js +76 -64
  76. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/search-suggestion-statistics-modal.js +1 -1
  77. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/session-timeout-modal.js +1 -1
  78. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/version-info-modal.js +3 -3
  79. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/actions/ui-actions.js +3 -0
  80. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/events/context-menu-events.js +52 -11
  81. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/events/keyboard-events.js +272 -30
  82. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/events/mouse-events.js +35 -4
  83. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/events/search-events.js +25 -2
  84. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/mode-context.js +27 -0
  85. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/dictation-paste-service.js +18 -3
  86. metalist-0.23.0/app/static/js/modules/mode-manager/services/find-in-list-service.js +779 -0
  87. metalist-0.23.0/app/static/js/modules/mode-manager/services/reference-source-navigation-service.js +606 -0
  88. metalist-0.23.0/app/static/js/modules/mode-manager/services/reference-view-transition-service.js +206 -0
  89. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/root-sort-indicator-service.js +7 -4
  90. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/root-sort-service.js +59 -26
  91. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/scroll-anchor-service.js +7 -2
  92. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/search-debounce-service.js +5 -0
  93. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/search-highlight-service.js +3 -2
  94. metalist-0.23.0/app/static/js/modules/mode-manager/services/search-input-chip-service.js +85 -0
  95. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/tab-state-service.js +5 -3
  96. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/untagged-view-indicator-service.js +3 -1
  97. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/viewport-hold-service.js +67 -8
  98. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/namespace-deleted.js +18 -18
  99. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/namespace-renamed.js +5 -5
  100. metalist-0.23.0/app/static/js/vendor/dompurify-3.4.17.min.js +7 -0
  101. {metalist-0.22.0 → metalist-0.23.0}/app/templates/base.html +1 -1
  102. {metalist-0.22.0 → metalist-0.23.0}/app/templates/index.html +55 -35
  103. {metalist-0.22.0 → metalist-0.23.0}/app/templates/namespace_deleted.html +5 -5
  104. {metalist-0.22.0 → metalist-0.23.0}/app/templates/namespace_renamed.html +1 -1
  105. {metalist-0.22.0 → metalist-0.23.0}/app/version.py +1 -1
  106. {metalist-0.22.0 → metalist-0.23.0}/main.py +6 -6
  107. {metalist-0.22.0 → metalist-0.23.0/metalist.egg-info}/PKG-INFO +17 -2
  108. {metalist-0.22.0 → metalist-0.23.0}/metalist.egg-info/SOURCES.txt +6 -2
  109. {metalist-0.22.0 → metalist-0.23.0}/metalist.egg-info/requires.txt +1 -1
  110. {metalist-0.22.0 → metalist-0.23.0}/pyproject.toml +1 -1
  111. metalist-0.22.0/app/static/js/modules/mode-manager/services/reference-source-navigation-service.js +0 -309
  112. metalist-0.22.0/app/static/js/vendor/dompurify-3.4.16.min.js +0 -7
  113. {metalist-0.22.0 → metalist-0.23.0}/MANIFEST.in +0 -0
  114. {metalist-0.22.0 → metalist-0.23.0}/app/__init__.py +0 -0
  115. {metalist-0.22.0 → metalist-0.23.0}/app/api/__init__.py +0 -0
  116. {metalist-0.22.0 → metalist-0.23.0}/app/api/deps.py +0 -0
  117. {metalist-0.22.0 → metalist-0.23.0}/app/api/dev.py +0 -0
  118. {metalist-0.22.0 → metalist-0.23.0}/app/api/middleware/auth.py +0 -0
  119. {metalist-0.22.0 → metalist-0.23.0}/app/api/request_auth.py +0 -0
  120. {metalist-0.22.0 → metalist-0.23.0}/app/api/routes/ai.py +0 -0
  121. {metalist-0.22.0 → metalist-0.23.0}/app/api/routes/app_updates.py +0 -0
  122. {metalist-0.22.0 → metalist-0.23.0}/app/api/routes/files.py +0 -0
  123. {metalist-0.22.0 → metalist-0.23.0}/app/api/routes/reminders.py +0 -0
  124. {metalist-0.22.0 → metalist-0.23.0}/app/api/routes/remote_images.py +0 -0
  125. {metalist-0.22.0 → metalist-0.23.0}/app/api/routes/test.py +0 -0
  126. {metalist-0.22.0 → metalist-0.23.0}/app/api/upload_limits.py +0 -0
  127. {metalist-0.22.0 → metalist-0.23.0}/app/config.py +0 -0
  128. {metalist-0.22.0 → metalist-0.23.0}/app/contracts.py +0 -0
  129. {metalist-0.22.0 → metalist-0.23.0}/app/data_directory.py +0 -0
  130. {metalist-0.22.0 → metalist-0.23.0}/app/db/__init__.py +0 -0
  131. {metalist-0.22.0 → metalist-0.23.0}/app/db/backup_settings_sql.py +0 -0
  132. {metalist-0.22.0 → metalist-0.23.0}/app/db/content_migrations_sql.py +0 -0
  133. {metalist-0.22.0 → metalist-0.23.0}/app/db/editable_files_migration.py +0 -0
  134. {metalist-0.22.0 → metalist-0.23.0}/app/db/file_schema.py +0 -0
  135. {metalist-0.22.0 → metalist-0.23.0}/app/db/file_session.py +0 -0
  136. {metalist-0.22.0 → metalist-0.23.0}/app/db/files_sql.py +0 -0
  137. {metalist-0.22.0 → metalist-0.23.0}/app/db/link_titles_sql.py +0 -0
  138. {metalist-0.22.0 → metalist-0.23.0}/app/db/live_recovery.py +0 -0
  139. {metalist-0.22.0 → metalist-0.23.0}/app/db/migrations.py +0 -0
  140. {metalist-0.22.0 → metalist-0.23.0}/app/db/notes_sql.py +0 -0
  141. {metalist-0.22.0 → metalist-0.23.0}/app/db/ontology_rules_sql.py +0 -0
  142. {metalist-0.22.0 → metalist-0.23.0}/app/db/raw_connection.py +0 -0
  143. {metalist-0.22.0 → metalist-0.23.0}/app/db/reminders_sql.py +0 -0
  144. {metalist-0.22.0 → metalist-0.23.0}/app/db/retire_sounds.py +0 -0
  145. {metalist-0.22.0 → metalist-0.23.0}/app/db/schema.py +0 -0
  146. {metalist-0.22.0 → metalist-0.23.0}/app/db/search_history_sql.py +0 -0
  147. {metalist-0.22.0 → metalist-0.23.0}/app/db/session.py +0 -0
  148. {metalist-0.22.0 → metalist-0.23.0}/app/db/settings_sql.py +0 -0
  149. {metalist-0.22.0 → metalist-0.23.0}/app/db/tab_state_sql.py +0 -0
  150. {metalist-0.22.0 → metalist-0.23.0}/app/db/version.py +0 -0
  151. {metalist-0.22.0 → metalist-0.23.0}/app/encryption_audit.py +0 -0
  152. {metalist-0.22.0 → metalist-0.23.0}/app/exception_boundaries.py +0 -0
  153. {metalist-0.22.0 → metalist-0.23.0}/app/https_proxy.py +0 -0
  154. {metalist-0.22.0 → metalist-0.23.0}/app/launch_clock.py +0 -0
  155. {metalist-0.22.0 → metalist-0.23.0}/app/models/database.py +0 -0
  156. {metalist-0.22.0 → metalist-0.23.0}/app/models/utils.py +0 -0
  157. {metalist-0.22.0 → metalist-0.23.0}/app/network_settings.py +0 -0
  158. {metalist-0.22.0 → metalist-0.23.0}/app/presentation/__init__.py +0 -0
  159. {metalist-0.22.0 → metalist-0.23.0}/app/presentation/login_page.py +0 -0
  160. {metalist-0.22.0 → metalist-0.23.0}/app/presentation/render/__init__.py +0 -0
  161. {metalist-0.22.0 → metalist-0.23.0}/app/presentation/render/note_renderer.py +0 -0
  162. {metalist-0.22.0 → metalist-0.23.0}/app/presentation/templates.py +0 -0
  163. {metalist-0.22.0 → metalist-0.23.0}/app/process_memory.py +0 -0
  164. {metalist-0.22.0 → metalist-0.23.0}/app/security/crypto_sizes.py +0 -0
  165. {metalist-0.22.0 → metalist-0.23.0}/app/security/encryption.py +0 -0
  166. {metalist-0.22.0 → metalist-0.23.0}/app/security/http_error_diagnostics.py +0 -0
  167. {metalist-0.22.0 → metalist-0.23.0}/app/security/http_headers.py +0 -0
  168. {metalist-0.22.0 → metalist-0.23.0}/app/security/note_html.py +0 -0
  169. {metalist-0.22.0 → metalist-0.23.0}/app/security/rendered_html.py +0 -0
  170. {metalist-0.22.0 → metalist-0.23.0}/app/security/request_boundary.py +0 -0
  171. {metalist-0.22.0 → metalist-0.23.0}/app/security/request_hosts.py +0 -0
  172. {metalist-0.22.0 → metalist-0.23.0}/app/security/sensitive_cache.py +0 -0
  173. {metalist-0.22.0 → metalist-0.23.0}/app/security/sensitive_logging.py +0 -0
  174. {metalist-0.22.0 → metalist-0.23.0}/app/security/shell_execution.py +0 -0
  175. {metalist-0.22.0 → metalist-0.23.0}/app/security/validation_errors.py +0 -0
  176. {metalist-0.22.0 → metalist-0.23.0}/app/services/__init__.py +0 -0
  177. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/__init__.py +0 -0
  178. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/action_log.py +0 -0
  179. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/agent_loop.py +0 -0
  180. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/ai_send.py +0 -0
  181. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/citation_tokens.py +0 -0
  182. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/cloud_privacy.py +0 -0
  183. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/context.py +0 -0
  184. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/evidence_serialization.py +0 -0
  185. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/execution_errors.py +0 -0
  186. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/export_title_suggestions.py +0 -0
  187. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/failure_explanations.py +0 -0
  188. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/history.py +0 -0
  189. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/inference.py +0 -0
  190. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/investigation.py +0 -0
  191. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/judging.py +0 -0
  192. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/menu_actions.py +0 -0
  193. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/model_policy.py +0 -0
  194. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/note_aliases.py +0 -0
  195. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/note_tag_suggestions.py +0 -0
  196. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/openai_cost_tracking.py +0 -0
  197. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/openai_inference.py +0 -0
  198. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/openai_models.py +0 -0
  199. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/privacy_guard.py +0 -0
  200. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/prompt_settings.py +0 -0
  201. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/prompts/__init__.py +0 -0
  202. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/prompts/agent.md +0 -0
  203. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/prompts/final-response.md +0 -0
  204. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/prompts/system.md +0 -0
  205. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/release_notes.py +0 -0
  206. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/retrieval_settings.py +0 -0
  207. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/runtime.py +0 -0
  208. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/scope.py +0 -0
  209. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skill_settings.py +0 -0
  210. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/__init__.py +0 -0
  211. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/staged-summary.md +0 -0
  212. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/tag-proposals.md +0 -0
  213. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/skills/web-browsing.md +0 -0
  214. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/staged_summary.py +0 -0
  215. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/strict_structured_outputs.py +0 -0
  216. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/structured_inference.py +0 -0
  217. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/summary_batch_store.py +0 -0
  218. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/token_estimation.py +0 -0
  219. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/tool_calling.py +0 -0
  220. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/trace.py +0 -0
  221. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/web_actions.py +0 -0
  222. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/web_capabilities.py +0 -0
  223. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/web_evidence.py +0 -0
  224. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/web_fetch.py +0 -0
  225. {metalist-0.22.0 → metalist-0.23.0}/app/services/agent/web_settings.py +0 -0
  226. {metalist-0.22.0 → metalist-0.23.0}/app/services/ai_chat.py +0 -0
  227. {metalist-0.22.0 → metalist-0.23.0}/app/services/ai_chat_rendering.py +0 -0
  228. {metalist-0.22.0 → metalist-0.23.0}/app/services/ai_chat_stream.py +0 -0
  229. {metalist-0.22.0 → metalist-0.23.0}/app/services/ai_setup.py +0 -0
  230. {metalist-0.22.0 → metalist-0.23.0}/app/services/app_update_worker.py +0 -0
  231. {metalist-0.22.0 → metalist-0.23.0}/app/services/auth.py +0 -0
  232. {metalist-0.22.0 → metalist-0.23.0}/app/services/auth_cache_state.py +0 -0
  233. {metalist-0.22.0 → metalist-0.23.0}/app/services/backlink_index.py +0 -0
  234. {metalist-0.22.0 → metalist-0.23.0}/app/services/backlinks.py +0 -0
  235. {metalist-0.22.0 → metalist-0.23.0}/app/services/backup_settings_service.py +0 -0
  236. {metalist-0.22.0 → metalist-0.23.0}/app/services/chess_rendering.py +0 -0
  237. {metalist-0.22.0 → metalist-0.23.0}/app/services/client_state_service.py +0 -0
  238. {metalist-0.22.0 → metalist-0.23.0}/app/services/code_rendering.py +0 -0
  239. {metalist-0.22.0 → metalist-0.23.0}/app/services/content_cache.py +0 -0
  240. {metalist-0.22.0 → metalist-0.23.0}/app/services/content_formatting.py +0 -0
  241. {metalist-0.22.0 → metalist-0.23.0}/app/services/diagnostics.py +0 -0
  242. {metalist-0.22.0 → metalist-0.23.0}/app/services/diff_rendering.py +0 -0
  243. {metalist-0.22.0 → metalist-0.23.0}/app/services/editing_image_sizes.py +0 -0
  244. {metalist-0.22.0 → metalist-0.23.0}/app/services/encryption.py +0 -0
  245. {metalist-0.22.0 → metalist-0.23.0}/app/services/exception_capture.py +0 -0
  246. {metalist-0.22.0 → metalist-0.23.0}/app/services/file_edit_sessions.py +0 -0
  247. {metalist-0.22.0 → metalist-0.23.0}/app/services/file_registry.py +0 -0
  248. {metalist-0.22.0 → metalist-0.23.0}/app/services/file_storage.py +0 -0
  249. {metalist-0.22.0 → metalist-0.23.0}/app/services/file_text_preview.py +0 -0
  250. {metalist-0.22.0 → metalist-0.23.0}/app/services/footnote_layout.py +0 -0
  251. {metalist-0.22.0 → metalist-0.23.0}/app/services/footnote_rendering.py +0 -0
  252. {metalist-0.22.0 → metalist-0.23.0}/app/services/hierarchy.py +0 -0
  253. {metalist-0.22.0 → metalist-0.23.0}/app/services/html_export.py +0 -0
  254. {metalist-0.22.0 → metalist-0.23.0}/app/services/html_unformatting.py +0 -0
  255. {metalist-0.22.0 → metalist-0.23.0}/app/services/hydration_state.py +0 -0
  256. {metalist-0.22.0 → metalist-0.23.0}/app/services/image_size_formatting.py +0 -0
  257. {metalist-0.22.0 → metalist-0.23.0}/app/services/inline_image_dimensions.py +0 -0
  258. {metalist-0.22.0 → metalist-0.23.0}/app/services/inline_image_occurrences.py +0 -0
  259. {metalist-0.22.0 → metalist-0.23.0}/app/services/input_errors.py +0 -0
  260. {metalist-0.22.0 → metalist-0.23.0}/app/services/integrity.py +0 -0
  261. {metalist-0.22.0 → metalist-0.23.0}/app/services/latex_rendering.py +0 -0
  262. {metalist-0.22.0 → metalist-0.23.0}/app/services/link_title_retry.py +0 -0
  263. {metalist-0.22.0 → metalist-0.23.0}/app/services/link_titles.py +0 -0
  264. {metalist-0.22.0 → metalist-0.23.0}/app/services/login_rate_limit.py +0 -0
  265. {metalist-0.22.0 → metalist-0.23.0}/app/services/maintenance_mode.py +0 -0
  266. {metalist-0.22.0 → metalist-0.23.0}/app/services/markdown_rendering.py +0 -0
  267. {metalist-0.22.0 → metalist-0.23.0}/app/services/memory_breakdown.py +0 -0
  268. {metalist-0.22.0 → metalist-0.23.0}/app/services/memory_usage.py +0 -0
  269. {metalist-0.22.0 → metalist-0.23.0}/app/services/mermaid_note_rendering.py +0 -0
  270. {metalist-0.22.0 → metalist-0.23.0}/app/services/namespace_rename_jobs.py +0 -0
  271. {metalist-0.22.0 → metalist-0.23.0}/app/services/note_fullscreen.py +0 -0
  272. {metalist-0.22.0 → metalist-0.23.0}/app/services/note_image_tags.py +0 -0
  273. {metalist-0.22.0 → metalist-0.23.0}/app/services/note_ordering.py +0 -0
  274. {metalist-0.22.0 → metalist-0.23.0}/app/services/ontology_rules_store.py +0 -0
  275. {metalist-0.22.0 → metalist-0.23.0}/app/services/password_note_fields.py +0 -0
  276. {metalist-0.22.0 → metalist-0.23.0}/app/services/preference_values.py +0 -0
  277. {metalist-0.22.0 → metalist-0.23.0}/app/services/public_http.py +0 -0
  278. {metalist-0.22.0 → metalist-0.23.0}/app/services/reference_presentation.py +0 -0
  279. {metalist-0.22.0 → metalist-0.23.0}/app/services/reminders.py +0 -0
  280. {metalist-0.22.0 → metalist-0.23.0}/app/services/remote_image_proxy.py +0 -0
  281. {metalist-0.22.0 → metalist-0.23.0}/app/services/request_recovery.py +0 -0
  282. {metalist-0.22.0 → metalist-0.23.0}/app/services/reset_for_tests.py +0 -0
  283. {metalist-0.22.0 → metalist-0.23.0}/app/services/resource_limits.py +0 -0
  284. {metalist-0.22.0 → metalist-0.23.0}/app/services/runtime_generation.py +0 -0
  285. {metalist-0.22.0 → metalist-0.23.0}/app/services/runtime_hardening.py +0 -0
  286. {metalist-0.22.0 → metalist-0.23.0}/app/services/runtime_lock.py +0 -0
  287. {metalist-0.22.0 → metalist-0.23.0}/app/services/search_history.py +0 -0
  288. {metalist-0.22.0 → metalist-0.23.0}/app/services/search_history_storage.py +0 -0
  289. {metalist-0.22.0 → metalist-0.23.0}/app/services/search_query.py +0 -0
  290. {metalist-0.22.0 → metalist-0.23.0}/app/services/search_text.py +0 -0
  291. {metalist-0.22.0 → metalist-0.23.0}/app/services/selected_text_tag.py +0 -0
  292. {metalist-0.22.0 → metalist-0.23.0}/app/services/session_timeout_service.py +0 -0
  293. {metalist-0.22.0 → metalist-0.23.0}/app/services/shared_sets.py +0 -0
  294. {metalist-0.22.0 → metalist-0.23.0}/app/services/shell_session_service.py +0 -0
  295. {metalist-0.22.0 → metalist-0.23.0}/app/services/store.py +0 -0
  296. {metalist-0.22.0 → metalist-0.23.0}/app/services/structured_note_renderers.py +0 -0
  297. {metalist-0.22.0 → metalist-0.23.0}/app/services/sync.py +0 -0
  298. {metalist-0.22.0 → metalist-0.23.0}/app/services/tag_case.py +0 -0
  299. {metalist-0.22.0 → metalist-0.23.0}/app/services/tag_details.py +0 -0
  300. {metalist-0.22.0 → metalist-0.23.0}/app/services/tag_ontology.py +0 -0
  301. {metalist-0.22.0 → metalist-0.23.0}/app/services/tag_plural_variants.py +0 -0
  302. {metalist-0.22.0 → metalist-0.23.0}/app/services/tag_rename.py +0 -0
  303. {metalist-0.22.0 → metalist-0.23.0}/app/services/tag_suggestion_reasons.py +0 -0
  304. {metalist-0.22.0 → metalist-0.23.0}/app/services/tag_suggestions.py +0 -0
  305. {metalist-0.22.0 → metalist-0.23.0}/app/services/tag_term_matching.py +0 -0
  306. {metalist-0.22.0 → metalist-0.23.0}/app/services/tokens.py +0 -0
  307. {metalist-0.22.0 → metalist-0.23.0}/app/services/undo_state.py +0 -0
  308. {metalist-0.22.0 → metalist-0.23.0}/app/services/update_installer.py +0 -0
  309. {metalist-0.22.0 → metalist-0.23.0}/app/services/view_cache.py +0 -0
  310. {metalist-0.22.0 → metalist-0.23.0}/app/services/view_diff.py +0 -0
  311. {metalist-0.22.0 → metalist-0.23.0}/app/services/view_state.py +0 -0
  312. {metalist-0.22.0 → metalist-0.23.0}/app/services/windows_process_control.py +0 -0
  313. {metalist-0.22.0 → metalist-0.23.0}/app/startup_console.py +0 -0
  314. {metalist-0.22.0 → metalist-0.23.0}/app/startup_environment.py +0 -0
  315. {metalist-0.22.0 → metalist-0.23.0}/app/startup_js_sanity.py +0 -0
  316. {metalist-0.22.0 → metalist-0.23.0}/app/startup_sanity.py +0 -0
  317. {metalist-0.22.0 → metalist-0.23.0}/app/startup_sanity_config.py +0 -0
  318. {metalist-0.22.0 → metalist-0.23.0}/app/startup_shockharness.py +0 -0
  319. {metalist-0.22.0 → metalist-0.23.0}/app/static/css/floating-notes.css +0 -0
  320. {metalist-0.22.0 → metalist-0.23.0}/app/static/css/forms.css +0 -0
  321. {metalist-0.22.0 → metalist-0.23.0}/app/static/img/favicon.ico +0 -0
  322. {metalist-0.22.0 → metalist-0.23.0}/app/static/img/metalist-logo-black-1024.png +0 -0
  323. {metalist-0.22.0 → metalist-0.23.0}/app/static/img/metalist-logo-black-512.png +0 -0
  324. {metalist-0.22.0 → metalist-0.23.0}/app/static/img/metalist-logo-black.svg +0 -0
  325. {metalist-0.22.0 → metalist-0.23.0}/app/static/img/metalist-logo-white-1024.png +0 -0
  326. {metalist-0.22.0 → metalist-0.23.0}/app/static/img/metalist-logo-white-512.png +0 -0
  327. {metalist-0.22.0 → metalist-0.23.0}/app/static/img/metalist-logo-white.svg +0 -0
  328. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/locked.js +0 -0
  329. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/main.js +0 -0
  330. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/activity-tracker.js +0 -0
  331. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/agent-menu-actions.js +0 -0
  332. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/agent-retrieval-settings.js +0 -0
  333. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/agent-web-settings.js +0 -0
  334. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/ai-agent-debug-view.js +0 -0
  335. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/ai-chat-api.js +0 -0
  336. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/ai-chat-message-placement.js +0 -0
  337. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/ai-chat-panel-controller.js +0 -0
  338. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/ai-chat-panel-service.js +0 -0
  339. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/ai-chat-refused-turns.js +0 -0
  340. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/ai-chat-size-limits.js +0 -0
  341. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/ai-thinking-level-service.js +0 -0
  342. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/bulk-elapsed-clock.js +0 -0
  343. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/bulk-proposal-ui.js +0 -0
  344. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/bulk-scope-question.js +0 -0
  345. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/cloud-privacy-policy.js +0 -0
  346. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/confirmation-card.js +0 -0
  347. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/confirmation-question.js +0 -0
  348. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/ai-chat/summary-batch-preview.js +0 -0
  349. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/api-error-diagnostics.js +0 -0
  350. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/api-failure-classification-service.js +0 -0
  351. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/app-notice-stack.js +0 -0
  352. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/app-update-service.js +0 -0
  353. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/application-state.js +0 -0
  354. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/async-result.js +0 -0
  355. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/backup-reminder-service.js +0 -0
  356. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/byte-sizes.js +0 -0
  357. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/client-state-api.js +0 -0
  358. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/client-state-migration.js +0 -0
  359. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/command-palette/activation-auth-policy.js +0 -0
  360. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/command-palette/backup-command-availability.js +0 -0
  361. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/command-palette/click-activation-service.js +0 -0
  362. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/command-palette/note-layout-preferences.js +0 -0
  363. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/command-palette/preferences-store.js +0 -0
  364. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/command-palette/usage-store.js +0 -0
  365. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/context-menu/context-menu-target-service.js +0 -0
  366. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/context-menu/input-caret-service.js +0 -0
  367. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/decimal-integer.js +0 -0
  368. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/disconnect-editing-state-service.js +0 -0
  369. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/dom-focus.js +0 -0
  370. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/dom-utils.js +0 -0
  371. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/editor-commands.js +0 -0
  372. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/editor-selection.js +0 -0
  373. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/editor-toolbar.js +0 -0
  374. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/elapsed-time.js +0 -0
  375. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/error-handler.js +0 -0
  376. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/error-overlay.js +0 -0
  377. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/excalidraw/excalidraw-actions.js +0 -0
  378. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/excalidraw/excalidraw-autosave.js +0 -0
  379. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/excalidraw/excalidraw-editor-service.js +0 -0
  380. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/excalidraw/excalidraw-editor-state.js +0 -0
  381. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/excalidraw/excalidraw-loader.js +0 -0
  382. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/excalidraw/excalidraw-preview-service.js +0 -0
  383. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/excalidraw/excalidraw-scene.js +0 -0
  384. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/expected-errors.js +0 -0
  385. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/half.js +0 -0
  386. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/html-escape.js +0 -0
  387. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/http-status.js +0 -0
  388. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/list-selection.js +0 -0
  389. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/local-date-text.js +0 -0
  390. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/location-flags.js +0 -0
  391. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/maintenance.js +0 -0
  392. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/alphabetize-root-notes-modal.js +0 -0
  393. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/base-modal.js +0 -0
  394. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/confirmation-modal.js +0 -0
  395. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/delete-namespace-validation.js +0 -0
  396. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/dictation-settings-modal.js +0 -0
  397. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/export-options-modal.js +0 -0
  398. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/link-title-retry-modal.js +0 -0
  399. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/namespace-loading-page.js +0 -0
  400. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/namespace-ports-profile.js +0 -0
  401. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/namespace-rename-validation.js +0 -0
  402. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/password-modal.js +0 -0
  403. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/prioritize-modal.js +0 -0
  404. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/random-password-modal.js +0 -0
  405. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/reminder-modal.js +0 -0
  406. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/reset-updated-at-modal.js +0 -0
  407. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/modals/visual-cues-modal.js +0 -0
  408. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/actions/content-actions.js +0 -0
  409. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/actions/history-actions.js +0 -0
  410. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/actions/note-actions.js +0 -0
  411. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/actions/search-actions.js +0 -0
  412. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/actions/selection-actions.js +0 -0
  413. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/events/focus-events.js +0 -0
  414. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/events/inactivity-events.js +0 -0
  415. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/events/input-events.js +0 -0
  416. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/mode-logger.js +0 -0
  417. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/mode-manager-controller.js +0 -0
  418. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/add-style-service.js +0 -0
  419. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/animated-scroll-service.js +0 -0
  420. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/backlinks-navigation-service.js +0 -0
  421. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/clipboard-shortcut-policy-service.js +0 -0
  422. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/collapse-affordance-service.js +0 -0
  423. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/collapse-editing-policy-service.js +0 -0
  424. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/command-gate-service.js +0 -0
  425. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/context-menu-target-service.js +0 -0
  426. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/deselect-selection-state-service.js +0 -0
  427. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/dictation-note-paste.js +0 -0
  428. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/dictation-paste-padding.js +0 -0
  429. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/differential-view-service.js +0 -0
  430. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/dropped-file-preview-service.js +0 -0
  431. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/edit-session-collapse-policy-service.js +0 -0
  432. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/edit-session-collapse-service.js +0 -0
  433. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/editing-image-size-service.js +0 -0
  434. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/embedded-image-service.js +0 -0
  435. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/export-service.js +0 -0
  436. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/export-title-service.js +0 -0
  437. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/file-drop-policy-service.js +0 -0
  438. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/file-image-preview-service.js +0 -0
  439. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/file-reference-service.js +0 -0
  440. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/filtered-refresh-selection-service.js +0 -0
  441. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/floating-note-dom.js +0 -0
  442. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/floating-note-layout.js +0 -0
  443. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/floating-note-service.js +0 -0
  444. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/footnote-navigation-service.js +0 -0
  445. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/history-selection-policy-service.js +0 -0
  446. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/history-shortcut-policy-service.js +0 -0
  447. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/html-paste-sanitizer-service.js +0 -0
  448. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/image-context-menu-action-service.js +0 -0
  449. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/image-file-insert-choice-modal-service.js +0 -0
  450. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/infinite-scroll-service.js +0 -0
  451. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/link-context-menu-action-service.js +0 -0
  452. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/link-target-service.js +0 -0
  453. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/link-title-prefetch-service.js +0 -0
  454. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/mermaid-render-service.js +0 -0
  455. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/note-click-target-service.js +0 -0
  456. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/note-clipboard-write-service.js +0 -0
  457. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/note-collapse-animation-service.js +0 -0
  458. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/note-context-menu-action-service.js +0 -0
  459. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/note-delete-shortcut-policy-service.js +0 -0
  460. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/note-drag-indicator-service.js +0 -0
  461. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/note-drag-service.js +0 -0
  462. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/note-fullscreen-service.js +0 -0
  463. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/note-reposition-animation-service.js +0 -0
  464. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/note-split-service.js +0 -0
  465. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/note-timestamp-hover-service.js +0 -0
  466. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/password-clipboard-service.js +0 -0
  467. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/paste-format-detection-service.js +0 -0
  468. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/paste-format-guess-service.js +0 -0
  469. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/paste-format-offer-service.js +0 -0
  470. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/paste-reference-here-service.js +0 -0
  471. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/polling-service.js +0 -0
  472. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/print-service.js +0 -0
  473. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/referenced-note-removal-service.js +0 -0
  474. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/remote-image-proxy-service.js +0 -0
  475. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/remove-formatting-service.js +0 -0
  476. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/right-press-focus-service.js +0 -0
  477. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/root-date-separator-service.js +0 -0
  478. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/root-note-creation-service.js +0 -0
  479. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/scroll-restoration-service.js +0 -0
  480. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/scroll-to-top-service.js +0 -0
  481. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/search-contexts-overlay-service.js +0 -0
  482. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/search-highlight-matching.js +0 -0
  483. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/search-input-service.js +0 -0
  484. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/search-interaction-service.js +0 -0
  485. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/search-redaction-reveal-service.js +0 -0
  486. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/search-suggestion-statistics-service.js +0 -0
  487. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/search-suggestion-window-labels-service.js +0 -0
  488. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/search-suggestion-windows-service.js +0 -0
  489. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/search-suggestions-service.js +0 -0
  490. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/search-syntax-service.js +0 -0
  491. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/selected-formatting-removal-service.js +0 -0
  492. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/selected-text-tag-service.js +0 -0
  493. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/shell-output-service.js +0 -0
  494. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/tab-dom-cache-service.js +0 -0
  495. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/tab-drag-service.js +0 -0
  496. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/tab-duplication-service.js +0 -0
  497. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/tag-bar-service.js +0 -0
  498. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/tag-input-selection-service.js +0 -0
  499. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/tag-proposal-service.js +0 -0
  500. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/tag-suggestions-service.js +0 -0
  501. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/tag-syntax-service.js +0 -0
  502. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/todo-toggle-editing-service.js +0 -0
  503. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/view-mode-search-shortcut-service.js +0 -0
  504. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/mode-manager/services/viewport-reference.js +0 -0
  505. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/not-found.js +0 -0
  506. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/note-html-sanitizer.js +0 -0
  507. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/password-generator.js +0 -0
  508. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/password-operation-response.js +0 -0
  509. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/password-policy.js +0 -0
  510. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/password-strength.js +0 -0
  511. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/reminder-store.js +0 -0
  512. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/reminder-surface-service.js +0 -0
  513. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/server-rendered-html.js +0 -0
  514. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/session-auth.js +0 -0
  515. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/startup-timing.js +0 -0
  516. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/tag-token.js +0 -0
  517. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/tcp-ports.js +0 -0
  518. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/time-units.js +0 -0
  519. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/url-tracking-cleaner.js +0 -0
  520. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/modules/uuid.js +0 -0
  521. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/shockharness/contracts.d.ts +0 -0
  522. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/shockharness/contracts.js +0 -0
  523. /metalist-0.22.0/app/static/js/vendor/dompurify-3.4.16.LICENSE.txt → /metalist-0.23.0/app/static/js/vendor/dompurify-3.4.17.LICENSE.txt +0 -0
  524. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/excalidraw.css +0 -0
  525. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Bold.woff2 +0 -0
  526. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Medium.woff2 +0 -0
  527. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Regular.woff2 +0 -0
  528. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-SemiBold.woff2 +0 -0
  529. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Cascadia/CascadiaCode-Regular.woff2 +0 -0
  530. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2 +0 -0
  531. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2 +0 -0
  532. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2 +0 -0
  533. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2 +0 -0
  534. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2 +0 -0
  535. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2 +0 -0
  536. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2 +0 -0
  537. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2 +0 -0
  538. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2 +0 -0
  539. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2 +0 -0
  540. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2 +0 -0
  541. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2 +0 -0
  542. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2 +0 -0
  543. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2 +0 -0
  544. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2 +0 -0
  545. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2 +0 -0
  546. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2 +0 -0
  547. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2 +0 -0
  548. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Virgil/Virgil-Regular.woff2 +0 -0
  549. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1.LICENSE.txt +0 -0
  550. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/excalidraw-0.18.1.min.js +0 -0
  551. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/mermaid-11.16.1.LICENSE.txt +0 -0
  552. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/mermaid-11.16.1.min.js +0 -0
  553. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/zxcvbn-4.4.2.LICENSE.txt +0 -0
  554. {metalist-0.22.0 → metalist-0.23.0}/app/static/js/vendor/zxcvbn-4.4.2.js +0 -0
  555. {metalist-0.22.0 → metalist-0.23.0}/app/static/note-html-policy.json +0 -0
  556. {metalist-0.22.0 → metalist-0.23.0}/app/templates/_logo_mark.html +0 -0
  557. {metalist-0.22.0 → metalist-0.23.0}/app/templates/locked.html +0 -0
  558. {metalist-0.22.0 → metalist-0.23.0}/app/templates/maintenance.html +0 -0
  559. {metalist-0.22.0 → metalist-0.23.0}/app/templates/notes_list.html +0 -0
  560. {metalist-0.22.0 → metalist-0.23.0}/app/upload_limits.py +0 -0
  561. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/__init__.py +0 -0
  562. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/add_selected_text_tag.py +0 -0
  563. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/alphabetize_root_notes.py +0 -0
  564. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/base.py +0 -0
  565. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/bulk_tag_proposals.py +0 -0
  566. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/collapse.py +0 -0
  567. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/copy_note.py +0 -0
  568. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/create_child.py +0 -0
  569. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/create_file_preview_child.py +0 -0
  570. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/create_note.py +0 -0
  571. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/create_sibling.py +0 -0
  572. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/delete_subtree.py +0 -0
  573. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/delete_tag.py +0 -0
  574. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/expand.py +0 -0
  575. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/file_edit_session.py +0 -0
  576. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/indent.py +0 -0
  577. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/move.py +0 -0
  578. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/move_to_top.py +0 -0
  579. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/outdent.py +0 -0
  580. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/paste_child.py +0 -0
  581. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/paste_reference.py +0 -0
  582. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/paste_sibling.py +0 -0
  583. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/prefetch_link_titles.py +0 -0
  584. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/prioritize.py +0 -0
  585. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/redo.py +0 -0
  586. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/rename_tag.py +0 -0
  587. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/reset_updated_at.py +0 -0
  588. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/resize_image.py +0 -0
  589. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/run_shell.py +0 -0
  590. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/search_comment_autofill.py +0 -0
  591. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/search_context_tags.py +0 -0
  592. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/set_collapse_bulk.py +0 -0
  593. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/set_collapse_in_context.py +0 -0
  594. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/split_note.py +0 -0
  595. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/tag_proposals.py +0 -0
  596. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/toggle_todo_done.py +0 -0
  597. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/undo.py +0 -0
  598. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/unformat_content.py +0 -0
  599. {metalist-0.22.0 → metalist-0.23.0}/app/usecases/update_content.py +0 -0
  600. {metalist-0.22.0 → metalist-0.23.0}/app/utils/__init__.py +0 -0
  601. {metalist-0.22.0 → metalist-0.23.0}/app/utils/byte_sizes.py +0 -0
  602. {metalist-0.22.0 → metalist-0.23.0}/app/utils/encryption.py +0 -0
  603. {metalist-0.22.0 → metalist-0.23.0}/app/utils/not_found.py +0 -0
  604. {metalist-0.22.0 → metalist-0.23.0}/app/utils/sent_fields.py +0 -0
  605. {metalist-0.22.0 → metalist-0.23.0}/app/utils/tcp_ports.py +0 -0
  606. {metalist-0.22.0 → metalist-0.23.0}/app/utils/text_utils.py +0 -0
  607. {metalist-0.22.0 → metalist-0.23.0}/app/utils/time_units.py +0 -0
  608. {metalist-0.22.0 → metalist-0.23.0}/convert-from-legacy.py +0 -0
  609. {metalist-0.22.0 → metalist-0.23.0}/metalist.egg-info/dependency_links.txt +0 -0
  610. {metalist-0.22.0 → metalist-0.23.0}/metalist.egg-info/entry_points.txt +0 -0
  611. {metalist-0.22.0 → metalist-0.23.0}/metalist.egg-info/top_level.txt +0 -0
  612. {metalist-0.22.0 → metalist-0.23.0}/scripts/generate-lan-cert.sh +0 -0
  613. {metalist-0.22.0 → metalist-0.23.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metalist
3
- Version: 0.22.0
3
+ Version: 0.23.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://metalist.app
6
6
  Project-URL: Repository, https://github.com/metalist-app/metalist
@@ -36,7 +36,7 @@ Provides-Extra: dev
36
36
  Requires-Dist: hypothesis==6.164.0; extra == "dev"
37
37
  Requires-Dist: pytest==9.1.1; extra == "dev"
38
38
  Requires-Dist: pytest-cov==7.1.0; extra == "dev"
39
- Requires-Dist: shockharness==0.17.0; extra == "dev"
39
+ Requires-Dist: shockharness==0.26.0; extra == "dev"
40
40
  Requires-Dist: mypy==2.4.0; extra == "dev"
41
41
 
42
42
  # MetaList
@@ -53,6 +53,21 @@ A minimalist single-user note-taking app focused on server-side rendering (SSR),
53
53
  - Multi-tab search contexts with server-persisted scroll/search state (survives browser restarts)
54
54
  - Manual namespace backups/restores to a user-selected backup folder with retention controls
55
55
 
56
+ ## Changes in 0.23.0
57
+
58
+ - **Reference views.** Following a reference (a link, an embed's reference icon, Go to Source Note) or an AI answer's references slides the list to the left, and a gray chip takes the search box's place: **Source note** (its first line is the tooltip), **Reference** or **All references**. `←` or Escape goes back one level, `×` straight back to your search, each to the exact place you left; the list slides back to the right. With Reduce Motion it is a quick fade. The magnifier beside the chip starts a new search. Reference tabs keep their label and chip after a reload and in every window: no tab is named by a note ID any more.
59
+ - One reference icon, a page with an arrow coming into it, on embeds, links, the chip, the tab list and the right-click menu's **Go to Source Note**; All references has two pages. A collapsed embed shows its source's first line in its own formatting (a green heading stays a green heading), and embeds are a shade darker grey, deeper again for an embed inside an embed.
60
+ - Sort orders and Untagged show as chips inside the search box (`Created`, `Updated`, `A–Z`, `Size`, `Untagged`; the full name is the tooltip). New **Reverse Order** in Sort by works with any order: Z to A, oldest or smallest first, or your own order bottom to top. Typing a new search or leaving a tab ends its sort; a new tab starts unsorted; a reference view and back keeps it.
61
+ - Right-clicking the list offers **Paste Note as Reference at Top** (⌘R) beside Paste Note at Top.
62
+ - Backlinks (`↖`) are hidden for now, until they have a sign of their own.
63
+ - Coming back to a tab, or from a reference view, lands exactly where you were; a note just below the top could put you up to 80px further down.
64
+ - **Find in the list** (Cmd/Ctrl+F) finds text far below the loaded notes and inside folded ones; a folded match opens just for the find.
65
+ - Namespaces are called **vaults** on screen; `--vault` works like `--namespace`.
66
+ - Edit tag relationships: suggestions list tags linked to the focus tag first, a condition shows one part per line, and with no focus tag the `+` buttons are dimmed instead of stopping MetaList.
67
+ - A file link downloads only from its badge and name; a click beside it edits the note.
68
+ - Make Bigger, Make Smaller and Reset Size keep the caret on its side of the image.
69
+ - Logging out while a log entry was being written could close the log under it; the logout now waits.
70
+
56
71
  ## Changes in 0.22.0
57
72
 
58
73
  - Tag suggestions only narrow as you type, however many letters: `q`, `qu`, `que` keep their order, and a tag that already applies (a parent's, or implied by a rule) stays right after the tags with evidence instead of dropping to the bottom. Each letter after the first answers in a few milliseconds. Measured on a 107,000-note namespace, the wanted tag is in the top five more often after two and three letters (90% and 96%, up from 88% and 93%).
@@ -12,6 +12,21 @@ 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.23.0
16
+
17
+ - **Reference views.** Following a reference (a link, an embed's reference icon, Go to Source Note) or an AI answer's references slides the list to the left, and a gray chip takes the search box's place: **Source note** (its first line is the tooltip), **Reference** or **All references**. `←` or Escape goes back one level, `×` straight back to your search, each to the exact place you left; the list slides back to the right. With Reduce Motion it is a quick fade. The magnifier beside the chip starts a new search. Reference tabs keep their label and chip after a reload and in every window: no tab is named by a note ID any more.
18
+ - One reference icon, a page with an arrow coming into it, on embeds, links, the chip, the tab list and the right-click menu's **Go to Source Note**; All references has two pages. A collapsed embed shows its source's first line in its own formatting (a green heading stays a green heading), and embeds are a shade darker grey, deeper again for an embed inside an embed.
19
+ - Sort orders and Untagged show as chips inside the search box (`Created`, `Updated`, `A–Z`, `Size`, `Untagged`; the full name is the tooltip). New **Reverse Order** in Sort by works with any order: Z to A, oldest or smallest first, or your own order bottom to top. Typing a new search or leaving a tab ends its sort; a new tab starts unsorted; a reference view and back keeps it.
20
+ - Right-clicking the list offers **Paste Note as Reference at Top** (⌘R) beside Paste Note at Top.
21
+ - Backlinks (`↖`) are hidden for now, until they have a sign of their own.
22
+ - Coming back to a tab, or from a reference view, lands exactly where you were; a note just below the top could put you up to 80px further down.
23
+ - **Find in the list** (Cmd/Ctrl+F) finds text far below the loaded notes and inside folded ones; a folded match opens just for the find.
24
+ - Namespaces are called **vaults** on screen; `--vault` works like `--namespace`.
25
+ - Edit tag relationships: suggestions list tags linked to the focus tag first, a condition shows one part per line, and with no focus tag the `+` buttons are dimmed instead of stopping MetaList.
26
+ - A file link downloads only from its badge and name; a click beside it edits the note.
27
+ - Make Bigger, Make Smaller and Reset Size keep the caret on its side of the image.
28
+ - Logging out while a log entry was being written could close the log under it; the logout now waits.
29
+
15
30
  ## Changes in 0.22.0
16
31
 
17
32
  - Tag suggestions only narrow as you type, however many letters: `q`, `qu`, `que` keep their order, and a tag that already applies (a parent's, or implied by a rule) stays right after the tags with evidence instead of dropping to the bottom. Each letter after the first answers in a few milliseconds. Measured on a 107,000-note namespace, the wanted tag is in the top five more often after two and three letters (90% and 96%, up from 88% and 93%).
@@ -56,18 +56,26 @@ class Viewport(TypedDict):
56
56
  scrollY: Nonnegative
57
57
  scrollAnchor: ScrollAnchor | None
58
58
 
59
+ # A root sort order, and the same order reversed (app/services/root_sorting.py).
60
+ SortMode = Literal[
61
+ 'normal', 'created', 'updated', 'alphabetical', 'content-volume',
62
+ 'normal-reversed', 'created-reversed', 'updated-reversed', 'alphabetical-reversed', 'content-volume-reversed',
63
+ ]
64
+
59
65
  @with_config(ConfigDict(strict=True))
60
66
  class Tab(TypedDict):
61
67
  searchQuery: Text
62
68
  scrollY: Nonnegative
63
69
  anchorRootId: Text | None
64
70
  scrollAnchor: ScrollAnchor | None
65
- sortMode: Literal['normal', 'created', 'updated', 'alphabetical', 'content-volume']
71
+ sortMode: SortMode
66
72
 
67
73
  @with_config(ConfigDict(strict=True))
68
74
  class ViewDiffRequest(TypedDict):
69
75
  clientId: Identifier
70
76
  editingNoteId: Text | None
77
+ # The note find opened to show a match folded away, for this view only (docs/ui/find.md).
78
+ findRevealNoteId: Text | None
71
79
  search: Text | None
72
80
  tabId: Identifier
73
81
  undoContext: UndoContext
@@ -77,16 +85,42 @@ class ViewDiffRequest(TypedDict):
77
85
  isUntaggedView: bool
78
86
  startAtListEnd: bool
79
87
 
88
+ # Find in the list (docs/ui/find.md): one step from a root position of the view.
89
+ @with_config(ConfigDict(strict=True))
90
+ class FindInListRequest(TypedDict):
91
+ tabId: Identifier
92
+ search: Text | None
93
+ isUntaggedView: bool
94
+ text: Annotated[str, Field(min_length=1, max_length=KIB)]
95
+ fromRootIndex: Nonnegative
96
+ direction: Literal['forward', 'backward']
97
+
98
+ @with_config(ConfigDict(strict=True))
99
+ class ReferenceOriginScope(TypedDict):
100
+ scopeTabId: Identifier
101
+ searchQuery: Text
102
+ sortMode: SortMode
103
+ isUntaggedView: bool
104
+
105
+ # A tab showing a reference view, opened from another tab (app/services/tab_state.py).
106
+ @with_config(ConfigDict(strict=True))
107
+ class ReferenceView(TypedDict):
108
+ fromTabId: Identifier
109
+ referenceQuery: Text
110
+ viewKind: Literal['source', 'backlinks', 'reference', 'references']
111
+ originScope: ReferenceOriginScope
112
+
80
113
  @with_config(ConfigDict(strict=True))
81
114
  class UpdateTabStateRequest(TypedDict):
82
115
  activeTabId: Identifier
83
116
  tabs: dict[Identifier, Tab]
84
117
  tabOrder: list[Identifier]
118
+ referenceViews: dict[Identifier, ReferenceView]
85
119
 
86
120
  @with_config(ConfigDict(strict=True))
87
121
  class UpdateTabSortModeRequest(TypedDict):
88
122
  tabId: Identifier
89
- sortMode: Literal['normal', 'created', 'updated', 'alphabetical', 'content-volume']
123
+ sortMode: SortMode
90
124
  clientId: Identifier
91
125
  undoContext: UndoContext
92
126
 
@@ -126,7 +160,7 @@ class TabSearchInteractionRequest(TypedDict):
126
160
  class DictationPasteRequest(TypedDict):
127
161
  """Text pasted into the search bar or the tag bar, and the field's current value."""
128
162
  text: Text
129
- target: Literal["search", "tags", "tag", "condition"]
163
+ target: Literal["search", "tags", "tag"]
130
164
  current_value: Text
131
165
  # The spoken phrases around a quoted phrase (Dictation Settings).
132
166
  quote_open: Identifier
@@ -1024,7 +1024,7 @@ def namespace_delete_job_status(
1024
1024
  exc = job_record_capture.captured_exception
1025
1025
  raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail=str(exc)) from exc
1026
1026
  if job_record is None:
1027
- raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail=f"Namespace deletion job not found: {job_id}")
1027
+ raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail=f"Vault deletion job not found: {job_id}")
1028
1028
  return job_record
1029
1029
 
1030
1030
 
@@ -1038,7 +1038,7 @@ def namespace_rename_job_status(job_id: str):
1038
1038
  exc = job_record_capture.captured_exception
1039
1039
  raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail=str(exc)) from exc
1040
1040
  if job_record is None:
1041
- raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail=f"Namespace rename job not found: {job_id}")
1041
+ raise HTTPException(status_code=HTTPStatus.NOT_FOUND, detail=f"Vault rename job not found: {job_id}")
1042
1042
  return job_record
1043
1043
 
1044
1044
 
@@ -301,7 +301,7 @@ def _normalize_selected_namespaces(*, selected_namespaces: list[str]) -> list[st
301
301
  raise TypeError("selected_namespaces must be a list")
302
302
  normalized_selected_namespaces = _order_namespaces(namespaces=selected_namespaces)
303
303
  if len(normalized_selected_namespaces) == 0:
304
- raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="Select at least one namespace to back up")
304
+ raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="Select at least one vault to back up")
305
305
  return normalized_selected_namespaces
306
306
 
307
307
 
@@ -310,7 +310,7 @@ def _require_existing_selected_namespaces(*, selected_namespaces: list[str]) ->
310
310
  for namespace in normalized_selected_namespaces:
311
311
  database_path = resolve_namespaced_database_path(namespace=namespace)
312
312
  if not database_path.is_file():
313
- raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail=f"Selected namespace has no database yet: {namespace}")
313
+ raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail=f"Selected vault has no database yet: {namespace}")
314
314
  return normalized_selected_namespaces
315
315
 
316
316
 
@@ -324,7 +324,7 @@ def _filter_deleted_selected_namespaces(*, selected_namespaces: list[str]) -> li
324
324
  if len(existing_selected_namespaces) == 0:
325
325
  raise HTTPException(
326
326
  status_code=HTTPStatus.BAD_REQUEST,
327
- detail="None of the selected backup namespaces still exist",
327
+ detail="None of the selected backup vaults still exist",
328
328
  )
329
329
  return existing_selected_namespaces
330
330
 
@@ -583,7 +583,7 @@ def _verify_target_namespace_password(*, target_namespace: str, password: str) -
583
583
  if not _target_auth_settings_have_password(settings=settings):
584
584
  return
585
585
  if password == "":
586
- raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="Target namespace password is required")
586
+ raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="Target vault password is required")
587
587
 
588
588
  assert settings is not None
589
589
  auth_salt = settings["auth_salt"]
@@ -610,7 +610,7 @@ def _verify_target_namespace_password(*, target_namespace: str, password: str) -
610
610
  parallelism,
611
611
  ).hex()
612
612
  if not secrets.compare_digest(candidate, auth_verifier):
613
- raise HTTPException(status_code=HTTPStatus.FORBIDDEN, detail="Target namespace password is incorrect")
613
+ raise HTTPException(status_code=HTTPStatus.FORBIDDEN, detail="Target vault password is incorrect")
614
614
 
615
615
 
616
616
  def _collect_import_profile_port_conflicts(
@@ -633,7 +633,7 @@ def _collect_import_profile_port_conflicts(
633
633
  continue
634
634
  conflict_namespace, conflict_service = occupied_ports[port]
635
635
  conflicts.append(
636
- f"{service} port {port} conflicts with {conflict_service} port reserved for namespace {conflict_namespace}"
636
+ f"{service} port {port} conflicts with {conflict_service} port reserved for vault {conflict_namespace}"
637
637
  )
638
638
  return conflicts
639
639
 
@@ -959,7 +959,7 @@ def restore_backup_preflight(
959
959
 
960
960
  folder_namespace, folder_filename = _parse_folder_backup_id(payload.backup_id)
961
961
  if folder_namespace != backup_namespace:
962
- raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="folder backup namespace does not match payload")
962
+ raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="folder backup vault does not match payload")
963
963
  if folder_filename != payload.backup_filename:
964
964
  raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="folder backup filename does not match payload")
965
965
  settings = load_backup_settings(token=token)
@@ -1030,7 +1030,7 @@ def restore_backup(
1030
1030
 
1031
1031
  folder_namespace, folder_filename = _parse_folder_backup_id(payload.backup_id)
1032
1032
  if folder_namespace != backup_namespace:
1033
- raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="folder backup namespace does not match payload")
1033
+ raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="folder backup vault does not match payload")
1034
1034
  if folder_filename != payload.backup_filename:
1035
1035
  raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="folder backup filename does not match payload")
1036
1036
  settings = load_backup_settings(token=token)
@@ -1101,7 +1101,7 @@ def import_backup(
1101
1101
  if target_exists and not payload.overwrite_existing_target:
1102
1102
  raise HTTPException(
1103
1103
  status_code=HTTPStatus.CONFLICT,
1104
- detail=f"Target namespace already exists: {target_namespace}",
1104
+ detail=f"Target vault already exists: {target_namespace}",
1105
1105
  )
1106
1106
  if target_exists:
1107
1107
  _verify_target_namespace_password(
@@ -1112,7 +1112,7 @@ def import_backup(
1112
1112
  target_database_path = resolve_namespaced_database_path(namespace=target_namespace)
1113
1113
  folder_namespace, folder_filename = _parse_folder_backup_id(payload.backup_id)
1114
1114
  if folder_namespace != backup_namespace:
1115
- raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="folder backup namespace does not match payload")
1115
+ raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="folder backup vault does not match payload")
1116
1116
  if folder_filename != payload.backup_filename:
1117
1117
  raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="folder backup filename does not match payload")
1118
1118
  settings = load_backup_settings(token=token)
@@ -11,6 +11,7 @@ from pydantic import BaseModel
11
11
 
12
12
  from app.api.note_requests import (
13
13
  ViewDiffRequest,
14
+ FindInListRequest,
14
15
  UpdateTabStateRequest,
15
16
  UpdateTabSortModeRequest,
16
17
  CreateNewTabRequest,
@@ -63,6 +64,7 @@ from app.api.note_requests import (
63
64
  from app.api.transactions import serialized_read_route, transactional_route
64
65
  from app.services.sync import touch_client
65
66
  from app.services.snapshot import build_view_state
67
+ from app.services.snapshot import find_in_view
66
68
  from app.services.snapshot import resolve_search_scope
67
69
  from app.services.snapshot import resolve_view_scope_membership
68
70
  from app.services.note_store import store as note_store
@@ -300,6 +302,7 @@ def view_diff(payload: ViewDiffRequest):
300
302
  client_id = payload["clientId"]
301
303
  touch_client(client_id)
302
304
  editing_note_id = payload["editingNoteId"]
305
+ find_reveal_note_id = payload["findRevealNoteId"]
303
306
  search = payload["search"]
304
307
  tab_id = payload["tabId"]
305
308
  undo_context = payload["undoContext"]
@@ -341,6 +344,10 @@ def view_diff(payload: ViewDiffRequest):
341
344
  if not note_store.has_note(normalized_editing_note_id):
342
345
  normalized_editing_note_id = None
343
346
 
347
+ # Like editingNoteId, the note find opened can be gone by now (deleted, undone).
348
+ if find_reveal_note_id is not None and not note_store.has_note(find_reveal_note_id):
349
+ find_reveal_note_id = None
350
+
344
351
  # The server keeps each tab's warm view (what that browser tab displays),
345
352
  # so the browser sends only where it is. A tab with no warm view, or one
346
353
  # whose browser shows nothing for it, gets its initial window.
@@ -357,6 +364,7 @@ def view_diff(payload: ViewDiffRequest):
357
364
 
358
365
  state = build_view_state(
359
366
  editing_note_id=normalized_editing_note_id,
367
+ find_reveal_note_id=find_reveal_note_id,
360
368
  search=normalized_search,
361
369
  sort_mode=sort_mode,
362
370
  client_known_note_ids=client_known_note_ids,
@@ -414,17 +422,26 @@ def get_tab_state() -> Dict[str, object]:
414
422
  @router.post("/notes/tab-state")
415
423
  @transactional_route
416
424
  def update_tab_state(payload: UpdateTabStateRequest) -> Dict[str, object]:
417
- if "activeTabId" not in payload or "tabs" not in payload or "tabOrder" not in payload:
418
- raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="activeTabId, tabs, and tabOrder are required")
425
+ if (
426
+ "activeTabId" not in payload or "tabs" not in payload or "tabOrder" not in payload
427
+ or "referenceViews" not in payload
428
+ ):
429
+ raise HTTPException(
430
+ status_code=HTTPStatus.BAD_REQUEST,
431
+ detail="activeTabId, tabs, tabOrder, and referenceViews are required",
432
+ )
419
433
  active_tab_id = payload["activeTabId"]
420
434
  tabs = payload["tabs"]
421
435
  tab_order = payload["tabOrder"]
436
+ reference_views = payload["referenceViews"]
422
437
  if not isinstance(tab_order, list):
423
438
  raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="tabOrder must be a list")
424
439
  tab_order_list = [str(entry) for entry in tab_order]
425
440
  capture = CapturedExceptionContext(InputRejected, boundary='app/api/routes/notes.py:update_tab_state:capture')
426
441
  with capture:
427
- response = tab_state_store.update(active_tab_id=active_tab_id, tabs=tabs, tab_order=tab_order_list)
442
+ response = tab_state_store.update(
443
+ active_tab_id=active_tab_id, tabs=tabs, tab_order=tab_order_list, reference_views=reference_views,
444
+ )
428
445
  if capture.captured_exception is not None:
429
446
  raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="Invalid or stale tab state") from capture.captured_exception
430
447
  return response
@@ -632,6 +649,39 @@ def get_memory_usage(request: Request) -> Dict[str, object]:
632
649
  return describe_memory_usage()
633
650
 
634
651
 
652
+ @router.post("/notes/find")
653
+ @transactional_route
654
+ def find_in_list(payload: FindInListRequest) -> Dict[str, object]:
655
+ """One step of find through the list a tab shows (docs/ui/find.md): the notes the
656
+ text occurs in, in list order, from a root position forward or before it backward."""
657
+ search = payload["search"]
658
+ if search is None or search.strip() == "":
659
+ search = ""
660
+ else:
661
+ # A search that does not parse is answered as rejected input, as the view does.
662
+ parse_search_query(search)
663
+ if payload["text"].strip() == "":
664
+ raise HTTPException(status_code=HTTPStatus.BAD_REQUEST, detail="text must hold more than spaces")
665
+ window = find_in_view(
666
+ find_text=payload["text"], search=search, sort_mode=_resolve_tab_sort_mode(payload["tabId"]),
667
+ is_untagged_view=payload["isUntaggedView"], from_root_index=payload["fromRootIndex"],
668
+ direction=payload["direction"],
669
+ )
670
+ return {
671
+ "matches": [
672
+ {
673
+ "noteId": match.note_id, "rootId": match.root_id, "rootIndex": match.root_index,
674
+ "contentCount": match.content_count, "commentCount": match.comment_count,
675
+ "previewCount": match.preview_count, "isUnderFoldedNote": match.is_under_folded_note,
676
+ }
677
+ for match in window.matches
678
+ ],
679
+ "firstRootIndex": window.first_root_index,
680
+ "endRootIndex": window.end_root_index,
681
+ "rootCount": window.root_count,
682
+ }
683
+
684
+
635
685
  @router.get("/notes/memory-usage/breakdown")
636
686
  @serialized_read_route
637
687
  def get_memory_breakdown(request: Request) -> Dict[str, object]:
@@ -1,5 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections import Counter
4
+ from dataclasses import dataclass
5
+
3
6
  from app.utils.byte_sizes import MIB
4
7
  from http import HTTPStatus
5
8
  from fastapi import APIRouter, HTTPException, Request
@@ -10,7 +13,12 @@ from pydantic import ConfigDict, Field, with_config
10
13
 
11
14
  from app.api.request_auth import get_request_auth_token
12
15
  from app.api.transactions import transactional_route
16
+ from app.security.sensitive_cache import SensitiveMemo
17
+ from app.services.resource_limits import SENSITIVE_MEMO_BYTES
13
18
  from app.services.search_index import search_index
19
+ from app.services.tag_ontology import TagOntology
20
+ from app.services.tag_term_matching import list_significant_content_match_segments
21
+ from app.utils.not_found import NOT_FOUND
14
22
  from app.services.note_store import store as note_store
15
23
  from app.services.sync import generate_new_uuid
16
24
  from app.services.tag_ontology import RegexAtom, TagAtom, TextAtom, parse_rules_text
@@ -35,6 +43,15 @@ _EQUALITY_LINE_RULE_COUNT = 2
35
43
  _PREFIX_MATCH_RANK = 0
36
44
  _SUBSTRING_MATCH_RANK = 1
37
45
  _FUZZY_MATCH_RANK = 2
46
+ # What a Tag Relationships field adds next to its focus tag; "none" ranks tags by use alone.
47
+ _SUGGESTION_RELATIONS = frozenset({"none", "incoming", "implied", "synonym"})
48
+ # A tag counts as linked to the focus tag once they share this many notes: one shared
49
+ # note is chance.
50
+ _MIN_SHARED_NOTES = 2
51
+ # The focus tags whose related order is kept while their dialog is open (tag names
52
+ # are private: the memo is cleared on lock).
53
+ _RELATED_ORDER_MEMO_ENTRIES = 4
54
+ _related_orders = SensitiveMemo(maxsize=_RELATED_ORDER_MEMO_ENTRIES, max_bytes=SENSITIVE_MEMO_BYTES)
38
55
 
39
56
 
40
57
  def _maybe_bearer_token(request: Request) -> str:
@@ -389,27 +406,27 @@ def focus_view(tag: str) -> dict:
389
406
  for candidate in sorted(left):
390
407
  if candidate in equals:
391
408
  continue
392
- rule_ids: set[int] = set()
409
+ left_rule_ids: set[int] = set()
393
410
  for member in equals:
394
411
  key = (candidate, member)
395
412
  if key in edge_map:
396
- rule_ids.add(edge_map[key])
397
- if not rule_ids:
413
+ left_rule_ids.add(edge_map[key])
414
+ if not left_rule_ids:
398
415
  continue
399
- direct_left.append({"tag": candidate, "ruleIds": sorted(rule_ids)})
416
+ direct_left.append({"tag": candidate, "ruleIds": sorted(left_rule_ids)})
400
417
 
401
418
  for candidate in sorted(right):
402
419
  if candidate in equals:
403
420
  continue
404
- rule_ids: set[int] = set()
421
+ right_rule_ids: set[int] = set()
405
422
  for member in equals:
406
423
  key = (member, candidate)
407
424
  if key in edge_map:
408
- rule_ids.add(edge_map[key])
409
- if not rule_ids:
425
+ right_rule_ids.add(edge_map[key])
426
+ if not right_rule_ids:
410
427
  continue
411
428
  direct_right_tags.add(candidate)
412
- direct_right.append({"tag": candidate, "ruleIds": sorted(rule_ids)})
429
+ direct_right.append({"tag": candidate, "ruleIds": sorted(right_rule_ids)})
413
430
 
414
431
  for candidate in sorted(equals):
415
432
  if candidate == tag:
@@ -442,53 +459,128 @@ def focus_view(tag: str) -> dict:
442
459
  }
443
460
 
444
461
 
462
+ @dataclass(frozen=True)
463
+ class _RelatedOrder:
464
+ """Tags in the order a Tag Relationships field suggests them for its focus tag: linked
465
+ tags first, then tags sharing a word with it, then the rest by use."""
466
+
467
+ index_revision: int
468
+ # Compared by identity: editing the rules compiles a new ontology.
469
+ ontology: TagOntology
470
+ linked: tuple[str, ...]
471
+ named_alike: tuple[str, ...]
472
+ by_use: tuple[str, ...]
473
+
474
+
475
+ def _link_score(*, relation: str, shared: int, focus_notes: int, tag_notes: int) -> float:
476
+ """How strongly a tag is linked to the focus tag for `relation` (0 to 1)."""
477
+ assert 0 < shared <= tag_notes and shared <= focus_notes, (shared, tag_notes, focus_notes)
478
+ if relation == "incoming":
479
+ # tag => focus: how many of the tag's notes carry the focus tag.
480
+ return shared / tag_notes
481
+ if relation == "implied":
482
+ # focus => tag: how many of the focus tag's notes carry the tag.
483
+ return shared / focus_notes
484
+ assert relation == "synonym", relation
485
+ # Both ways: the notes they share among the notes either is on.
486
+ return shared / (focus_notes + tag_notes - shared)
487
+
488
+
489
+ def _related_order(*, focus: str, relation: str, tag_counts: dict[str, int]) -> _RelatedOrder:
490
+ ontology = get_ontology()
491
+ key = (focus.casefold(), relation)
492
+ found, kept = _related_orders.lookup(key)
493
+ if found and kept.index_revision == search_index.revision and kept.ontology is ontology:
494
+ return kept
495
+ index_revision = search_index.revision
496
+ focus_notes, written_with_focus = search_index.count_written_tags_on_notes_with(focus)
497
+ left, equal, right = ontology.focus_view(tag=focus)
498
+ # The focus tag, its synonyms, and tags already on this side of it say nothing new.
499
+ excluded = {tag.casefold() for tag in equal} | {focus.casefold()}
500
+ if relation == "incoming":
501
+ excluded |= {tag.casefold() for tag in left}
502
+ elif relation == "implied":
503
+ excluded |= {tag.casefold() for tag in right}
504
+ candidates = [tag for tag in tag_counts if tag.casefold() not in excluded]
505
+ scored = []
506
+ for tag in candidates:
507
+ # A meta tag (@bold, @todo) is formatting or a state, not a topic linked to the
508
+ # focus tag; it is still listed by use, and when "@" is typed.
509
+ if tag.startswith("@") or tag.casefold() not in written_with_focus:
510
+ continue
511
+ tag_shared, tag_notes = written_with_focus[tag.casefold()]
512
+ if tag_shared >= _MIN_SHARED_NOTES:
513
+ score = _link_score(relation=relation, shared=tag_shared, focus_notes=focus_notes, tag_notes=tag_notes)
514
+ scored.append((-score, -tag_shared, tag.casefold(), tag))
515
+ linked = tuple(tag for *_ordering, tag in sorted(scored))
516
+ linked_set = set(linked)
517
+ focus_words = set(list_significant_content_match_segments(focus))
518
+ by_use_order = sorted((tag for tag in candidates if tag not in linked_set), key=lambda tag: (-tag_counts[tag], tag))
519
+ named_alike = tuple(tag for tag in by_use_order if focus_words & set(list_significant_content_match_segments(tag)))
520
+ named_alike_set = set(named_alike)
521
+ order = _RelatedOrder(
522
+ index_revision=index_revision, ontology=ontology, linked=linked, named_alike=named_alike,
523
+ by_use=tuple(tag for tag in by_use_order if tag not in named_alike_set),
524
+ )
525
+ _related_orders.store(key, order)
526
+ return order
527
+
528
+
529
+ def _match_rank(*, needle: str, tag: str) -> int:
530
+ """How a typed text matches a tag (prefix, substring or fuzzy), NOT_FOUND if not at all."""
531
+ folded = tag.casefold()
532
+ if folded.startswith(needle):
533
+ return _PREFIX_MATCH_RANK
534
+ if needle in folded:
535
+ return _SUBSTRING_MATCH_RANK
536
+ if _fuzzy_match(needle, folded):
537
+ return _FUZZY_MATCH_RANK
538
+ return NOT_FOUND
539
+
540
+
445
541
  @router.get("/tags")
446
- def list_tags(q: str, limit: int) -> dict:
447
- if not isinstance(q, str):
448
- raise TypeError("q must be a string")
542
+ def list_tags(q: str, limit: int, focus: str, relation: str) -> dict:
543
+ """Tags for a Tag Relationships field. With a `relation` to `focus`, tags linked to the
544
+ focus tag come first, then tags sharing a word with it, then the rest by use; typing
545
+ narrows that order (app/services/agent/skills/help-ontology.md, "Relationship dialogs"). Without one (`relation` "none",
546
+ `focus` ""), by match, then use."""
547
+ if not isinstance(q, str) or not isinstance(focus, str) or not isinstance(relation, str):
548
+ raise TypeError("q, focus and relation must be strings")
449
549
  if not isinstance(limit, int):
450
550
  raise TypeError("limit must be an int")
451
551
  if limit < 0:
452
552
  raise ValueError("limit must be >= 0")
553
+ if relation not in _SUGGESTION_RELATIONS:
554
+ raise ValueError(f"Unknown suggestion relation: {relation!r}")
555
+ if (relation == "none") != (focus == ""):
556
+ raise ValueError("A focus tag goes with a relation, and only with one")
453
557
 
454
558
  ontology = get_ontology()
455
559
  # A tag only the rules name is on no note yet.
456
560
  tag_counts = {tag: 0 for tag in extract_ontology_tags(ontology)}
457
561
  tag_counts.update(search_index.list_tag_frequencies())
458
- tags = set(tag_counts.keys())
459
-
460
562
  needle = q.casefold().strip()
461
563
 
564
+ if relation != "none":
565
+ order = _related_order(focus=focus, relation=relation, tag_counts=tag_counts)
566
+ ordered: list[str] = []
567
+ for group in (order.linked, order.named_alike):
568
+ ordered.extend(tag for tag in group if needle == "" or _match_rank(needle=needle, tag=tag) != NOT_FOUND)
569
+ rest = [(_match_rank(needle=needle, tag=tag), index, tag) for index, tag in enumerate(order.by_use)]
570
+ ordered.extend(tag for rank, _index, tag in sorted(rest) if needle == "" or rank != NOT_FOUND)
571
+ payload = [{"tag": tag, "count": tag_counts[tag]} for tag in ordered[:limit]]
572
+ return {"totalCount": len(tag_counts), "tags": payload}
573
+
462
574
  if needle == "":
463
- ordered = sorted(tags, key=lambda tag: (-tag_counts[tag], tag))
464
- ordered = ordered[:limit]
465
- payload = [
466
- {"tag": tag, "count": tag_counts[tag]}
467
- for tag in ordered
468
- ]
469
- return {"totalCount": len(tags), "tags": payload}
575
+ ordered = sorted(tag_counts, key=lambda tag: (-tag_counts[tag], tag))[:limit]
576
+ return {"totalCount": len(tag_counts), "tags": [{"tag": tag, "count": tag_counts[tag]} for tag in ordered]}
470
577
 
471
578
  matches: list[tuple[int, int, str]] = []
472
- for tag in tags:
473
- folded = tag.casefold()
474
- if folded.startswith(needle):
475
- rank = _PREFIX_MATCH_RANK
476
- elif needle in folded:
477
- rank = _SUBSTRING_MATCH_RANK
478
- elif _fuzzy_match(needle, folded):
479
- rank = _FUZZY_MATCH_RANK
480
- else:
481
- continue
482
- count = tag_counts[tag]
483
- matches.append((rank, -count, tag))
484
-
579
+ for tag in tag_counts:
580
+ rank = _match_rank(needle=needle, tag=tag)
581
+ if rank != NOT_FOUND:
582
+ matches.append((rank, -tag_counts[tag], tag))
485
583
  # By rank, then most used, then name.
486
584
  matches.sort()
487
- results = [tag for _rank, _negative_count, tag in matches]
488
- results = results[:limit]
489
-
490
- payload = [
491
- {"tag": tag, "count": tag_counts[tag]}
492
- for tag in results
493
- ]
494
- return {"totalCount": len(tags), "tags": payload}
585
+ payload = [{"tag": tag, "count": tag_counts[tag]} for _rank, _negative_count, tag in matches[:limit]]
586
+ return {"totalCount": len(tag_counts), "tags": payload}
@@ -86,7 +86,7 @@ def transactional_route(func: Callable[P, R] | Callable[P, Awaitable[R]]) -> Cal
86
86
  _check_bulk_guard(func.__name__)
87
87
  maintenance = nullcontext()
88
88
  if func.__name__ in _STORAGE_TRANSITIONS:
89
- maintenance = maintenance_service.hold_for_transaction("Updating namespace storage")
89
+ maintenance = maintenance_service.hold_for_transaction("Updating vault storage")
90
90
  with maintenance:
91
91
  with begin_request_transaction():
92
92
  register_runtime_recovery()
@@ -147,7 +147,7 @@ def assert_mutation_routes_wrapped(app: FastAPI) -> None:
147
147
 
148
148
  def _check_bulk_guard(endpoint_name: str) -> None:
149
149
  if endpoint_name in _STORAGE_TRANSITIONS and bulk_operation_guard.active_mutations > 1:
150
- raise HTTPException(status_code=HTTPStatus.CONFLICT, detail="Wait for the current request to finish before changing namespace storage.")
150
+ raise HTTPException(status_code=HTTPStatus.CONFLICT, detail="Wait for the current request to finish before changing vault storage.")
151
151
  # Preferences never touch notes, and every operation reads them once when it
152
152
  # starts, so saving them (e.g. the chat panel width) cannot disturb it.
153
153
  permitted = {"answer_bulk_question", "preview_cloud_privacy", "put_ai_debug_details", "put_client_preferences"}
@@ -60,10 +60,6 @@ class GuardedConnection:
60
60
  return self._connection
61
61
 
62
62
 
63
- def enable_read_guard() -> None:
64
- _safe_session().enable_read_guard()
65
-
66
-
67
63
  @contextmanager
68
64
  def allow_reads(reason: str) -> Iterator[None]:
69
65
  with _safe_session().allow_reads(reason):