MetaList 0.10.0__tar.gz → 0.12.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 (546) hide show
  1. {metalist-0.10.0 → metalist-0.12.0}/PKG-INFO +20 -1
  2. {metalist-0.10.0 → metalist-0.12.0}/README.md +19 -0
  3. {metalist-0.10.0 → metalist-0.12.0}/app/api/middleware/auth.py +0 -16
  4. {metalist-0.10.0 → metalist-0.12.0}/app/api/note_requests.py +4 -2
  5. {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/ai.py +8 -57
  6. {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/auth.py +2 -1
  7. {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/notes.py +49 -158
  8. {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/ontology.py +0 -4
  9. {metalist-0.10.0 → metalist-0.12.0}/app/api/transactions.py +3 -1
  10. {metalist-0.10.0 → metalist-0.12.0}/app/db/notes_sql.py +9 -8
  11. {metalist-0.10.0 → metalist-0.12.0}/app/encryption_audit.py +11 -2
  12. {metalist-0.10.0 → metalist-0.12.0}/app/exception_boundaries.py +3 -1
  13. {metalist-0.10.0 → metalist-0.12.0}/app/main.py +8 -1
  14. {metalist-0.10.0 → metalist-0.12.0}/app/models/utils.py +4 -1
  15. metalist-0.12.0/app/security/sensitive_cache.py +116 -0
  16. metalist-0.12.0/app/services/agent/agent_loop.py +556 -0
  17. metalist-0.12.0/app/services/agent/agent_tools.py +464 -0
  18. metalist-0.12.0/app/services/agent/citation_tokens.py +62 -0
  19. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/context.py +59 -258
  20. metalist-0.12.0/app/services/agent/execution_errors.py +7 -0
  21. metalist-0.12.0/app/services/agent/failure_explanations.py +164 -0
  22. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/help_catalog.py +2 -21
  23. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/history.py +19 -1
  24. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/inference.py +29 -0
  25. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/investigation.py +67 -0
  26. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/model_policy.py +1 -2
  27. metalist-0.12.0/app/services/agent/note_aliases.py +77 -0
  28. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/openai_inference.py +169 -1
  29. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/prompt_settings.py +8 -49
  30. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/prompts/__init__.py +1 -1
  31. metalist-0.12.0/app/services/agent/prompts/agent.md +125 -0
  32. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/prompts/final-response.md +3 -5
  33. metalist-0.12.0/app/services/agent/prompts/system.md +28 -0
  34. metalist-0.12.0/app/services/agent/release_notes.py +50 -0
  35. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/runtime.py +90 -1341
  36. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/scope.py +16 -1
  37. metalist-0.12.0/app/services/agent/skill_settings.py +130 -0
  38. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/__init__.py +0 -2
  39. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-ai.md +45 -22
  40. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-formatting.md +4 -1
  41. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-menus.md +4 -8
  42. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-notes.md +17 -3
  43. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-privacy.md +1 -1
  44. metalist-0.12.0/app/services/agent/skills/help-releases.md +100 -0
  45. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-search.md +1 -1
  46. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/structured_inference.py +34 -17
  47. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/tagging.py +0 -15
  48. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/tagging_run.py +49 -37
  49. metalist-0.12.0/app/services/agent/tool_calling.py +147 -0
  50. metalist-0.12.0/app/services/agent/web_actions.py +214 -0
  51. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/web_capabilities.py +21 -0
  52. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/web_evidence.py +22 -0
  53. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/web_fetch.py +16 -3
  54. {metalist-0.10.0 → metalist-0.12.0}/app/services/ai_chat_stream.py +5 -2
  55. {metalist-0.10.0 → metalist-0.12.0}/app/services/bulk_operation.py +31 -7
  56. {metalist-0.10.0 → metalist-0.12.0}/app/services/client_state_service.py +9 -22
  57. {metalist-0.10.0 → metalist-0.12.0}/app/services/content_formatting.py +46 -3
  58. {metalist-0.10.0 → metalist-0.12.0}/app/services/embedded_references.py +53 -26
  59. {metalist-0.10.0 → metalist-0.12.0}/app/services/encryption.py +29 -12
  60. {metalist-0.10.0 → metalist-0.12.0}/app/services/html_export.py +3 -2
  61. metalist-0.12.0/app/services/inline_image_dimensions.py +140 -0
  62. {metalist-0.10.0 → metalist-0.12.0}/app/services/integrity.py +3 -2
  63. {metalist-0.10.0 → metalist-0.12.0}/app/services/link_titles.py +16 -0
  64. {metalist-0.10.0 → metalist-0.12.0}/app/services/markdown_rendering.py +16 -1
  65. {metalist-0.10.0 → metalist-0.12.0}/app/services/note_image_tags.py +11 -0
  66. {metalist-0.10.0 → metalist-0.12.0}/app/services/note_store.py +193 -48
  67. {metalist-0.10.0 → metalist-0.12.0}/app/services/request_recovery.py +4 -0
  68. {metalist-0.10.0 → metalist-0.12.0}/app/services/root_sorting.py +127 -59
  69. {metalist-0.10.0 → metalist-0.12.0}/app/services/search_history.py +84 -35
  70. {metalist-0.10.0 → metalist-0.12.0}/app/services/search_index.py +125 -61
  71. {metalist-0.10.0 → metalist-0.12.0}/app/services/search_query.py +5 -1
  72. {metalist-0.10.0 → metalist-0.12.0}/app/services/snapshot.py +400 -179
  73. {metalist-0.10.0 → metalist-0.12.0}/app/services/store.py +3 -1
  74. {metalist-0.10.0 → metalist-0.12.0}/app/services/sync.py +7 -1
  75. {metalist-0.10.0 → metalist-0.12.0}/app/services/tab_state.py +8 -0
  76. {metalist-0.10.0 → metalist-0.12.0}/app/services/tag_suggestions.py +24 -31
  77. {metalist-0.10.0 → metalist-0.12.0}/app/services/tag_term_matching.py +35 -33
  78. {metalist-0.10.0 → metalist-0.12.0}/app/services/undo_state.py +13 -2
  79. metalist-0.12.0/app/services/view_cache.py +99 -0
  80. {metalist-0.10.0 → metalist-0.12.0}/app/startup_sanity.py +28 -1
  81. {metalist-0.10.0 → metalist-0.12.0}/app/static/config/agent-menu-actions.json +9 -9
  82. {metalist-0.10.0 → metalist-0.12.0}/app/static/config/command_palette_tags.json +6 -6
  83. {metalist-0.10.0 → metalist-0.12.0}/app/static/css/main.css +182 -143
  84. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/main.js +2 -0
  85. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/ai-chat-api.js +0 -9
  86. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/ai-chat-panel-controller.js +80 -32
  87. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/ai-chat-panel-service.js +0 -66
  88. metalist-0.12.0/app/static/js/modules/ai-chat/confirmation-card.js +93 -0
  89. metalist-0.12.0/app/static/js/modules/ai-chat/confirmation-question.js +28 -0
  90. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/proposal-menu.js +6 -7
  91. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/api-client.js +18 -6
  92. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/auth.js +2 -0
  93. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/command-palette-controller.js +44 -79
  94. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/endpoint-registry.js +10 -10
  95. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/config.js +2 -2
  96. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/error-overlay.js +22 -1
  97. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/excalidraw/excalidraw-actions.js +5 -0
  98. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/excalidraw/excalidraw-preview-service.js +29 -0
  99. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/expected-errors.js +9 -0
  100. metalist-0.12.0/app/static/js/modules/modals/visual-cues-modal.js +138 -0
  101. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/actions/content-actions.js +2 -11
  102. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/actions/note-actions.js +70 -21
  103. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/actions/selection-actions.js +71 -4
  104. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/actions/ui-actions.js +104 -30
  105. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/events/input-events.js +0 -3
  106. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/events/keyboard-events.js +51 -6
  107. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/events/mouse-events.js +253 -30
  108. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/mode-context.js +93 -0
  109. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/mode-manager-controller.js +10 -2
  110. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/animated-scroll-service.js +4 -0
  111. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/collapse-affordance-service.js +50 -21
  112. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/collapse-editing-policy-service.js +8 -0
  113. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/differential-view-service.js +2 -0
  114. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/edit-session-collapse-policy-service.js +3 -1
  115. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/edit-session-collapse-service.js +9 -2
  116. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/file-image-preview-service.js +25 -0
  117. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/file-reference-service.js +3 -2
  118. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/floating-note-service.js +2 -0
  119. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/html-paste-sanitizer-service.js +4 -2
  120. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/infinite-scroll-service.js +41 -52
  121. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/mermaid-render-service.js +49 -0
  122. metalist-0.12.0/app/static/js/modules/mode-manager/services/note-drag-indicator-service.js +117 -0
  123. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/polling-service.js +42 -6
  124. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/root-date-separator-service.js +1 -1
  125. metalist-0.12.0/app/static/js/modules/mode-manager/services/root-note-creation-service.js +34 -0
  126. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/root-sort-service.js +31 -2
  127. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/scroll-restoration-service.js +28 -3
  128. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/scroll-to-top-service.js +13 -2
  129. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-syntax-service.js +28 -0
  130. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tab-state-service.js +17 -4
  131. metalist-0.12.0/app/static/js/modules/mode-manager/services/viewport-hold-service.js +755 -0
  132. metalist-0.12.0/app/static/js/vendor/dompurify-3.4.16.min.js +7 -0
  133. {metalist-0.10.0 → metalist-0.12.0}/app/templates/base.html +1 -1
  134. {metalist-0.10.0 → metalist-0.12.0}/app/templates/index.html +1 -0
  135. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/bulk_tag_proposals.py +9 -5
  136. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/delete_subtree.py +3 -1
  137. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/delete_tag.py +10 -7
  138. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/prioritize.py +5 -4
  139. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/rename_tag.py +6 -5
  140. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/view.py +3 -3
  141. {metalist-0.10.0 → metalist-0.12.0}/app/utils/text_utils.py +3 -4
  142. {metalist-0.10.0 → metalist-0.12.0}/app/version.py +1 -1
  143. {metalist-0.10.0 → metalist-0.12.0}/metalist.egg-info/PKG-INFO +20 -1
  144. {metalist-0.10.0 → metalist-0.12.0}/metalist.egg-info/SOURCES.txt +20 -10
  145. metalist-0.10.0/app/security/sensitive_cache.py +0 -78
  146. metalist-0.10.0/app/services/agent/actions.py +0 -292
  147. metalist-0.10.0/app/services/agent/permissions.py +0 -30
  148. metalist-0.10.0/app/services/agent/prompts/help-response.md +0 -25
  149. metalist-0.10.0/app/services/agent/prompts/system.md +0 -92
  150. metalist-0.10.0/app/services/agent/prompts/tool-result.md +0 -2
  151. metalist-0.10.0/app/services/agent/skill_settings.py +0 -219
  152. metalist-0.10.0/app/services/agent/skills/scoped-investigation.md +0 -27
  153. metalist-0.10.0/app/services/agent/tools.py +0 -323
  154. metalist-0.10.0/app/services/view_cache.py +0 -122
  155. metalist-0.10.0/app/static/js/modules/ai-chat/agent-prompt-service.js +0 -257
  156. metalist-0.10.0/app/static/js/modules/modals/agent-prompt-editor-modal.js +0 -347
  157. metalist-0.10.0/app/static/js/vendor/dompurify-3.4.13.min.js +0 -3
  158. {metalist-0.10.0 → metalist-0.12.0}/MANIFEST.in +0 -0
  159. {metalist-0.10.0 → metalist-0.12.0}/app/__init__.py +0 -0
  160. {metalist-0.10.0 → metalist-0.12.0}/app/api/__init__.py +0 -0
  161. {metalist-0.10.0 → metalist-0.12.0}/app/api/deps.py +0 -0
  162. {metalist-0.10.0 → metalist-0.12.0}/app/api/dev.py +0 -0
  163. {metalist-0.10.0 → metalist-0.12.0}/app/api/request_auth.py +0 -0
  164. {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/app_updates.py +0 -0
  165. {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/backups.py +0 -0
  166. {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/files.py +0 -0
  167. {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/reminders.py +0 -0
  168. {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/remote_images.py +0 -0
  169. {metalist-0.10.0 → metalist-0.12.0}/app/api/routes/test.py +0 -0
  170. {metalist-0.10.0 → metalist-0.12.0}/app/api/upload_limits.py +0 -0
  171. {metalist-0.10.0 → metalist-0.12.0}/app/config.py +0 -0
  172. {metalist-0.10.0 → metalist-0.12.0}/app/data_directory.py +0 -0
  173. {metalist-0.10.0 → metalist-0.12.0}/app/db/__init__.py +0 -0
  174. {metalist-0.10.0 → metalist-0.12.0}/app/db/backup_settings_sql.py +0 -0
  175. {metalist-0.10.0 → metalist-0.12.0}/app/db/editable_files_migration.py +0 -0
  176. {metalist-0.10.0 → metalist-0.12.0}/app/db/engine.py +0 -0
  177. {metalist-0.10.0 → metalist-0.12.0}/app/db/file_schema.py +0 -0
  178. {metalist-0.10.0 → metalist-0.12.0}/app/db/file_session.py +0 -0
  179. {metalist-0.10.0 → metalist-0.12.0}/app/db/files_sql.py +0 -0
  180. {metalist-0.10.0 → metalist-0.12.0}/app/db/link_titles_sql.py +0 -0
  181. {metalist-0.10.0 → metalist-0.12.0}/app/db/live_recovery.py +0 -0
  182. {metalist-0.10.0 → metalist-0.12.0}/app/db/migrations.py +0 -0
  183. {metalist-0.10.0 → metalist-0.12.0}/app/db/ontology_rules_sql.py +0 -0
  184. {metalist-0.10.0 → metalist-0.12.0}/app/db/reminders_sql.py +0 -0
  185. {metalist-0.10.0 → metalist-0.12.0}/app/db/retire_sounds.py +0 -0
  186. {metalist-0.10.0 → metalist-0.12.0}/app/db/schema.py +0 -0
  187. {metalist-0.10.0 → metalist-0.12.0}/app/db/search_history_sql.py +0 -0
  188. {metalist-0.10.0 → metalist-0.12.0}/app/db/session.py +0 -0
  189. {metalist-0.10.0 → metalist-0.12.0}/app/db/settings_sql.py +0 -0
  190. {metalist-0.10.0 → metalist-0.12.0}/app/db/tab_state_sql.py +0 -0
  191. {metalist-0.10.0 → metalist-0.12.0}/app/db/version.py +0 -0
  192. {metalist-0.10.0 → metalist-0.12.0}/app/https_proxy.py +0 -0
  193. {metalist-0.10.0 → metalist-0.12.0}/app/models/commands.py +0 -0
  194. {metalist-0.10.0 → metalist-0.12.0}/app/models/database.py +0 -0
  195. {metalist-0.10.0 → metalist-0.12.0}/app/models/entities.py +0 -0
  196. {metalist-0.10.0 → metalist-0.12.0}/app/models/enums.py +0 -0
  197. {metalist-0.10.0 → metalist-0.12.0}/app/models/linked_list.py +0 -0
  198. {metalist-0.10.0 → metalist-0.12.0}/app/models/list_operations.py +0 -0
  199. {metalist-0.10.0 → metalist-0.12.0}/app/models/list_traversal.py +0 -0
  200. {metalist-0.10.0 → metalist-0.12.0}/app/models/note_crud.py +0 -0
  201. {metalist-0.10.0 → metalist-0.12.0}/app/network_settings.py +0 -0
  202. {metalist-0.10.0 → metalist-0.12.0}/app/presentation/__init__.py +0 -0
  203. {metalist-0.10.0 → metalist-0.12.0}/app/presentation/render/__init__.py +0 -0
  204. {metalist-0.10.0 → metalist-0.12.0}/app/presentation/render/note_renderer.py +0 -0
  205. {metalist-0.10.0 → metalist-0.12.0}/app/presentation/templates.py +0 -0
  206. {metalist-0.10.0 → metalist-0.12.0}/app/security/authenticated_logging.py +0 -0
  207. {metalist-0.10.0 → metalist-0.12.0}/app/security/encryption.py +0 -0
  208. {metalist-0.10.0 → metalist-0.12.0}/app/security/http_error_diagnostics.py +0 -0
  209. {metalist-0.10.0 → metalist-0.12.0}/app/security/http_headers.py +0 -0
  210. {metalist-0.10.0 → metalist-0.12.0}/app/security/note_html.py +0 -0
  211. {metalist-0.10.0 → metalist-0.12.0}/app/security/request_boundary.py +0 -0
  212. {metalist-0.10.0 → metalist-0.12.0}/app/security/request_hosts.py +0 -0
  213. {metalist-0.10.0 → metalist-0.12.0}/app/security/sensitive_logging.py +0 -0
  214. {metalist-0.10.0 → metalist-0.12.0}/app/security/shell_execution.py +0 -0
  215. {metalist-0.10.0 → metalist-0.12.0}/app/security/validation_errors.py +0 -0
  216. {metalist-0.10.0 → metalist-0.12.0}/app/server_runtime.py +0 -0
  217. {metalist-0.10.0 → metalist-0.12.0}/app/services/__init__.py +0 -0
  218. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/__init__.py +0 -0
  219. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/cloud_privacy.py +0 -0
  220. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/evidence_serialization.py +0 -0
  221. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/judging.py +0 -0
  222. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/menu_actions.py +0 -0
  223. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/openai_cost_tracking.py +0 -0
  224. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/retrieval_settings.py +0 -0
  225. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-data.md +0 -0
  226. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-references.md +0 -0
  227. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-reminders.md +0 -0
  228. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/help-tags.md +0 -0
  229. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/staged-summary.md +0 -0
  230. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/tag-proposals.md +0 -0
  231. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/skills/web-browsing.md +0 -0
  232. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/staged_summary.py +0 -0
  233. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/token_estimation.py +0 -0
  234. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/trace.py +0 -0
  235. {metalist-0.10.0 → metalist-0.12.0}/app/services/agent/web_settings.py +0 -0
  236. {metalist-0.10.0 → metalist-0.12.0}/app/services/ai_chat.py +0 -0
  237. {metalist-0.10.0 → metalist-0.12.0}/app/services/ai_chat_rendering.py +0 -0
  238. {metalist-0.10.0 → metalist-0.12.0}/app/services/app_update_worker.py +0 -0
  239. {metalist-0.10.0 → metalist-0.12.0}/app/services/app_updates.py +0 -0
  240. {metalist-0.10.0 → metalist-0.12.0}/app/services/auth.py +0 -0
  241. {metalist-0.10.0 → metalist-0.12.0}/app/services/auth_cache_state.py +0 -0
  242. {metalist-0.10.0 → metalist-0.12.0}/app/services/auth_service.py +0 -0
  243. {metalist-0.10.0 → metalist-0.12.0}/app/services/backlink_index.py +0 -0
  244. {metalist-0.10.0 → metalist-0.12.0}/app/services/backlinks.py +0 -0
  245. {metalist-0.10.0 → metalist-0.12.0}/app/services/backup_service.py +0 -0
  246. {metalist-0.10.0 → metalist-0.12.0}/app/services/backup_settings_service.py +0 -0
  247. {metalist-0.10.0 → metalist-0.12.0}/app/services/content_cache.py +0 -0
  248. {metalist-0.10.0 → metalist-0.12.0}/app/services/diagnostics.py +0 -0
  249. {metalist-0.10.0 → metalist-0.12.0}/app/services/exception_capture.py +0 -0
  250. {metalist-0.10.0 → metalist-0.12.0}/app/services/file_edit_sessions.py +0 -0
  251. {metalist-0.10.0 → metalist-0.12.0}/app/services/file_registry.py +0 -0
  252. {metalist-0.10.0 → metalist-0.12.0}/app/services/file_storage.py +0 -0
  253. {metalist-0.10.0 → metalist-0.12.0}/app/services/footnote_layout.py +0 -0
  254. {metalist-0.10.0 → metalist-0.12.0}/app/services/footnote_rendering.py +0 -0
  255. {metalist-0.10.0 → metalist-0.12.0}/app/services/hierarchy.py +0 -0
  256. {metalist-0.10.0 → metalist-0.12.0}/app/services/html_unformatting.py +0 -0
  257. {metalist-0.10.0 → metalist-0.12.0}/app/services/hydration_state.py +0 -0
  258. {metalist-0.10.0 → metalist-0.12.0}/app/services/image_size_formatting.py +0 -0
  259. {metalist-0.10.0 → metalist-0.12.0}/app/services/inline_image_occurrences.py +0 -0
  260. {metalist-0.10.0 → metalist-0.12.0}/app/services/input_errors.py +0 -0
  261. {metalist-0.10.0 → metalist-0.12.0}/app/services/latex_rendering.py +0 -0
  262. {metalist-0.10.0 → metalist-0.12.0}/app/services/login_rate_limit.py +0 -0
  263. {metalist-0.10.0 → metalist-0.12.0}/app/services/maintenance_mode.py +0 -0
  264. {metalist-0.10.0 → metalist-0.12.0}/app/services/namespace_deletion_jobs.py +0 -0
  265. {metalist-0.10.0 → metalist-0.12.0}/app/services/namespace_deletion_worker.py +0 -0
  266. {metalist-0.10.0 → metalist-0.12.0}/app/services/namespace_rename_jobs.py +0 -0
  267. {metalist-0.10.0 → metalist-0.12.0}/app/services/namespace_rename_worker.py +0 -0
  268. {metalist-0.10.0 → metalist-0.12.0}/app/services/namespace_runtime_guard.py +0 -0
  269. {metalist-0.10.0 → metalist-0.12.0}/app/services/namespace_switcher.py +0 -0
  270. {metalist-0.10.0 → metalist-0.12.0}/app/services/note_fullscreen.py +0 -0
  271. {metalist-0.10.0 → metalist-0.12.0}/app/services/note_ordering.py +0 -0
  272. {metalist-0.10.0 → metalist-0.12.0}/app/services/ontology_rules_store.py +0 -0
  273. {metalist-0.10.0 → metalist-0.12.0}/app/services/openai_credentials.py +0 -0
  274. {metalist-0.10.0 → metalist-0.12.0}/app/services/password_note_fields.py +0 -0
  275. {metalist-0.10.0 → metalist-0.12.0}/app/services/public_http.py +0 -0
  276. {metalist-0.10.0 → metalist-0.12.0}/app/services/reference_presentation.py +0 -0
  277. {metalist-0.10.0 → metalist-0.12.0}/app/services/reminders.py +0 -0
  278. {metalist-0.10.0 → metalist-0.12.0}/app/services/remote_image_proxy.py +0 -0
  279. {metalist-0.10.0 → metalist-0.12.0}/app/services/resource_limits.py +0 -0
  280. {metalist-0.10.0 → metalist-0.12.0}/app/services/runtime_generation.py +0 -0
  281. {metalist-0.10.0 → metalist-0.12.0}/app/services/runtime_hardening.py +0 -0
  282. {metalist-0.10.0 → metalist-0.12.0}/app/services/runtime_lock.py +0 -0
  283. {metalist-0.10.0 → metalist-0.12.0}/app/services/search_history_storage.py +0 -0
  284. {metalist-0.10.0 → metalist-0.12.0}/app/services/search_text.py +0 -0
  285. {metalist-0.10.0 → metalist-0.12.0}/app/services/selected_text_tag.py +0 -0
  286. {metalist-0.10.0 → metalist-0.12.0}/app/services/self_update.py +0 -0
  287. {metalist-0.10.0 → metalist-0.12.0}/app/services/session_timeout_service.py +0 -0
  288. {metalist-0.10.0 → metalist-0.12.0}/app/services/shell_session_service.py +0 -0
  289. {metalist-0.10.0 → metalist-0.12.0}/app/services/structured_note_renderers.py +0 -0
  290. {metalist-0.10.0 → metalist-0.12.0}/app/services/sync_state.py +0 -0
  291. {metalist-0.10.0 → metalist-0.12.0}/app/services/tag_case.py +0 -0
  292. {metalist-0.10.0 → metalist-0.12.0}/app/services/tag_ontology.py +0 -0
  293. {metalist-0.10.0 → metalist-0.12.0}/app/services/tag_rename.py +0 -0
  294. {metalist-0.10.0 → metalist-0.12.0}/app/services/test_reset.py +0 -0
  295. {metalist-0.10.0 → metalist-0.12.0}/app/services/tokens.py +0 -0
  296. {metalist-0.10.0 → metalist-0.12.0}/app/services/update_backups.py +0 -0
  297. {metalist-0.10.0 → metalist-0.12.0}/app/services/update_installer.py +0 -0
  298. {metalist-0.10.0 → metalist-0.12.0}/app/services/update_preflight.py +0 -0
  299. {metalist-0.10.0 → metalist-0.12.0}/app/services/view_diff.py +0 -0
  300. {metalist-0.10.0 → metalist-0.12.0}/app/services/view_state.py +0 -0
  301. {metalist-0.10.0 → metalist-0.12.0}/app/services/windows_process_control.py +0 -0
  302. {metalist-0.10.0 → metalist-0.12.0}/app/startup_environment.py +0 -0
  303. {metalist-0.10.0 → metalist-0.12.0}/app/startup_js_sanity.py +0 -0
  304. {metalist-0.10.0 → metalist-0.12.0}/app/startup_sanity_config.py +0 -0
  305. {metalist-0.10.0 → metalist-0.12.0}/app/static/css/floating-notes.css +0 -0
  306. {metalist-0.10.0 → metalist-0.12.0}/app/static/css/forms.css +0 -0
  307. {metalist-0.10.0 → metalist-0.12.0}/app/static/img/favicon.ico +0 -0
  308. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/locked.js +0 -0
  309. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/activity-tracker.js +0 -0
  310. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/agent-menu-actions.js +0 -0
  311. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/agent-retrieval-settings.js +0 -0
  312. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/agent-web-settings.js +0 -0
  313. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/ai-agent-debug-view.js +0 -0
  314. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/ai-chat-message-placement.js +0 -0
  315. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/ai-thinking-level-service.js +0 -0
  316. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/bulk-elapsed-clock.js +0 -0
  317. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/bulk-proposal-ui.js +0 -0
  318. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/bulk-scope-question.js +0 -0
  319. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/cloud-privacy-policy.js +0 -0
  320. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/ai-chat/summary-batch-preview.js +0 -0
  321. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/api-error-diagnostics.js +0 -0
  322. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/api-failure-classification-service.js +0 -0
  323. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/app-update-service.js +0 -0
  324. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/application-state.js +0 -0
  325. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/async-result.js +0 -0
  326. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/client-state-api.js +0 -0
  327. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/client-state-migration.js +0 -0
  328. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/activation-auth-policy.js +0 -0
  329. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/backup-command-availability.js +0 -0
  330. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/click-activation-service.js +0 -0
  331. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/note-layout-preferences.js +0 -0
  332. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/preferences-store.js +0 -0
  333. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/tag-config-loader.js +0 -0
  334. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/command-palette/usage-store.js +0 -0
  335. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/connectivity-monitor.js +0 -0
  336. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/context-menu/context-menu-registry.js +0 -0
  337. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/context-menu/context-menu-service.js +0 -0
  338. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/context-menu/context-menu-target-service.js +0 -0
  339. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/context-menu/input-caret-service.js +0 -0
  340. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/disconnect-editing-state-service.js +0 -0
  341. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/dom-utils-fixed.js +0 -0
  342. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/dom-utils.js +0 -0
  343. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/editor-commands.js +0 -0
  344. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/editor-selection.js +0 -0
  345. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/editor-toolbar.js +0 -0
  346. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/elapsed-time.js +0 -0
  347. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/error-handler.js +0 -0
  348. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/excalidraw/excalidraw-autosave.js +0 -0
  349. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/excalidraw/excalidraw-editor-service.js +0 -0
  350. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/excalidraw/excalidraw-editor-state.js +0 -0
  351. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/excalidraw/excalidraw-loader.js +0 -0
  352. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/excalidraw/excalidraw-scene.js +0 -0
  353. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/location-flags.js +0 -0
  354. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/login-namespace-picker.js +0 -0
  355. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/maintenance.js +0 -0
  356. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/ai-agent-settings-modal.js +0 -0
  357. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/alphabetize-root-notes-modal.js +0 -0
  358. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/backup-restore-modal.js +0 -0
  359. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/backup-result-modal.js +0 -0
  360. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/backup-retention-modal.js +0 -0
  361. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/backup-settings-modal.js +0 -0
  362. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/base-modal.js +0 -0
  363. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/confirmation-modal.js +0 -0
  364. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/delete-namespace-modal.js +0 -0
  365. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/delete-namespace-validation.js +0 -0
  366. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/help-modal.js +0 -0
  367. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/namespace-loading-page.js +0 -0
  368. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/namespace-modals.js +0 -0
  369. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/namespace-ports-profile.js +0 -0
  370. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/namespace-rename-validation.js +0 -0
  371. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/note-layout-appearance-modal.js +0 -0
  372. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/ontology-modal.js +0 -0
  373. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/password-modal.js +0 -0
  374. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/prioritize-modal.js +0 -0
  375. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/random-password-modal.js +0 -0
  376. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/reminder-modal.js +0 -0
  377. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/reset-updated-at-modal.js +0 -0
  378. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/search-suggestion-statistics-modal.js +0 -0
  379. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/session-timeout-modal.js +0 -0
  380. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/modals/version-info-modal.js +0 -0
  381. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/actions/history-actions.js +0 -0
  382. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/actions/search-actions.js +0 -0
  383. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/events/context-menu-events.js +0 -0
  384. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/events/focus-events.js +0 -0
  385. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/events/inactivity-events.js +0 -0
  386. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/events/search-events.js +0 -0
  387. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/mode-logger.js +0 -0
  388. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/add-style-service.js +0 -0
  389. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/backlinks-navigation-service.js +0 -0
  390. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/backlinks-panel-service.js +0 -0
  391. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/clipboard-shortcut-policy-service.js +0 -0
  392. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/command-gate-service.js +0 -0
  393. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/context-menu-target-service.js +0 -0
  394. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/deselect-selection-state-service.js +0 -0
  395. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/embedded-image-service.js +0 -0
  396. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/file-drop-policy-service.js +0 -0
  397. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/filtered-refresh-selection-service.js +0 -0
  398. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/floating-note-dom.js +0 -0
  399. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/floating-note-layout.js +0 -0
  400. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/footnote-navigation-service.js +0 -0
  401. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/history-selection-policy-service.js +0 -0
  402. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/history-shortcut-policy-service.js +0 -0
  403. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/image-context-menu-action-service.js +0 -0
  404. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/image-file-insert-choice-modal-service.js +0 -0
  405. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/link-context-menu-action-service.js +0 -0
  406. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/link-title-prefetch-service.js +0 -0
  407. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/markdown-render-service.js +0 -0
  408. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-click-target-service.js +0 -0
  409. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-clipboard-write-service.js +0 -0
  410. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-collapse-animation-service.js +0 -0
  411. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-context-menu-action-service.js +0 -0
  412. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-delete-shortcut-policy-service.js +0 -0
  413. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-drag-service.js +0 -0
  414. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-fullscreen-service.js +0 -0
  415. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-reposition-animation-service.js +0 -0
  416. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-split-service.js +0 -0
  417. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/note-timestamp-hover-service.js +0 -0
  418. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/password-clipboard-service.js +0 -0
  419. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/reference-source-navigation-service.js +0 -0
  420. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/remote-image-proxy-service.js +0 -0
  421. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/remove-formatting-service.js +0 -0
  422. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/root-sort-indicator-service.js +0 -0
  423. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/scroll-anchor-service.js +0 -0
  424. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-contexts-overlay-service.js +0 -0
  425. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-debounce-service.js +0 -0
  426. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-input-service.js +0 -0
  427. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-interaction-service.js +0 -0
  428. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-redaction-reveal-service.js +0 -0
  429. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-suggestion-statistics-service.js +0 -0
  430. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-suggestion-window-labels-service.js +0 -0
  431. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-suggestion-windows-service.js +0 -0
  432. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/search-suggestions-service.js +0 -0
  433. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/selected-formatting-removal-service.js +0 -0
  434. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/selected-text-tag-service.js +0 -0
  435. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/shell-output-service.js +0 -0
  436. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tab-dom-cache-service.js +0 -0
  437. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tab-drag-service.js +0 -0
  438. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tab-duplication-service.js +0 -0
  439. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tag-bar-service.js +0 -0
  440. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tag-input-selection-service.js +0 -0
  441. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tag-proposal-service.js +0 -0
  442. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tag-suggestions-service.js +0 -0
  443. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/tag-syntax-service.js +0 -0
  444. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/todo-toggle-editing-service.js +0 -0
  445. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/untagged-view-indicator-service.js +0 -0
  446. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/mode-manager/services/view-mode-search-shortcut-service.js +0 -0
  447. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/note-html-sanitizer.js +0 -0
  448. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/password-generator.js +0 -0
  449. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/password-operation-response.js +0 -0
  450. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/password-policy.js +0 -0
  451. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/password-strength.js +0 -0
  452. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/reminder-store.js +0 -0
  453. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/reminder-surface-service.js +0 -0
  454. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/selection-markers.js +0 -0
  455. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/session-auth.js +0 -0
  456. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/tag-token.js +0 -0
  457. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/modules/uuid.js +0 -0
  458. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/namespace-deleted.js +0 -0
  459. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/namespace-renamed.js +0 -0
  460. /metalist-0.10.0/app/static/js/vendor/dompurify-3.4.13.LICENSE.txt → /metalist-0.12.0/app/static/js/vendor/dompurify-3.4.16.LICENSE.txt +0 -0
  461. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/excalidraw.css +0 -0
  462. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Bold.woff2 +0 -0
  463. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Medium.woff2 +0 -0
  464. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-Regular.woff2 +0 -0
  465. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Assistant/Assistant-SemiBold.woff2 +0 -0
  466. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Cascadia/CascadiaCode-Regular.woff2 +0 -0
  467. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2 +0 -0
  468. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2 +0 -0
  469. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2 +0 -0
  470. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/ComicShanns/ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2 +0 -0
  471. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2 +0 -0
  472. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2 +0 -0
  473. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2 +0 -0
  474. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2 +0 -0
  475. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2 +0 -0
  476. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2 +0 -0
  477. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Excalifont/Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2 +0 -0
  478. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2 +0 -0
  479. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Lilita/Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2 +0 -0
  480. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2 +0 -0
  481. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2 +0 -0
  482. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2 +0 -0
  483. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2 +0 -0
  484. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Nunito/Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2 +0 -0
  485. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1-assets/fonts/Virgil/Virgil-Regular.woff2 +0 -0
  486. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1.LICENSE.txt +0 -0
  487. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/excalidraw-0.18.1.min.js +0 -0
  488. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/markdown-it-14.3.2.LICENSE.txt +0 -0
  489. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/markdown-it-14.3.2.min.js +0 -0
  490. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/mermaid-11.16.1.LICENSE.txt +0 -0
  491. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/mermaid-11.16.1.min.js +0 -0
  492. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/zxcvbn-4.4.2.LICENSE.txt +0 -0
  493. {metalist-0.10.0 → metalist-0.12.0}/app/static/js/vendor/zxcvbn-4.4.2.js +0 -0
  494. {metalist-0.10.0 → metalist-0.12.0}/app/static/note-html-policy.json +0 -0
  495. {metalist-0.10.0 → metalist-0.12.0}/app/static/video/login-startup.mp4 +0 -0
  496. {metalist-0.10.0 → metalist-0.12.0}/app/templates/locked.html +0 -0
  497. {metalist-0.10.0 → metalist-0.12.0}/app/templates/maintenance.html +0 -0
  498. {metalist-0.10.0 → metalist-0.12.0}/app/templates/namespace_deleted.html +0 -0
  499. {metalist-0.10.0 → metalist-0.12.0}/app/templates/namespace_renamed.html +0 -0
  500. {metalist-0.10.0 → metalist-0.12.0}/app/templates/notes_list.html +0 -0
  501. {metalist-0.10.0 → metalist-0.12.0}/app/upload_limits.py +0 -0
  502. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/__init__.py +0 -0
  503. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/add_selected_text_tag.py +0 -0
  504. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/alphabetize_root_notes.py +0 -0
  505. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/base.py +0 -0
  506. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/collapse.py +0 -0
  507. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/copy_note.py +0 -0
  508. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/create_child.py +0 -0
  509. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/create_note.py +0 -0
  510. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/create_sibling.py +0 -0
  511. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/expand.py +0 -0
  512. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/file_edit_session.py +0 -0
  513. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/indent.py +0 -0
  514. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/lock.py +0 -0
  515. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/move.py +0 -0
  516. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/move_to_top.py +0 -0
  517. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/outdent.py +0 -0
  518. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/paste_child.py +0 -0
  519. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/paste_sibling.py +0 -0
  520. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/prefetch_link_titles.py +0 -0
  521. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/redo.py +0 -0
  522. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/reset_updated_at.py +0 -0
  523. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/resize_image.py +0 -0
  524. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/run_shell.py +0 -0
  525. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/search_comment_autofill.py +0 -0
  526. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/search_context_tags.py +0 -0
  527. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/set_collapse_bulk.py +0 -0
  528. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/set_collapse_in_context.py +0 -0
  529. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/split_note.py +0 -0
  530. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/tag_proposals.py +0 -0
  531. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/toggle_reference_mode.py +0 -0
  532. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/toggle_todo_done.py +0 -0
  533. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/undo.py +0 -0
  534. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/unformat_content.py +0 -0
  535. {metalist-0.10.0 → metalist-0.12.0}/app/usecases/update_content.py +0 -0
  536. {metalist-0.10.0 → metalist-0.12.0}/app/utils/__init__.py +0 -0
  537. {metalist-0.10.0 → metalist-0.12.0}/app/utils/encryption.py +0 -0
  538. {metalist-0.10.0 → metalist-0.12.0}/convert-from-legacy.py +0 -0
  539. {metalist-0.10.0 → metalist-0.12.0}/main.py +0 -0
  540. {metalist-0.10.0 → metalist-0.12.0}/metalist.egg-info/dependency_links.txt +0 -0
  541. {metalist-0.10.0 → metalist-0.12.0}/metalist.egg-info/entry_points.txt +0 -0
  542. {metalist-0.10.0 → metalist-0.12.0}/metalist.egg-info/requires.txt +0 -0
  543. {metalist-0.10.0 → metalist-0.12.0}/metalist.egg-info/top_level.txt +0 -0
  544. {metalist-0.10.0 → metalist-0.12.0}/pyproject.toml +0 -0
  545. {metalist-0.10.0 → metalist-0.12.0}/scripts/generate-lan-cert.sh +0 -0
  546. {metalist-0.10.0 → metalist-0.12.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metalist
3
- Version: 0.10.0
3
+ Version: 0.12.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,25 @@ 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.12.0
53
+
54
+ - 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.
55
+ - Nothing changes without your Yes: tag operations ask first with the exact change, and web addresses that carry words from your notes ask before opening. Summaries that fit in one pass start without a dialog, and summaries never block other edits while they run.
56
+ - "How do I change…" questions open the menu that holds the setting; release notes are part of the help. AI prompts and skills are no longer editable, and a $ button shows or hides the spend estimate.
57
+ - The AI is told only that a note is private, never which privacy setting hides it, and failed AI steps are explained in the chat.
58
+ - Leaving edit mode keeps your place, with no highlight; a collapsed note you changed stays expanded. Clicking into a note keeps the clicked spot under the pointer, including in diagrams and formulas.
59
+ - Dragging a note shows a ghost, a drop line and a direction cursor; the note lands where you dropped it without the page scrolling.
60
+ - Searches that cannot be parsed are explained politely instead of failing.
61
+
62
+ ## Changes in 0.11.0
63
+
64
+ - Large namespaces stay fast while scrolling: only a band of root notes around the viewport is loaded, the server remembers what each tab shows so the browser no longer sends note hashes, and rendered notes are cached.
65
+ - Tag suggestions, searches with only exclusions (`-tag`), and the updated/content-volume sort orders respond much faster on large namespaces.
66
+ - Accepting or removing tag proposals in bulk, renaming or deleting a tag, and undoing a large delete no longer rebuild every note's inherited tags.
67
+ - Unlocking an encrypted namespace is faster, and the startup encryption audit no longer loads every attachment into memory.
68
+ - Fixed undo of deleting a note whose children have several children, and "accept all" failing on tag bars with leading or trailing spaces.
69
+ - Fixed crashes in the status check after returning to a tab and in scroll-position saving.
70
+
52
71
  ## Changes in 0.10.0
53
72
 
54
73
  - Excalidraw diagrams: add one from the note's right-click menu or the command palette, and double-click a diagram to edit it full screen. Diagrams autosave, show light and dark previews, resize like images, and each editing session is one undo step. The editor is bundled locally and needs no Node server.
@@ -12,6 +12,25 @@ 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.12.0
16
+
17
+ - 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.
18
+ - Nothing changes without your Yes: tag operations ask first with the exact change, and web addresses that carry words from your notes ask before opening. Summaries that fit in one pass start without a dialog, and summaries never block other edits while they run.
19
+ - "How do I change…" questions open the menu that holds the setting; release notes are part of the help. AI prompts and skills are no longer editable, and a $ button shows or hides the spend estimate.
20
+ - The AI is told only that a note is private, never which privacy setting hides it, and failed AI steps are explained in the chat.
21
+ - Leaving edit mode keeps your place, with no highlight; a collapsed note you changed stays expanded. Clicking into a note keeps the clicked spot under the pointer, including in diagrams and formulas.
22
+ - Dragging a note shows a ghost, a drop line and a direction cursor; the note lands where you dropped it without the page scrolling.
23
+ - Searches that cannot be parsed are explained politely instead of failing.
24
+
25
+ ## Changes in 0.11.0
26
+
27
+ - Large namespaces stay fast while scrolling: only a band of root notes around the viewport is loaded, the server remembers what each tab shows so the browser no longer sends note hashes, and rendered notes are cached.
28
+ - Tag suggestions, searches with only exclusions (`-tag`), and the updated/content-volume sort orders respond much faster on large namespaces.
29
+ - Accepting or removing tag proposals in bulk, renaming or deleting a tag, and undoing a large delete no longer rebuild every note's inherited tags.
30
+ - Unlocking an encrypted namespace is faster, and the startup encryption audit no longer loads every attachment into memory.
31
+ - Fixed undo of deleting a note whose children have several children, and "accept all" failing on tag bars with leading or trailing spaces.
32
+ - Fixed crashes in the status check after returning to a tab and in scroll-position saving.
33
+
15
34
  ## Changes in 0.10.0
16
35
 
17
36
  - Excalidraw diagrams: add one from the note's right-click menu or the command palette, and double-click a diagram to edit it full screen. Diagrams autosave, show light and dark previews, resize like images, and each editing session is one undo step. The editor is bundled locally and needs no Node server.
@@ -37,11 +37,6 @@ class AuthMiddleware(BaseHTTPMiddleware):
37
37
  )
38
38
  assert all(path.endswith("/") for path in PUBLIC_PREFIX_PATHS)
39
39
 
40
- # Paths to suppress verbose logging for (frequent polling endpoints)
41
- QUIET_PATHS = [
42
- f"{API_PREFIX}/auth/status",
43
- ]
44
-
45
40
  # Background/automated paths that should NOT refresh tokens (not user activity)
46
41
  NO_TOKEN_REFRESH_PATHS = [
47
42
  f"{API_PREFIX}/auth/status", # Polling service pings this for connectivity
@@ -75,20 +70,9 @@ class AuthMiddleware(BaseHTTPMiddleware):
75
70
  # Redirect all other requests to maintenance page
76
71
  return RedirectResponse(url="/maintenance", status_code=302)
77
72
 
78
- # Check if this is a quiet path (suppress verbose logging)
79
- is_quiet = any(path.startswith(quiet) for quiet in self.QUIET_PATHS)
80
-
81
- if not is_quiet:
82
- print(f"Middleware checking path: {path}")
83
-
84
73
  if self.is_public_path(path=path):
85
- if not is_quiet:
86
- print(f"Path {path} is explicitly public, skipping auth")
87
74
  return await call_next(request)
88
75
 
89
- if not is_quiet:
90
- print(f"Path {path} is NOT public, checking auth")
91
-
92
76
  # Startup and recoverable password transitions publish this memory-owned flag.
93
77
  if path == f"{API_PREFIX}/auth/settings/password/create" and not is_encryption_required():
94
78
  return await call_next(request)
@@ -56,8 +56,9 @@ class ViewDiffRequest(TypedDict):
56
56
  search: Text | None
57
57
  tabId: Identifier
58
58
  undoContext: UndoContext
59
- clientNoteUuidHashes: dict[Identifier, Text]
60
- visibleRootAnchorId: Text | None
59
+ tabViewEmpty: bool
60
+ visibleTopRootId: Text | None
61
+ visibleBottomRootId: Text | None
61
62
  isUntaggedView: bool
62
63
 
63
64
  @with_config(ConfigDict(strict=True))
@@ -76,6 +77,7 @@ class UpdateTabSortModeRequest(TypedDict):
76
77
  @with_config(ConfigDict(strict=True))
77
78
  class CreateNewTabRequest(TypedDict):
78
79
  copyFromTabId: Identifier
80
+ clientId: Identifier
79
81
 
80
82
  @with_config(ConfigDict(strict=True))
81
83
  class DeleteTabRequest(TypedDict):
@@ -33,21 +33,17 @@ from app.services.agent.openai_inference import OpenAIInferenceAdapter
33
33
  from app.services.agent.openai_inference import validate_openai_model
34
34
  from app.services.agent.openai_cost_tracking import OpenAICostSnapshot
35
35
  from app.services.agent.openai_cost_tracking import openai_cost_tracker
36
- from app.services.agent.permissions import AgentPermissionPolicy
37
36
  from app.services.agent.prompt_settings import AgentPromptSet
38
37
  from app.services.agent.skill_settings import AgentSkillSet
39
38
  from app.services.agent.retrieval_settings import AgentRetrievalSettings
40
39
  from app.services.agent.scope import ScopedSearchSnapshot
41
40
  from app.services.agent.prompt_settings import DEFAULT_AGENT_PROMPTS
42
- from app.services.agent.prompt_settings import resolve_agent_prompt_set
43
41
  from app.services.agent.retrieval_settings import resolve_agent_retrieval_settings
44
42
  from app.services.agent.scope import AgentScopeDescriptor
45
43
  from app.services.agent.scope import scoped_search_snapshot_factory
46
44
  from app.services.agent.runtime import AgentRuntime
47
45
  from app.services.agent.skill_settings import DEFAULT_AGENT_SKILLS
48
- from app.services.agent.skill_settings import resolve_agent_skill_set
49
46
  from app.services.agent.token_estimation import estimate_input_tokens
50
- from app.services.agent.tools import read_only_agent_tools
51
47
  from app.services.agent.trace import agent_trace_store
52
48
  from app.services.agent.menu_actions import MenuResult, menu_action_store
53
49
  from app.services.client_state_service import load_client_preferences
@@ -62,7 +58,7 @@ from app.services.agent.retrieval_settings import resolve_tagging_batch_tokens
62
58
  from app.services.agent.web_settings import AgentWebSettings
63
59
  from app.services.agent.web_settings import resolve_agent_web_settings
64
60
  from app.services.agent.web_evidence import web_evidence_store
65
- from app.services.agent.tagging import TAGGING_PROMPT_KEY, TAGGING_POLICY_KEY, DEFAULT_TAGGING_PROMPT
61
+ from app.services.agent.tagging import TAGGING_POLICY_KEY
66
62
  from app.usecases.bulk_tag_proposals import apply_bulk_proposals, prepare_proposal_changes
67
63
  from app.services.bulk_operation import bulk_operation_guard
68
64
  from app.services.tab_state import tab_state_store
@@ -79,8 +75,6 @@ def _agent_runtime(*, inference: InferenceAdapter) -> AgentRuntime:
79
75
  context_builder=agent_context_builder,
80
76
  inference=inference,
81
77
  model_policy=SingleModelPolicy(),
82
- permission_policy=AgentPermissionPolicy(),
83
- tool_registry=read_only_agent_tools,
84
78
  trace_store=agent_trace_store,
85
79
  provider_label=inference.provider_label,
86
80
  )
@@ -136,23 +130,6 @@ class CloudPrivacyPreviewResponse(BaseModel):
136
130
  hidden_note_ids: list[str]
137
131
 
138
132
 
139
- class AiSkillDefaultResponse(BaseModel):
140
- skill_id: str
141
- title: str
142
- description: str
143
- trigger_action: str
144
- preference_key: str
145
- content: str
146
- superseded_preference_keys: list[str]
147
-
148
-
149
- class AiPromptDefaultsResponse(BaseModel):
150
- system_prompt: str
151
- final_response_prompt: str
152
- tool_result_prompt: str
153
- skills: list[AiSkillDefaultResponse]
154
-
155
-
156
133
  class AiChatRequest(BaseModel):
157
134
  model_config = ConfigDict(extra="forbid")
158
135
 
@@ -384,32 +361,6 @@ def reset_openai_cost(
384
361
  return _openai_cost_response(openai_cost_tracker.snapshot())
385
362
 
386
363
 
387
- @router.get("/prompts/defaults", response_model=AiPromptDefaultsResponse)
388
- def get_ai_prompt_defaults(
389
- response: Response,
390
- token: Annotated[str, Depends(require_request_auth_token)],
391
- ) -> AiPromptDefaultsResponse:
392
- del token
393
- response.headers["Cache-Control"] = "no-store"
394
- return AiPromptDefaultsResponse(
395
- system_prompt=DEFAULT_AGENT_PROMPTS.system_prompt,
396
- final_response_prompt=DEFAULT_AGENT_PROMPTS.final_response_prompt,
397
- tool_result_prompt=DEFAULT_AGENT_PROMPTS.tool_result_prompt,
398
- skills=[
399
- AiSkillDefaultResponse(
400
- skill_id=skill.skill_id,
401
- title=skill.title,
402
- description=skill.description,
403
- trigger_action=skill.trigger_action,
404
- preference_key=skill.preference_key,
405
- content=skill.content,
406
- superseded_preference_keys=list(skill.superseded_preference_keys),
407
- )
408
- for skill in DEFAULT_AGENT_SKILLS.skills
409
- ],
410
- )
411
-
412
-
413
364
  @router.post(
414
365
  "/cloud-privacy/preview",
415
366
  response_model=CloudPrivacyPreviewResponse,
@@ -637,8 +588,8 @@ def stream_ai_chat(
637
588
  session_key=session_key,
638
589
  )
639
590
  preferences = load_client_preferences(token=token)
640
- prompts = resolve_agent_prompt_set(preferences=preferences)
641
- skills = resolve_agent_skill_set(preferences=preferences)
591
+ prompts = DEFAULT_AGENT_PROMPTS
592
+ skills = DEFAULT_AGENT_SKILLS
642
593
  retrieval_settings = resolve_agent_retrieval_settings(
643
594
  preferences=preferences,
644
595
  provider=payload.provider,
@@ -731,11 +682,11 @@ async def _stream_runtime_events(
731
682
  approx_input_tokens=initial_input_tokens, output_tokens_received=0, duration_ms=0.0)
732
683
  yield dict(type='action_status', action=action, status='completed', label=ready_label,
733
684
  approx_input_tokens=initial_input_tokens, output_tokens_received=0, duration_ms=0.0)
734
- events = runtime.stream_scoped(session_key=session_key, base_url=base_url,
685
+ events = runtime.stream_agent(session_key=session_key, base_url=base_url,
735
686
  selected_model=payload.model, thinking_level=payload.thinking_level,
736
687
  canonical_messages=provider_messages, prompts=prompts, skills=skills,
737
688
  retrieval_settings=retrieval_settings, web_settings=web_settings,
738
- frozen_scope=frozen_scope, tag_handler=tagging_run.stream)
689
+ frozen_scope=frozen_scope, tagging_run=tagging_run)
739
690
  try:
740
691
  async for event in events:
741
692
  yield event
@@ -771,6 +722,8 @@ class BulkAnswerRequest(BaseModel):
771
722
  "prefix_focus_both",
772
723
  "summarize_all",
773
724
  "use_prefix",
725
+ "yes",
726
+ "no",
774
727
  ]
775
728
 
776
729
 
@@ -820,6 +773,4 @@ def manage_bulk_proposals(payload: BulkManageRequest, token: Annotated[str, Depe
820
773
  @router.get("/proposals/settings")
821
774
  def get_tagging_settings(token: Annotated[str, Depends(require_request_auth_token)]):
822
775
  preferences = load_client_preferences(token=token)
823
- return {"policy": preferences.get(TAGGING_POLICY_KEY, ""),
824
- "prompt": preferences.get(TAGGING_PROMPT_KEY, DEFAULT_TAGGING_PROMPT),
825
- "default_prompt": DEFAULT_TAGGING_PROMPT}
776
+ return {"policy": preferences.get(TAGGING_POLICY_KEY, "")}
@@ -713,7 +713,8 @@ def auth_status(
713
713
  "version": VERSION,
714
714
  "database_user_version": database_user_version,
715
715
  "authenticated": token is not None,
716
- "has_password": auth.has_password(),
716
+ # Same answer as AuthService.has_password(), from the row already read.
717
+ "has_password": settings is not None and bool(settings.encryption_enabled),
717
718
  "encryption_enabled": settings.encryption_enabled if settings else False,
718
719
  "encryption_algorithm": settings.encryption_algorithm if settings else None,
719
720
  "vault_version": settings.vault_version if settings else None,
@@ -241,28 +241,25 @@ def view_diff(payload: ViewDiffRequest):
241
241
  search = payload["search"]
242
242
  tab_id = payload["tabId"]
243
243
  undo_context = payload["undoContext"]
244
- client_note_uuid_hashes = payload["clientNoteUuidHashes"]
245
- anchor_root_id = payload["visibleRootAnchorId"]
244
+ tab_view_empty = payload["tabViewEmpty"]
245
+ visible_top_root_id = payload["visibleTopRootId"]
246
+ visible_bottom_root_id = payload["visibleBottomRootId"]
246
247
  is_untagged_view = payload["isUntaggedView"]
247
248
  if not isinstance(is_untagged_view, bool):
248
249
  raise TypeError("isUntaggedView must be a boolean")
250
+ if not isinstance(tab_view_empty, bool):
251
+ raise TypeError("tabViewEmpty must be a boolean")
249
252
 
250
253
  sort_mode = _resolve_tab_sort_mode(tab_id)
251
- if not isinstance(client_note_uuid_hashes, dict):
252
- raise TypeError("clientNoteUuidHashes must be an object")
253
-
254
254
  normalized_search = search
255
255
  if isinstance(normalized_search, str) and normalized_search == "":
256
256
  normalized_search = None
257
257
  if normalized_search is not None:
258
258
  if not isinstance(normalized_search, str):
259
259
  raise HTTPException(status_code=400, detail="search must be a string or null")
260
- capture = CapturedExceptionContext(InputRejected, boundary='app/api/routes/notes.py:view_diff:capture')
261
- with capture:
262
- parse_search_query(normalized_search)
263
- if capture.captured_exception is not None:
264
- exc = capture.captured_exception
265
- raise HTTPException(status_code=400, detail=str(exc)) from exc
260
+ # Validated before anything changes; a search that does not parse is
261
+ # answered as rejected input (main.py), shown as a polite warning.
262
+ parse_search_query(normalized_search)
266
263
 
267
264
  maybe_reset_on_context(client_id, undo_context)
268
265
 
@@ -278,164 +275,63 @@ def view_diff(payload: ViewDiffRequest):
278
275
  if not note_store.has_note(normalized_editing_note_id):
279
276
  normalized_editing_note_id = None
280
277
 
281
- # Known hashes plus a viewport anchor so the server can extend the window
282
- client_hashes = {
283
- k: v for k, v in client_note_uuid_hashes.items() if k
284
- }
285
- # Fallback: if client didn't provide an anchor, use the last known root from cached state
286
- cache_key = {
287
- "client_id": client_id,
288
- "tab_id": tab_id,
289
- "search": normalized_search,
290
- "sort_mode": sort_mode,
291
- "is_untagged_view": is_untagged_view,
292
- }
293
- cached_state = view_cache.get(**cache_key)
294
- if not anchor_root_id and cached_state and client_hashes:
295
- last_roots = list(cached_state.children_by_parent.get(None, []))
296
- if last_roots:
297
- anchor_root_id = last_roots[-1]
278
+ # The server keeps each tab's warm view (what that browser tab displays),
279
+ # so the browser sends only where it is. A tab with no warm view, or one
280
+ # whose browser shows nothing for it, gets its initial window.
281
+ warm_view = view_cache.get(client_id=client_id, tab_id=tab_id)
282
+ if tab_view_empty:
283
+ warm_view = None
284
+ client_known_note_ids: set[str] = set()
285
+ # The tab's previous root order: a sorted tab keeps the edited note's root there.
286
+ previous_root_ids: list[str] = []
287
+ if warm_view is not None:
288
+ client_known_note_ids = set(warm_view.hash_by_id)
289
+ if None in warm_view.children_by_parent:
290
+ previous_root_ids = warm_view.children_by_parent[None]
298
291
 
299
292
  state = build_view_state(
300
293
  editing_note_id=normalized_editing_note_id,
301
294
  search=normalized_search,
302
295
  sort_mode=sort_mode,
303
- client_known_note_ids=set(client_hashes.keys()),
304
- client_seen_root_ids=set(),
305
- anchor_root_id=anchor_root_id,
296
+ client_known_note_ids=client_known_note_ids,
297
+ previous_root_ids=previous_root_ids,
298
+ visible_top_root_id=visible_top_root_id,
299
+ visible_bottom_root_id=visible_bottom_root_id,
306
300
  is_untagged_view=is_untagged_view,
307
301
  )
308
302
  update_uuid = get_current_sync_uuid()
309
303
  root_ids = list(state.children_by_parent.get(None, []))
310
- root_count_total = state.metadata["rootCountTotal"]
311
- search_root_count_total = state.metadata["searchRootCountTotal"]
312
-
313
- client_note_ids = set(client_hashes.keys())
314
- current_note_ids = set(state.hash_by_id.keys())
315
- if cached_state is None:
316
- cached_note_ids = set()
317
- else:
318
- cached_note_ids = set(cached_state.hash_by_id.keys())
319
- extra_client_ids = _unknown_client_note_ids(
320
- client_note_ids=client_note_ids,
321
- current_note_ids=current_note_ids,
322
- cached_note_ids=cached_note_ids,
323
- )
324
- force_full_snapshot = bool(extra_client_ids)
325
- if force_full_snapshot:
326
- logger.info(
327
- "notes.view forcing full snapshot (client has unknown ids): extra_count=%s",
328
- len(extra_client_ids),
329
- )
330
-
331
- client_has_state = bool(client_hashes)
332
-
333
- if not cached_state or force_full_snapshot:
334
- view_cache.set(state=state, **cache_key)
335
- if force_full_snapshot:
336
- filtered_notes = dict(state.payloads)
337
- else:
338
- filtered_notes = {
339
- note_id: data
340
- for note_id, data in state.payloads.items()
341
- if client_hashes.get(note_id) != data.get("hash")
342
- }
343
-
344
- # Optimization: when the server cache is cold but the client already has a
345
- # complete, matching hash map for the visible window, avoid resending the
346
- # full structure + note payloads. This is common when a new tab is created
347
- # by cloning the existing DOM.
348
- if client_has_state and not filtered_notes and not force_full_snapshot:
349
- response_snapshot = {
350
- "diffOps": [],
351
- "notes": {},
352
- "locks": state.locks,
353
- "rootIds": root_ids,
354
- "lockDiffs": {},
355
- "updateUUID": update_uuid,
356
- "version": VERSION,
357
- "currentClientId": client_id,
358
- "searchQuery": search,
359
- "sortMode": sort_mode,
360
- "isUntaggedView": is_untagged_view,
361
- "rootCountTotal": root_count_total,
362
- "searchRootCountTotal": search_root_count_total,
363
- "rootSortBuckets": state.metadata["rootSortBuckets"],
364
- "editingNoteId": normalized_editing_note_id,
365
- }
366
- return {"snapshot": response_snapshot, "updateUUID": update_uuid}
367
-
368
- response_snapshot = {
369
- "structure": state.structure,
370
- "notes": filtered_notes,
371
- "locks": state.locks,
372
- "rootIds": root_ids,
373
- "updateUUID": update_uuid,
374
- "version": VERSION,
375
- "currentClientId": client_id,
376
- "searchQuery": search,
377
- "sortMode": sort_mode,
378
- "isUntaggedView": is_untagged_view,
379
- "rootCountTotal": root_count_total,
380
- "searchRootCountTotal": search_root_count_total,
381
- "rootSortBuckets": state.metadata["rootSortBuckets"],
382
- "editingNoteId": normalized_editing_note_id,
383
- }
384
- return {"snapshot": response_snapshot, "updateUUID": update_uuid}
385
-
386
- if not client_has_state:
387
- view_cache.set(state=state, **cache_key)
388
- filtered_notes = {
389
- note_id: data
390
- for note_id, data in state.payloads.items()
391
- if client_hashes.get(note_id) != data.get("hash")
392
- }
393
- response_snapshot = {
394
- "structure": state.structure,
395
- "notes": filtered_notes,
396
- "locks": state.locks,
397
- "rootIds": root_ids,
398
- "updateUUID": update_uuid,
399
- "version": VERSION,
400
- "currentClientId": client_id,
401
- "searchQuery": search,
402
- "sortMode": sort_mode,
403
- "isUntaggedView": is_untagged_view,
404
- "rootCountTotal": root_count_total,
405
- "searchRootCountTotal": search_root_count_total,
406
- "rootSortBuckets": state.metadata["rootSortBuckets"],
407
- "editingNoteId": normalized_editing_note_id,
408
- }
409
- return {"snapshot": response_snapshot, "updateUUID": update_uuid}
410
-
411
- diff_ops = generate_diff_ops(cached_state, state)
412
- note_updates = {
413
- note_id: payload
414
- for note_id, payload in state.payloads.items()
415
- if cached_state.hash_by_id.get(note_id) != payload["hash"]
416
- }
417
-
418
- view_cache.set(state=state, **cache_key)
419
-
420
- lock_diff = _compute_lock_diff(cached_state.locks, state.locks)
421
-
304
+ view_cache.set(client_id=client_id, tab_id=tab_id, state=state)
422
305
  response_snapshot = {
423
- "diffOps": diff_ops,
424
- "notes": note_updates,
306
+ "notes": {},
425
307
  "locks": state.locks,
426
308
  "rootIds": root_ids,
427
- "lockDiffs": lock_diff,
428
309
  "updateUUID": update_uuid,
429
310
  "version": VERSION,
430
311
  "currentClientId": client_id,
431
312
  "searchQuery": search,
432
313
  "sortMode": sort_mode,
433
314
  "isUntaggedView": is_untagged_view,
434
- "rootCountTotal": root_count_total,
435
- "searchRootCountTotal": search_root_count_total,
315
+ "rootCountTotal": state.metadata["rootCountTotal"],
316
+ "searchRootCountTotal": state.metadata["searchRootCountTotal"],
436
317
  "rootSortBuckets": state.metadata["rootSortBuckets"],
318
+ "rootWindowStart": state.metadata["rootWindowStart"],
319
+ "rootBandMargin": state.metadata["rootBandMargin"],
320
+ "rootSortKeyBeforeWindow": state.metadata["rootSortKeyBeforeWindow"],
437
321
  "editingNoteId": normalized_editing_note_id,
438
322
  }
323
+ if warm_view is None:
324
+ response_snapshot["structure"] = state.structure
325
+ response_snapshot["notes"] = dict(state.payloads)
326
+ return {"snapshot": response_snapshot, "updateUUID": update_uuid}
327
+
328
+ response_snapshot["diffOps"] = generate_diff_ops(warm_view, state)
329
+ response_snapshot["notes"] = {
330
+ note_id: note_payload
331
+ for note_id, note_payload in state.payloads.items()
332
+ if note_id not in warm_view.hash_by_id or warm_view.hash_by_id[note_id] != note_payload["hash"]
333
+ }
334
+ response_snapshot["lockDiffs"] = _compute_lock_diff(warm_view.locks, state.locks)
439
335
  return {"snapshot": response_snapshot, "updateUUID": update_uuid}
440
336
 
441
337
 
@@ -501,6 +397,11 @@ def create_new_tab(payload: CreateNewTabRequest) -> Dict[str, object]:
501
397
  response = tab_state_store.create_tab(copy_from_tab_id=copy_from_tab_id)
502
398
  if capture.captured_exception is not None:
503
399
  raise HTTPException(status_code=400, detail="Invalid or stale tab state") from capture.captured_exception
400
+ # The browser clones the source tab's DOM into the new tab, so the new tab
401
+ # starts from the source tab's warm view.
402
+ view_cache.copy_tab(
403
+ client_id=payload["clientId"], source_tab_id=copy_from_tab_id, target_tab_id=response["newTabId"],
404
+ )
504
405
  return response
505
406
 
506
407
 
@@ -790,16 +691,6 @@ def _compute_lock_diff(previous: Dict[str, str], current: Dict[str, str]) -> Dic
790
691
  return diff
791
692
 
792
693
 
793
- def _unknown_client_note_ids(
794
- *,
795
- client_note_ids: set[str],
796
- current_note_ids: set[str],
797
- cached_note_ids: set[str],
798
- ) -> set[str]:
799
- stale_deleted_ids = client_note_ids - current_note_ids
800
- return stale_deleted_ids - cached_note_ids
801
-
802
-
803
694
  # Stub endpoints for the rest of the notes API (501 Not Implemented)
804
695
 
805
696
  def _not_impl(exc: Exception) -> None:
@@ -11,7 +11,6 @@ from app.api.transactions import transactional_route
11
11
  from app.services.search_index import search_index
12
12
  from app.services.note_store import store as note_store
13
13
  from app.services.sync import generate_new_uuid
14
- from app.services.view_cache import view_cache
15
14
  from app.services.tag_ontology import RegexAtom, TagAtom, TextAtom, parse_rules_text
16
15
  from app.services.ontology_rules_store import (
17
16
  build_direct_edge_rule_map,
@@ -155,7 +154,6 @@ def create_rule(request: Request, payload: RuleTextRequest) -> dict:
155
154
  rule_id, normalized = create_rule_line(text=text, token=token)
156
155
  if note_store.loaded:
157
156
  note_store.rebuild_search_index_tag_terms_for_notes(candidate_note_ids)
158
- view_cache.clear()
159
157
  update_uuid = generate_new_uuid()
160
158
  return {"id": rule_id, "text": normalized, "updateUUID": update_uuid}
161
159
  return {"id": rule_id, "text": normalized}
@@ -193,7 +191,6 @@ def update_rule(request: Request, rule_id: int, payload: RuleTextRequest) -> dic
193
191
  updated_id, normalized = update_rule_line(rule_id=rule_id, text=text, token=token)
194
192
  if note_store.loaded:
195
193
  note_store.rebuild_search_index_tag_terms_for_notes(candidate_note_ids)
196
- view_cache.clear()
197
194
  update_uuid = generate_new_uuid()
198
195
  return {"id": updated_id, "text": normalized, "updateUUID": update_uuid}
199
196
  return {"id": updated_id, "text": normalized}
@@ -224,7 +221,6 @@ def delete_rule(rule_id: int) -> dict:
224
221
  delete_rule_line(rule_id=rule_id)
225
222
  if note_store.loaded:
226
223
  note_store.rebuild_search_index_tag_terms_for_notes(candidate_note_ids)
227
- view_cache.clear()
228
224
  update_uuid = generate_new_uuid()
229
225
  return {"ok": True, "updateUUID": update_uuid}
230
226
  return {"ok": True}
@@ -125,6 +125,8 @@ def assert_mutation_routes_wrapped(app: FastAPI) -> None:
125
125
  def _check_bulk_guard(endpoint_name: str) -> None:
126
126
  if endpoint_name in _STORAGE_TRANSITIONS and bulk_operation_guard.active_mutations > 1:
127
127
  raise HTTPException(status_code=409, detail="Wait for the current request to finish before changing namespace storage.")
128
- permitted = {"answer_bulk_question", "preview_cloud_privacy", "put_ai_debug_details"}
128
+ # Preferences never touch notes, and every operation reads them once when it
129
+ # starts, so saving them (e.g. the chat panel width) cannot disturb it.
130
+ permitted = {"answer_bulk_question", "preview_cloud_privacy", "put_ai_debug_details", "put_client_preferences"}
129
131
  if bulk_operation_guard.operation_id and endpoint_name not in permitted:
130
132
  raise HTTPException(status_code=409, detail="A bulk operation is running. Wait or cancel it before changing the app.")
@@ -3,7 +3,6 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import sqlite3
6
- import time
7
6
  from datetime import datetime
8
7
  from typing import Iterable, Optional, Any
9
8
 
@@ -12,6 +11,9 @@ from .schema import NOTES_TABLE
12
11
  from app.services.hierarchy import validate_database_parent
13
12
 
14
13
 
14
+ _DELETE_CHUNK_SIZE = 900
15
+
16
+
15
17
  def _conn(connection: GuardedConnection | sqlite3.Connection) -> sqlite3.Connection:
16
18
  raw_connection = getattr(connection, "raw_connection", None)
17
19
  if isinstance(raw_connection, sqlite3.Connection):
@@ -403,14 +405,13 @@ def delete_notes(
403
405
  identifiers = list(note_ids)
404
406
  if not identifiers:
405
407
  return
406
- placeholders = ",".join(["?"] * len(identifiers))
407
- sql = f"DELETE FROM {NOTES_TABLE} WHERE id IN ({placeholders})"
408
- print('DEBUG CHECKPOINT 1')
409
- t1 = time.perf_counter()
410
408
  conn = _conn(connection)
411
- conn.execute(sql, tuple(identifiers))
412
- t2 = time.perf_counter()
413
- print(f'DEBUG CHECKPOINT 2 took {(t2-t1)} seconds')
409
+ # Chunk below SQLite's bound-variable limit (999 on older builds) so large
410
+ # subtree deletes do not fail; the caller's transaction keeps it atomic.
411
+ for start in range(0, len(identifiers), _DELETE_CHUNK_SIZE):
412
+ chunk = identifiers[start : start + _DELETE_CHUNK_SIZE]
413
+ placeholders = ",".join(["?"] * len(chunk))
414
+ conn.execute(f"DELETE FROM {NOTES_TABLE} WHERE id IN ({placeholders})", tuple(chunk))
414
415
 
415
416
 
416
417
  def fetch_note(
@@ -679,9 +679,18 @@ def _audit_payloads(
679
679
  needed_columns = {spec.value_column, spec.nonce_column, spec.tag_column}
680
680
  if not needed_columns.issubset(actual_columns):
681
681
  continue
682
+ value_expression = spec.value_column
683
+ if spec.storage_kind == "bytes":
684
+ # Binary checks need only the storage type: stand an empty BLOB in
685
+ # for each BLOB so file contents are never read into memory.
686
+ value_expression = (
687
+ f"CASE WHEN typeof({spec.value_column}) = 'blob' THEN zeroblob(0) "
688
+ f"ELSE {spec.value_column} END AS {spec.value_column}"
689
+ )
690
+ # Stream rows: payload tables can be far larger than memory should hold.
682
691
  rows = connection.execute(
683
- f"SELECT {spec.value_column}, {spec.nonce_column}, {spec.tag_column} FROM {spec.table}"
684
- ).fetchall()
692
+ f"SELECT {value_expression}, {spec.nonce_column}, {spec.tag_column} FROM {spec.table}"
693
+ )
685
694
  for row in rows:
686
695
  _audit_payload_row(
687
696
  row=row,
@@ -14,7 +14,9 @@ CAPTURE_BOUNDARIES = {
14
14
  'app/services/agent/web_fetch.py:_extract_pdf_content:pdf_capture': ('PyPdfError',),
15
15
  'app/services/agent/web_fetch.py:_decode_web_text:encoding_capture': ('LookupError',),
16
16
  'app/services/agent/web_fetch.py:handle_starttag:join_capture': ('ValueError',),
17
- 'app/services/agent/runtime.py:_open_web_action:evidence_capacity_capture': ('WebEvidenceCapacityError',),
17
+ 'app/services/agent/web_actions.py:open_web_pages:evidence_capacity_capture': ('WebEvidenceCapacityError',),
18
+ # A model's tool call is untrusted input; rejected arguments are explained back to the model.
19
+ 'app/services/agent/agent_tools.py:parse_tool_call:arguments_capture': ('ValidationError',),
18
20
  # In-app updates translate only external transport, installation eligibility and job lookup errors.
19
21
  'app/services/app_updates.py:check_for_update:eligibility': ('AppUpdateRejected',),
20
22
  'app/services/app_updates.py:job_path:validation': ('ValueError',),