MetaList 0.13.0__tar.gz → 0.14.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 (550) hide show
  1. {metalist-0.13.0/metalist.egg-info → metalist-0.14.0}/PKG-INFO +11 -1
  2. {metalist-0.13.0 → metalist-0.14.0}/README.md +9 -0
  3. {metalist-0.13.0 → metalist-0.14.0}/app/api/middleware/auth.py +1 -0
  4. {metalist-0.13.0 → metalist-0.14.0}/app/api/routes/auth.py +6 -0
  5. {metalist-0.13.0 → metalist-0.14.0}/app/api/routes/notes.py +25 -0
  6. {metalist-0.13.0 → metalist-0.14.0}/app/config.py +0 -1
  7. {metalist-0.13.0 → metalist-0.14.0}/app/encryption_audit.py +16 -9
  8. {metalist-0.13.0 → metalist-0.14.0}/app/exception_boundaries.py +8 -0
  9. {metalist-0.13.0 → metalist-0.14.0}/app/main.py +5 -3
  10. metalist-0.14.0/app/presentation/login_page.py +18 -0
  11. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/skills/help-dictation.md +2 -0
  12. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/skills/help-formatting.md +6 -3
  13. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/skills/help-menus.md +1 -0
  14. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/skills/help-privacy.md +8 -0
  15. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/skills/help-references.md +1 -1
  16. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/skills/help-releases.md +9 -0
  17. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/skills/help-search.md +9 -0
  18. {metalist-0.13.0 → metalist-0.14.0}/app/services/backlink_index.py +1 -1
  19. {metalist-0.13.0 → metalist-0.14.0}/app/services/content_formatting.py +11 -5
  20. {metalist-0.13.0 → metalist-0.14.0}/app/services/embedded_references.py +15 -59
  21. metalist-0.14.0/app/services/link_title_retry.py +169 -0
  22. {metalist-0.13.0 → metalist-0.14.0}/app/services/link_titles.py +389 -5
  23. {metalist-0.13.0 → metalist-0.14.0}/app/services/note_store.py +15 -6
  24. {metalist-0.13.0 → metalist-0.14.0}/app/services/reference_presentation.py +1 -1
  25. {metalist-0.13.0 → metalist-0.14.0}/app/services/search_index.py +67 -12
  26. {metalist-0.13.0 → metalist-0.14.0}/app/services/search_text.py +44 -3
  27. {metalist-0.13.0 → metalist-0.14.0}/app/services/tab_state.py +20 -6
  28. metalist-0.14.0/app/startup_console.py +100 -0
  29. {metalist-0.13.0 → metalist-0.14.0}/app/static/config/agent-menu-actions.json +6 -0
  30. {metalist-0.13.0 → metalist-0.14.0}/app/static/config/command_palette_tags.json +4 -0
  31. {metalist-0.13.0 → metalist-0.14.0}/app/static/css/main.css +247 -183
  32. metalist-0.14.0/app/static/js/locked.js +36 -0
  33. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/main.js +0 -1
  34. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/ai-chat/ai-chat-panel-controller.js +4 -2
  35. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/api-client.js +13 -0
  36. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/auth.js +162 -284
  37. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/command-palette/command-palette-controller.js +18 -0
  38. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/command-palette/endpoint-registry.js +8 -0
  39. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/command-palette/preferences-store.js +38 -23
  40. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/config.js +2 -10
  41. metalist-0.14.0/app/static/js/modules/modals/link-title-retry-modal.js +308 -0
  42. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/dictation-paste-service.js +9 -0
  43. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/reference-source-navigation-service.js +9 -1
  44. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/search-syntax-service.js +52 -0
  45. metalist-0.14.0/app/templates/_logo_mark.html +6 -0
  46. {metalist-0.13.0 → metalist-0.14.0}/app/templates/base.html +0 -5
  47. {metalist-0.13.0 → metalist-0.14.0}/app/templates/index.html +37 -51
  48. metalist-0.14.0/app/templates/locked.html +37 -0
  49. {metalist-0.13.0 → metalist-0.14.0}/app/utils/text_utils.py +42 -0
  50. {metalist-0.13.0 → metalist-0.14.0}/app/version.py +1 -1
  51. {metalist-0.13.0 → metalist-0.14.0}/main.py +57 -25
  52. {metalist-0.13.0 → metalist-0.14.0/metalist.egg-info}/PKG-INFO +11 -1
  53. {metalist-0.13.0 → metalist-0.14.0}/metalist.egg-info/SOURCES.txt +5 -1
  54. {metalist-0.13.0 → metalist-0.14.0}/metalist.egg-info/requires.txt +1 -0
  55. {metalist-0.13.0 → metalist-0.14.0}/pyproject.toml +1 -0
  56. metalist-0.13.0/app/static/js/locked.js +0 -14
  57. metalist-0.13.0/app/static/video/login-startup.mp4 +0 -0
  58. metalist-0.13.0/app/templates/locked.html +0 -85
  59. {metalist-0.13.0 → metalist-0.14.0}/MANIFEST.in +0 -0
  60. {metalist-0.13.0 → metalist-0.14.0}/app/__init__.py +0 -0
  61. {metalist-0.13.0 → metalist-0.14.0}/app/api/__init__.py +0 -0
  62. {metalist-0.13.0 → metalist-0.14.0}/app/api/deps.py +0 -0
  63. {metalist-0.13.0 → metalist-0.14.0}/app/api/dev.py +0 -0
  64. {metalist-0.13.0 → metalist-0.14.0}/app/api/note_requests.py +0 -0
  65. {metalist-0.13.0 → metalist-0.14.0}/app/api/request_auth.py +0 -0
  66. {metalist-0.13.0 → metalist-0.14.0}/app/api/routes/ai.py +0 -0
  67. {metalist-0.13.0 → metalist-0.14.0}/app/api/routes/app_updates.py +0 -0
  68. {metalist-0.13.0 → metalist-0.14.0}/app/api/routes/backups.py +0 -0
  69. {metalist-0.13.0 → metalist-0.14.0}/app/api/routes/files.py +0 -0
  70. {metalist-0.13.0 → metalist-0.14.0}/app/api/routes/ontology.py +0 -0
  71. {metalist-0.13.0 → metalist-0.14.0}/app/api/routes/reminders.py +0 -0
  72. {metalist-0.13.0 → metalist-0.14.0}/app/api/routes/remote_images.py +0 -0
  73. {metalist-0.13.0 → metalist-0.14.0}/app/api/routes/test.py +0 -0
  74. {metalist-0.13.0 → metalist-0.14.0}/app/api/transactions.py +0 -0
  75. {metalist-0.13.0 → metalist-0.14.0}/app/api/upload_limits.py +0 -0
  76. {metalist-0.13.0 → metalist-0.14.0}/app/data_directory.py +0 -0
  77. {metalist-0.13.0 → metalist-0.14.0}/app/db/__init__.py +0 -0
  78. {metalist-0.13.0 → metalist-0.14.0}/app/db/backup_settings_sql.py +0 -0
  79. {metalist-0.13.0 → metalist-0.14.0}/app/db/editable_files_migration.py +0 -0
  80. {metalist-0.13.0 → metalist-0.14.0}/app/db/engine.py +0 -0
  81. {metalist-0.13.0 → metalist-0.14.0}/app/db/file_schema.py +0 -0
  82. {metalist-0.13.0 → metalist-0.14.0}/app/db/file_session.py +0 -0
  83. {metalist-0.13.0 → metalist-0.14.0}/app/db/files_sql.py +0 -0
  84. {metalist-0.13.0 → metalist-0.14.0}/app/db/link_titles_sql.py +0 -0
  85. {metalist-0.13.0 → metalist-0.14.0}/app/db/live_recovery.py +0 -0
  86. {metalist-0.13.0 → metalist-0.14.0}/app/db/migrations.py +0 -0
  87. {metalist-0.13.0 → metalist-0.14.0}/app/db/notes_sql.py +0 -0
  88. {metalist-0.13.0 → metalist-0.14.0}/app/db/ontology_rules_sql.py +0 -0
  89. {metalist-0.13.0 → metalist-0.14.0}/app/db/reminders_sql.py +0 -0
  90. {metalist-0.13.0 → metalist-0.14.0}/app/db/retire_sounds.py +0 -0
  91. {metalist-0.13.0 → metalist-0.14.0}/app/db/schema.py +0 -0
  92. {metalist-0.13.0 → metalist-0.14.0}/app/db/search_history_sql.py +0 -0
  93. {metalist-0.13.0 → metalist-0.14.0}/app/db/session.py +0 -0
  94. {metalist-0.13.0 → metalist-0.14.0}/app/db/settings_sql.py +0 -0
  95. {metalist-0.13.0 → metalist-0.14.0}/app/db/tab_state_sql.py +0 -0
  96. {metalist-0.13.0 → metalist-0.14.0}/app/db/version.py +0 -0
  97. {metalist-0.13.0 → metalist-0.14.0}/app/https_proxy.py +0 -0
  98. {metalist-0.13.0 → metalist-0.14.0}/app/models/commands.py +0 -0
  99. {metalist-0.13.0 → metalist-0.14.0}/app/models/database.py +0 -0
  100. {metalist-0.13.0 → metalist-0.14.0}/app/models/entities.py +0 -0
  101. {metalist-0.13.0 → metalist-0.14.0}/app/models/enums.py +0 -0
  102. {metalist-0.13.0 → metalist-0.14.0}/app/models/linked_list.py +0 -0
  103. {metalist-0.13.0 → metalist-0.14.0}/app/models/list_operations.py +0 -0
  104. {metalist-0.13.0 → metalist-0.14.0}/app/models/list_traversal.py +0 -0
  105. {metalist-0.13.0 → metalist-0.14.0}/app/models/note_crud.py +0 -0
  106. {metalist-0.13.0 → metalist-0.14.0}/app/models/utils.py +0 -0
  107. {metalist-0.13.0 → metalist-0.14.0}/app/network_settings.py +0 -0
  108. {metalist-0.13.0 → metalist-0.14.0}/app/presentation/__init__.py +0 -0
  109. {metalist-0.13.0 → metalist-0.14.0}/app/presentation/render/__init__.py +0 -0
  110. {metalist-0.13.0 → metalist-0.14.0}/app/presentation/render/note_renderer.py +0 -0
  111. {metalist-0.13.0 → metalist-0.14.0}/app/presentation/templates.py +0 -0
  112. {metalist-0.13.0 → metalist-0.14.0}/app/security/authenticated_logging.py +0 -0
  113. {metalist-0.13.0 → metalist-0.14.0}/app/security/encryption.py +0 -0
  114. {metalist-0.13.0 → metalist-0.14.0}/app/security/http_error_diagnostics.py +0 -0
  115. {metalist-0.13.0 → metalist-0.14.0}/app/security/http_headers.py +0 -0
  116. {metalist-0.13.0 → metalist-0.14.0}/app/security/note_html.py +0 -0
  117. {metalist-0.13.0 → metalist-0.14.0}/app/security/request_boundary.py +0 -0
  118. {metalist-0.13.0 → metalist-0.14.0}/app/security/request_hosts.py +0 -0
  119. {metalist-0.13.0 → metalist-0.14.0}/app/security/sensitive_cache.py +0 -0
  120. {metalist-0.13.0 → metalist-0.14.0}/app/security/sensitive_logging.py +0 -0
  121. {metalist-0.13.0 → metalist-0.14.0}/app/security/shell_execution.py +0 -0
  122. {metalist-0.13.0 → metalist-0.14.0}/app/security/validation_errors.py +0 -0
  123. {metalist-0.13.0 → metalist-0.14.0}/app/server_runtime.py +0 -0
  124. {metalist-0.13.0 → metalist-0.14.0}/app/services/__init__.py +0 -0
  125. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/__init__.py +0 -0
  126. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/action_log.py +0 -0
  127. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/agent_loop.py +0 -0
  128. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/agent_tools.py +0 -0
  129. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/citation_tokens.py +0 -0
  130. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/cloud_privacy.py +0 -0
  131. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/context.py +0 -0
  132. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/evidence_serialization.py +0 -0
  133. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/execution_errors.py +0 -0
  134. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/failure_explanations.py +0 -0
  135. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/help_catalog.py +0 -0
  136. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/history.py +0 -0
  137. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/inference.py +0 -0
  138. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/investigation.py +0 -0
  139. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/judging.py +0 -0
  140. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/menu_actions.py +0 -0
  141. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/model_policy.py +0 -0
  142. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/note_aliases.py +0 -0
  143. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/openai_cost_tracking.py +0 -0
  144. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/openai_inference.py +0 -0
  145. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/prompt_settings.py +0 -0
  146. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/prompts/__init__.py +0 -0
  147. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/prompts/agent.md +0 -0
  148. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/prompts/final-response.md +0 -0
  149. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/prompts/system.md +0 -0
  150. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/release_notes.py +0 -0
  151. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/retrieval_settings.py +0 -0
  152. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/runtime.py +0 -0
  153. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/scope.py +0 -0
  154. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/skill_settings.py +0 -0
  155. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/skills/__init__.py +0 -0
  156. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/skills/help-ai.md +0 -0
  157. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/skills/help-data.md +0 -0
  158. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/skills/help-notes.md +0 -0
  159. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/skills/help-reminders.md +0 -0
  160. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/skills/help-tags.md +0 -0
  161. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/skills/staged-summary.md +0 -0
  162. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/skills/tag-proposals.md +0 -0
  163. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/skills/web-browsing.md +0 -0
  164. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/staged_summary.py +0 -0
  165. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/structured_inference.py +0 -0
  166. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/tagging.py +0 -0
  167. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/tagging_run.py +0 -0
  168. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/token_estimation.py +0 -0
  169. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/tool_calling.py +0 -0
  170. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/trace.py +0 -0
  171. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/web_actions.py +0 -0
  172. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/web_capabilities.py +0 -0
  173. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/web_evidence.py +0 -0
  174. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/web_fetch.py +0 -0
  175. {metalist-0.13.0 → metalist-0.14.0}/app/services/agent/web_settings.py +0 -0
  176. {metalist-0.13.0 → metalist-0.14.0}/app/services/ai_chat.py +0 -0
  177. {metalist-0.13.0 → metalist-0.14.0}/app/services/ai_chat_rendering.py +0 -0
  178. {metalist-0.13.0 → metalist-0.14.0}/app/services/ai_chat_stream.py +0 -0
  179. {metalist-0.13.0 → metalist-0.14.0}/app/services/app_update_worker.py +0 -0
  180. {metalist-0.13.0 → metalist-0.14.0}/app/services/app_updates.py +0 -0
  181. {metalist-0.13.0 → metalist-0.14.0}/app/services/auth.py +0 -0
  182. {metalist-0.13.0 → metalist-0.14.0}/app/services/auth_cache_state.py +0 -0
  183. {metalist-0.13.0 → metalist-0.14.0}/app/services/auth_service.py +0 -0
  184. {metalist-0.13.0 → metalist-0.14.0}/app/services/backlinks.py +0 -0
  185. {metalist-0.13.0 → metalist-0.14.0}/app/services/backup_service.py +0 -0
  186. {metalist-0.13.0 → metalist-0.14.0}/app/services/backup_settings_service.py +0 -0
  187. {metalist-0.13.0 → metalist-0.14.0}/app/services/bulk_operation.py +0 -0
  188. {metalist-0.13.0 → metalist-0.14.0}/app/services/client_state_service.py +0 -0
  189. {metalist-0.13.0 → metalist-0.14.0}/app/services/content_cache.py +0 -0
  190. {metalist-0.13.0 → metalist-0.14.0}/app/services/diagnostics.py +0 -0
  191. {metalist-0.13.0 → metalist-0.14.0}/app/services/dictation_cleanup.py +0 -0
  192. {metalist-0.13.0 → metalist-0.14.0}/app/services/encryption.py +0 -0
  193. {metalist-0.13.0 → metalist-0.14.0}/app/services/exception_capture.py +0 -0
  194. {metalist-0.13.0 → metalist-0.14.0}/app/services/file_edit_sessions.py +0 -0
  195. {metalist-0.13.0 → metalist-0.14.0}/app/services/file_registry.py +0 -0
  196. {metalist-0.13.0 → metalist-0.14.0}/app/services/file_storage.py +0 -0
  197. {metalist-0.13.0 → metalist-0.14.0}/app/services/file_text_preview.py +0 -0
  198. {metalist-0.13.0 → metalist-0.14.0}/app/services/footnote_layout.py +0 -0
  199. {metalist-0.13.0 → metalist-0.14.0}/app/services/footnote_rendering.py +0 -0
  200. {metalist-0.13.0 → metalist-0.14.0}/app/services/hierarchy.py +0 -0
  201. {metalist-0.13.0 → metalist-0.14.0}/app/services/html_export.py +0 -0
  202. {metalist-0.13.0 → metalist-0.14.0}/app/services/html_unformatting.py +0 -0
  203. {metalist-0.13.0 → metalist-0.14.0}/app/services/hydration_state.py +0 -0
  204. {metalist-0.13.0 → metalist-0.14.0}/app/services/image_size_formatting.py +0 -0
  205. {metalist-0.13.0 → metalist-0.14.0}/app/services/inline_image_dimensions.py +0 -0
  206. {metalist-0.13.0 → metalist-0.14.0}/app/services/inline_image_occurrences.py +0 -0
  207. {metalist-0.13.0 → metalist-0.14.0}/app/services/input_errors.py +0 -0
  208. {metalist-0.13.0 → metalist-0.14.0}/app/services/integrity.py +0 -0
  209. {metalist-0.13.0 → metalist-0.14.0}/app/services/latex_rendering.py +0 -0
  210. {metalist-0.13.0 → metalist-0.14.0}/app/services/login_rate_limit.py +0 -0
  211. {metalist-0.13.0 → metalist-0.14.0}/app/services/maintenance_mode.py +0 -0
  212. {metalist-0.13.0 → metalist-0.14.0}/app/services/markdown_rendering.py +0 -0
  213. {metalist-0.13.0 → metalist-0.14.0}/app/services/namespace_deletion_jobs.py +0 -0
  214. {metalist-0.13.0 → metalist-0.14.0}/app/services/namespace_deletion_worker.py +0 -0
  215. {metalist-0.13.0 → metalist-0.14.0}/app/services/namespace_rename_jobs.py +0 -0
  216. {metalist-0.13.0 → metalist-0.14.0}/app/services/namespace_rename_worker.py +0 -0
  217. {metalist-0.13.0 → metalist-0.14.0}/app/services/namespace_runtime_guard.py +0 -0
  218. {metalist-0.13.0 → metalist-0.14.0}/app/services/namespace_switcher.py +0 -0
  219. {metalist-0.13.0 → metalist-0.14.0}/app/services/note_fullscreen.py +0 -0
  220. {metalist-0.13.0 → metalist-0.14.0}/app/services/note_image_tags.py +0 -0
  221. {metalist-0.13.0 → metalist-0.14.0}/app/services/note_ordering.py +0 -0
  222. {metalist-0.13.0 → metalist-0.14.0}/app/services/ontology_rules_store.py +0 -0
  223. {metalist-0.13.0 → metalist-0.14.0}/app/services/openai_credentials.py +0 -0
  224. {metalist-0.13.0 → metalist-0.14.0}/app/services/password_note_fields.py +0 -0
  225. {metalist-0.13.0 → metalist-0.14.0}/app/services/public_http.py +0 -0
  226. {metalist-0.13.0 → metalist-0.14.0}/app/services/reminders.py +0 -0
  227. {metalist-0.13.0 → metalist-0.14.0}/app/services/remote_image_proxy.py +0 -0
  228. {metalist-0.13.0 → metalist-0.14.0}/app/services/request_recovery.py +0 -0
  229. {metalist-0.13.0 → metalist-0.14.0}/app/services/resource_limits.py +0 -0
  230. {metalist-0.13.0 → metalist-0.14.0}/app/services/root_sorting.py +0 -0
  231. {metalist-0.13.0 → metalist-0.14.0}/app/services/runtime_generation.py +0 -0
  232. {metalist-0.13.0 → metalist-0.14.0}/app/services/runtime_hardening.py +0 -0
  233. {metalist-0.13.0 → metalist-0.14.0}/app/services/runtime_lock.py +0 -0
  234. {metalist-0.13.0 → metalist-0.14.0}/app/services/search_history.py +0 -0
  235. {metalist-0.13.0 → metalist-0.14.0}/app/services/search_history_storage.py +0 -0
  236. {metalist-0.13.0 → metalist-0.14.0}/app/services/search_query.py +0 -0
  237. {metalist-0.13.0 → metalist-0.14.0}/app/services/selected_text_tag.py +0 -0
  238. {metalist-0.13.0 → metalist-0.14.0}/app/services/self_update.py +0 -0
  239. {metalist-0.13.0 → metalist-0.14.0}/app/services/session_timeout_service.py +0 -0
  240. {metalist-0.13.0 → metalist-0.14.0}/app/services/shell_session_service.py +0 -0
  241. {metalist-0.13.0 → metalist-0.14.0}/app/services/snapshot.py +0 -0
  242. {metalist-0.13.0 → metalist-0.14.0}/app/services/store.py +0 -0
  243. {metalist-0.13.0 → metalist-0.14.0}/app/services/structured_note_renderers.py +0 -0
  244. {metalist-0.13.0 → metalist-0.14.0}/app/services/sync.py +0 -0
  245. {metalist-0.13.0 → metalist-0.14.0}/app/services/sync_state.py +0 -0
  246. {metalist-0.13.0 → metalist-0.14.0}/app/services/tag_case.py +0 -0
  247. {metalist-0.13.0 → metalist-0.14.0}/app/services/tag_ontology.py +0 -0
  248. {metalist-0.13.0 → metalist-0.14.0}/app/services/tag_rename.py +0 -0
  249. {metalist-0.13.0 → metalist-0.14.0}/app/services/tag_suggestions.py +0 -0
  250. {metalist-0.13.0 → metalist-0.14.0}/app/services/tag_term_matching.py +0 -0
  251. {metalist-0.13.0 → metalist-0.14.0}/app/services/test_reset.py +0 -0
  252. {metalist-0.13.0 → metalist-0.14.0}/app/services/tokens.py +0 -0
  253. {metalist-0.13.0 → metalist-0.14.0}/app/services/undo_state.py +0 -0
  254. {metalist-0.13.0 → metalist-0.14.0}/app/services/update_backups.py +0 -0
  255. {metalist-0.13.0 → metalist-0.14.0}/app/services/update_installer.py +0 -0
  256. {metalist-0.13.0 → metalist-0.14.0}/app/services/update_preflight.py +0 -0
  257. {metalist-0.13.0 → metalist-0.14.0}/app/services/view_cache.py +0 -0
  258. {metalist-0.13.0 → metalist-0.14.0}/app/services/view_diff.py +0 -0
  259. {metalist-0.13.0 → metalist-0.14.0}/app/services/view_state.py +0 -0
  260. {metalist-0.13.0 → metalist-0.14.0}/app/services/windows_process_control.py +0 -0
  261. {metalist-0.13.0 → metalist-0.14.0}/app/startup_environment.py +0 -0
  262. {metalist-0.13.0 → metalist-0.14.0}/app/startup_js_sanity.py +0 -0
  263. {metalist-0.13.0 → metalist-0.14.0}/app/startup_sanity.py +0 -0
  264. {metalist-0.13.0 → metalist-0.14.0}/app/startup_sanity_config.py +0 -0
  265. {metalist-0.13.0 → metalist-0.14.0}/app/static/css/floating-notes.css +0 -0
  266. {metalist-0.13.0 → metalist-0.14.0}/app/static/css/forms.css +0 -0
  267. {metalist-0.13.0 → metalist-0.14.0}/app/static/img/favicon.ico +0 -0
  268. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/activity-tracker.js +0 -0
  269. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/ai-chat/agent-menu-actions.js +0 -0
  270. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/ai-chat/agent-retrieval-settings.js +0 -0
  271. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/ai-chat/agent-web-settings.js +0 -0
  272. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/ai-chat/ai-agent-debug-view.js +0 -0
  273. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/ai-chat/ai-chat-api.js +0 -0
  274. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/ai-chat/ai-chat-message-placement.js +0 -0
  275. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/ai-chat/ai-chat-panel-service.js +0 -0
  276. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/ai-chat/ai-thinking-level-service.js +0 -0
  277. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/ai-chat/bulk-elapsed-clock.js +0 -0
  278. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/ai-chat/bulk-proposal-ui.js +0 -0
  279. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/ai-chat/bulk-scope-question.js +0 -0
  280. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/ai-chat/cloud-privacy-policy.js +0 -0
  281. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/ai-chat/confirmation-card.js +0 -0
  282. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/ai-chat/confirmation-question.js +0 -0
  283. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/ai-chat/proposal-menu.js +0 -0
  284. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/ai-chat/summary-batch-preview.js +0 -0
  285. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/api-error-diagnostics.js +0 -0
  286. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/api-failure-classification-service.js +0 -0
  287. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/app-update-service.js +0 -0
  288. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/application-state.js +0 -0
  289. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/async-result.js +0 -0
  290. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/client-state-api.js +0 -0
  291. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/client-state-migration.js +0 -0
  292. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/command-palette/activation-auth-policy.js +0 -0
  293. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/command-palette/backup-command-availability.js +0 -0
  294. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/command-palette/click-activation-service.js +0 -0
  295. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/command-palette/note-layout-preferences.js +0 -0
  296. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/command-palette/tag-config-loader.js +0 -0
  297. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/command-palette/usage-store.js +0 -0
  298. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/connectivity-monitor.js +0 -0
  299. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/context-menu/context-menu-registry.js +0 -0
  300. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/context-menu/context-menu-service.js +0 -0
  301. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/context-menu/context-menu-target-service.js +0 -0
  302. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/context-menu/input-caret-service.js +0 -0
  303. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/disconnect-editing-state-service.js +0 -0
  304. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/dom-utils-fixed.js +0 -0
  305. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/dom-utils.js +0 -0
  306. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/editor-commands.js +0 -0
  307. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/editor-selection.js +0 -0
  308. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/editor-toolbar.js +0 -0
  309. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/elapsed-time.js +0 -0
  310. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/error-handler.js +0 -0
  311. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/error-overlay.js +0 -0
  312. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/excalidraw/excalidraw-actions.js +0 -0
  313. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/excalidraw/excalidraw-autosave.js +0 -0
  314. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/excalidraw/excalidraw-editor-service.js +0 -0
  315. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/excalidraw/excalidraw-editor-state.js +0 -0
  316. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/excalidraw/excalidraw-loader.js +0 -0
  317. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/excalidraw/excalidraw-preview-service.js +0 -0
  318. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/excalidraw/excalidraw-scene.js +0 -0
  319. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/expected-errors.js +0 -0
  320. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/location-flags.js +0 -0
  321. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/login-namespace-picker.js +0 -0
  322. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/maintenance.js +0 -0
  323. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/ai-agent-settings-modal.js +0 -0
  324. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/alphabetize-root-notes-modal.js +0 -0
  325. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/backup-restore-modal.js +0 -0
  326. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/backup-result-modal.js +0 -0
  327. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/backup-retention-modal.js +0 -0
  328. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/backup-settings-modal.js +0 -0
  329. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/base-modal.js +0 -0
  330. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/confirmation-modal.js +0 -0
  331. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/delete-namespace-modal.js +0 -0
  332. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/delete-namespace-validation.js +0 -0
  333. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/dictation-settings-modal.js +0 -0
  334. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/help-modal.js +0 -0
  335. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/namespace-loading-page.js +0 -0
  336. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/namespace-modals.js +0 -0
  337. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/namespace-ports-profile.js +0 -0
  338. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/namespace-rename-validation.js +0 -0
  339. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/note-layout-appearance-modal.js +0 -0
  340. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/ontology-modal.js +0 -0
  341. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/password-modal.js +0 -0
  342. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/prioritize-modal.js +0 -0
  343. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/random-password-modal.js +0 -0
  344. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/reminder-modal.js +0 -0
  345. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/reset-updated-at-modal.js +0 -0
  346. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/search-suggestion-statistics-modal.js +0 -0
  347. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/session-timeout-modal.js +0 -0
  348. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/version-info-modal.js +0 -0
  349. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/modals/visual-cues-modal.js +0 -0
  350. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/actions/content-actions.js +0 -0
  351. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/actions/history-actions.js +0 -0
  352. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/actions/note-actions.js +0 -0
  353. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/actions/search-actions.js +0 -0
  354. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/actions/selection-actions.js +0 -0
  355. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/actions/ui-actions.js +0 -0
  356. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/events/context-menu-events.js +0 -0
  357. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/events/focus-events.js +0 -0
  358. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/events/inactivity-events.js +0 -0
  359. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/events/input-events.js +0 -0
  360. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/events/keyboard-events.js +0 -0
  361. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/events/mouse-events.js +0 -0
  362. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/events/search-events.js +0 -0
  363. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/mode-context.js +0 -0
  364. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/mode-logger.js +0 -0
  365. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/mode-manager-controller.js +0 -0
  366. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/add-style-service.js +0 -0
  367. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/animated-scroll-service.js +0 -0
  368. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/backlinks-navigation-service.js +0 -0
  369. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/backlinks-panel-service.js +0 -0
  370. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/clipboard-shortcut-policy-service.js +0 -0
  371. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/collapse-affordance-service.js +0 -0
  372. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/collapse-editing-policy-service.js +0 -0
  373. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/command-gate-service.js +0 -0
  374. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/context-menu-target-service.js +0 -0
  375. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/deselect-selection-state-service.js +0 -0
  376. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/dictation-note-paste.js +0 -0
  377. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/dictation-paste-padding.js +0 -0
  378. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/differential-view-service.js +0 -0
  379. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/dropped-file-preview-service.js +0 -0
  380. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/edit-session-collapse-policy-service.js +0 -0
  381. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/edit-session-collapse-service.js +0 -0
  382. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/embedded-image-service.js +0 -0
  383. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/file-drop-policy-service.js +0 -0
  384. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/file-image-preview-service.js +0 -0
  385. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/file-reference-service.js +0 -0
  386. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/filtered-refresh-selection-service.js +0 -0
  387. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/floating-note-dom.js +0 -0
  388. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/floating-note-layout.js +0 -0
  389. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/floating-note-service.js +0 -0
  390. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/footnote-navigation-service.js +0 -0
  391. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/history-selection-policy-service.js +0 -0
  392. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/history-shortcut-policy-service.js +0 -0
  393. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/html-paste-sanitizer-service.js +0 -0
  394. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/image-context-menu-action-service.js +0 -0
  395. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/image-file-insert-choice-modal-service.js +0 -0
  396. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/infinite-scroll-service.js +0 -0
  397. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/link-context-menu-action-service.js +0 -0
  398. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/link-title-prefetch-service.js +0 -0
  399. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/markdown-render-service.js +0 -0
  400. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/mermaid-render-service.js +0 -0
  401. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/note-click-target-service.js +0 -0
  402. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/note-clipboard-write-service.js +0 -0
  403. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/note-collapse-animation-service.js +0 -0
  404. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/note-context-menu-action-service.js +0 -0
  405. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/note-delete-shortcut-policy-service.js +0 -0
  406. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/note-drag-indicator-service.js +0 -0
  407. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/note-drag-service.js +0 -0
  408. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/note-fullscreen-service.js +0 -0
  409. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/note-reposition-animation-service.js +0 -0
  410. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/note-split-service.js +0 -0
  411. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/note-timestamp-hover-service.js +0 -0
  412. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/password-clipboard-service.js +0 -0
  413. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/polling-service.js +0 -0
  414. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/remote-image-proxy-service.js +0 -0
  415. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/remove-formatting-service.js +0 -0
  416. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/root-date-separator-service.js +0 -0
  417. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/root-note-creation-service.js +0 -0
  418. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/root-sort-indicator-service.js +0 -0
  419. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/root-sort-service.js +0 -0
  420. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/scroll-anchor-service.js +0 -0
  421. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/scroll-restoration-service.js +0 -0
  422. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/scroll-to-top-service.js +0 -0
  423. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/search-contexts-overlay-service.js +0 -0
  424. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/search-debounce-service.js +0 -0
  425. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/search-input-service.js +0 -0
  426. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/search-interaction-service.js +0 -0
  427. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/search-redaction-reveal-service.js +0 -0
  428. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/search-suggestion-statistics-service.js +0 -0
  429. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/search-suggestion-window-labels-service.js +0 -0
  430. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/search-suggestion-windows-service.js +0 -0
  431. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/search-suggestions-service.js +0 -0
  432. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/selected-formatting-removal-service.js +0 -0
  433. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/selected-text-tag-service.js +0 -0
  434. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/shell-output-service.js +0 -0
  435. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/tab-dom-cache-service.js +0 -0
  436. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/tab-drag-service.js +0 -0
  437. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/tab-duplication-service.js +0 -0
  438. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/tab-state-service.js +0 -0
  439. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/tag-bar-service.js +0 -0
  440. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/tag-input-selection-service.js +0 -0
  441. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/tag-proposal-service.js +0 -0
  442. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/tag-suggestions-service.js +0 -0
  443. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/tag-syntax-service.js +0 -0
  444. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/todo-toggle-editing-service.js +0 -0
  445. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/untagged-view-indicator-service.js +0 -0
  446. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/view-mode-search-shortcut-service.js +0 -0
  447. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/mode-manager/services/viewport-hold-service.js +0 -0
  448. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/note-html-sanitizer.js +0 -0
  449. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/password-generator.js +0 -0
  450. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/password-operation-response.js +0 -0
  451. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/password-policy.js +0 -0
  452. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/password-strength.js +0 -0
  453. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/reminder-store.js +0 -0
  454. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/reminder-surface-service.js +0 -0
  455. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/selection-markers.js +0 -0
  456. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/session-auth.js +0 -0
  457. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/tag-token.js +0 -0
  458. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/modules/uuid.js +0 -0
  459. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/namespace-deleted.js +0 -0
  460. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/namespace-renamed.js +0 -0
  461. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/dompurify-3.4.16.LICENSE.txt +0 -0
  462. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/dompurify-3.4.16.min.js +0 -0
  463. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/excalidraw.css +0 -0
  464. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Bold.woff2 +0 -0
  465. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Medium.woff2 +0 -0
  466. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Regular.woff2 +0 -0
  467. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-SemiBold.woff2 +0 -0
  468. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Cascadia/CascadiaCode-Regular.woff2 +0 -0
  469. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2 +0 -0
  470. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2 +0 -0
  471. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2 +0 -0
  472. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2 +0 -0
  473. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2 +0 -0
  474. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2 +0 -0
  475. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2 +0 -0
  476. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2 +0 -0
  477. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2 +0 -0
  478. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2 +0 -0
  479. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2 +0 -0
  480. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2 +0 -0
  481. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2 +0 -0
  482. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2 +0 -0
  483. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2 +0 -0
  484. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2 +0 -0
  485. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2 +0 -0
  486. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2 +0 -0
  487. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Virgil/Virgil-Regular.woff2 +0 -0
  488. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1.LICENSE.txt +0 -0
  489. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/excalidraw-0.18.1.min.js +0 -0
  490. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/markdown-it-14.3.2.LICENSE.txt +0 -0
  491. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/markdown-it-14.3.2.min.js +0 -0
  492. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/mermaid-11.16.1.LICENSE.txt +0 -0
  493. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/mermaid-11.16.1.min.js +0 -0
  494. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/zxcvbn-4.4.2.LICENSE.txt +0 -0
  495. {metalist-0.13.0 → metalist-0.14.0}/app/static/js/vendor/zxcvbn-4.4.2.js +0 -0
  496. {metalist-0.13.0 → metalist-0.14.0}/app/static/note-html-policy.json +0 -0
  497. {metalist-0.13.0 → metalist-0.14.0}/app/templates/maintenance.html +0 -0
  498. {metalist-0.13.0 → metalist-0.14.0}/app/templates/namespace_deleted.html +0 -0
  499. {metalist-0.13.0 → metalist-0.14.0}/app/templates/namespace_renamed.html +0 -0
  500. {metalist-0.13.0 → metalist-0.14.0}/app/templates/notes_list.html +0 -0
  501. {metalist-0.13.0 → metalist-0.14.0}/app/upload_limits.py +0 -0
  502. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/__init__.py +0 -0
  503. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/add_selected_text_tag.py +0 -0
  504. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/alphabetize_root_notes.py +0 -0
  505. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/base.py +0 -0
  506. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/bulk_tag_proposals.py +0 -0
  507. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/collapse.py +0 -0
  508. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/copy_note.py +0 -0
  509. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/create_child.py +0 -0
  510. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/create_file_preview_child.py +0 -0
  511. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/create_note.py +0 -0
  512. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/create_sibling.py +0 -0
  513. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/delete_subtree.py +0 -0
  514. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/delete_tag.py +0 -0
  515. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/expand.py +0 -0
  516. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/file_edit_session.py +0 -0
  517. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/indent.py +0 -0
  518. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/lock.py +0 -0
  519. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/move.py +0 -0
  520. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/move_to_top.py +0 -0
  521. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/outdent.py +0 -0
  522. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/paste_child.py +0 -0
  523. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/paste_sibling.py +0 -0
  524. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/prefetch_link_titles.py +0 -0
  525. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/prioritize.py +0 -0
  526. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/redo.py +0 -0
  527. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/rename_tag.py +0 -0
  528. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/reset_updated_at.py +0 -0
  529. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/resize_image.py +0 -0
  530. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/run_shell.py +0 -0
  531. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/search_comment_autofill.py +0 -0
  532. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/search_context_tags.py +0 -0
  533. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/set_collapse_bulk.py +0 -0
  534. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/set_collapse_in_context.py +0 -0
  535. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/split_note.py +0 -0
  536. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/tag_proposals.py +0 -0
  537. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/toggle_reference_mode.py +0 -0
  538. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/toggle_todo_done.py +0 -0
  539. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/undo.py +0 -0
  540. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/unformat_content.py +0 -0
  541. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/update_content.py +0 -0
  542. {metalist-0.13.0 → metalist-0.14.0}/app/usecases/view.py +0 -0
  543. {metalist-0.13.0 → metalist-0.14.0}/app/utils/__init__.py +0 -0
  544. {metalist-0.13.0 → metalist-0.14.0}/app/utils/encryption.py +0 -0
  545. {metalist-0.13.0 → metalist-0.14.0}/convert-from-legacy.py +0 -0
  546. {metalist-0.13.0 → metalist-0.14.0}/metalist.egg-info/dependency_links.txt +0 -0
  547. {metalist-0.13.0 → metalist-0.14.0}/metalist.egg-info/entry_points.txt +0 -0
  548. {metalist-0.13.0 → metalist-0.14.0}/metalist.egg-info/top_level.txt +0 -0
  549. {metalist-0.13.0 → metalist-0.14.0}/scripts/generate-lan-cert.sh +0 -0
  550. {metalist-0.13.0 → metalist-0.14.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metalist
3
- Version: 0.13.0
3
+ Version: 0.14.0
4
4
  Summary: A minimalist single-user note-taking app with SSR, fast in-memory tree operations, and efficient sync.
5
5
  Project-URL: Homepage, https://github.com/evolvingstuff/metalist
6
6
  Project-URL: Repository, https://github.com/evolvingstuff/metalist
@@ -23,6 +23,7 @@ Requires-Dist: pydantic==2.13.4
23
23
  Requires-Dist: pypdf==6.19.0
24
24
  Requires-Dist: python-dotenv==1.2.2
25
25
  Requires-Dist: python-multipart==0.0.32
26
+ Requires-Dist: rich==14.3.4
26
27
  Requires-Dist: starlette==1.3.1
27
28
  Requires-Dist: tqdm==4.70.0
28
29
  Requires-Dist: tree-sitter==0.25.2
@@ -49,6 +50,15 @@ A minimalist single-user note-taking app focused on server-side rendering (SSR),
49
50
  - Multi-tab search contexts with server-persisted scroll/search state (survives browser restarts)
50
51
  - Manual namespace backups/restores to a user-selected backup folder with retention controls
51
52
 
53
+ ## Changes in 0.14.0
54
+
55
+ - A new login screen: one dark screen with the MetaList logo. The namespace, password and OK fade in together; once the password is accepted, the loading progress slides in with the current step and the seconds elapsed. When the first login after an update backs up and upgrades the namespace, a note under OK says so. The Session locked page has the same look, and there is no white flash between them.
56
+ - Web link titles: links to Reddit (including share links), YouTube, Vimeo, TikTok, Spotify and SoundCloud get their real titles. Lookups are paced per site, so a note full of links no longer trips a site's rate limit. Login, consent and site-name-only titles ("Sign in", "Reddit") show the link instead. The new command palette action Retry failed link titles asks every failed link again, with a progress dialog.
57
+ - Quoted search also matches link titles and the URLs hidden behind link labels, and the AI sees those URLs too. Pasting into a quoted search inserts the text as copied.
58
+ - `[[note id]]` is always a link, even in a note with a `[[ ]]` formatting tag.
59
+ - The startup output in the terminal is easier to read: the version, a check mark per check, and each namespace's URLs lined up.
60
+ - Fixed: clicking the AI chat's $ or eye button twice quickly crashed with "Redundant state change".
61
+
52
62
  ## Changes in 0.13.0
53
63
 
54
64
  - Dictation: text from speech-to-text tools such as Superwhisper, pasted into the search bar or any tag field, becomes your existing tags ("neural network" gives `neural-network`). Say "quote … end quote" for text, "minus" to exclude, "at" before meta tags such as `@todo`. In a note, the words after "start tags" go to its tag bar. The phrases are set in Dictation Settings, and one undo restores what was pasted.
@@ -12,6 +12,15 @@ 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.14.0
16
+
17
+ - A new login screen: one dark screen with the MetaList logo. The namespace, password and OK fade in together; once the password is accepted, the loading progress slides in with the current step and the seconds elapsed. When the first login after an update backs up and upgrades the namespace, a note under OK says so. The Session locked page has the same look, and there is no white flash between them.
18
+ - Web link titles: links to Reddit (including share links), YouTube, Vimeo, TikTok, Spotify and SoundCloud get their real titles. Lookups are paced per site, so a note full of links no longer trips a site's rate limit. Login, consent and site-name-only titles ("Sign in", "Reddit") show the link instead. The new command palette action Retry failed link titles asks every failed link again, with a progress dialog.
19
+ - Quoted search also matches link titles and the URLs hidden behind link labels, and the AI sees those URLs too. Pasting into a quoted search inserts the text as copied.
20
+ - `[[note id]]` is always a link, even in a note with a `[[ ]]` formatting tag.
21
+ - The startup output in the terminal is easier to read: the version, a check mark per check, and each namespace's URLs lined up.
22
+ - Fixed: clicking the AI chat's $ or eye button twice quickly crashed with "Redundant state change".
23
+
15
24
  ## Changes in 0.13.0
16
25
 
17
26
  - Dictation: text from speech-to-text tools such as Superwhisper, pasted into the search bar or any tag field, becomes your existing tags ("neural network" gives `neural-network`). Say "quote … end quote" for text, "minus" to exclude, "at" before meta tags such as `@todo`. In a note, the words after "start tags" go to its tag bar. The phrases are set in Dictation Settings, and one undo restores what was pasted.
@@ -41,6 +41,7 @@ class AuthMiddleware(BaseHTTPMiddleware):
41
41
  NO_TOKEN_REFRESH_PATHS = [
42
42
  f"{API_PREFIX}/auth/status", # Polling service pings this for connectivity
43
43
  f"{API_PREFIX}/reminders/evaluate", # Reminder polling is not user-initiated activity
44
+ f"{API_PREFIX}/notes/link-titles/retry", # The retry dialog polls its progress
44
45
  ]
45
46
 
46
47
  # Note: /api/notes/* paths are NOT in this list - they require auth when password is set
@@ -97,6 +97,7 @@ from app.services.client_state_service import save_client_preferences
97
97
  from app.services.client_state_service import save_command_palette_usage
98
98
  from app.services.openai_credentials import openai_credential_store
99
99
  from app.services.input_errors import NamespaceInputRejected
100
+ from app.services.link_title_retry import stop_link_title_retry
100
101
 
101
102
 
102
103
  router = APIRouter(prefix="/auth", tags=["auth2"])
@@ -595,6 +596,9 @@ def logout(
595
596
  openai_credential_store.clear_session(session_key=session_key)
596
597
  token_service.revoke_token(token)
597
598
  shell_session_service.reset()
599
+ # Lock and login end a retry through the runtime generation; a passwordless
600
+ # logout does not change it, so stop the retry here.
601
+ stop_link_title_retry()
598
602
  view_cache.clear()
599
603
  reset_all_undo_state()
600
604
  reset_sync_state()
@@ -712,6 +716,8 @@ def auth_status(
712
716
  return {
713
717
  "version": VERSION,
714
718
  "database_user_version": database_user_version,
719
+ # The next login backs up and upgrades this database (the login screen says so).
720
+ "database_upgrade_pending": database_user_version < CURRENT_DATABASE_VERSION,
715
721
  "authenticated": token is not None,
716
722
  # Same answer as AuthService.has_password(), from the row already read.
717
723
  "has_password": settings is not None and bool(settings.encryption_enabled),
@@ -68,6 +68,11 @@ from app.usecases.create_child import CmdCreateChild
68
68
  from app.usecases.create_file_preview_child import CmdCreateFilePreviewChild
69
69
  from app.usecases.update_content import CmdUpdateContent
70
70
  from app.usecases.prefetch_link_titles import CmdPrefetchLinkTitles
71
+ from app.services.link_title_retry import (
72
+ link_title_retry_snapshot,
73
+ start_link_title_retry,
74
+ stop_link_title_retry,
75
+ )
71
76
  from app.usecases.add_selected_text_tag import CmdAddSelectedTextTag
72
77
  from app.usecases.tag_proposals import (
73
78
  CmdAcceptTagProposal,
@@ -159,6 +164,26 @@ def prefetch_link_titles(request: Request, draft: LinkTitlePrefetchRequest) -> d
159
164
  return CmdPrefetchLinkTitles(content=draft.content, tags=draft.tags).execute()
160
165
 
161
166
 
167
+ @router.get("/notes/link-titles/retry")
168
+ def link_title_retry_progress(request: Request) -> dict[str, object]:
169
+ require_request_auth_token(request)
170
+ return link_title_retry_snapshot()
171
+
172
+
173
+ @router.post("/notes/link-titles/retry")
174
+ @transactional_route
175
+ def start_link_title_retry_route(request: Request) -> dict[str, object]:
176
+ require_request_auth_token(request)
177
+ return start_link_title_retry()
178
+
179
+
180
+ @router.post("/notes/link-titles/retry/stop")
181
+ @transactional_route
182
+ def stop_link_title_retry_route(request: Request) -> dict[str, object]:
183
+ require_request_auth_token(request)
184
+ return stop_link_title_retry()
185
+
186
+
162
187
  def _require_note_present(note_id: str, *, context: str) -> None:
163
188
  if not isinstance(context, str) or not context:
164
189
  raise ValueError("context must be a non-empty string")
@@ -45,7 +45,6 @@ def _env_int(name: str, default: int) -> int:
45
45
  CRASH_SERVER_ON_FAIL = _env_flag("CRASH_SERVER_ON_FAIL", True)
46
46
  DEV_ENFORCE_INTEGRITY_CHECKS = _env_flag("DEV_ENFORCE_INTEGRITY_CHECKS", False)
47
47
  DISABLE_UNDO_SNAPSHOT = _env_flag("DISABLE_UNDO_SNAPSHOT", True)
48
- STARTUP_ANIMATION_ENABLED = _env_flag("STARTUP_ANIMATION_ENABLED", False)
49
48
 
50
49
  # Tag suggestions
51
50
  TAG_SUGGESTION_CONNECTORS = "-_/."
@@ -94,6 +94,20 @@ class EncryptionAuditReport:
94
94
  def startup_allowed(self) -> bool:
95
95
  return self.namespace_count > 0 and len(self.fatal_findings) == 0
96
96
 
97
+ def namespace_statuses(self) -> list[tuple[str, str]]:
98
+ """(namespace, PASS | MIGRATION REQUIRED | FAIL | SKIPPED (not encrypted)) per namespace."""
99
+ statuses: list[tuple[str, str]] = []
100
+ for result in self.results:
101
+ result_status = "SKIPPED (not encrypted)"
102
+ if result.is_encrypted:
103
+ result_status = "PASS"
104
+ if result.findings:
105
+ result_status = "MIGRATION REQUIRED"
106
+ if any(not finding.is_migration_deferred for finding in result.findings):
107
+ result_status = "FAIL"
108
+ statuses.append((result.namespace, result_status))
109
+ return statuses
110
+
97
111
  def render_text(self) -> str:
98
112
  status = "FAIL"
99
113
  if self.passed:
@@ -110,15 +124,8 @@ class EncryptionAuditReport:
110
124
  ),
111
125
  f"Sensitive payloads checked: {self.checked_payload_count}",
112
126
  ]
113
- for result in self.results:
114
- result_status = "SKIPPED (not encrypted)"
115
- if result.is_encrypted:
116
- result_status = "PASS"
117
- if result.findings:
118
- result_status = "MIGRATION REQUIRED"
119
- if any(not finding.is_migration_deferred for finding in result.findings):
120
- result_status = "FAIL"
121
- lines.append(f"- {result.namespace}: {result_status}")
127
+ for namespace, result_status in self.namespace_statuses():
128
+ lines.append(f"- {namespace}: {result_status}")
122
129
  if self.findings:
123
130
  lines.append("Findings:")
124
131
  for finding in self.findings:
@@ -26,6 +26,8 @@ CAPTURE_BOUNDARIES = {
26
26
  'app/api/routes/app_updates.py:update_status:lookup': ('AppUpdateRejected', 'FileNotFoundError'),
27
27
  # Release smoke polls only its own disposable HTTP listeners during an actual update.
28
28
  'scripts/smoke_self_update.py:_has_updated_namespace:probe_capture': ('HTTPError',),
29
+ # Release smoke cleanup: on Windows an exiting process refuses termination; the wait then checks it stopped.
30
+ 'scripts/smoke_installed_package.py:_terminate_on_windows:exit_capture': ('ProcessLookupError', 'PermissionError'),
29
31
  # A child can exit between poll and terminate; hung children must be killed and reaped.
30
32
  'app/services/namespace_switcher.py:_stop_failed_namespace_launch:terminate_capture': ('ProcessLookupError',),
31
33
  'app/services/namespace_switcher.py:_stop_failed_namespace_launch:wait_capture': ('TimeoutExpired',),
@@ -125,6 +127,12 @@ CAPTURE_BOUNDARIES = {
125
127
  # Handle expected external I/O, provider, image or LaTeX parsing failure.
126
128
  'app/services/link_titles.py:fetch_link_title:target_capture': ('PublicHttpTargetRejected',),
127
129
  # Handle expected external I/O, provider, image or LaTeX parsing failure.
130
+ 'app/services/link_titles.py:_fetch_oembed_title:target_capture': ('PublicHttpTargetRejected',),
131
+ # Handle expected external I/O, provider, image or LaTeX parsing failure.
132
+ 'app/services/link_titles.py:_fetch_oembed_title:json_capture': ('JSONDecodeError', 'UnicodeDecodeError'),
133
+ # Handle expected external I/O, provider, image or LaTeX parsing failure.
134
+ 'app/services/link_titles.py:_download_oembed:capture': ('TimeoutException', 'NetworkError', 'HTTPError', 'TimeoutException', 'NetworkError', 'ProtocolError'),
135
+ # Handle expected external I/O, provider, image or LaTeX parsing failure.
128
136
  'app/services/namespace_deletion_worker.py:_is_process_running:kill_capture': ('ProcessLookupError', 'PermissionError'),
129
137
  # Handle expected external I/O, provider, image or LaTeX parsing failure.
130
138
  'app/services/namespace_deletion_worker.py:_send_signal_if_running:signal_capture': ('ProcessLookupError',),
@@ -16,7 +16,7 @@ from app.api.upload_limits import UploadLimitMiddleware
16
16
  from app.presentation.templates import get_templates
17
17
  from .api import dev
18
18
  from .api.middleware.auth import AuthMiddleware
19
- from app.config import ACTIVE_NAMESPACE, STARTUP_ANIMATION_ENABLED, VERSION
19
+ from app.config import ACTIVE_NAMESPACE, VERSION
20
20
  from .db.session import begin_writer, enable_read_guard
21
21
  from .db.schema import initialize_schema
22
22
  from .db.migrations import CURRENT_DATABASE_VERSION
@@ -61,6 +61,7 @@ from app.services.diagnostics import track_request
61
61
  from app.services.diagnostics import write_encrypted_exception_trace
62
62
  from app.security.sensitive_logging import traceback_frame_summary
63
63
  from app.api.request_auth import clear_auth_cookie
64
+ from app.presentation.login_page import login_is_certainly_needed
64
65
  from app.api.routes.notes import router as api2_router
65
66
  from app.api.routes.auth import router as api2_auth_router
66
67
  from app.api.routes.app_updates import router as api2_app_updates_router
@@ -463,7 +464,7 @@ async def home(request: Request, db: Annotated[SafeSession, Depends(get_db)]):
463
464
  asset_version=ASSET_VERSION,
464
465
  page_title=_resolve_page_title(base_title="MetaList"),
465
466
  needs_auth=True,
466
- startup_animation_enabled=STARTUP_ANIMATION_ENABLED,
467
+ shows_login_at_once=login_is_certainly_needed(request),
467
468
  )
468
469
  return template.render(
469
470
  request=request,
@@ -472,10 +473,11 @@ async def home(request: Request, db: Annotated[SafeSession, Depends(get_db)]):
472
473
  asset_version=ASSET_VERSION,
473
474
  page_title=_resolve_page_title(base_title="MetaList"),
474
475
  needs_auth=False,
475
- startup_animation_enabled=STARTUP_ANIMATION_ENABLED,
476
+ shows_login_at_once=False,
476
477
  )
477
478
 
478
479
 
480
+
479
481
  @app.get("/maintenance", response_class=HTMLResponse)
480
482
  async def maintenance_page(request: Request):
481
483
  """Maintenance mode page shown during bulk operations."""
@@ -0,0 +1,18 @@
1
+ """Whether the page opens straight on the login screen (docs/AI-SUMMARY.md, Login screen)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from starlette.requests import Request
6
+
7
+ from app.api.request_auth import AUTH_COOKIE_NAME
8
+
9
+
10
+ def login_is_certainly_needed(request: Request) -> bool:
11
+ """Whether a password namespace's page can open on the login screen at once,
12
+ with no white page before the browser checks its session: a re-login was asked
13
+ for (the Session locked page's Go to Login), or the browser has no session."""
14
+ if not isinstance(request, Request):
15
+ raise TypeError("request must be a Request")
16
+ if request.query_params.get("force_reauth") == "1":
17
+ return True
18
+ return request.cookies.get(AUTH_COOKIE_NAME) is None
@@ -47,6 +47,8 @@ fixed rules, no AI, and it only reacts to pasting: typed text is never changed.
47
47
  exclusion phrase ("minus" by default) excludes the next term ("neural network
48
48
  minus python" gives `neural-network -python`), and a quoted phrase becomes a text
49
49
  search. "not" is an ordinary word unless it is set as the exclusion phrase.
50
+ With the cursor inside a quoted phrase (after `"`), a paste is not cleaned up:
51
+ it goes in exactly as copied, on one line, with quote marks escaped.
50
52
  - **Tag bar:** words matching no tag become new tags, lowercased unless they look
51
53
  like an acronym (`GPT`). Each word is its own tag unless the words together match
52
54
  one of the user's tags; a new multi-word tag has to be typed.
@@ -41,11 +41,14 @@ Sources: docs/ui/content-formatting.md
41
41
  - Standalone bare URLs, pasted URL-only anchors, and Markdown URL-only links can render as compact cached title links (`title · domain`) when the server already has a successful title fetch for that URL. Custom link labels remain unchanged.
42
42
  - Compact note-reference previews reuse the same standalone URL rule, including collapsed embeds and expanded embed source links.
43
43
  - Unknown, failed, unsupported, or inline URLs render as raw URL links exactly as before. Failed standalone lookups can expose their status/retry timing through the browser's normal hover tooltip.
44
+ - Lookups are polite to each site (the hostname without `www.`): one request to a site at a time, at least 2 seconds apart, so a note full of links to one site does not trip its rate limit. A site that answers HTTP 429 (too many requests) is left alone for its `Retry-After` time (1 minute to 6 hours; 10 minutes when it gives none), and lookups of its other links wait until then without being recorded as failures. The rate-limited link itself is retried after 10 minutes, 1 hour, 6 hours, 1 day, then weekly.
44
45
  - Title fetches are server-side background work; note rendering never waits on network I/O, and edit mode always shows the original stored URL. When background fetches complete, the server increments a link-title revision exposed by `/api2/auth/status`; the browser polling loop batches those changes and triggers a view refresh so newly resolved titles appear without a manual page reload.
45
46
  - While editing, the existing 500 ms inactivity check observes the current draft and requests title prefetch after it remains unchanged for at least 600 ms (typically 1–1.5 seconds after input). `POST /api2/notes/link-titles/prefetch` uses the same view-formatting eligibility and background fetch cache without saving the draft or replacing editor HTML. Identical drafts are requested once per editing session; typing and pasting restart the pause.
46
47
  - Leaving edit mode always completes a view refresh, including when another view request is in flight. Title revision refreshes defer while editing, then require a refresh so slower lookups appear automatically without disturbing typing.
47
- - Title extraction is generic HTML metadata parsing (`og:title`, `twitter:title`, `meta name=title`, `itemprop=name`, and `<title>`). It does not use domain-specific APIs.
48
- - Challenge/interstitial titles such as verification, browser-check, or access-denied pages are treated as `no_title` and cleared from existing cache rows on startup/login so they fall back to the raw URL instead of being displayed as valid page titles.
48
+ - Links to Reddit, YouTube (including `youtu.be`), Vimeo, TikTok, Spotify and SoundCloud first ask the site's public oEmbed service, the preview service those sites provide, for the title. It gives the real post or video title where the page itself is blocked for automated requests or built by JavaScript. The request is paced like any request to that site. A link that forwards elsewhere (a Reddit share link such as `/r/…/s/…` forwards to its post) is also looked up at each address it forwards to. When the service has no usable answer (not a post or video, removed, private), the page is read as for any other site. X is not included: its oEmbed service returns no title.
49
+ - Otherwise, title extraction is generic HTML metadata parsing (`og:title`, `twitter:title`, `meta name=title`, `itemprop=name`, and `<title>`).
50
+ - A title that is only the site's name ("Reddit" for reddit.com, "YouTube", "BBC" for bbc.co.uk, or the domain itself) says nothing the domain does not; it is treated as no title, so the link shows its URL (Reddit's URLs name the subreddit and post). Reddit's generic page titles ("Reddit - Dive into anything") count as no title too. Saved ones are cleared at the next login.
51
+ - Challenge/interstitial titles such as verification, browser-check, or access-denied pages are treated as `no_title` and cleared from existing cache rows on startup/login so they fall back to the raw URL instead of being displayed as valid page titles. So are login, consent and not-found pages, also when the site adds its name: a title is split at the site-name separators (`|`, `·`, `–`, `—`, and ` - ` with spaces) and is not a real title when a part is only a phrase such as "Sign in", "Log in", "Sign up" or "Page not found" ("Sign in - Google Accounts", "Log in | LinkedIn"), or when it contains "before you continue" (YouTube's consent page) or "log in or sign up". Titles that merely mention these words ("How to sign in to Gmail") are kept.
49
52
  - Existing rendered anchors are normalized to open in a new browser tab.
50
53
  - Clicking a rendered note link (including its title/domain spans) leaves the note in view mode; links do not initiate note dragging. Links inside the active editor keep normal editing behavior.
51
54
  - Internal hash-style anchors used by MetaList note-reference UI are left unchanged so in-app reference navigation still works.
@@ -56,7 +59,7 @@ Sources: docs/ui/content-formatting.md
56
59
  - Depth 1–3 is supported (e.g. `{{{...}}}`).
57
60
  - Wrappers in content are **only consumed/hidden** in view mode when there is a matching *scoped wrapper tag* in the tag bar.
58
61
  - If there is **no matching scoped wrapper tag**, wrappers are treated as literal text and remain visible even out of edit mode.
59
- - When a matching `[[...]]` scoped wrapper tag is active, that wrapper is treated as formatting syntax instead of a UUID link reference. `![[UUID]]` still renders as an embedded reference.
62
+ - When a matching `[[...]]` scoped wrapper tag is active, `[[...]]` is formatting syntax, except that `[[UUID]]` containing exactly a note or file UUID is always a link. `![[UUID]]` still renders as an embedded reference.
60
63
 
61
64
  Scoped wrapper tags do not need to be meta tags:
62
65
  - Example: tag bar `[foo]` causes all `[...]` regions in the note to render without the brackets in view mode.
@@ -96,6 +96,7 @@ Opening or dismissing the command palette does not clear undo/redo. Global actio
96
96
  - `Attach file`: opens the native file picker, uploads the selected file, and inserts an embedded file reference token into the current note. If no note is active, it creates a new note first.
97
97
  - `Add Excalidraw diagram`: attaches a new, empty Excalidraw diagram to the current note (or a new note when none is active) and opens the full-screen diagram editor.
98
98
  - `Trim unused files`: deletes file rows whose UUIDs are no longer referenced anywhere in note content. This is the only automatic cleanup path for orphaned attachments.
99
+ - `Retry failed link titles`: asks every web link whose title lookup failed (rate limited, refused, login or verification page, no title, timed out, page not found and other errors) again now. It opens a dialog saying how many links it would ask; nothing runs until its **Retry N links** button (or Enter). Unsupported links (such as PDFs) and private-network links are not retried. It uses the usual polite pacing: one request per site at a time, 2 seconds apart; a site that answers "too many requests" is skipped for the rest of the run and its links keep their normal retry schedule. The same dialog then shows progress: links asked, titles found, what still fails and why, and skipped sites. It does not block the app: closing the dialog (×, Escape or a click outside) leaves the retry running, and running the action again shows its progress instead of starting another. **Stop** drops the lookups not yet started; logging out, locking or logging in also stops it. Titles found appear in notes at the next view refresh.
99
100
  - `Prioritize tag to front (global)`: opens a warning modal with single-tag input and suggestions from all root notes. Applying it stably moves all matching root notes to the front of the global root order while preserving relative order inside the matching and non-matching groups. Cmd+Z cannot undo this action; the undo/redo queue is cleared.
100
101
  - `Prioritize tag to back (global)`: same as above, but stably moves all matching root notes to the back of the global root order.
101
102
  - `Alphabetize root notes A-Z (current view)`: after confirmation, permanently rearranges only root-level notes in the active search context by root-note content. Hidden roots and child notes are not reordered. Cmd+Z cannot undo this action; the undo/redo queue is cleared like a view-context switch.
@@ -112,6 +112,14 @@ loudly; known old-version issues may require authenticated migration. This is a
112
112
  storage-contract check, not proof of every disk byte being encrypted or a scan
113
113
  of all logs/backups/swap. It does not authenticate ciphertext without the key.
114
114
 
115
+ Logging in: the login screen shows the MetaList logo with the namespace dropdown,
116
+ the password field and OK. A wrong password shows the reason under OK without
117
+ leaving the form. After the password is accepted, a progress bar shows the
118
+ current loading step and the seconds elapsed. When a database upgrade is due,
119
+ "Backing up and upgrading this namespace…" appears under OK while it checks, and
120
+ that login takes longer. "Session locked" means the session moved to another tab
121
+ or device; Go to Login opens the login screen.
122
+
115
123
  The Add password, Change password, and Remove password menus open forms. Opening
116
124
  is not submitting. An encryption explanation alone does not request a form or a
117
125
  password change. Never ask for an actual password or API key in chat.
@@ -16,7 +16,7 @@ Sources: docs/ui/references.md
16
16
  - Implemented reference syntaxes:
17
17
  - `![[UUID]]` = embedded mode
18
18
  - `[[UUID]]` = link mode
19
- - If the note has a matching `[[...]]` scoped wrapper tag (for example `[[@LaTeX]]`), `[[...]]` is parsed as content formatting instead of link mode. Use `![[UUID]]` for embedded references in that case, or use a different formatting wrapper delimiter.
19
+ - `[[...]]` containing exactly a note or file UUID is always a link, even when the note has a matching `[[...]]` scoped wrapper tag (for example `[[@LaTeX]]`); other `[[...]]` text is formatted by that wrapper, and links nested inside it still render.
20
20
  - A UUID can resolve to:
21
21
  - a note
22
22
  - a file attachment
@@ -5,6 +5,15 @@ README. Changes made after the newest listed version are not described here.
5
5
  Compare with installed_version from the help lookup to tell the user whether
6
6
  they already have a release. Version info offers updates (see the data topic).
7
7
 
8
+ ## 0.14.0
9
+
10
+ - A new login screen: one dark screen with the MetaList logo. The namespace, password and OK fade in together; once the password is accepted, the loading progress slides in with the current step and the seconds elapsed. When the first login after an update backs up and upgrades the namespace, a note under OK says so. The Session locked page has the same look, and there is no white flash between them.
11
+ - Web link titles: links to Reddit (including share links), YouTube, Vimeo, TikTok, Spotify and SoundCloud get their real titles. Lookups are paced per site, so a note full of links no longer trips a site's rate limit. Login, consent and site-name-only titles ("Sign in", "Reddit") show the link instead. The new command palette action Retry failed link titles asks every failed link again, with a progress dialog.
12
+ - Quoted search also matches link titles and the URLs hidden behind link labels, and the AI sees those URLs too. Pasting into a quoted search inserts the text as copied.
13
+ - `[[note id]]` is always a link, even in a note with a `[[ ]]` formatting tag.
14
+ - The startup output in the terminal is easier to read: the version, a check mark per check, and each namespace's URLs lined up.
15
+ - Fixed: clicking the AI chat's $ or eye button twice quickly crashed with "Redundant state change".
16
+
8
17
  ## 0.13.0
9
18
 
10
19
  - Dictation: text from speech-to-text tools such as Superwhisper, pasted into the search bar or any tag field, becomes your existing tags ("neural network" gives `neural-network`). Say "quote … end quote" for text, "minus" to exclude, "at" before meta tags such as `@todo`. In a note, the words after "start tags" go to its tag bar. The phrases are set in Dictation Settings, and one undo restores what was pasted.
@@ -162,6 +162,15 @@ Text matching is:
162
162
  - Case-insensitive (`casefold`).
163
163
  - Against **visible text**, extracted by stripping HTML (scripts/styles ignored).
164
164
  - Also against tag-bar `/* ... */` comment text (whitespace-normalized).
165
+ - Also against the URL of a web link whose label hides it (for example a link
166
+ pasted from a web page that shows a video title): the note is searched as
167
+ "Video title (https://...)".
168
+ - Also against the titles of web pages linked in the note: for each `http(s)` URL
169
+ in the note (written out, or hidden behind a link label), the page title
170
+ MetaList has already fetched and stored. Titles are fetched when a URL on its own
171
+ line is first displayed, so a note matches by title once its title has been
172
+ fetched; a title fetched later makes the note match from then on. Titles are not
173
+ available while the namespace is locked. The URL itself remains searchable.
165
174
  - A space at the edge of the quotes marks a word boundary on that side: `"fat "` needs
166
175
  the word to end there (a space, punctuation or the end of the text follows), so it
167
176
  matches "fat cat" and "fat." but not "father"; `" fat"` needs it to start there, so
@@ -22,7 +22,7 @@ class BacklinkIndex:
22
22
  def upsert(self, note_id: str, content: str, tags: str) -> None:
23
23
  assert isinstance(note_id, str) and note_id
24
24
  counts = dict(Counter(
25
- token.note_id for token in collect_active_reference_tokens(content, tags)
25
+ token.note_id for token in collect_active_reference_tokens(content)
26
26
  if token.note_id != note_id
27
27
  ))
28
28
  self.remove(note_id)
@@ -38,7 +38,7 @@ from app.services.structured_note_renderers import (
38
38
  )
39
39
  from app.services.footnote_rendering import collect_footnotes, finish_footnotes
40
40
  from app.services.latex_rendering import render_latex_to_html
41
- from app.utils.text_utils import HTMLStripper, strip_html
41
+ from app.utils.text_utils import HTMLStripper, LinkUrlKeepingStripper, strip_html
42
42
  from app.services.markdown_rendering import render_markdown_to_html
43
43
  from app.services.ontology_rules_store import get_ontology_if_ready
44
44
  from app.services.link_titles import display_domain_for_url
@@ -346,8 +346,8 @@ class MetaTagConfig:
346
346
  scoped_renderers: Mapping[Tuple[str, int], str]
347
347
 
348
348
 
349
- class _AgentNoteText(HTMLStripper):
350
- """Preserve visible text and anchor destinations for cached-title lookup."""
349
+ class _AgentNoteText(LinkUrlKeepingStripper):
350
+ """Visible text with the URLs link labels hide, and anchor destinations for cached-title lookup."""
351
351
 
352
352
  def __init__(self) -> None:
353
353
  super().__init__()
@@ -361,9 +361,15 @@ class _AgentNoteText(HTMLStripper):
361
361
  self.anchor_urls.append(value)
362
362
 
363
363
 
364
+ def find_plain_text_urls(text: str) -> list[str]:
365
+ """URLs written out in plain text, in order, without trailing punctuation."""
366
+ if not isinstance(text, str):
367
+ raise TypeError(f"text must be a string, got {type(text)}")
368
+ return [_split_trailing_url_punctuation(match.group(0))[0] for match in _PLAIN_URL_RE.finditer(text)]
369
+
370
+
364
371
  def _cached_agent_url_titles(text: str, anchor_urls: list[str], title_lookup: Callable[[str], str | None]) -> list[dict[str, str]]:
365
- urls = [*anchor_urls, *(_split_trailing_url_punctuation(match.group(0))[0]
366
- for match in _PLAIN_URL_RE.finditer(text))]
372
+ urls = [*anchor_urls, *find_plain_text_urls(text)]
367
373
  seen = set()
368
374
  titles = []
369
375
  for url in urls:
@@ -220,18 +220,15 @@ def replace_reference_token_mode_in_html(
220
220
  return updated_content, True
221
221
 
222
222
 
223
- def collect_active_reference_tokens(content_html: str, tags: str) -> List[ReferenceToken]:
224
- """Exclude square scopes consumed as formatting, just as the renderer does."""
223
+ def collect_active_reference_tokens(content_html: str) -> List[ReferenceToken]:
224
+ """The note references the renderer shows: every [[note id]] and ![[note id]].
225
+
226
+ A [[...]] holding exactly a note id is a link even in a note whose tag bar
227
+ has a [[...]] formatting wrapper (docs/ui/references.md).
228
+ """
225
229
  if "[[" not in content_html:
226
230
  return []
227
- ignored_keys = _ignored_link_wrapper_keys_for_tags(tags)
228
- return [
229
- token for token in collect_reference_tokens_from_html(content_html)
230
- if _ignored_scoped_square_wrapper_depth_at(
231
- text=content_html, index=token.start,
232
- ignored_link_wrapper_keys=ignored_keys, is_embed=token.is_embed,
233
- ) == 0
234
- ]
231
+ return collect_reference_tokens_from_html(content_html)
235
232
 
236
233
 
237
234
  def render_note_content_with_embeds(
@@ -458,7 +455,6 @@ def _replace_reference_tokens_in_html(
458
455
  parts = _HTML_TOKEN_SPLIT_RE.split(content_html)
459
456
  output: List[str] = []
460
457
  occurrence_index = 0
461
- ignored_link_wrapper_keys = _ignored_link_wrapper_keys_for_tags(tags)
462
458
  for part in parts:
463
459
  if _is_html_segment(part):
464
460
  output.append(part)
@@ -469,7 +465,6 @@ def _replace_reference_tokens_in_html(
469
465
  context=context,
470
466
  ancestry=ancestry,
471
467
  occurrence_start=occurrence_index,
472
- ignored_link_wrapper_keys=ignored_link_wrapper_keys,
473
468
  static_export=static_export,
474
469
  redact_passwords=redact_passwords,
475
470
  render_note_embeds_as_links=render_note_embeds_as_links,
@@ -486,7 +481,6 @@ def _replace_reference_tokens_in_text(
486
481
  context: EmbedRenderContext,
487
482
  ancestry: Tuple[str, ...],
488
483
  occurrence_start: int,
489
- ignored_link_wrapper_keys: FrozenSet[Tuple[str, int]],
490
484
  static_export: bool,
491
485
  redact_passwords: bool,
492
486
  render_note_embeds_as_links: bool,
@@ -503,17 +497,6 @@ def _replace_reference_tokens_in_text(
503
497
  output.append(text[index:])
504
498
  break
505
499
 
506
- ignored_wrapper_depth = _ignored_scoped_square_wrapper_depth_at(
507
- text=text,
508
- index=token_start,
509
- ignored_link_wrapper_keys=ignored_link_wrapper_keys,
510
- is_embed=is_embed,
511
- )
512
- if ignored_wrapper_depth > 0:
513
- output.append(text[index : token_start + ignored_wrapper_depth])
514
- index = token_start + ignored_wrapper_depth
515
- continue
516
-
517
500
  output.append(text[index:token_start])
518
501
  end = text.find("]]", token_start + token_open_length)
519
502
  if end == -1:
@@ -524,8 +507,10 @@ def _replace_reference_tokens_in_text(
524
507
  reference_note_id = raw_id.strip()
525
508
 
526
509
  if not _is_valid_embed_note_id(reference_note_id):
527
- output.append(text[token_start : end + 2])
528
- index = end + 2
510
+ # Not a note id (a formatting wrapper or plain brackets): keep the opener
511
+ # and scan on, so a link nested inside, as in [[see [[id]] here]], still counts.
512
+ output.append(text[token_start : token_start + token_open_length])
513
+ index = token_start + token_open_length
529
514
  continue
530
515
 
531
516
  output.append(
@@ -578,8 +563,10 @@ def _collect_reference_tokens_in_text(
578
563
  )
579
564
  )
580
565
  occurrence_index += 1
581
-
582
- index = token_end_inner + 2
566
+ index = token_end_inner + 2
567
+ else:
568
+ # Same rule as rendering: only the opener is skipped, so nested links are found.
569
+ index = token_start + token_open_length
583
570
 
584
571
  return tokens
585
572
 
@@ -1213,37 +1200,6 @@ def _render_embedded_note_node(
1213
1200
  )
1214
1201
 
1215
1202
 
1216
- def _ignored_link_wrapper_keys_for_tags(tags: str) -> FrozenSet[Tuple[str, int]]:
1217
- consumed_wrapper_keys = find_consumed_content_wrapper_keys(tags)
1218
- return frozenset(
1219
- key
1220
- for key in consumed_wrapper_keys
1221
- if key[0] == "[" and key[1] >= 2
1222
- )
1223
-
1224
-
1225
- def _ignored_scoped_square_wrapper_depth_at(
1226
- *,
1227
- text: str,
1228
- index: int,
1229
- ignored_link_wrapper_keys: FrozenSet[Tuple[str, int]],
1230
- is_embed: bool,
1231
- ) -> int:
1232
- if is_embed:
1233
- return 0
1234
- for depth in sorted((key[1] for key in ignored_link_wrapper_keys), reverse=True):
1235
- opener = "[" * depth
1236
- if not text.startswith(opener, index):
1237
- continue
1238
- if index + depth < len(text) and text[index + depth] == "[":
1239
- continue
1240
- closer = "]" * depth
1241
- if text.find(closer, index + depth) == -1:
1242
- continue
1243
- return depth
1244
- return 0
1245
-
1246
-
1247
1203
  def _extract_first_line_preview(content_html: str) -> str:
1248
1204
  if not isinstance(content_html, str):
1249
1205
  raise TypeError("content_html must be a string")