MetaList 0.12.0__tar.gz → 0.13.0__tar.gz

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