MetaList 0.7.1__tar.gz → 0.7.3__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 (474) hide show
  1. {metalist-0.7.1 → metalist-0.7.3}/MANIFEST.in +2 -0
  2. {metalist-0.7.1/metalist.egg-info → metalist-0.7.3}/PKG-INFO +16 -1
  3. {metalist-0.7.1 → metalist-0.7.3}/README.md +15 -0
  4. {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/ai.py +53 -104
  5. {metalist-0.7.1 → metalist-0.7.3}/app/config.py +2 -2
  6. {metalist-0.7.1 → metalist-0.7.3}/app/db/live_recovery.py +4 -1
  7. {metalist-0.7.1 → metalist-0.7.3}/app/exception_boundaries.py +0 -10
  8. {metalist-0.7.1 → metalist-0.7.3}/app/models/database.py +3 -18
  9. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/actions.py +14 -77
  10. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/cloud_privacy.py +33 -9
  11. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/context.py +67 -22
  12. metalist-0.7.3/app/services/agent/help_catalog.py +43 -0
  13. metalist-0.7.3/app/services/agent/history.py +106 -0
  14. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/investigation.py +5 -3
  15. metalist-0.7.3/app/services/agent/judging.py +15 -0
  16. metalist-0.7.3/app/services/agent/menu_actions.py +63 -0
  17. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/openai_inference.py +16 -6
  18. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/prompts/final-response.md +14 -0
  19. metalist-0.7.3/app/services/agent/prompts/help-response.md +25 -0
  20. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/prompts/system.md +24 -7
  21. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/retrieval_settings.py +7 -31
  22. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/runtime.py +128 -137
  23. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/scope.py +109 -0
  24. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/skill_settings.py +8 -1
  25. metalist-0.7.3/app/services/agent/skills/help-ai.md +79 -0
  26. metalist-0.7.3/app/services/agent/skills/help-data.md +40 -0
  27. metalist-0.7.3/app/services/agent/skills/help-formatting.md +176 -0
  28. metalist-0.7.3/app/services/agent/skills/help-menus.md +116 -0
  29. metalist-0.7.3/app/services/agent/skills/help-notes.md +200 -0
  30. metalist-0.7.3/app/services/agent/skills/help-privacy.md +135 -0
  31. metalist-0.7.3/app/services/agent/skills/help-references.md +106 -0
  32. metalist-0.7.3/app/services/agent/skills/help-reminders.md +152 -0
  33. metalist-0.7.3/app/services/agent/skills/help-search.md +214 -0
  34. metalist-0.7.3/app/services/agent/skills/help-tags.md +354 -0
  35. metalist-0.7.1/app/services/agent/ollama_inference.py → metalist-0.7.3/app/services/agent/structured_inference.py +22 -151
  36. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/trace.py +82 -7
  37. {metalist-0.7.1 → metalist-0.7.3}/app/services/ai_chat_stream.py +2 -3
  38. {metalist-0.7.1 → metalist-0.7.3}/app/services/app_updates.py +18 -15
  39. {metalist-0.7.1 → metalist-0.7.3}/app/services/client_state_service.py +10 -17
  40. {metalist-0.7.1 → metalist-0.7.3}/app/services/content_formatting.py +51 -2
  41. {metalist-0.7.1 → metalist-0.7.3}/app/services/search_index.py +52 -11
  42. {metalist-0.7.1 → metalist-0.7.3}/app/services/snapshot.py +3 -1
  43. metalist-0.7.3/app/services/update_installer.py +122 -0
  44. {metalist-0.7.1 → metalist-0.7.3}/app/services/update_preflight.py +4 -0
  45. {metalist-0.7.1 → metalist-0.7.3}/app/startup_js_sanity.py +1 -1
  46. {metalist-0.7.1 → metalist-0.7.3}/app/startup_sanity.py +1 -1
  47. {metalist-0.7.1 → metalist-0.7.3}/app/startup_sanity_config.py +0 -5
  48. metalist-0.7.3/app/static/config/agent-menu-actions.json +326 -0
  49. {metalist-0.7.1 → metalist-0.7.3}/app/static/config/command_palette_tags.json +3 -3
  50. {metalist-0.7.1 → metalist-0.7.3}/app/static/css/main.css +24 -22
  51. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/main.js +1 -0
  52. metalist-0.7.3/app/static/js/modules/ai-chat/agent-menu-actions.js +43 -0
  53. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/agent-retrieval-settings.js +2 -22
  54. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/ai-agent-debug-view.js +16 -0
  55. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/ai-chat-api.js +30 -101
  56. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/ai-chat-panel-controller.js +37 -9
  57. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/ai-chat-panel-service.js +8 -12
  58. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/ai-thinking-level-service.js +4 -15
  59. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/auth.js +8 -20
  60. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/command-palette-controller.js +51 -54
  61. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/config.js +2 -1
  62. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/ai-agent-settings-modal.js +48 -236
  63. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/backup-restore-modal.js +2 -0
  64. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/base-modal.js +8 -3
  65. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/delete-namespace-modal.js +3 -0
  66. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/namespace-modals.js +12 -0
  67. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/password-modal.js +6 -3
  68. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/session-timeout-modal.js +3 -0
  69. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/actions/content-actions.js +33 -10
  70. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/events/context-menu-events.js +6 -0
  71. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/events/keyboard-events.js +1 -1
  72. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/events/mouse-events.js +20 -0
  73. metalist-0.7.3/app/static/js/modules/session-auth.js +43 -0
  74. {metalist-0.7.1 → metalist-0.7.3}/app/templates/index.html +3 -2
  75. {metalist-0.7.1 → metalist-0.7.3}/app/version.py +1 -1
  76. {metalist-0.7.1 → metalist-0.7.3/metalist.egg-info}/PKG-INFO +16 -1
  77. {metalist-0.7.1 → metalist-0.7.3}/metalist.egg-info/SOURCES.txt +19 -3
  78. metalist-0.7.1/app/services/managed_ollama_runtime.py +0 -499
  79. metalist-0.7.1/app/services/ollama_provider.py +0 -519
  80. metalist-0.7.1/app/static/js/modules/session-auth.js +0 -22
  81. {metalist-0.7.1 → metalist-0.7.3}/app/__init__.py +0 -0
  82. {metalist-0.7.1 → metalist-0.7.3}/app/api/__init__.py +0 -0
  83. {metalist-0.7.1 → metalist-0.7.3}/app/api/deps.py +0 -0
  84. {metalist-0.7.1 → metalist-0.7.3}/app/api/dev.py +0 -0
  85. {metalist-0.7.1 → metalist-0.7.3}/app/api/middleware/auth.py +0 -0
  86. {metalist-0.7.1 → metalist-0.7.3}/app/api/note_requests.py +0 -0
  87. {metalist-0.7.1 → metalist-0.7.3}/app/api/request_auth.py +0 -0
  88. {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/app_updates.py +0 -0
  89. {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/auth.py +0 -0
  90. {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/backups.py +0 -0
  91. {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/files.py +0 -0
  92. {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/notes.py +0 -0
  93. {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/ontology.py +0 -0
  94. {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/reminders.py +0 -0
  95. {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/remote_images.py +0 -0
  96. {metalist-0.7.1 → metalist-0.7.3}/app/api/routes/test.py +0 -0
  97. {metalist-0.7.1 → metalist-0.7.3}/app/api/transactions.py +0 -0
  98. {metalist-0.7.1 → metalist-0.7.3}/app/api/upload_limits.py +0 -0
  99. {metalist-0.7.1 → metalist-0.7.3}/app/data_directory.py +0 -0
  100. {metalist-0.7.1 → metalist-0.7.3}/app/db/__init__.py +0 -0
  101. {metalist-0.7.1 → metalist-0.7.3}/app/db/backup_settings_sql.py +0 -0
  102. {metalist-0.7.1 → metalist-0.7.3}/app/db/engine.py +0 -0
  103. {metalist-0.7.1 → metalist-0.7.3}/app/db/file_schema.py +0 -0
  104. {metalist-0.7.1 → metalist-0.7.3}/app/db/file_session.py +0 -0
  105. {metalist-0.7.1 → metalist-0.7.3}/app/db/files_sql.py +0 -0
  106. {metalist-0.7.1 → metalist-0.7.3}/app/db/link_titles_sql.py +0 -0
  107. {metalist-0.7.1 → metalist-0.7.3}/app/db/migrations.py +0 -0
  108. {metalist-0.7.1 → metalist-0.7.3}/app/db/notes_sql.py +0 -0
  109. {metalist-0.7.1 → metalist-0.7.3}/app/db/ontology_rules_sql.py +0 -0
  110. {metalist-0.7.1 → metalist-0.7.3}/app/db/reminders_sql.py +0 -0
  111. {metalist-0.7.1 → metalist-0.7.3}/app/db/retire_sounds.py +0 -0
  112. {metalist-0.7.1 → metalist-0.7.3}/app/db/schema.py +0 -0
  113. {metalist-0.7.1 → metalist-0.7.3}/app/db/search_history_sql.py +0 -0
  114. {metalist-0.7.1 → metalist-0.7.3}/app/db/session.py +0 -0
  115. {metalist-0.7.1 → metalist-0.7.3}/app/db/settings_sql.py +0 -0
  116. {metalist-0.7.1 → metalist-0.7.3}/app/db/tab_state_sql.py +0 -0
  117. {metalist-0.7.1 → metalist-0.7.3}/app/db/version.py +0 -0
  118. {metalist-0.7.1 → metalist-0.7.3}/app/encryption_audit.py +0 -0
  119. {metalist-0.7.1 → metalist-0.7.3}/app/https_proxy.py +0 -0
  120. {metalist-0.7.1 → metalist-0.7.3}/app/main.py +0 -0
  121. {metalist-0.7.1 → metalist-0.7.3}/app/models/commands.py +0 -0
  122. {metalist-0.7.1 → metalist-0.7.3}/app/models/entities.py +0 -0
  123. {metalist-0.7.1 → metalist-0.7.3}/app/models/enums.py +0 -0
  124. {metalist-0.7.1 → metalist-0.7.3}/app/models/linked_list.py +0 -0
  125. {metalist-0.7.1 → metalist-0.7.3}/app/models/list_operations.py +0 -0
  126. {metalist-0.7.1 → metalist-0.7.3}/app/models/list_traversal.py +0 -0
  127. {metalist-0.7.1 → metalist-0.7.3}/app/models/note_crud.py +0 -0
  128. {metalist-0.7.1 → metalist-0.7.3}/app/models/utils.py +0 -0
  129. {metalist-0.7.1 → metalist-0.7.3}/app/network_settings.py +0 -0
  130. {metalist-0.7.1 → metalist-0.7.3}/app/presentation/__init__.py +0 -0
  131. {metalist-0.7.1 → metalist-0.7.3}/app/presentation/render/__init__.py +0 -0
  132. {metalist-0.7.1 → metalist-0.7.3}/app/presentation/render/note_renderer.py +0 -0
  133. {metalist-0.7.1 → metalist-0.7.3}/app/presentation/templates.py +0 -0
  134. {metalist-0.7.1 → metalist-0.7.3}/app/security/authenticated_logging.py +0 -0
  135. {metalist-0.7.1 → metalist-0.7.3}/app/security/encryption.py +0 -0
  136. {metalist-0.7.1 → metalist-0.7.3}/app/security/http_headers.py +0 -0
  137. {metalist-0.7.1 → metalist-0.7.3}/app/security/note_html.py +0 -0
  138. {metalist-0.7.1 → metalist-0.7.3}/app/security/request_boundary.py +0 -0
  139. {metalist-0.7.1 → metalist-0.7.3}/app/security/request_hosts.py +0 -0
  140. {metalist-0.7.1 → metalist-0.7.3}/app/security/sensitive_cache.py +0 -0
  141. {metalist-0.7.1 → metalist-0.7.3}/app/security/sensitive_logging.py +0 -0
  142. {metalist-0.7.1 → metalist-0.7.3}/app/security/shell_execution.py +0 -0
  143. {metalist-0.7.1 → metalist-0.7.3}/app/security/validation_errors.py +0 -0
  144. {metalist-0.7.1 → metalist-0.7.3}/app/server_runtime.py +0 -0
  145. {metalist-0.7.1 → metalist-0.7.3}/app/services/__init__.py +0 -0
  146. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/__init__.py +0 -0
  147. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/evidence_serialization.py +0 -0
  148. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/inference.py +0 -0
  149. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/model_policy.py +0 -0
  150. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/openai_cost_tracking.py +0 -0
  151. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/permissions.py +0 -0
  152. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/prompt_settings.py +0 -0
  153. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/prompts/__init__.py +0 -0
  154. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/prompts/tool-result.md +0 -0
  155. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/skills/__init__.py +0 -0
  156. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/skills/scoped-investigation.md +0 -0
  157. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/tagging.py +0 -0
  158. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/tagging_run.py +0 -0
  159. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/token_estimation.py +0 -0
  160. {metalist-0.7.1 → metalist-0.7.3}/app/services/agent/tools.py +0 -0
  161. {metalist-0.7.1 → metalist-0.7.3}/app/services/ai_chat.py +0 -0
  162. {metalist-0.7.1 → metalist-0.7.3}/app/services/ai_chat_rendering.py +0 -0
  163. {metalist-0.7.1 → metalist-0.7.3}/app/services/app_update_worker.py +0 -0
  164. {metalist-0.7.1 → metalist-0.7.3}/app/services/auth.py +0 -0
  165. {metalist-0.7.1 → metalist-0.7.3}/app/services/auth_cache_state.py +0 -0
  166. {metalist-0.7.1 → metalist-0.7.3}/app/services/auth_service.py +0 -0
  167. {metalist-0.7.1 → metalist-0.7.3}/app/services/backlink_index.py +0 -0
  168. {metalist-0.7.1 → metalist-0.7.3}/app/services/backlinks.py +0 -0
  169. {metalist-0.7.1 → metalist-0.7.3}/app/services/backup_service.py +0 -0
  170. {metalist-0.7.1 → metalist-0.7.3}/app/services/backup_settings_service.py +0 -0
  171. {metalist-0.7.1 → metalist-0.7.3}/app/services/bulk_operation.py +0 -0
  172. {metalist-0.7.1 → metalist-0.7.3}/app/services/content_cache.py +0 -0
  173. {metalist-0.7.1 → metalist-0.7.3}/app/services/diagnostics.py +0 -0
  174. {metalist-0.7.1 → metalist-0.7.3}/app/services/embedded_references.py +0 -0
  175. {metalist-0.7.1 → metalist-0.7.3}/app/services/encryption.py +0 -0
  176. {metalist-0.7.1 → metalist-0.7.3}/app/services/exception_capture.py +0 -0
  177. {metalist-0.7.1 → metalist-0.7.3}/app/services/file_registry.py +0 -0
  178. {metalist-0.7.1 → metalist-0.7.3}/app/services/file_storage.py +0 -0
  179. {metalist-0.7.1 → metalist-0.7.3}/app/services/footnote_layout.py +0 -0
  180. {metalist-0.7.1 → metalist-0.7.3}/app/services/footnote_rendering.py +0 -0
  181. {metalist-0.7.1 → metalist-0.7.3}/app/services/hierarchy.py +0 -0
  182. {metalist-0.7.1 → metalist-0.7.3}/app/services/html_export.py +0 -0
  183. {metalist-0.7.1 → metalist-0.7.3}/app/services/html_unformatting.py +0 -0
  184. {metalist-0.7.1 → metalist-0.7.3}/app/services/hydration_state.py +0 -0
  185. {metalist-0.7.1 → metalist-0.7.3}/app/services/image_size_formatting.py +0 -0
  186. {metalist-0.7.1 → metalist-0.7.3}/app/services/inline_image_occurrences.py +0 -0
  187. {metalist-0.7.1 → metalist-0.7.3}/app/services/input_errors.py +0 -0
  188. {metalist-0.7.1 → metalist-0.7.3}/app/services/integrity.py +0 -0
  189. {metalist-0.7.1 → metalist-0.7.3}/app/services/latex_rendering.py +0 -0
  190. {metalist-0.7.1 → metalist-0.7.3}/app/services/link_titles.py +0 -0
  191. {metalist-0.7.1 → metalist-0.7.3}/app/services/login_rate_limit.py +0 -0
  192. {metalist-0.7.1 → metalist-0.7.3}/app/services/maintenance_mode.py +0 -0
  193. {metalist-0.7.1 → metalist-0.7.3}/app/services/markdown_rendering.py +0 -0
  194. {metalist-0.7.1 → metalist-0.7.3}/app/services/namespace_deletion_jobs.py +0 -0
  195. {metalist-0.7.1 → metalist-0.7.3}/app/services/namespace_deletion_worker.py +0 -0
  196. {metalist-0.7.1 → metalist-0.7.3}/app/services/namespace_rename_jobs.py +0 -0
  197. {metalist-0.7.1 → metalist-0.7.3}/app/services/namespace_rename_worker.py +0 -0
  198. {metalist-0.7.1 → metalist-0.7.3}/app/services/namespace_runtime_guard.py +0 -0
  199. {metalist-0.7.1 → metalist-0.7.3}/app/services/namespace_switcher.py +0 -0
  200. {metalist-0.7.1 → metalist-0.7.3}/app/services/note_fullscreen.py +0 -0
  201. {metalist-0.7.1 → metalist-0.7.3}/app/services/note_image_tags.py +0 -0
  202. {metalist-0.7.1 → metalist-0.7.3}/app/services/note_ordering.py +0 -0
  203. {metalist-0.7.1 → metalist-0.7.3}/app/services/note_store.py +0 -0
  204. {metalist-0.7.1 → metalist-0.7.3}/app/services/ontology_rules_store.py +0 -0
  205. {metalist-0.7.1 → metalist-0.7.3}/app/services/openai_credentials.py +0 -0
  206. {metalist-0.7.1 → metalist-0.7.3}/app/services/password_note_fields.py +0 -0
  207. {metalist-0.7.1 → metalist-0.7.3}/app/services/reference_presentation.py +0 -0
  208. {metalist-0.7.1 → metalist-0.7.3}/app/services/reminders.py +0 -0
  209. {metalist-0.7.1 → metalist-0.7.3}/app/services/remote_image_proxy.py +0 -0
  210. {metalist-0.7.1 → metalist-0.7.3}/app/services/request_recovery.py +0 -0
  211. {metalist-0.7.1 → metalist-0.7.3}/app/services/resource_limits.py +0 -0
  212. {metalist-0.7.1 → metalist-0.7.3}/app/services/root_sorting.py +0 -0
  213. {metalist-0.7.1 → metalist-0.7.3}/app/services/runtime_generation.py +0 -0
  214. {metalist-0.7.1 → metalist-0.7.3}/app/services/runtime_hardening.py +0 -0
  215. {metalist-0.7.1 → metalist-0.7.3}/app/services/runtime_lock.py +0 -0
  216. {metalist-0.7.1 → metalist-0.7.3}/app/services/search_history.py +0 -0
  217. {metalist-0.7.1 → metalist-0.7.3}/app/services/search_history_storage.py +0 -0
  218. {metalist-0.7.1 → metalist-0.7.3}/app/services/search_query.py +0 -0
  219. {metalist-0.7.1 → metalist-0.7.3}/app/services/search_text.py +0 -0
  220. {metalist-0.7.1 → metalist-0.7.3}/app/services/selected_text_tag.py +0 -0
  221. {metalist-0.7.1 → metalist-0.7.3}/app/services/self_update.py +0 -0
  222. {metalist-0.7.1 → metalist-0.7.3}/app/services/session_timeout_service.py +0 -0
  223. {metalist-0.7.1 → metalist-0.7.3}/app/services/shell_session_service.py +0 -0
  224. {metalist-0.7.1 → metalist-0.7.3}/app/services/store.py +0 -0
  225. {metalist-0.7.1 → metalist-0.7.3}/app/services/structured_note_renderers.py +0 -0
  226. {metalist-0.7.1 → metalist-0.7.3}/app/services/sync.py +0 -0
  227. {metalist-0.7.1 → metalist-0.7.3}/app/services/sync_state.py +0 -0
  228. {metalist-0.7.1 → metalist-0.7.3}/app/services/tab_state.py +0 -0
  229. {metalist-0.7.1 → metalist-0.7.3}/app/services/tag_case.py +0 -0
  230. {metalist-0.7.1 → metalist-0.7.3}/app/services/tag_ontology.py +0 -0
  231. {metalist-0.7.1 → metalist-0.7.3}/app/services/tag_rename.py +0 -0
  232. {metalist-0.7.1 → metalist-0.7.3}/app/services/tag_suggestions.py +0 -0
  233. {metalist-0.7.1 → metalist-0.7.3}/app/services/tag_term_matching.py +0 -0
  234. {metalist-0.7.1 → metalist-0.7.3}/app/services/test_reset.py +0 -0
  235. {metalist-0.7.1 → metalist-0.7.3}/app/services/tokens.py +0 -0
  236. {metalist-0.7.1 → metalist-0.7.3}/app/services/undo_state.py +0 -0
  237. {metalist-0.7.1 → metalist-0.7.3}/app/services/update_backups.py +0 -0
  238. {metalist-0.7.1 → metalist-0.7.3}/app/services/view_cache.py +0 -0
  239. {metalist-0.7.1 → metalist-0.7.3}/app/services/view_diff.py +0 -0
  240. {metalist-0.7.1 → metalist-0.7.3}/app/services/view_state.py +0 -0
  241. {metalist-0.7.1 → metalist-0.7.3}/app/services/windows_process_control.py +0 -0
  242. {metalist-0.7.1 → metalist-0.7.3}/app/startup_environment.py +0 -0
  243. {metalist-0.7.1 → metalist-0.7.3}/app/static/css/floating-notes.css +0 -0
  244. {metalist-0.7.1 → metalist-0.7.3}/app/static/css/forms.css +0 -0
  245. {metalist-0.7.1 → metalist-0.7.3}/app/static/img/favicon.ico +0 -0
  246. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/locked.js +0 -0
  247. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/activity-tracker.js +0 -0
  248. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/agent-prompt-service.js +0 -0
  249. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/bulk-elapsed-clock.js +0 -0
  250. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/bulk-proposal-ui.js +0 -0
  251. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/cloud-privacy-policy.js +0 -0
  252. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/ai-chat/proposal-menu.js +0 -0
  253. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/api-client.js +0 -0
  254. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/api-failure-classification-service.js +0 -0
  255. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/app-update-service.js +0 -0
  256. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/application-state.js +0 -0
  257. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/async-result.js +0 -0
  258. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/client-state-api.js +0 -0
  259. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/client-state-migration.js +0 -0
  260. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/activation-auth-policy.js +0 -0
  261. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/backup-command-availability.js +0 -0
  262. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/click-activation-service.js +0 -0
  263. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/endpoint-registry.js +0 -0
  264. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/note-layout-preferences.js +0 -0
  265. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/preferences-store.js +0 -0
  266. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/tag-config-loader.js +0 -0
  267. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/command-palette/usage-store.js +0 -0
  268. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/connectivity-monitor.js +0 -0
  269. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/context-menu/context-menu-registry.js +0 -0
  270. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/context-menu/context-menu-service.js +0 -0
  271. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/context-menu/context-menu-target-service.js +0 -0
  272. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/context-menu/input-caret-service.js +0 -0
  273. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/disconnect-editing-state-service.js +0 -0
  274. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/dom-utils-fixed.js +0 -0
  275. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/dom-utils.js +0 -0
  276. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/editor-commands.js +0 -0
  277. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/editor-selection.js +0 -0
  278. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/editor-toolbar.js +0 -0
  279. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/elapsed-time.js +0 -0
  280. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/error-handler.js +0 -0
  281. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/error-overlay.js +0 -0
  282. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/expected-errors.js +0 -0
  283. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/location-flags.js +0 -0
  284. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/login-namespace-picker.js +0 -0
  285. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/maintenance.js +0 -0
  286. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/agent-prompt-editor-modal.js +0 -0
  287. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/alphabetize-root-notes-modal.js +0 -0
  288. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/backup-result-modal.js +0 -0
  289. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/backup-retention-modal.js +0 -0
  290. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/backup-settings-modal.js +0 -0
  291. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/confirmation-modal.js +0 -0
  292. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/delete-namespace-validation.js +0 -0
  293. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/help-modal.js +0 -0
  294. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/namespace-loading-page.js +0 -0
  295. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/namespace-ports-profile.js +0 -0
  296. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/namespace-rename-validation.js +0 -0
  297. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/note-layout-appearance-modal.js +0 -0
  298. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/ontology-modal.js +0 -0
  299. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/prioritize-modal.js +0 -0
  300. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/random-password-modal.js +0 -0
  301. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/reminder-modal.js +0 -0
  302. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/reset-updated-at-modal.js +0 -0
  303. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/search-suggestion-statistics-modal.js +0 -0
  304. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/modals/version-info-modal.js +0 -0
  305. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/actions/history-actions.js +0 -0
  306. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/actions/note-actions.js +0 -0
  307. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/actions/search-actions.js +0 -0
  308. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/actions/selection-actions.js +0 -0
  309. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/actions/ui-actions.js +0 -0
  310. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/events/focus-events.js +0 -0
  311. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/events/inactivity-events.js +0 -0
  312. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/events/input-events.js +0 -0
  313. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/events/search-events.js +0 -0
  314. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/mode-context.js +0 -0
  315. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/mode-logger.js +0 -0
  316. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/mode-manager-controller.js +0 -0
  317. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/add-style-service.js +0 -0
  318. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/animated-scroll-service.js +0 -0
  319. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/backlinks-navigation-service.js +0 -0
  320. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/backlinks-panel-service.js +0 -0
  321. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/clipboard-shortcut-policy-service.js +0 -0
  322. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/collapse-affordance-service.js +0 -0
  323. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/collapse-editing-policy-service.js +0 -0
  324. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/command-gate-service.js +0 -0
  325. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/context-menu-target-service.js +0 -0
  326. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/deselect-selection-state-service.js +0 -0
  327. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/differential-view-service.js +0 -0
  328. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/edit-session-collapse-policy-service.js +0 -0
  329. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/edit-session-collapse-service.js +0 -0
  330. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/embedded-image-service.js +0 -0
  331. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/file-drop-policy-service.js +0 -0
  332. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/file-image-preview-service.js +0 -0
  333. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/file-reference-service.js +0 -0
  334. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/filtered-refresh-selection-service.js +0 -0
  335. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/floating-note-dom.js +0 -0
  336. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/floating-note-layout.js +0 -0
  337. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/floating-note-service.js +0 -0
  338. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/footnote-navigation-service.js +0 -0
  339. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/history-selection-policy-service.js +0 -0
  340. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/history-shortcut-policy-service.js +0 -0
  341. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/html-paste-sanitizer-service.js +0 -0
  342. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/image-context-menu-action-service.js +0 -0
  343. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/image-file-insert-choice-modal-service.js +0 -0
  344. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/infinite-scroll-service.js +0 -0
  345. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/link-context-menu-action-service.js +0 -0
  346. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/link-title-prefetch-service.js +0 -0
  347. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/markdown-render-service.js +0 -0
  348. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/mermaid-render-service.js +0 -0
  349. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-click-target-service.js +0 -0
  350. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-clipboard-write-service.js +0 -0
  351. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-collapse-animation-service.js +0 -0
  352. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-context-menu-action-service.js +0 -0
  353. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-delete-shortcut-policy-service.js +0 -0
  354. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-drag-service.js +0 -0
  355. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-fullscreen-service.js +0 -0
  356. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-reposition-animation-service.js +0 -0
  357. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-split-service.js +0 -0
  358. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/note-timestamp-hover-service.js +0 -0
  359. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/password-clipboard-service.js +0 -0
  360. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/polling-service.js +0 -0
  361. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/reference-source-navigation-service.js +0 -0
  362. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/remote-image-proxy-service.js +0 -0
  363. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/remove-formatting-service.js +0 -0
  364. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/root-date-separator-service.js +0 -0
  365. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/root-sort-indicator-service.js +0 -0
  366. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/root-sort-service.js +0 -0
  367. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/scroll-anchor-service.js +0 -0
  368. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/scroll-restoration-service.js +0 -0
  369. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/scroll-to-top-service.js +0 -0
  370. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-contexts-overlay-service.js +0 -0
  371. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-debounce-service.js +0 -0
  372. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-input-service.js +0 -0
  373. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-interaction-service.js +0 -0
  374. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-redaction-reveal-service.js +0 -0
  375. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-suggestion-statistics-service.js +0 -0
  376. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-suggestion-window-labels-service.js +0 -0
  377. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-suggestion-windows-service.js +0 -0
  378. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-suggestions-service.js +0 -0
  379. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/search-syntax-service.js +0 -0
  380. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/selected-formatting-removal-service.js +0 -0
  381. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/selected-text-tag-service.js +0 -0
  382. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/shell-output-service.js +0 -0
  383. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tab-dom-cache-service.js +0 -0
  384. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tab-drag-service.js +0 -0
  385. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tab-duplication-service.js +0 -0
  386. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tab-state-service.js +0 -0
  387. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tag-bar-service.js +0 -0
  388. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tag-input-selection-service.js +0 -0
  389. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tag-proposal-service.js +0 -0
  390. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tag-suggestions-service.js +0 -0
  391. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/tag-syntax-service.js +0 -0
  392. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/todo-toggle-editing-service.js +0 -0
  393. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/untagged-view-indicator-service.js +0 -0
  394. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/mode-manager/services/view-mode-search-shortcut-service.js +0 -0
  395. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/note-html-sanitizer.js +0 -0
  396. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/password-generator.js +0 -0
  397. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/password-operation-response.js +0 -0
  398. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/password-policy.js +0 -0
  399. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/password-strength.js +0 -0
  400. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/reminder-store.js +0 -0
  401. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/reminder-surface-service.js +0 -0
  402. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/selection-markers.js +0 -0
  403. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/tag-token.js +0 -0
  404. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/modules/uuid.js +0 -0
  405. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/namespace-deleted.js +0 -0
  406. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/namespace-renamed.js +0 -0
  407. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/vendor/dompurify-3.4.13.LICENSE.txt +0 -0
  408. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/vendor/dompurify-3.4.13.min.js +0 -0
  409. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/vendor/markdown-it-14.3.2.LICENSE.txt +0 -0
  410. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/vendor/markdown-it-14.3.2.min.js +0 -0
  411. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/vendor/mermaid-11.16.1.LICENSE.txt +0 -0
  412. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/vendor/mermaid-11.16.1.min.js +0 -0
  413. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/vendor/zxcvbn-4.4.2.LICENSE.txt +0 -0
  414. {metalist-0.7.1 → metalist-0.7.3}/app/static/js/vendor/zxcvbn-4.4.2.js +0 -0
  415. {metalist-0.7.1 → metalist-0.7.3}/app/static/note-html-policy.json +0 -0
  416. {metalist-0.7.1 → metalist-0.7.3}/app/static/video/login-startup.mp4 +0 -0
  417. {metalist-0.7.1 → metalist-0.7.3}/app/templates/base.html +0 -0
  418. {metalist-0.7.1 → metalist-0.7.3}/app/templates/locked.html +0 -0
  419. {metalist-0.7.1 → metalist-0.7.3}/app/templates/maintenance.html +0 -0
  420. {metalist-0.7.1 → metalist-0.7.3}/app/templates/namespace_deleted.html +0 -0
  421. {metalist-0.7.1 → metalist-0.7.3}/app/templates/namespace_renamed.html +0 -0
  422. {metalist-0.7.1 → metalist-0.7.3}/app/templates/notes_list.html +0 -0
  423. {metalist-0.7.1 → metalist-0.7.3}/app/upload_limits.py +0 -0
  424. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/__init__.py +0 -0
  425. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/add_selected_text_tag.py +0 -0
  426. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/alphabetize_root_notes.py +0 -0
  427. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/base.py +0 -0
  428. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/bulk_tag_proposals.py +0 -0
  429. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/collapse.py +0 -0
  430. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/copy_note.py +0 -0
  431. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/create_child.py +0 -0
  432. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/create_note.py +0 -0
  433. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/create_sibling.py +0 -0
  434. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/delete_subtree.py +0 -0
  435. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/delete_tag.py +0 -0
  436. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/expand.py +0 -0
  437. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/indent.py +0 -0
  438. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/lock.py +0 -0
  439. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/move.py +0 -0
  440. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/move_to_top.py +0 -0
  441. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/outdent.py +0 -0
  442. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/paste_child.py +0 -0
  443. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/paste_sibling.py +0 -0
  444. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/prefetch_link_titles.py +0 -0
  445. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/prioritize.py +0 -0
  446. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/redo.py +0 -0
  447. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/rename_tag.py +0 -0
  448. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/reset_updated_at.py +0 -0
  449. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/resize_image.py +0 -0
  450. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/run_shell.py +0 -0
  451. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/search_comment_autofill.py +0 -0
  452. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/search_context_tags.py +0 -0
  453. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/set_collapse_bulk.py +0 -0
  454. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/set_collapse_in_context.py +0 -0
  455. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/split_note.py +0 -0
  456. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/tag_proposals.py +0 -0
  457. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/toggle_reference_mode.py +0 -0
  458. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/toggle_todo_done.py +0 -0
  459. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/undo.py +0 -0
  460. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/unformat_content.py +0 -0
  461. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/update_content.py +0 -0
  462. {metalist-0.7.1 → metalist-0.7.3}/app/usecases/view.py +0 -0
  463. {metalist-0.7.1 → metalist-0.7.3}/app/utils/__init__.py +0 -0
  464. {metalist-0.7.1 → metalist-0.7.3}/app/utils/encryption.py +0 -0
  465. {metalist-0.7.1 → metalist-0.7.3}/app/utils/text_utils.py +0 -0
  466. {metalist-0.7.1 → metalist-0.7.3}/convert-from-legacy.py +0 -0
  467. {metalist-0.7.1 → metalist-0.7.3}/main.py +0 -0
  468. {metalist-0.7.1 → metalist-0.7.3}/metalist.egg-info/dependency_links.txt +0 -0
  469. {metalist-0.7.1 → metalist-0.7.3}/metalist.egg-info/entry_points.txt +0 -0
  470. {metalist-0.7.1 → metalist-0.7.3}/metalist.egg-info/requires.txt +0 -0
  471. {metalist-0.7.1 → metalist-0.7.3}/metalist.egg-info/top_level.txt +0 -0
  472. {metalist-0.7.1 → metalist-0.7.3}/pyproject.toml +0 -0
  473. {metalist-0.7.1 → metalist-0.7.3}/scripts/generate-lan-cert.sh +0 -0
  474. {metalist-0.7.1 → metalist-0.7.3}/setup.cfg +0 -0
@@ -1,4 +1,6 @@
1
1
  recursive-include app/static *
2
2
  recursive-include app/templates *.html
3
+ prune evals
4
+ prune tests
3
5
  prune app/__pycache__
4
6
  global-exclude .DS_Store
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metalist
3
- Version: 0.7.1
3
+ Version: 0.7.3
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
@@ -48,6 +48,19 @@ A minimalist single-user note-taking app focused on server-side rendering (SSR),
48
48
  - Multi-tab search contexts with server-persisted scroll/search state (survives browser restarts)
49
49
  - Manual namespace backups/restores to a user-selected backup folder with retention controls
50
50
 
51
+ ## Changes in 0.7.3
52
+
53
+ - Windows updates use a private verified uv release when an older installer is vulnerable to the reported PE-resource access-denied failure. A standalone repair ZIP can bootstrap installations whose existing updater cannot update itself.
54
+ - Release candidates now run the complete test and installed-package matrix on Windows, macOS, and Linux across Python 3.10–3.14. Real Chrome and Firefox exercise repeated cold loads and encrypted login on every operating system; Windows also checks Edge over verified LAN HTTPS and the repair path from a published older release.
55
+
56
+ ## Changes in 0.7.2
57
+
58
+ - Login, hydration, and workspace requests share one initialized browser-tab identity. Losing the `sessionStorage` copy while opening the workspace no longer causes the reported missing-tab-ID crash. The external trigger for that storage loss remains unconfirmed.
59
+ - AI chat preserves the edited note and includes its permitted tree, tags, and cached URL titles. Search redaction and cloud privacy restrictions apply to every node; blocked selections expose only their availability reason.
60
+ - Added on-demand AI help and menu actions, privacy previews, and Copy Response throughout assistant message bubbles. OpenAI is the supported inference provider.
61
+ - LLM regressions use current production prompts, default to five trials with cache-aware parallel scheduling, and can run only cases affected by prompt or skill changes.
62
+ - Improved Grammarly edit preservation and search suggestions that match the complete active clause.
63
+
51
64
  ## Changes in 0.6.3
52
65
 
53
66
  - Restored HTTPS connection reuse and aligned the pending accept queue with the existing worker capacity, so a browser’s six-connection startup burst is admitted.
@@ -139,6 +152,8 @@ metalist update
139
152
  ```
140
153
  The updater checks the installed version against the latest PyPI release first. If MetaList is already current, it reports the installed version and leaves all running namespaces untouched. When an update is available, it checks installer prerequisites and uses uv to install the candidate into a disposable tool environment with the current base Python interpreter. It checks dependencies and starts a temporary namespace to verify HTTP readiness, version, and runtime assets. A failed preflight leaves the current installation and running namespaces unchanged. After preflight succeeds, it stops running namespaces, and creates and verifies a new backup of every namespace before installation can begin. Each archive includes the complete notes/settings database, the attachments database when present, and any legacy search-history database. Locked namespaces are backed up with their encrypted data and key metadata intact, without requiring a password.
141
154
 
155
+ On Windows, the updater checks uv before installing packages. Versions older than 0.12.13 use a temporary PE-resource editing operation that can fail with `uv-trampoline.exe: Access is denied`. This checkout selects a private, checksum-verified uv 0.12.17 for those installations, keeping the same installer through preflight and final installation. It does not replace global uv. Already-installed MetaList releases retain their own updater code; the standalone repair launcher described in [recovery](docs/security/recovery.md#windows-updater-pe-resource-failure) supplies the compatible installer to that existing updater.
156
+
142
157
  Backups are saved to `~/MetaList/namespaces/<namespace>/backups/<namespace>-<timestamp>.metalist-backup.tar.gz`; the updater prints each verified path. Existing backups remain unchanged and are not pruned. If any backup fails, the update aborts with the current installation intact; run `metalist` to restart the stopped servers after resolving the failure.
143
158
 
144
159
  Only after all backups pass does the updater hand off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock. It delegates installation to uv, pinning the current base interpreter and the exact tested package/dependency versions, using the cache populated during preflight with network access disabled. It then launches MetaList again, and reports the installed version (for example, `MetaList updated to v0.5.0.`). This protection requires an installed version containing the backup safeguard and applies to `metalist update` and the in-app update action; direct pip/uv install commands do not run it.
@@ -12,6 +12,19 @@ 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.7.3
16
+
17
+ - Windows updates use a private verified uv release when an older installer is vulnerable to the reported PE-resource access-denied failure. A standalone repair ZIP can bootstrap installations whose existing updater cannot update itself.
18
+ - Release candidates now run the complete test and installed-package matrix on Windows, macOS, and Linux across Python 3.10–3.14. Real Chrome and Firefox exercise repeated cold loads and encrypted login on every operating system; Windows also checks Edge over verified LAN HTTPS and the repair path from a published older release.
19
+
20
+ ## Changes in 0.7.2
21
+
22
+ - Login, hydration, and workspace requests share one initialized browser-tab identity. Losing the `sessionStorage` copy while opening the workspace no longer causes the reported missing-tab-ID crash. The external trigger for that storage loss remains unconfirmed.
23
+ - AI chat preserves the edited note and includes its permitted tree, tags, and cached URL titles. Search redaction and cloud privacy restrictions apply to every node; blocked selections expose only their availability reason.
24
+ - Added on-demand AI help and menu actions, privacy previews, and Copy Response throughout assistant message bubbles. OpenAI is the supported inference provider.
25
+ - LLM regressions use current production prompts, default to five trials with cache-aware parallel scheduling, and can run only cases affected by prompt or skill changes.
26
+ - Improved Grammarly edit preservation and search suggestions that match the complete active clause.
27
+
15
28
  ## Changes in 0.6.3
16
29
 
17
30
  - Restored HTTPS connection reuse and aligned the pending accept queue with the existing worker capacity, so a browser’s six-connection startup burst is admitted.
@@ -103,6 +116,8 @@ metalist update
103
116
  ```
104
117
  The updater checks the installed version against the latest PyPI release first. If MetaList is already current, it reports the installed version and leaves all running namespaces untouched. When an update is available, it checks installer prerequisites and uses uv to install the candidate into a disposable tool environment with the current base Python interpreter. It checks dependencies and starts a temporary namespace to verify HTTP readiness, version, and runtime assets. A failed preflight leaves the current installation and running namespaces unchanged. After preflight succeeds, it stops running namespaces, and creates and verifies a new backup of every namespace before installation can begin. Each archive includes the complete notes/settings database, the attachments database when present, and any legacy search-history database. Locked namespaces are backed up with their encrypted data and key metadata intact, without requiring a password.
105
118
 
119
+ On Windows, the updater checks uv before installing packages. Versions older than 0.12.13 use a temporary PE-resource editing operation that can fail with `uv-trampoline.exe: Access is denied`. This checkout selects a private, checksum-verified uv 0.12.17 for those installations, keeping the same installer through preflight and final installation. It does not replace global uv. Already-installed MetaList releases retain their own updater code; the standalone repair launcher described in [recovery](docs/security/recovery.md#windows-updater-pe-resource-failure) supplies the compatible installer to that existing updater.
120
+
106
121
  Backups are saved to `~/MetaList/namespaces/<namespace>/backups/<namespace>-<timestamp>.metalist-backup.tar.gz`; the updater prints each verified path. Existing backups remain unchanged and are not pruned. If any backup fails, the update aborts with the current installation intact; run `metalist` to restart the stopped servers after resolving the failure.
107
122
 
108
123
  Only after all backups pass does the updater hand off to an external PowerShell process on Windows or `/bin/sh` on macOS/Linux so the installed environment can unlock. It delegates installation to uv, pinning the current base interpreter and the exact tested package/dependency versions, using the cache populated during preflight with network access disabled. It then launches MetaList again, and reports the installed version (for example, `MetaList updated to v0.5.0.`). This protection requires an installed version containing the backup safeguard and applies to `metalist update` and the in-app update action; direct pip/uv install commands do not run it.
@@ -2,7 +2,6 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import asyncio
6
5
  import json
7
6
  import math
8
7
  from collections.abc import AsyncIterator
@@ -27,7 +26,6 @@ from app.services.agent.cloud_privacy import cloud_privacy_evaluator
27
26
  from app.services.agent.cloud_privacy import resolve_cloud_privacy_boundary
28
27
  from app.services.agent.inference import InferenceAdapter
29
28
  from app.services.agent.model_policy import SingleModelPolicy
30
- from app.services.agent.ollama_inference import OllamaInferenceAdapter
31
29
  from app.services.agent.openai_inference import OPENAI_API_BASE_URL
32
30
  from app.services.agent.openai_inference import OPENAI_MODELS
33
31
  from app.services.agent.openai_inference import OpenAIInferenceAdapter
@@ -50,15 +48,10 @@ from app.services.agent.skill_settings import resolve_agent_skill_set
50
48
  from app.services.agent.token_estimation import estimate_input_tokens
51
49
  from app.services.agent.tools import read_only_agent_tools
52
50
  from app.services.agent.trace import agent_trace_store
51
+ from app.services.agent.menu_actions import MenuResult, menu_action_store
53
52
  from app.services.client_state_service import load_client_preferences
54
53
  from app.services.markdown_rendering import render_markdown_to_html
55
- from app.services.managed_ollama_runtime import ManagedOllamaRuntimeError
56
- from app.services.managed_ollama_runtime import managed_ollama_runtime
57
54
  from app.services.note_store import store as note_store
58
- from app.services.ollama_provider import OllamaProviderError
59
- from app.services.ollama_provider import ollama_provider
60
- from app.services.ollama_provider import resolve_ollama_think_value
61
- from app.services.ollama_provider import validate_ollama_model
62
55
  from app.services.openai_credentials import OpenAICredentialInputError
63
56
  from app.services.openai_credentials import openai_credential_store
64
57
  from app.services.openai_credentials import validate_openai_api_key
@@ -89,17 +82,10 @@ def _agent_runtime(*, inference: InferenceAdapter) -> AgentRuntime:
89
82
  )
90
83
 
91
84
 
92
- agent_runtime = _agent_runtime(
93
- inference=OllamaInferenceAdapter(provider=ollama_provider)
94
- )
95
-
96
-
97
-
98
-
99
85
  class AiModelsRequest(BaseModel):
100
86
  model_config = ConfigDict(extra="forbid")
101
87
 
102
- provider: Literal["ollama", "openai"]
88
+ provider: Literal["openai"]
103
89
 
104
90
 
105
91
  class AiModelsResponse(BaseModel):
@@ -128,7 +114,7 @@ class OpenAICostResponse(BaseModel):
128
114
  class CloudPrivacyPreviewRequest(BaseModel):
129
115
  model_config = ConfigDict(extra="forbid")
130
116
 
131
- provider: Literal["ollama", "openai"]
117
+ provider: Literal["openai"]
132
118
  note_ids: list[str] = Field(..., max_length=20_000)
133
119
 
134
120
  @field_validator("note_ids")
@@ -163,27 +149,16 @@ class AiPromptDefaultsResponse(BaseModel):
163
149
  skills: list[AiSkillDefaultResponse]
164
150
 
165
151
 
166
- class AiModelPullRequest(BaseModel):
167
- model_config = ConfigDict(extra="forbid")
168
-
169
- provider: Literal["ollama"]
170
- model: str
171
-
172
- @field_validator("model")
173
- @classmethod
174
- def validate_model(cls, value: str) -> str:
175
- return validate_ollama_model(value)
176
-
177
-
178
152
  class AiChatRequest(BaseModel):
179
153
  model_config = ConfigDict(extra="forbid")
180
154
 
181
- provider: Literal["ollama", "openai"]
155
+ provider: Literal["openai"]
182
156
  model: str
183
157
  thinking_level: Literal["off", "low", "medium", "high"]
184
158
  show_diagnostics: bool
185
159
  message: str = Field(..., max_length=32_000)
186
160
  scope: AgentScopeDescriptor
161
+ selected_note_id: str = Field(..., max_length=128, pattern=r"^(?:\S+)?$")
187
162
 
188
163
  @field_validator("model")
189
164
  @classmethod
@@ -202,14 +177,7 @@ class AiChatRequest(BaseModel):
202
177
 
203
178
  @model_validator(mode="after")
204
179
  def validate_thinking_level_for_model(self) -> Self:
205
- if self.provider == "ollama":
206
- validate_ollama_model(self.model)
207
- resolve_ollama_think_value(
208
- model=self.model,
209
- thinking_level=self.thinking_level,
210
- )
211
- else:
212
- validate_openai_model(self.model)
180
+ validate_openai_model(self.model)
213
181
  return self
214
182
 
215
183
 
@@ -239,7 +207,7 @@ class AiChatMessage(BaseModel):
239
207
  rendered_thinking: str
240
208
  status: Literal["complete", "streaming", "error"]
241
209
  error: str
242
- provider: Literal["ollama", "openai"]
210
+ provider: Literal["openai"]
243
211
  model: str
244
212
  activities: list[AiChatActivity]
245
213
 
@@ -308,15 +276,8 @@ async def list_ai_models(
308
276
  payload: AiModelsRequest,
309
277
  token: Annotated[str, Depends(require_request_auth_token)],
310
278
  ) -> AiModelsResponse:
311
- del token
312
- if payload.provider == "openai":
313
- return AiModelsResponse(models=list(OPENAI_MODELS))
314
- try:
315
- runtime_info = await asyncio.to_thread(managed_ollama_runtime.ensure_running)
316
- models = await ollama_provider.list_models(base_url=runtime_info.base_url)
317
- except (ManagedOllamaRuntimeError, OllamaProviderError) as exc:
318
- raise HTTPException(status_code=502, detail=str(exc)) from exc
319
- return AiModelsResponse(models=models)
279
+ del token, payload
280
+ return AiModelsResponse(models=list(OPENAI_MODELS))
320
281
 
321
282
 
322
283
  @router.get(
@@ -476,38 +437,6 @@ def preview_cloud_privacy(
476
437
  )
477
438
 
478
439
 
479
- @router.post("/models/pull")
480
- @transactional_route
481
- def pull_ai_model(
482
- payload: AiModelPullRequest,
483
- token: Annotated[str, Depends(require_request_auth_token)],
484
- ) -> StreamingResponse:
485
- del token
486
-
487
- async def stream_events() -> AsyncIterator[str]:
488
- try:
489
- runtime_info = await asyncio.to_thread(managed_ollama_runtime.ensure_running)
490
- async for event in ollama_provider.stream_pull(
491
- base_url=runtime_info.base_url,
492
- model=payload.model,
493
- ):
494
- yield f"{json.dumps(event, separators=(',', ':'))}\n"
495
- # lint: allow-PY001 rationale="pull errors must be delivered after response headers are sent"
496
- except (ManagedOllamaRuntimeError, OllamaProviderError) as exc:
497
- error_event = {"type": "error", "message": str(exc)}
498
- yield f"{json.dumps(error_event, separators=(',', ':'))}\n"
499
-
500
- return StreamingResponse(
501
- stream_events(),
502
- media_type="application/x-ndjson",
503
- headers={
504
- "X-Accel-Buffering": "no",
505
- "Cache-Control": "no-store",
506
- "Content-Encoding": "identity",
507
- },
508
- )
509
-
510
-
511
440
  @router.get("/session", response_model=AiSessionResponse)
512
441
  def get_ai_session(
513
442
  response: Response,
@@ -589,6 +518,17 @@ def get_ai_debug_snapshot(
589
518
  )
590
519
 
591
520
 
521
+ @router.get("/history")
522
+ def get_ai_history(
523
+ response: Response,
524
+ token: Annotated[str, Depends(require_request_auth_token)],
525
+ ) -> list:
526
+ response.headers["Cache-Control"] = "no-store"
527
+ return agent_trace_store.export_history(
528
+ session_key=token_service.get_session_key(token)
529
+ )
530
+
531
+
592
532
  @router.put("/debug", response_model=AiDebugSnapshotResponse)
593
533
  @transactional_route
594
534
  def put_ai_debug_details(
@@ -666,21 +606,19 @@ def stream_ai_chat(
666
606
  token: Annotated[str, Depends(require_request_auth_token)],
667
607
  ) -> StreamingResponse:
668
608
  session_key = token_service.get_session_key(token)
669
- openai_api_key = ""
670
- if payload.provider == "openai":
671
- credential_status = openai_credential_store.status(
672
- token=token,
673
- session_key=session_key,
674
- )
675
- if not credential_status.configured:
676
- raise HTTPException(
677
- status_code=409,
678
- detail="OpenAI API key is not configured",
679
- )
680
- openai_api_key = openai_credential_store.resolve(
681
- token=token,
682
- session_key=session_key,
609
+ credential_status = openai_credential_store.status(
610
+ token=token,
611
+ session_key=session_key,
612
+ )
613
+ if not credential_status.configured:
614
+ raise HTTPException(
615
+ status_code=409,
616
+ detail="OpenAI API key is not configured",
683
617
  )
618
+ openai_api_key = openai_credential_store.resolve(
619
+ token=token,
620
+ session_key=session_key,
621
+ )
684
622
  preferences = load_client_preferences(token=token)
685
623
  prompts = resolve_agent_prompt_set(preferences=preferences)
686
624
  skills = resolve_agent_skill_set(preferences=preferences)
@@ -704,6 +642,11 @@ def stream_ai_chat(
704
642
  authoritative_sort_mode = tab_state_store.get_sort_mode(
705
643
  tab_id=payload.scope.scope_tab_id
706
644
  )
645
+ active_search_query = authoritative_search_query
646
+ active_sort_mode = authoritative_sort_mode
647
+ if payload.selected_note_id and payload.scope.active_tab_id != payload.scope.scope_tab_id:
648
+ active_search_query = tab_state_store.get_search_query(tab_id=authoritative_active_tab_id)
649
+ active_sort_mode = tab_state_store.get_sort_mode(tab_id=authoritative_active_tab_id)
707
650
  frozen_scope = scoped_search_snapshot_factory.freeze(
708
651
  descriptor=payload.scope,
709
652
  authoritative_search_query=authoritative_search_query,
@@ -711,6 +654,9 @@ def stream_ai_chat(
711
654
  run_id=str(uuid4()),
712
655
  session_key=session_key,
713
656
  privacy_boundary=privacy_boundary,
657
+ selected_note_id=payload.selected_note_id,
658
+ authoritative_active_search_query=active_search_query,
659
+ authoritative_active_sort_mode=active_sort_mode,
714
660
  )
715
661
  tagging_run = TaggingRun(token=token, snapshot=frozen_scope, preferences=preferences, sync_uuid=get_current_sync_uuid(),
716
662
  batch_tokens=resolve_tagging_batch_tokens(preferences, payload.provider))
@@ -758,18 +704,9 @@ async def _stream_runtime_events(
758
704
  action, start_label = 'provider_runtime', 'Connecting to OpenAI API'
759
705
  ready_label = 'OpenAI API ready · 1,050,000-token context'
760
706
  base_url = OPENAI_API_BASE_URL
761
- if payload.provider == 'ollama':
762
- action = 'ollama_runtime'
763
- start_label = 'Starting MetaList-managed Ollama · 32,768-token context'
764
- runtime = agent_runtime
765
- else:
766
- runtime = _agent_runtime(inference=OpenAIInferenceAdapter(api_key=openai_api_key, cost_tracker=openai_cost_tracker))
707
+ runtime = _agent_runtime(inference=OpenAIInferenceAdapter(api_key=openai_api_key, cost_tracker=openai_cost_tracker))
767
708
  yield dict(type='action_status', action=action, status='started', label=start_label,
768
709
  approx_input_tokens=initial_input_tokens, output_tokens_received=0, duration_ms=0.0)
769
- if payload.provider == 'ollama':
770
- runtime_info = await asyncio.to_thread(managed_ollama_runtime.ensure_running)
771
- base_url = runtime_info.base_url
772
- ready_label = f'MetaList-managed Ollama ready · {runtime_info.context_tokens:,}-token context'
773
710
  yield dict(type='action_status', action=action, status='completed', label=ready_label,
774
711
  approx_input_tokens=initial_input_tokens, output_tokens_received=0, duration_ms=0.0)
775
712
  events = runtime.stream_scoped(session_key=session_key, base_url=base_url,
@@ -783,6 +720,18 @@ async def _stream_runtime_events(
783
720
  await events.aclose()
784
721
 
785
722
 
723
+ @router.post("/menu-result")
724
+ @transactional_route
725
+ async def acknowledge_menu_result(payload: MenuResult, token: Annotated[str, Depends(require_request_auth_token)]):
726
+ # lint: allow-PY001 rationale="browser acknowledgments can be stale or belong to another session"
727
+ try:
728
+ menu_action_store.acknowledge(session_key=token_service.get_session_key(token), result=payload)
729
+ # lint: allow-PY001 rationale="reject invalid external menu acknowledgment with a conflict response"
730
+ except ValueError as exc:
731
+ raise HTTPException(status_code=409, detail=str(exc)) from exc
732
+ return {"acknowledged": True}
733
+
734
+
786
735
  class BulkAnswerRequest(BaseModel):
787
736
  model_config = ConfigDict(extra="forbid")
788
737
  question_id: str = Field(..., min_length=1)
@@ -114,9 +114,9 @@ if TEST_MODE:
114
114
  # Delete existing test.db if it exists
115
115
  if test_database_path.exists():
116
116
  test_database_path.unlink()
117
- print("🧪 Deleted existing test.db")
117
+ print("Deleted existing test.db")
118
118
 
119
- print("🧪 Running in TEST MODE - using test.db")
119
+ print("Running in TEST MODE - using test.db")
120
120
  else:
121
121
  # Use production database
122
122
  DEFAULT_DB_PATH = str(resolve_default_database_path())
@@ -44,7 +44,10 @@ def _sync_directory(path: Path) -> None:
44
44
 
45
45
 
46
46
  def _sync_file(path: Path) -> None:
47
- with path.open('rb') as handle:
47
+ # Windows' CRT rejects fsync/_commit on a read-only descriptor with EBADF.
48
+ # These are live or recovery files owned by this transaction, so open them
49
+ # without truncation using a descriptor that every supported OS can flush.
50
+ with path.open('r+b') as handle:
48
51
  os.fsync(handle.fileno())
49
52
 
50
53
 
@@ -112,16 +112,6 @@ CAPTURE_BOUNDARIES = {
112
112
  # Handle expected external I/O, provider, image or LaTeX parsing failure.
113
113
  'app/services/link_titles.py:fetch_link_title:target_capture': ('_LinkTitleTargetRejected',),
114
114
  # Handle expected external I/O, provider, image or LaTeX parsing failure.
115
- 'app/services/managed_ollama_runtime.py:_acquire_startup_lock:lock_capture': ('FileExistsError',),
116
- # Handle expected external I/O, provider, image or LaTeX parsing failure.
117
- 'app/services/managed_ollama_runtime.py:_is_process_running:process_capture': ('ProcessLookupError', 'PermissionError'),
118
- # Handle expected external I/O, provider, image or LaTeX parsing failure.
119
- 'app/services/managed_ollama_runtime.py:_probe_ollama_version:probe_capture': ('HTTPError', 'JSONDecodeError'),
120
- # Handle expected external I/O, provider, image or LaTeX parsing failure.
121
- 'app/services/managed_ollama_runtime.py:_remove_stale_lock:missing_capture': ('FileNotFoundError',),
122
- # Handle expected external I/O, provider, image or LaTeX parsing failure.
123
- 'app/services/managed_ollama_runtime.py:_remove_stale_lock:read_capture': ('FileNotFoundError',),
124
- # Handle expected external I/O, provider, image or LaTeX parsing failure.
125
115
  'app/services/namespace_deletion_worker.py:_is_process_running:kill_capture': ('ProcessLookupError', 'PermissionError'),
126
116
  # Handle expected external I/O, provider, image or LaTeX parsing failure.
127
117
  'app/services/namespace_deletion_worker.py:_send_signal_if_running:signal_capture': ('ProcessLookupError',),
@@ -124,15 +124,8 @@ class SafeSession:
124
124
  _configure_sql_logging(anchor)
125
125
  cls._memory_anchor = anchor
126
126
  print("\n" + "=" * 50)
127
- print(
128
- """
129
- 🧪 SWITCHING TO TEST MODE 🧪
130
- ┌──────────────────────────┐
131
- │ IN-MEMORY DATABASE │
132
- │ *All Data is Temporary │
133
- └──────────────────────────┘
134
- """
135
- )
127
+ print("TEST MODE: IN-MEMORY DATABASE")
128
+ print("All data is temporary")
136
129
  print("=" * 50 + "\n")
137
130
  return {"status": "ok", "message": "Using in-memory database"}
138
131
 
@@ -159,15 +152,7 @@ class SafeSession:
159
152
  _configure_sql_logging(conn)
160
153
  conn.close()
161
154
  print("\n" + "=" * 50)
162
- print(
163
- """
164
- 📝 RETURNING TO PRODUCTION MODE 📝
165
- ┌──────────────────────────┐
166
- │ PROD DATABASE │
167
- │ │
168
- └──────────────────────────┘
169
- """
170
- )
155
+ print("PRODUCTION MODE: FILE DATABASE")
171
156
  print("=" * 50 + "\n")
172
157
  return {"status": "ok", "message": "Using file database"}
173
158
 
@@ -2,73 +2,13 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import re
6
- from collections.abc import Iterator
7
- from contextlib import contextmanager
8
- from contextvars import ContextVar
9
- from dataclasses import dataclass
10
5
  from typing import Annotated, Literal, Union
11
6
 
12
7
  from pydantic import BaseModel, ConfigDict, Field, TypeAdapter, field_validator, model_validator
13
8
  from typing_extensions import Self
14
9
 
15
10
  from app.services.search_query import parse_search_query
16
-
17
-
18
- @dataclass(frozen=True, slots=True)
19
- class ScopedRouteConstraints:
20
- explicit_saved_notes_request: bool
21
-
22
- def __post_init__(self) -> None:
23
- if not isinstance(self.explicit_saved_notes_request, bool):
24
- raise TypeError("explicit_saved_notes_request must be bool")
25
-
26
-
27
- _SCOPED_ROUTE_CONSTRAINTS: ContextVar[ScopedRouteConstraints | None] = ContextVar(
28
- "scoped_route_constraints",
29
- default=None,
30
- )
31
-
32
- _EXPLICIT_SAVED_NOTES_PATTERNS = (
33
- re.compile(r"\b(?:my|our)\s+(?:saved\s+)?notes?\b", re.IGNORECASE),
34
- re.compile(
35
- r"\b(?:summari[sz]e|search|find|review|read|inspect|analy[sz]e|"
36
- r"synthesi[sz]e)\b(?:\W+\w+){0,12}\W+notes?\b",
37
- re.IGNORECASE,
38
- ),
39
- )
40
- _SAVED_NOTES_EXCLUSION_PATTERN = re.compile(
41
- r"\b(?:without|do\s+not|don't|dont)\b.{0,48}"
42
- r"\b(?:use|using|search|read|consult|reference)\b.{0,48}"
43
- r"\b(?:my|our)?\s*(?:saved\s+)?notes?\b",
44
- re.IGNORECASE,
45
- )
46
-
47
-
48
- def request_explicitly_requires_saved_notes(user_message: str) -> bool:
49
- if not isinstance(user_message, str):
50
- raise TypeError("user_message must be a string")
51
- if user_message.strip() == "":
52
- raise ValueError("user_message must not be blank")
53
- if _SAVED_NOTES_EXCLUSION_PATTERN.search(user_message) is not None:
54
- return False
55
- return any(
56
- pattern.search(user_message) is not None
57
- for pattern in _EXPLICIT_SAVED_NOTES_PATTERNS
58
- )
59
-
60
-
61
- @contextmanager
62
- def bind_scoped_route_constraints(
63
- constraints: ScopedRouteConstraints,
64
- ) -> Iterator[None]:
65
- if not isinstance(constraints, ScopedRouteConstraints):
66
- raise TypeError("constraints must be ScopedRouteConstraints")
67
- token = _SCOPED_ROUTE_CONSTRAINTS.set(constraints)
68
- try:
69
- yield
70
- finally:
71
- _SCOPED_ROUTE_CONSTRAINTS.reset(token)
11
+ from app.services.agent.help_catalog import HelpTopic
72
12
 
73
13
 
74
14
  def _validate_agent_search_query(value: str) -> str:
@@ -163,10 +103,11 @@ class ScopedRouteEnvelope(BaseModel):
163
103
 
164
104
  model_config = ConfigDict(extra="forbid")
165
105
 
166
- kind: Literal["respond", "investigate_current_scope", "tag_proposals"] = Field(
106
+ kind: Literal["respond", "investigate_current_scope", "tag_proposals", "metalist_help"] = Field(
167
107
  ...,
168
108
  description=(
169
- "respond for requests answerable without the user's notes; "
109
+ "metalist_help for MetaList product questions or opening menus, with relevant help_topics; "
110
+ "respond for requests answerable from the supplied selected note tree alone or without note evidence; "
170
111
  "investigate_current_scope only when the answer depends on evidence "
171
112
  "inside the frozen active MetaList result scope. "
172
113
  "tag_proposals ONLY for an explicit current user request to generate, "
@@ -174,6 +115,16 @@ class ScopedRouteEnvelope(BaseModel):
174
115
  "hypotheticals, and unrelated requests must never select tag_proposals."
175
116
  ),
176
117
  )
118
+ help_topics: list[HelpTopic] = Field(..., max_length=10, description="Relevant product-help topics for metalist_help; empty for other routes.")
119
+
120
+ @model_validator(mode="after")
121
+ def validate_help_topics(self) -> Self:
122
+ if len(set(self.help_topics)) != len(self.help_topics):
123
+ raise ValueError("Help topics must be unique")
124
+ if (self.kind == "metalist_help") != bool(self.help_topics):
125
+ raise ValueError("Only metalist_help requires nonempty help_topics")
126
+ return self
127
+
177
128
  reason: str = Field(..., min_length=1, max_length=4_000)
178
129
 
179
130
  @field_validator("reason")
@@ -183,20 +134,6 @@ class ScopedRouteEnvelope(BaseModel):
183
134
  raise ValueError("Scoped route reason must not be blank")
184
135
  return value
185
136
 
186
- @model_validator(mode="after")
187
- def enforce_explicit_saved_notes_request(self) -> Self:
188
- constraints = _SCOPED_ROUTE_CONSTRAINTS.get()
189
- if (
190
- constraints is not None
191
- and constraints.explicit_saved_notes_request
192
- and self.kind not in {"investigate_current_scope", "tag_proposals"}
193
- ):
194
- raise ValueError(
195
- "The user explicitly requests evidence from saved notes; choose "
196
- "investigate_current_scope, not respond"
197
- )
198
- return self
199
-
200
137
 
201
138
  AgentAction = Annotated[
202
139
  Union[SearchNotesAction, ReadNotesByIdAction, RespondAction],
@@ -16,7 +16,7 @@ from app.utils.text_utils import strip_html
16
16
 
17
17
  CLOUD_PRIVACY_POLICY_PREFERENCE_KEY = "pref.ai.cloud_privacy_policy"
18
18
  _CLOUD_PROVIDERS = frozenset({"openai"})
19
- _SUPPORTED_PROVIDERS = frozenset({"ollama", "openai"})
19
+ _SUPPORTED_PROVIDERS = frozenset({"openai"})
20
20
  _MAX_POLICY_ENTRIES_PER_LIST = 200
21
21
  _MAX_POLICY_TAG_LENGTH = 256
22
22
  _MAX_POLICY_PHRASE_LENGTH = 500
@@ -261,16 +261,38 @@ class CloudPrivacyEvaluator:
261
261
  note_id: str,
262
262
  match_plan: _CloudPrivacyMatchPlan,
263
263
  ) -> bool:
264
+ return self._direct_exclusion_reason(note_id=note_id, match_plan=match_plan) != ""
265
+
266
+ def exclusion_reason(self, *, note_id: str, boundary: CloudPrivacyBoundary) -> str:
267
+ """Return a content-free reason, including restrictions on ancestors."""
268
+ match_plan = self._match_plan(boundary)
269
+ reasons = set()
270
+ seen = set()
271
+ current_id = note_id
272
+ while True:
273
+ assert current_id not in seen, "Hierarchy cycle in disclosure boundary"
274
+ seen.add(current_id)
275
+ reasons.add(self._direct_exclusion_reason(note_id=current_id, match_plan=match_plan))
276
+ parent_id = self._notes.get_note(current_id).parent_id
277
+ if parent_id is None:
278
+ break
279
+ current_id = parent_id
280
+ for reason in ("password_protected", "blacklisted", "not_whitelisted"):
281
+ if reason in reasons:
282
+ return reason
283
+ return ""
284
+
285
+ def _direct_exclusion_reason(self, *, note_id: str, match_plan: _CloudPrivacyMatchPlan) -> str:
264
286
  record = self._notes.get_note(note_id)
265
287
  effective_tags_casefold = {
266
288
  tag.casefold() for tag in self._effective_tags_provider(note_id)
267
289
  }
268
290
  if "@password" in effective_tags_casefold:
269
- return True
291
+ return "password_protected"
270
292
  if not match_plan.apply_cloud_policy:
271
- return False
293
+ return ""
272
294
  if effective_tags_casefold & match_plan.blacklist_tags:
273
- return True
295
+ return "blacklisted"
274
296
  needs_plaintext = any(
275
297
  (match_plan.blacklist_phrases, match_plan.whitelist_phrases)
276
298
  )
@@ -280,14 +302,16 @@ class CloudPrivacyEvaluator:
280
302
  if any(
281
303
  phrase in plaintext_casefold for phrase in match_plan.blacklist_phrases
282
304
  ):
283
- return True
305
+ return "blacklisted"
284
306
  if not match_plan.has_whitelist:
285
- return False
307
+ return ""
286
308
  if effective_tags_casefold & match_plan.whitelist_tags:
287
- return False
288
- return not any(
309
+ return ""
310
+ if any(
289
311
  phrase in plaintext_casefold for phrase in match_plan.whitelist_phrases
290
- )
312
+ ):
313
+ return ""
314
+ return "not_whitelisted"
291
315
 
292
316
  @staticmethod
293
317
  def _match_plan(boundary: CloudPrivacyBoundary) -> _CloudPrivacyMatchPlan: