basic-memory 0.19.1__tar.gz → 0.19.2__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 (637) hide show
  1. {basic_memory-0.19.1 → basic_memory-0.19.2}/CHANGELOG.md +12 -0
  2. {basic_memory-0.19.1 → basic_memory-0.19.2}/PKG-INFO +1 -1
  3. {basic_memory-0.19.1 → basic_memory-0.19.2}/server.json +2 -2
  4. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/__init__.py +1 -1
  5. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/canvas.py +5 -3
  6. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/search.py +12 -2
  7. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/write_note.py +4 -3
  8. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/search_repository_base.py +24 -9
  9. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/project_service.py +70 -44
  10. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/utils.py +63 -3
  11. basic_memory-0.19.2/test-int/mcp/test_string_params_integration.py +167 -0
  12. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_semantic_search_base.py +23 -0
  13. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_project_service_embedding_status.py +41 -0
  14. basic_memory-0.19.2/tests/test_coerce.py +58 -0
  15. basic_memory-0.19.2/tests/utils/test_setup_logging.py +162 -0
  16. {basic_memory-0.19.1 → basic_memory-0.19.2}/.claude/commands/release/beta.md +0 -0
  17. {basic_memory-0.19.1 → basic_memory-0.19.2}/.claude/commands/release/changelog.md +0 -0
  18. {basic_memory-0.19.1 → basic_memory-0.19.2}/.claude/commands/release/release-check.md +0 -0
  19. {basic_memory-0.19.1 → basic_memory-0.19.2}/.claude/commands/release/release.md +0 -0
  20. {basic_memory-0.19.1 → basic_memory-0.19.2}/.claude/commands/spec.md +0 -0
  21. {basic_memory-0.19.1 → basic_memory-0.19.2}/.claude/commands/test-live.md +0 -0
  22. {basic_memory-0.19.1 → basic_memory-0.19.2}/.claude/settings.json +0 -0
  23. {basic_memory-0.19.1 → basic_memory-0.19.2}/.dockerignore +0 -0
  24. {basic_memory-0.19.1 → basic_memory-0.19.2}/.env.example +0 -0
  25. {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  26. {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  27. {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
  28. {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  29. {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/dependabot.yml +0 -0
  30. {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/workflows/claude-code-review.yml +0 -0
  31. {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/workflows/claude-issue-triage.yml +0 -0
  32. {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/workflows/claude.yml +0 -0
  33. {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/workflows/dev-release.yml +0 -0
  34. {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/workflows/docker.yml +0 -0
  35. {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/workflows/pr-title.yml +0 -0
  36. {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/workflows/release.yml +0 -0
  37. {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/workflows/test.yml +0 -0
  38. {basic_memory-0.19.1 → basic_memory-0.19.2}/.gitignore +0 -0
  39. {basic_memory-0.19.1 → basic_memory-0.19.2}/.python-version +0 -0
  40. {basic_memory-0.19.1 → basic_memory-0.19.2}/AGENTS.md +0 -0
  41. {basic_memory-0.19.1 → basic_memory-0.19.2}/CITATION.cff +0 -0
  42. {basic_memory-0.19.1 → basic_memory-0.19.2}/CLA.md +0 -0
  43. {basic_memory-0.19.1 → basic_memory-0.19.2}/CLAUDE.md +0 -0
  44. {basic_memory-0.19.1 → basic_memory-0.19.2}/CODE_OF_CONDUCT.md +0 -0
  45. {basic_memory-0.19.1 → basic_memory-0.19.2}/CONTRIBUTING.md +0 -0
  46. {basic_memory-0.19.1 → basic_memory-0.19.2}/Dockerfile +0 -0
  47. {basic_memory-0.19.1 → basic_memory-0.19.2}/LICENSE +0 -0
  48. {basic_memory-0.19.1 → basic_memory-0.19.2}/NOTE-FORMAT.md +0 -0
  49. {basic_memory-0.19.1 → basic_memory-0.19.2}/README.md +0 -0
  50. {basic_memory-0.19.1 → basic_memory-0.19.2}/SECURITY.md +0 -0
  51. {basic_memory-0.19.1 → basic_memory-0.19.2}/docker-compose-postgres.yml +0 -0
  52. {basic_memory-0.19.1 → basic_memory-0.19.2}/docker-compose.yml +0 -0
  53. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/ARCHITECTURE.md +0 -0
  54. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/Docker.md +0 -0
  55. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/NOTE-FORMAT.md +0 -0
  56. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/SPEC-PER-PROJECT-ROUTING.md +0 -0
  57. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/ai-assistant-guide-extended.md +0 -0
  58. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/character-handling.md +0 -0
  59. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/cloud-cli.md +0 -0
  60. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/cloud-semantic-search-value.md +0 -0
  61. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/mcp-ui-bakeoff-instructions.md +0 -0
  62. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/metadata-search.md +0 -0
  63. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/post-v0.18.0-test-plan.md +0 -0
  64. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/releases/v0.19.0.md +0 -0
  65. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/semantic-search-test-log.md +0 -0
  66. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/semantic-search.md +0 -0
  67. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/specs/SPEC-LOCAL-PLUS-PUBLISH.md +0 -0
  68. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/specs/SPEC-SCHEMA-IMPL.md +0 -0
  69. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/specs/SPEC-SCHEMA.md +0 -0
  70. {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/testing-coverage.md +0 -0
  71. {basic_memory-0.19.1 → basic_memory-0.19.2}/justfile +0 -0
  72. {basic_memory-0.19.1 → basic_memory-0.19.2}/llms-install.md +0 -0
  73. {basic_memory-0.19.1 → basic_memory-0.19.2}/pyproject.toml +0 -0
  74. {basic_memory-0.19.1 → basic_memory-0.19.2}/smithery.yaml +0 -0
  75. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/alembic.ini +0 -0
  76. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/env.py +0 -0
  77. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/migrations.py +0 -0
  78. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/script.py.mako +0 -0
  79. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/314f1ea54dc4_add_postgres_full_text_search_support_.py +0 -0
  80. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +0 -0
  81. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +0 -0
  82. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +0 -0
  83. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +0 -0
  84. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/6830751f5fb6_merge_multiple_heads.py +0 -0
  85. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/9d9c1cb7d8f5_add_mtime_and_size_columns_to_entity_.py +0 -0
  86. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +0 -0
  87. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/a2b3c4d5e6f7_add_search_index_entity_cascade.py +0 -0
  88. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +0 -0
  89. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +0 -0
  90. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/d7e8f9a0b1c2_add_structured_metadata_indexes.py +0 -0
  91. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/e7e1f4367280_add_scan_watermark_tracking_to_project.py +0 -0
  92. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/f8a9b2c3d4e5_add_pg_trgm_for_fuzzy_link_resolution.py +0 -0
  93. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/g9a0b3c4d5e6_add_external_id_to_project_and_entity.py +0 -0
  94. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/h1b2c3d4e5f6_add_postgres_vector_search_tables.py +0 -0
  95. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/i2c3d4e5f6g7_auto_backfill_semantic_embeddings.py +0 -0
  96. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/j3d4e5f6g7h8_rename_entity_type_to_note_type.py +0 -0
  97. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/k4e5f6g7h8i9_add_created_by_and_last_updated_by_to_entity.py +0 -0
  98. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/__init__.py +0 -0
  99. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/app.py +0 -0
  100. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/container.py +0 -0
  101. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/template_loader.py +0 -0
  102. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/__init__.py +0 -0
  103. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/__init__.py +0 -0
  104. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/directory_router.py +0 -0
  105. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/importer_router.py +0 -0
  106. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/knowledge_router.py +0 -0
  107. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/memory_router.py +0 -0
  108. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/project_router.py +0 -0
  109. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/prompt_router.py +0 -0
  110. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/resource_router.py +0 -0
  111. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/schema_router.py +0 -0
  112. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/search_router.py +0 -0
  113. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/utils.py +0 -0
  114. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/__init__.py +0 -0
  115. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/analytics.py +0 -0
  116. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/app.py +0 -0
  117. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/auth.py +0 -0
  118. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/__init__.py +0 -0
  119. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/__init__.py +0 -0
  120. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/api_client.py +0 -0
  121. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/bisync_commands.py +0 -0
  122. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/cloud_utils.py +0 -0
  123. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/core_commands.py +0 -0
  124. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/project_sync.py +0 -0
  125. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/rclone_commands.py +0 -0
  126. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/rclone_config.py +0 -0
  127. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/rclone_installer.py +0 -0
  128. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/restore.py +0 -0
  129. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/schemas.py +0 -0
  130. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/snapshot.py +0 -0
  131. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/upload.py +0 -0
  132. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/upload_command.py +0 -0
  133. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/workspace.py +0 -0
  134. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/command_utils.py +0 -0
  135. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/db.py +0 -0
  136. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/doctor.py +0 -0
  137. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/format.py +0 -0
  138. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/import_chatgpt.py +0 -0
  139. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/import_claude_conversations.py +0 -0
  140. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/import_claude_projects.py +0 -0
  141. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/import_memory_json.py +0 -0
  142. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/mcp.py +0 -0
  143. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/project.py +0 -0
  144. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/routing.py +0 -0
  145. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/schema.py +0 -0
  146. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/status.py +0 -0
  147. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/tool.py +0 -0
  148. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/container.py +0 -0
  149. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/main.py +0 -0
  150. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/promo.py +0 -0
  151. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/config.py +0 -0
  152. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/db.py +0 -0
  153. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/deps/__init__.py +0 -0
  154. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/deps/config.py +0 -0
  155. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/deps/db.py +0 -0
  156. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/deps/importers.py +0 -0
  157. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/deps/projects.py +0 -0
  158. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/deps/repositories.py +0 -0
  159. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/deps/services.py +0 -0
  160. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/deps.py +0 -0
  161. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/file_utils.py +0 -0
  162. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/ignore_utils.py +0 -0
  163. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/importers/__init__.py +0 -0
  164. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/importers/base.py +0 -0
  165. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/importers/chatgpt_importer.py +0 -0
  166. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/importers/claude_conversations_importer.py +0 -0
  167. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/importers/claude_projects_importer.py +0 -0
  168. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/importers/memory_json_importer.py +0 -0
  169. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/importers/utils.py +0 -0
  170. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/markdown/__init__.py +0 -0
  171. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/markdown/entity_parser.py +0 -0
  172. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/markdown/markdown_processor.py +0 -0
  173. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/markdown/plugins.py +0 -0
  174. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/markdown/schemas.py +0 -0
  175. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/markdown/utils.py +0 -0
  176. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/__init__.py +0 -0
  177. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/async_client.py +0 -0
  178. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/clients/__init__.py +0 -0
  179. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/clients/directory.py +0 -0
  180. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/clients/knowledge.py +0 -0
  181. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/clients/memory.py +0 -0
  182. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/clients/project.py +0 -0
  183. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/clients/resource.py +0 -0
  184. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/clients/schema.py +0 -0
  185. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/clients/search.py +0 -0
  186. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/container.py +0 -0
  187. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/formatting.py +0 -0
  188. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/project_context.py +0 -0
  189. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/prompts/__init__.py +0 -0
  190. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/prompts/ai_assistant_guide.py +0 -0
  191. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/prompts/continue_conversation.py +0 -0
  192. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/prompts/recent_activity.py +0 -0
  193. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/prompts/search.py +0 -0
  194. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/prompts/utils.py +0 -0
  195. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/resources/__init__.py +0 -0
  196. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/resources/ai_assistant_guide.md +0 -0
  197. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/resources/cloud_info.md +0 -0
  198. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/resources/project_info.py +0 -0
  199. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/resources/release_notes.md +0 -0
  200. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/resources/ui.py +0 -0
  201. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/server.py +0 -0
  202. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/__init__.py +0 -0
  203. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/build_context.py +0 -0
  204. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/chatgpt_tools.py +0 -0
  205. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/cloud_info.py +0 -0
  206. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/delete_note.py +0 -0
  207. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/edit_note.py +0 -0
  208. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/list_directory.py +0 -0
  209. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/move_note.py +0 -0
  210. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/project_management.py +0 -0
  211. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/read_content.py +0 -0
  212. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/read_note.py +0 -0
  213. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/recent_activity.py +0 -0
  214. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/release_notes.py +0 -0
  215. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/schema.py +0 -0
  216. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/ui_sdk.py +0 -0
  217. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/utils.py +0 -0
  218. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/view_note.py +0 -0
  219. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/workspaces.py +0 -0
  220. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/__init__.py +0 -0
  221. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/html/note-preview-mcp-ui.html +0 -0
  222. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/html/note-preview-tool-ui.html +0 -0
  223. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/html/note-preview-vanilla.html +0 -0
  224. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/html/search-results-mcp-ui.html +0 -0
  225. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/html/search-results-tool-ui.html +0 -0
  226. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/html/search-results-vanilla.html +0 -0
  227. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/sdk.py +0 -0
  228. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/templates.py +0 -0
  229. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/models/__init__.py +0 -0
  230. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/models/base.py +0 -0
  231. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/models/knowledge.py +0 -0
  232. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/models/project.py +0 -0
  233. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/models/search.py +0 -0
  234. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/project_resolver.py +0 -0
  235. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/__init__.py +0 -0
  236. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/embedding_provider.py +0 -0
  237. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/embedding_provider_factory.py +0 -0
  238. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/entity_repository.py +0 -0
  239. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/fastembed_provider.py +0 -0
  240. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/metadata_filters.py +0 -0
  241. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/observation_repository.py +0 -0
  242. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/openai_provider.py +0 -0
  243. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/postgres_search_repository.py +0 -0
  244. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/project_info_repository.py +0 -0
  245. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/project_repository.py +0 -0
  246. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/relation_repository.py +0 -0
  247. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/repository.py +0 -0
  248. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/search_index_row.py +0 -0
  249. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/search_repository.py +0 -0
  250. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/semantic_errors.py +0 -0
  251. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/sqlite_search_repository.py +0 -0
  252. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/runtime.py +0 -0
  253. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schema/__init__.py +0 -0
  254. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schema/diff.py +0 -0
  255. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schema/inference.py +0 -0
  256. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schema/parser.py +0 -0
  257. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schema/resolver.py +0 -0
  258. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schema/validator.py +0 -0
  259. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/__init__.py +0 -0
  260. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/base.py +0 -0
  261. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/cloud.py +0 -0
  262. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/delete.py +0 -0
  263. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/directory.py +0 -0
  264. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/importer.py +0 -0
  265. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/memory.py +0 -0
  266. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/project_info.py +0 -0
  267. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/prompt.py +0 -0
  268. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/request.py +0 -0
  269. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/response.py +0 -0
  270. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/schema.py +0 -0
  271. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/search.py +0 -0
  272. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/sync_report.py +0 -0
  273. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/v2/__init__.py +0 -0
  274. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/v2/entity.py +0 -0
  275. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/v2/graph.py +0 -0
  276. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/v2/resource.py +0 -0
  277. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/__init__.py +0 -0
  278. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/context_service.py +0 -0
  279. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/directory_service.py +0 -0
  280. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/entity_service.py +0 -0
  281. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/exceptions.py +0 -0
  282. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/file_service.py +0 -0
  283. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/initialization.py +0 -0
  284. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/link_resolver.py +0 -0
  285. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/search_service.py +0 -0
  286. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/service.py +0 -0
  287. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/sync/__init__.py +0 -0
  288. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/sync/background_sync.py +0 -0
  289. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/sync/coordinator.py +0 -0
  290. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/sync/sync_service.py +0 -0
  291. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/sync/watch_service.py +0 -0
  292. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/templates/prompts/continue_conversation.hbs +0 -0
  293. {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/templates/prompts/search.hbs +0 -0
  294. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/BENCHMARKS.md +0 -0
  295. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/cli/test_cli_tool_edit_note_integration.py +0 -0
  296. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/cli/test_cli_tool_json_failure_integration.py +0 -0
  297. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/cli/test_cli_tool_json_integration.py +0 -0
  298. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/cli/test_project_commands_integration.py +0 -0
  299. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/cli/test_routing_integration.py +0 -0
  300. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/cli/test_search_notes_meta_integration.py +0 -0
  301. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/cli/test_version_integration.py +0 -0
  302. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/compare_search_benchmarks.py +0 -0
  303. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/conftest.py +0 -0
  304. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-01.md +0 -0
  305. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-02.md +0 -0
  306. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-03.md +0 -0
  307. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-04.md +0 -0
  308. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-05.md +0 -0
  309. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-06.md +0 -0
  310. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-07.md +0 -0
  311. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-08.md +0 -0
  312. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-09.md +0 -0
  313. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-10.md +0 -0
  314. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-11.md +0 -0
  315. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-12.md +0 -0
  316. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-13.md +0 -0
  317. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-14.md +0 -0
  318. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-15.md +0 -0
  319. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-16.md +0 -0
  320. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-17.md +0 -0
  321. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-18.md +0 -0
  322. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-19.md +0 -0
  323. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-20.md +0 -0
  324. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/schema/Person.md +0 -0
  325. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/edge-cases/array-single.md +0 -0
  326. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/edge-cases/empty-note.md +0 -0
  327. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/edge-cases/explicit-overrides-type.md +0 -0
  328. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/edge-cases/inline-and-type.md +0 -0
  329. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/edge-cases/no-frontmatter.md +0 -0
  330. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/edge-cases/relation-only.md +0 -0
  331. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/edge-cases/type-no-schema.md +0 -0
  332. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/edge-cases/unicode-fields.md +0 -0
  333. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/ada-lovelace.md +0 -0
  334. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/alan-turing.md +0 -0
  335. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/anders-hejlsberg.md +0 -0
  336. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/andrej-karpathy.md +0 -0
  337. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/barbara-liskov.md +0 -0
  338. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/bjarne-stroustrup.md +0 -0
  339. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/brendan-eich.md +0 -0
  340. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/claude-shannon.md +0 -0
  341. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/dennis-ritchie.md +0 -0
  342. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/dijkstra.md +0 -0
  343. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/donald-knuth.md +0 -0
  344. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/fei-fei-li.md +0 -0
  345. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/geoffrey-hinton.md +0 -0
  346. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/grace-hopper.md +0 -0
  347. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/guido-van-rossum.md +0 -0
  348. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/james-gosling.md +0 -0
  349. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/john-carmack.md +0 -0
  350. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/ken-thompson.md +0 -0
  351. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/larry-page.md +0 -0
  352. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/leslie-lamport.md +0 -0
  353. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/linus-torvalds.md +0 -0
  354. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/margaret-hamilton.md +0 -0
  355. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/rasmus-lerdorf.md +0 -0
  356. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/richard-stallman.md +0 -0
  357. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/rob-pike.md +0 -0
  358. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/satoshi-nakamoto.md +0 -0
  359. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/tim-berners-lee.md +0 -0
  360. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/vint-cerf.md +0 -0
  361. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/yann-lecun.md +0 -0
  362. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/yukihiro-matsumoto.md +0 -0
  363. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/schemas/Book.md +0 -0
  364. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/schemas/Meeting.md +0 -0
  365. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/schemas/Person.md +0 -0
  366. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/schemas/SoftwareProject.md +0 -0
  367. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/schemas/StrictSchema.md +0 -0
  368. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/valid/basic-memory.md +0 -0
  369. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/valid/explicit-ref-note.md +0 -0
  370. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/valid/no-schema-note.md +0 -0
  371. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/valid/paul-graham.md +0 -0
  372. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/valid/rich-hickey.md +0 -0
  373. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/valid/standup-2024-01-15.md +0 -0
  374. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/warnings/extra-observations.md +0 -0
  375. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/warnings/missing-multiple.md +0 -0
  376. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/warnings/missing-required.md +0 -0
  377. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/warnings/wrong-enum-value.md +0 -0
  378. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_build_context_underscore.py +0 -0
  379. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_build_context_validation.py +0 -0
  380. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_chatgpt_tools_integration.py +0 -0
  381. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_default_project_mode_integration.py +0 -0
  382. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_delete_directory_integration.py +0 -0
  383. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_delete_note_integration.py +0 -0
  384. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_edit_note_integration.py +0 -0
  385. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_lifespan_shutdown_sync_task_cancellation_integration.py +0 -0
  386. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_list_directory_integration.py +0 -0
  387. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_move_directory_integration.py +0 -0
  388. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_move_note_integration.py +0 -0
  389. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_output_format_json_integration.py +0 -0
  390. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_pagination_integration.py +0 -0
  391. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_permalink_collision_integration.py +0 -0
  392. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_project_management_integration.py +0 -0
  393. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_project_state_sync_integration.py +0 -0
  394. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_read_content_integration.py +0 -0
  395. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_read_note_integration.py +0 -0
  396. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_search_integration.py +0 -0
  397. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_single_project_mcp_integration.py +0 -0
  398. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_smoke_integration.py +0 -0
  399. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_ui_sdk_integration.py +0 -0
  400. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_write_note_integration.py +0 -0
  401. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/__init__.py +0 -0
  402. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/conftest.py +0 -0
  403. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/corpus.py +0 -0
  404. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/metrics.py +0 -0
  405. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/report.py +0 -0
  406. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/test_multiterm_semantic_queries.py +0 -0
  407. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/test_search_diagnostics.py +0 -0
  408. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/test_semantic_coverage.py +0 -0
  409. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/test_semantic_quality.py +0 -0
  410. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_db_wal_mode.py +0 -0
  411. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_disable_permalinks_integration.py +0 -0
  412. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_schema/__init__.py +0 -0
  413. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_schema/conftest.py +0 -0
  414. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_schema/helpers.py +0 -0
  415. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_schema/test_diff_integration.py +0 -0
  416. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_schema/test_inference_integration.py +0 -0
  417. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_schema/test_parser_integration.py +0 -0
  418. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_schema/test_validator_integration.py +0 -0
  419. {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_search_performance_benchmark.py +0 -0
  420. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/Non-MarkdownFileSupport.pdf +0 -0
  421. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/README.md +0 -0
  422. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/Screenshot.png +0 -0
  423. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/__init__.py +0 -0
  424. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/__init__.py +0 -0
  425. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/conftest.py +0 -0
  426. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_directory_router.py +0 -0
  427. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_importer_router.py +0 -0
  428. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_knowledge_router.py +0 -0
  429. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_memory_router.py +0 -0
  430. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_project_router.py +0 -0
  431. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_prompt_router.py +0 -0
  432. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_resource_router.py +0 -0
  433. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_schema_router.py +0 -0
  434. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_search_router.py +0 -0
  435. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/cloud/test_cloud_api_client_and_utils.py +0 -0
  436. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/cloud/test_rclone_config_and_bmignore_filters.py +0 -0
  437. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/cloud/test_upload_command_routing.py +0 -0
  438. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/cloud/test_upload_path.py +0 -0
  439. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/conftest.py +0 -0
  440. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_analytics.py +0 -0
  441. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_auth_cli_auth.py +0 -0
  442. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cli_container.py +0 -0
  443. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cli_exit.py +0 -0
  444. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cli_schema.py +0 -0
  445. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cli_tool_exit.py +0 -0
  446. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cli_tool_json_output.py +0 -0
  447. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cli_tools.py +0 -0
  448. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cloud_authentication.py +0 -0
  449. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cloud_promo.py +0 -0
  450. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cloud_status.py +0 -0
  451. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_db_reset_exit.py +0 -0
  452. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_ignore_utils.py +0 -0
  453. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_import_chatgpt.py +0 -0
  454. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_import_claude_conversations.py +0 -0
  455. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_import_claude_projects.py +0 -0
  456. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_import_memory_json.py +0 -0
  457. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_json_output.py +0 -0
  458. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_project_add_with_local_path.py +0 -0
  459. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_project_info_errors.py +0 -0
  460. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_project_list_and_ls.py +0 -0
  461. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_project_set_cloud_local.py +0 -0
  462. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_restore_commands.py +0 -0
  463. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_routing.py +0 -0
  464. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_snapshot_commands.py +0 -0
  465. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_upload.py +0 -0
  466. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_workspace_commands.py +0 -0
  467. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/conftest.py +0 -0
  468. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/db/test_issue_254_foreign_key_constraints.py +0 -0
  469. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/importers/test_conversation_indexing.py +0 -0
  470. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/importers/test_importer_base.py +0 -0
  471. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/importers/test_importer_utils.py +0 -0
  472. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/__init__.py +0 -0
  473. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_date_frontmatter_parsing.py +0 -0
  474. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_entity_parser.py +0 -0
  475. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_entity_parser_error_handling.py +0 -0
  476. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_markdown_plugins.py +0 -0
  477. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_markdown_processor.py +0 -0
  478. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_markdown_utils.py +0 -0
  479. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_observation_edge_cases.py +0 -0
  480. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_parser_edge_cases.py +0 -0
  481. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_relation_edge_cases.py +0 -0
  482. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_task_detection.py +0 -0
  483. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/clients/__init__.py +0 -0
  484. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/clients/test_clients.py +0 -0
  485. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/conftest.py +0 -0
  486. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_async_client_force_local.py +0 -0
  487. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_async_client_modes.py +0 -0
  488. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_client_schema.py +0 -0
  489. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_mcp_container.py +0 -0
  490. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_obsidian_yaml_formatting.py +0 -0
  491. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_permalink_collision_file_overwrite.py +0 -0
  492. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_project_context.py +0 -0
  493. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_prompt_tool_delegation.py +0 -0
  494. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_prompts.py +0 -0
  495. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_recent_activity_prompt_modes.py +0 -0
  496. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_resources.py +0 -0
  497. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_server_lifespan_branches.py +0 -0
  498. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_build_context.py +0 -0
  499. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_canvas.py +0 -0
  500. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_cloud_discovery.py +0 -0
  501. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_contracts.py +0 -0
  502. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_delete_note.py +0 -0
  503. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_edit_note.py +0 -0
  504. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_json_output_modes.py +0 -0
  505. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_list_directory.py +0 -0
  506. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_move_note.py +0 -0
  507. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_project_management.py +0 -0
  508. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_read_content.py +0 -0
  509. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_read_note.py +0 -0
  510. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_recent_activity.py +0 -0
  511. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_resource.py +0 -0
  512. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_schema.py +0 -0
  513. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_search.py +0 -0
  514. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_utils.py +0 -0
  515. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_utils_cloud_auth.py +0 -0
  516. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_view_note.py +0 -0
  517. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_workspace_management.py +0 -0
  518. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_write_note.py +0 -0
  519. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_write_note_kebab_filenames.py +0 -0
  520. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_write_note_metadata.py +0 -0
  521. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_ui_resources.py +0 -0
  522. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_ui_sdk.py +0 -0
  523. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_ui_templates.py +0 -0
  524. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/tools/test_chatgpt_tools.py +0 -0
  525. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_distance_to_similarity.py +0 -0
  526. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_entity_repository.py +0 -0
  527. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_entity_repository_upsert.py +0 -0
  528. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_entity_upsert_issue_187.py +0 -0
  529. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_fastembed_provider.py +0 -0
  530. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_hybrid_fusion.py +0 -0
  531. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_metadata_filters.py +0 -0
  532. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_metadata_filters_edge_cases.py +0 -0
  533. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_observation_repository.py +0 -0
  534. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_openai_provider.py +0 -0
  535. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_postgres_search_repository.py +0 -0
  536. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_postgres_search_repository_unit.py +0 -0
  537. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_project_info_repository.py +0 -0
  538. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_project_repository.py +0 -0
  539. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_relation_repository.py +0 -0
  540. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_repository.py +0 -0
  541. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_search_index_row.py +0 -0
  542. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_search_repository.py +0 -0
  543. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_search_repository_edit_bug_fix.py +0 -0
  544. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_search_text_with_metadata_filters.py +0 -0
  545. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_sqlite_vector_search_repository.py +0 -0
  546. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_vector_pagination.py +0 -0
  547. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_vector_threshold.py +0 -0
  548. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schema/__init__.py +0 -0
  549. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schema/test_diff.py +0 -0
  550. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schema/test_inference.py +0 -0
  551. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schema/test_parser.py +0 -0
  552. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schema/test_resolver.py +0 -0
  553. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schema/test_validator.py +0 -0
  554. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schemas/test_base_timeframe_minimum.py +0 -0
  555. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schemas/test_memory_serialization.py +0 -0
  556. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schemas/test_memory_url.py +0 -0
  557. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schemas/test_memory_url_validation.py +0 -0
  558. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schemas/test_relation_response_reference_resolution.py +0 -0
  559. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schemas/test_schemas.py +0 -0
  560. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schemas/test_search.py +0 -0
  561. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_context_service.py +0 -0
  562. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_directory_service.py +0 -0
  563. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_entity_service.py +0 -0
  564. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_entity_service_disable_permalinks.py +0 -0
  565. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_file_service.py +0 -0
  566. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_initialization.py +0 -0
  567. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_initialization_cloud_mode_branches.py +0 -0
  568. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_link_resolver.py +0 -0
  569. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_project_removal_bug.py +0 -0
  570. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_project_service.py +0 -0
  571. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_project_service_cloud_info.py +0 -0
  572. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_project_service_operations.py +0 -0
  573. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_search_service.py +0 -0
  574. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_semantic_search.py +0 -0
  575. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_task_scheduler_semantic.py +0 -0
  576. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_character_conflicts.py +0 -0
  577. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_coordinator.py +0 -0
  578. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_sync_service.py +0 -0
  579. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_sync_service_incremental.py +0 -0
  580. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_sync_wikilink_issue.py +0 -0
  581. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_tmp_files.py +0 -0
  582. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_watch_service.py +0 -0
  583. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_watch_service_atomic_adds.py +0 -0
  584. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_watch_service_edge_cases.py +0 -0
  585. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_watch_service_reload.py +0 -0
  586. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_watch_service_stress.py +0 -0
  587. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/test_config.py +0 -0
  588. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/test_deps.py +0 -0
  589. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/test_production_cascade_delete.py +0 -0
  590. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/test_project_resolver.py +0 -0
  591. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/test_rclone_commands.py +0 -0
  592. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/test_runtime.py +0 -0
  593. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/utils/test_file_utils.py +0 -0
  594. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/utils/test_frontmatter_obsidian_compatible.py +0 -0
  595. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/utils/test_parse_tags.py +0 -0
  596. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/utils/test_permalink_formatting.py +0 -0
  597. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/utils/test_timezone_utils.py +0 -0
  598. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/utils/test_utf8_handling.py +0 -0
  599. {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/utils/test_validate_project_path.py +0 -0
  600. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/.gitignore +0 -0
  601. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/build.mjs +0 -0
  602. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/package-lock.json +0 -0
  603. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/package.json +0 -0
  604. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/data-table/_adapter.tsx +0 -0
  605. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/data-table/data-table.tsx +0 -0
  606. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/data-table/error-boundary.tsx +0 -0
  607. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/data-table/formatters.tsx +0 -0
  608. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/data-table/index.tsx +0 -0
  609. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/data-table/schema.ts +0 -0
  610. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/data-table/types.ts +0 -0
  611. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/data-table/utilities.ts +0 -0
  612. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/_adapter.tsx +0 -0
  613. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/action-buttons.tsx +0 -0
  614. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/actions-config.ts +0 -0
  615. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/error-boundary.tsx +0 -0
  616. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/index.ts +0 -0
  617. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/media/aspect-ratio.ts +0 -0
  618. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/media/format-utils.ts +0 -0
  619. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/media/index.ts +0 -0
  620. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/media/overlay-gradient.ts +0 -0
  621. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/media/sanitize-href.ts +0 -0
  622. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/parse.ts +0 -0
  623. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/schema.ts +0 -0
  624. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/use-action-buttons.tsx +0 -0
  625. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/use-copy-to-clipboard.ts +0 -0
  626. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/utils.ts +0 -0
  627. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/ui/accordion.tsx +0 -0
  628. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/ui/badge.tsx +0 -0
  629. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/ui/button.tsx +0 -0
  630. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/ui/dropdown-menu.tsx +0 -0
  631. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/ui/table.tsx +0 -0
  632. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/ui/tooltip.tsx +0 -0
  633. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/note-preview.tsx +0 -0
  634. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/search-results.tsx +0 -0
  635. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/styles.css +0 -0
  636. {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/tailwind.config.js +0 -0
  637. {basic_memory-0.19.1 → basic_memory-0.19.2}/uv.lock +0 -0
@@ -2,6 +2,18 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## v0.19.2 (2026-03-09)
6
+
7
+ ### Bug Fixes
8
+
9
+ - **#657**: Coerce string params to list/dict in MCP tools
10
+ - MCP clients that serialize `list`/`dict` arguments as JSON strings no longer fail Pydantic validation
11
+ - Adds `BeforeValidator` coercion to `search_notes` (`entity_types`, `note_types`, `tags`, `metadata_filters`), `write_note` (`metadata`), and `canvas` (`nodes`, `edges`)
12
+ - **#655**: Handle SQLite and Windows semantic search regressions
13
+ - Fix embedding status query for non-semantic SQLite databases
14
+ - Windows-safe log file rotation with per-process log filenames
15
+ - Robust `setup_logging` that handles all environments cleanly
16
+
5
17
  ## v0.19.1 (2026-03-08)
6
18
 
7
19
  ### Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basic-memory
3
- Version: 0.19.1
3
+ Version: 0.19.2
4
4
  Summary: Local-first knowledge management combining Zettelkasten with knowledge graphs
5
5
  Project-URL: Homepage, https://github.com/basicmachines-co/basic-memory
6
6
  Project-URL: Repository, https://github.com/basicmachines-co/basic-memory
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/basicmachines-co/basic-memory.git",
7
7
  "source": "github"
8
8
  },
9
- "version": "0.19.1",
9
+ "version": "0.19.2",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "pypi",
13
13
  "identifier": "basic-memory",
14
- "version": "0.19.1",
14
+ "version": "0.19.2",
15
15
  "runtimeHint": "uvx",
16
16
  "runtimeArguments": [
17
17
  {"type": "positional", "value": "basic-memory"},
@@ -1,7 +1,7 @@
1
1
  """basic-memory - Local-first knowledge management combining Zettelkasten with knowledge graphs"""
2
2
 
3
3
  # Package version - updated by release automation
4
- __version__ = "0.19.1"
4
+ __version__ = "0.19.2"
5
5
 
6
6
  # API version for FastAPI - independent of package version
7
7
  __api_version__ = "v0"
@@ -4,12 +4,14 @@ This tool creates Obsidian canvas files (.canvas) using the JSON Canvas 1.0 spec
4
4
  """
5
5
 
6
6
  import json
7
- from typing import Dict, List, Any, Optional
7
+ from typing import Annotated, Dict, List, Any, Optional
8
8
 
9
9
  from loguru import logger
10
10
  from fastmcp import Context
11
+ from pydantic import BeforeValidator
11
12
 
12
13
  from basic_memory.mcp.project_context import get_project_client
14
+ from basic_memory.utils import coerce_list
13
15
  from basic_memory.mcp.server import mcp
14
16
  from basic_memory.mcp.tools.utils import call_put, call_post, resolve_entity_id
15
17
 
@@ -19,8 +21,8 @@ from basic_memory.mcp.tools.utils import call_put, call_post, resolve_entity_id
19
21
  annotations={"destructiveHint": False, "idempotentHint": True, "openWorldHint": False},
20
22
  )
21
23
  async def canvas(
22
- nodes: List[Dict[str, Any]],
23
- edges: List[Dict[str, Any]],
24
+ nodes: Annotated[List[Dict[str, Any]], BeforeValidator(coerce_list)],
25
+ edges: Annotated[List[Dict[str, Any]], BeforeValidator(coerce_list)],
24
26
  title: str,
25
27
  directory: str,
26
28
  project: Optional[str] = None,
@@ -6,8 +6,10 @@ from typing import Annotated, List, Optional, Dict, Any, Literal
6
6
 
7
7
  from loguru import logger
8
8
  from fastmcp import Context
9
+ from pydantic import BeforeValidator
9
10
 
10
11
  from basic_memory.config import ConfigManager
12
+ from basic_memory.utils import coerce_dict, coerce_list
11
13
  from basic_memory.mcp.container import get_container
12
14
  from basic_memory.mcp.project_context import (
13
15
  detect_project_from_url_prefix,
@@ -307,18 +309,26 @@ async def search_notes(
307
309
  output_format: Literal["text", "json"] = "text",
308
310
  note_types: Annotated[
309
311
  List[str] | None,
312
+ BeforeValidator(coerce_list),
310
313
  "Filter by the 'type' field in note frontmatter (e.g. 'note', 'chapter', 'person'). "
311
314
  "Case-insensitive.",
312
315
  ] = None,
313
316
  entity_types: Annotated[
314
317
  List[str] | None,
318
+ BeforeValidator(coerce_list),
315
319
  "Filter by knowledge graph item type: 'entity' (whole notes), 'observation', or "
316
320
  "'relation'. Defaults to 'entity'. Do NOT pass schema/frontmatter types like "
317
321
  "'Chapter' here — use note_types instead.",
318
322
  ] = None,
319
323
  after_date: Optional[str] = None,
320
- metadata_filters: Optional[Dict[str, Any]] = None,
321
- tags: Optional[List[str]] = None,
324
+ metadata_filters: Annotated[
325
+ Dict[str, Any] | None,
326
+ BeforeValidator(coerce_dict),
327
+ ] = None,
328
+ tags: Annotated[
329
+ List[str] | None,
330
+ BeforeValidator(coerce_list),
331
+ ] = None,
322
332
  status: Optional[str] = None,
323
333
  min_similarity: Optional[float] = None,
324
334
  context: Context | None = None,
@@ -1,16 +1,17 @@
1
1
  """Write note tool for Basic Memory MCP server."""
2
2
 
3
3
  import textwrap
4
- from typing import List, Union, Optional, Literal
4
+ from typing import Annotated, List, Union, Optional, Literal
5
5
 
6
6
  from loguru import logger
7
+ from pydantic import BeforeValidator
7
8
 
8
9
  from basic_memory.config import ConfigManager
9
10
  from basic_memory.mcp.project_context import get_project_client, add_project_metadata
10
11
  from basic_memory.mcp.server import mcp
11
12
  from fastmcp import Context
12
13
  from basic_memory.schemas.base import Entity
13
- from basic_memory.utils import parse_tags, validate_project_path
14
+ from basic_memory.utils import coerce_dict, parse_tags, validate_project_path
14
15
 
15
16
  # Define TagType as a Union that can accept either a string or a list of strings or None
16
17
  TagType = Union[List[str], str, None]
@@ -28,7 +29,7 @@ async def write_note(
28
29
  workspace: Optional[str] = None,
29
30
  tags: list[str] | str | None = None,
30
31
  note_type: str = "note",
31
- metadata: dict | None = None,
32
+ metadata: Annotated[dict | None, BeforeValidator(coerce_dict)] = None,
32
33
  overwrite: bool | None = None,
33
34
  output_format: Literal["text", "json"] = "text",
34
35
  context: Context | None = None,
@@ -451,21 +451,36 @@ class SearchRepositoryBase(ABC):
451
451
  return "\n\n".join(part for part in row_parts if part)
452
452
 
453
453
  def _build_chunk_records(self, rows) -> list[dict[str, str]]:
454
- records: list[dict[str, str]] = []
454
+ records_by_key: dict[str, dict[str, str]] = {}
455
+ duplicate_chunk_keys = 0
455
456
  for row in rows:
456
457
  source_text = self._compose_row_source_text(row)
457
458
  chunks = self._split_text_into_chunks(source_text)
458
459
  for chunk_index, chunk_text in enumerate(chunks):
459
460
  chunk_key = f"{row.type}:{row.id}:{chunk_index}"
460
461
  source_hash = hashlib.sha256(chunk_text.encode("utf-8")).hexdigest()
461
- records.append(
462
- {
463
- "chunk_key": chunk_key,
464
- "chunk_text": chunk_text,
465
- "source_hash": source_hash,
466
- }
467
- )
468
- return records
462
+ # Trigger: SQLite FTS5 can accumulate duplicate logical rows for the
463
+ # same search_index id because it does not enforce relational uniqueness.
464
+ # Why: duplicate chunk keys would schedule duplicate writes for the same
465
+ # chunk row and eventually trip UNIQUE(rowid) in search_vector_embeddings.
466
+ # Outcome: collapse chunk work to one deterministic record per chunk key.
467
+ if chunk_key in records_by_key:
468
+ duplicate_chunk_keys += 1
469
+ records_by_key[chunk_key] = {
470
+ "chunk_key": chunk_key,
471
+ "chunk_text": chunk_text,
472
+ "source_hash": source_hash,
473
+ }
474
+
475
+ if duplicate_chunk_keys:
476
+ logger.warning(
477
+ "Collapsed duplicate vector chunk keys before embedding sync: "
478
+ "project_id={project_id} duplicate_chunk_keys={duplicate_chunk_keys}",
479
+ project_id=self.project_id,
480
+ duplicate_chunk_keys=duplicate_chunk_keys,
481
+ )
482
+
483
+ return list(records_by_key.values())
469
484
 
470
485
  # --- Text splitting ---
471
486
 
@@ -11,6 +11,7 @@ from typing import TYPE_CHECKING, Dict, Optional, Sequence
11
11
 
12
12
  from loguru import logger
13
13
  from sqlalchemy import text
14
+ from sqlalchemy.exc import OperationalError as SAOperationalError
14
15
 
15
16
  from basic_memory.models import Project
16
17
  from basic_memory.repository.project_repository import ProjectRepository
@@ -1004,56 +1005,81 @@ class ProjectService:
1004
1005
  )
1005
1006
  total_indexed_entities = si_result.scalar() or 0
1006
1007
 
1007
- chunks_result = await self.repository.execute_query(
1008
- text("SELECT COUNT(*) FROM search_vector_chunks WHERE project_id = :project_id"),
1009
- {"project_id": project_id},
1010
- )
1011
- total_chunks = chunks_result.scalar() or 0
1012
-
1013
- entities_with_chunks_result = await self.repository.execute_query(
1014
- text(
1015
- "SELECT COUNT(DISTINCT entity_id) FROM search_vector_chunks "
1016
- "WHERE project_id = :project_id"
1017
- ),
1018
- {"project_id": project_id},
1019
- )
1020
- total_entities_with_chunks = entities_with_chunks_result.scalar() or 0
1021
-
1022
- # Embeddings count — join pattern differs between SQLite and Postgres
1023
- if is_postgres:
1024
- embeddings_sql = text(
1025
- "SELECT COUNT(*) FROM search_vector_chunks c "
1026
- "JOIN search_vector_embeddings e ON e.chunk_id = c.id "
1027
- "WHERE c.project_id = :project_id"
1028
- )
1029
- else:
1030
- embeddings_sql = text(
1031
- "SELECT COUNT(*) FROM search_vector_chunks c "
1032
- "JOIN search_vector_embeddings e ON e.rowid = c.id "
1033
- "WHERE c.project_id = :project_id"
1008
+ try:
1009
+ chunks_result = await self.repository.execute_query(
1010
+ text("SELECT COUNT(*) FROM search_vector_chunks WHERE project_id = :project_id"),
1011
+ {"project_id": project_id},
1034
1012
  )
1013
+ total_chunks = chunks_result.scalar() or 0
1035
1014
 
1036
- embeddings_result = await self.repository.execute_query(
1037
- embeddings_sql, {"project_id": project_id}
1038
- )
1039
- total_embeddings = embeddings_result.scalar() or 0
1015
+ entities_with_chunks_result = await self.repository.execute_query(
1016
+ text(
1017
+ "SELECT COUNT(DISTINCT entity_id) FROM search_vector_chunks "
1018
+ "WHERE project_id = :project_id"
1019
+ ),
1020
+ {"project_id": project_id},
1021
+ )
1022
+ total_entities_with_chunks = entities_with_chunks_result.scalar() or 0
1023
+
1024
+ # Embeddings count — join pattern differs between SQLite and Postgres
1025
+ if is_postgres:
1026
+ embeddings_sql = text(
1027
+ "SELECT COUNT(*) FROM search_vector_chunks c "
1028
+ "JOIN search_vector_embeddings e ON e.chunk_id = c.id "
1029
+ "WHERE c.project_id = :project_id"
1030
+ )
1031
+ else:
1032
+ embeddings_sql = text(
1033
+ "SELECT COUNT(*) FROM search_vector_chunks c "
1034
+ "JOIN search_vector_embeddings e ON e.rowid = c.id "
1035
+ "WHERE c.project_id = :project_id"
1036
+ )
1040
1037
 
1041
- # Orphaned chunks (chunks without embeddings — indicates interrupted indexing)
1042
- if is_postgres:
1043
- orphan_sql = text(
1044
- "SELECT COUNT(*) FROM search_vector_chunks c "
1045
- "LEFT JOIN search_vector_embeddings e ON e.chunk_id = c.id "
1046
- "WHERE c.project_id = :project_id AND e.chunk_id IS NULL"
1038
+ embeddings_result = await self.repository.execute_query(
1039
+ embeddings_sql, {"project_id": project_id}
1047
1040
  )
1048
- else:
1049
- orphan_sql = text(
1050
- "SELECT COUNT(*) FROM search_vector_chunks c "
1051
- "LEFT JOIN search_vector_embeddings e ON e.rowid = c.id "
1052
- "WHERE c.project_id = :project_id AND e.rowid IS NULL"
1041
+ total_embeddings = embeddings_result.scalar() or 0
1042
+
1043
+ # Orphaned chunks (chunks without embeddings indicates interrupted indexing)
1044
+ if is_postgres:
1045
+ orphan_sql = text(
1046
+ "SELECT COUNT(*) FROM search_vector_chunks c "
1047
+ "LEFT JOIN search_vector_embeddings e ON e.chunk_id = c.id "
1048
+ "WHERE c.project_id = :project_id AND e.chunk_id IS NULL"
1049
+ )
1050
+ else:
1051
+ orphan_sql = text(
1052
+ "SELECT COUNT(*) FROM search_vector_chunks c "
1053
+ "LEFT JOIN search_vector_embeddings e ON e.rowid = c.id "
1054
+ "WHERE c.project_id = :project_id AND e.rowid IS NULL"
1055
+ )
1056
+
1057
+ orphan_result = await self.repository.execute_query(
1058
+ orphan_sql, {"project_id": project_id}
1053
1059
  )
1060
+ orphaned_chunks = orphan_result.scalar() or 0
1061
+ except SAOperationalError as exc:
1062
+ # Trigger: sqlite_master can list vec0 virtual tables even when sqlite-vec
1063
+ # is not loaded in the current Python runtime.
1064
+ # Why: project info should degrade gracefully instead of crashing on stats queries.
1065
+ # Outcome: report vector tables as unavailable and point the user to install the
1066
+ # missing dependency before rebuilding embeddings.
1067
+ if is_postgres or "no such module: vec0" not in str(exc).lower():
1068
+ raise
1054
1069
 
1055
- orphan_result = await self.repository.execute_query(orphan_sql, {"project_id": project_id})
1056
- orphaned_chunks = orphan_result.scalar() or 0
1070
+ return EmbeddingStatus(
1071
+ semantic_search_enabled=True,
1072
+ embedding_provider=provider,
1073
+ embedding_model=model,
1074
+ embedding_dimensions=dimensions,
1075
+ total_indexed_entities=total_indexed_entities,
1076
+ vector_tables_exist=False,
1077
+ reindex_recommended=True,
1078
+ reindex_reason=(
1079
+ "SQLite vector tables exist but sqlite-vec is unavailable in this Python "
1080
+ "environment — install/update basic-memory, then run: bm reindex --embeddings"
1081
+ ),
1082
+ )
1057
1083
 
1058
1084
  # --- Reindex recommendation logic (priority order) ---
1059
1085
  reindex_recommended = False
@@ -1,5 +1,6 @@
1
1
  """Utility functions for basic-memory."""
2
2
 
3
+ import json
3
4
  import os
4
5
 
5
6
  import logging
@@ -7,7 +8,7 @@ import re
7
8
  import sys
8
9
  from datetime import datetime, timezone
9
10
  from pathlib import Path
10
- from typing import Protocol, Union, runtime_checkable, List, Optional
11
+ from typing import Any, Protocol, Union, runtime_checkable, List, Optional
11
12
 
12
13
  from loguru import logger
13
14
  from unidecode import unidecode
@@ -66,6 +67,7 @@ class PathLike(Protocol):
66
67
  # In type annotations, use Union[Path, str] instead of FilePath for now
67
68
  # This preserves compatibility with existing code while we migrate
68
69
  FilePath = Union[Path, str]
70
+ WINDOWS_LOG_FILE_RETENTION = 5
69
71
 
70
72
 
71
73
  def generate_permalink(file_path: Union[Path, str, PathLike], split_extension: bool = True) -> str:
@@ -250,7 +252,7 @@ def setup_logging(
250
252
  log_to_file: bool = False,
251
253
  log_to_stdout: bool = False,
252
254
  structured_context: bool = False,
253
- ) -> None: # pragma: no cover
255
+ ) -> None:
254
256
  """Configure logging with explicit settings.
255
257
 
256
258
  This function provides a simple, explicit interface for configuring logging.
@@ -273,8 +275,14 @@ def setup_logging(
273
275
 
274
276
  # Add file handler with rotation
275
277
  if log_to_file:
276
- log_path = Path.home() / ".basic-memory" / "basic-memory.log"
278
+ # Trigger: Windows does not allow renaming an open file held by another process.
279
+ # Why: multiple basic-memory processes can share the same log directory at once.
280
+ # Outcome: use per-process log files on Windows so log rotation stays local.
281
+ log_filename = f"basic-memory-{os.getpid()}.log" if os.name == "nt" else "basic-memory.log"
282
+ log_path = Path.home() / ".basic-memory" / log_filename
277
283
  log_path.parent.mkdir(parents=True, exist_ok=True)
284
+ if os.name == "nt":
285
+ _cleanup_windows_log_files(log_path.parent, log_path.name)
278
286
  # Keep logging synchronous (enqueue=False) to avoid background logging threads.
279
287
  # Background threads are a common source of "hang on exit" issues in CLI/test runs.
280
288
  logger.add(
@@ -308,6 +316,28 @@ def setup_logging(
308
316
  logging.getLogger("watchfiles.main").setLevel(logging.WARNING)
309
317
 
310
318
 
319
+ def _cleanup_windows_log_files(log_dir: Path, current_log_name: str) -> None:
320
+ """Trim stale per-process Windows log files so the directory stays bounded."""
321
+ stale_logs = [
322
+ path
323
+ for path in log_dir.glob("basic-memory-*.log*")
324
+ if path.is_file() and path.name != current_log_name
325
+ ]
326
+
327
+ if len(stale_logs) <= WINDOWS_LOG_FILE_RETENTION - 1:
328
+ return
329
+
330
+ # Trigger: per-process log filenames avoid Windows rename contention but fragment retention.
331
+ # Why: loguru retention applies per sink, not across the whole basic-memory log directory.
332
+ # Outcome: keep only the newest stale PID logs so repeated CLI/server launches stay bounded.
333
+ stale_logs.sort(key=lambda path: path.stat().st_mtime, reverse=True)
334
+ for stale_log in stale_logs[WINDOWS_LOG_FILE_RETENTION - 1 :]:
335
+ try:
336
+ stale_log.unlink()
337
+ except OSError:
338
+ logger.debug("Failed to delete stale Windows log file: {path}", path=stale_log)
339
+
340
+
311
341
  def parse_tags(tags: Union[List[str], str, None]) -> List[str]:
312
342
  """Parse tags from various input formats into a consistent list.
313
343
 
@@ -356,6 +386,36 @@ def parse_tags(tags: Union[List[str], str, None]) -> List[str]:
356
386
  return []
357
387
 
358
388
 
389
+ def coerce_list(v: Any) -> Any:
390
+ """Coerce string input to list for MCP clients that serialize lists as strings."""
391
+ if v is None:
392
+ return v
393
+ if isinstance(v, str):
394
+ try:
395
+ parsed = json.loads(v)
396
+ if isinstance(parsed, list):
397
+ return parsed
398
+ except (json.JSONDecodeError, TypeError):
399
+ pass
400
+ # Single string value — wrap in a list
401
+ return [v]
402
+ return v
403
+
404
+
405
+ def coerce_dict(v: Any) -> Any:
406
+ """Coerce string input to dict for MCP clients that serialize dicts as strings."""
407
+ if v is None:
408
+ return v
409
+ if isinstance(v, str):
410
+ try:
411
+ parsed = json.loads(v)
412
+ if isinstance(parsed, dict):
413
+ return parsed
414
+ except (json.JSONDecodeError, TypeError):
415
+ pass
416
+ return v
417
+
418
+
359
419
  def normalize_newlines(multiline: str) -> str:
360
420
  """Replace any \r\n, \r, or \n with the native newline.
361
421
 
@@ -0,0 +1,167 @@
1
+ """Integration tests for MCP tools accepting string-serialized list/dict params.
2
+
3
+ Goes through the full FastMCP Client → validate_call → tool function path,
4
+ which is where Pydantic rejects strings for list/dict params.
5
+ """
6
+
7
+ import pytest
8
+ from fastmcp import Client
9
+
10
+
11
+ @pytest.mark.asyncio
12
+ async def test_search_notes_entity_types_as_string(mcp_server, app, test_project):
13
+ """search_notes should accept entity_types as a JSON string via MCP protocol."""
14
+ async with Client(mcp_server) as client:
15
+ await client.call_tool(
16
+ "write_note",
17
+ {
18
+ "project": test_project.name,
19
+ "title": "Entity Type Coerce Test",
20
+ "directory": "test",
21
+ "content": "# Test\nContent for entity type coercion",
22
+ },
23
+ )
24
+
25
+ # MCP client sends entity_types as a string
26
+ result = await client.call_tool(
27
+ "search_notes",
28
+ {
29
+ "project": test_project.name,
30
+ "query": "coercion",
31
+ "entity_types": '["entity"]',
32
+ },
33
+ )
34
+ text = result.content[0].text
35
+ assert "Search Failed" not in text
36
+
37
+
38
+ @pytest.mark.asyncio
39
+ async def test_search_notes_note_types_as_string(mcp_server, app, test_project):
40
+ """search_notes should accept note_types as a JSON string via MCP protocol."""
41
+ async with Client(mcp_server) as client:
42
+ await client.call_tool(
43
+ "write_note",
44
+ {
45
+ "project": test_project.name,
46
+ "title": "Note Type Coerce Test",
47
+ "directory": "test",
48
+ "content": "# Test\nContent for note type coercion",
49
+ },
50
+ )
51
+
52
+ result = await client.call_tool(
53
+ "search_notes",
54
+ {
55
+ "project": test_project.name,
56
+ "query": "coercion",
57
+ "note_types": '["note"]',
58
+ },
59
+ )
60
+ text = result.content[0].text
61
+ assert "Search Failed" not in text
62
+
63
+
64
+ @pytest.mark.asyncio
65
+ async def test_search_notes_tags_as_string(mcp_server, app, test_project):
66
+ """search_notes should accept tags as a JSON string via MCP protocol."""
67
+ async with Client(mcp_server) as client:
68
+ await client.call_tool(
69
+ "write_note",
70
+ {
71
+ "project": test_project.name,
72
+ "title": "Tags Coerce Test",
73
+ "directory": "test",
74
+ "content": "# Test\nTagged content for coercion",
75
+ "tags": "alpha",
76
+ },
77
+ )
78
+
79
+ result = await client.call_tool(
80
+ "search_notes",
81
+ {
82
+ "project": test_project.name,
83
+ "query": "tagged",
84
+ "tags": '["alpha"]',
85
+ },
86
+ )
87
+ text = result.content[0].text
88
+ assert "Search Failed" not in text
89
+
90
+
91
+ @pytest.mark.asyncio
92
+ async def test_search_notes_metadata_filters_as_string(mcp_server, app, test_project):
93
+ """search_notes should accept metadata_filters as a JSON string via MCP protocol."""
94
+ async with Client(mcp_server) as client:
95
+ await client.call_tool(
96
+ "write_note",
97
+ {
98
+ "project": test_project.name,
99
+ "title": "Metadata Coerce Test",
100
+ "directory": "test",
101
+ "content": "# Test\nMetadata content for coercion",
102
+ },
103
+ )
104
+
105
+ result = await client.call_tool(
106
+ "search_notes",
107
+ {
108
+ "project": test_project.name,
109
+ "query": "metadata",
110
+ "metadata_filters": '{"type": "note"}',
111
+ },
112
+ )
113
+ text = result.content[0].text
114
+ assert "Search Failed" not in text
115
+
116
+
117
+ @pytest.mark.asyncio
118
+ async def test_write_note_metadata_as_string(mcp_server, app, test_project):
119
+ """write_note should accept metadata as a JSON string via MCP protocol."""
120
+ async with Client(mcp_server) as client:
121
+ result = await client.call_tool(
122
+ "write_note",
123
+ {
124
+ "project": test_project.name,
125
+ "title": "String Metadata Note",
126
+ "directory": "test",
127
+ "content": "# Test\nWith string metadata",
128
+ "metadata": '{"priority": "high"}',
129
+ },
130
+ )
131
+ text = result.content[0].text
132
+ assert "Created note" in text or "Updated note" in text
133
+
134
+
135
+ @pytest.mark.asyncio
136
+ async def test_canvas_nodes_edges_as_string(mcp_server, app, test_project):
137
+ """canvas should accept nodes and edges as JSON strings via MCP protocol."""
138
+ import json
139
+
140
+ nodes = [
141
+ {
142
+ "id": "n1",
143
+ "type": "text",
144
+ "text": "Hello",
145
+ "x": 0,
146
+ "y": 0,
147
+ "width": 200,
148
+ "height": 100,
149
+ }
150
+ ]
151
+ edges = [
152
+ {"id": "e1", "fromNode": "n1", "toNode": "n1", "label": "self"}
153
+ ]
154
+
155
+ async with Client(mcp_server) as client:
156
+ result = await client.call_tool(
157
+ "canvas",
158
+ {
159
+ "project": test_project.name,
160
+ "title": "Coerce Canvas Test",
161
+ "directory": "test",
162
+ "nodes": json.dumps(nodes),
163
+ "edges": json.dumps(edges),
164
+ },
165
+ )
166
+ text = result.content[0].text
167
+ assert "Created" in text or "Updated" in text
@@ -237,6 +237,29 @@ class TestBuildChunkRecords:
237
237
  records = self.repo._build_chunk_records(rows)
238
238
  assert any("99" in r["chunk_key"] for r in records)
239
239
 
240
+ def test_duplicate_rows_collapse_to_unique_chunk_keys(self):
241
+ rows = [
242
+ _make_row(
243
+ row_type=SearchItemType.ENTITY.value,
244
+ title="Spec",
245
+ permalink="spec",
246
+ content_snippet="shared content",
247
+ row_id=77,
248
+ ),
249
+ _make_row(
250
+ row_type=SearchItemType.ENTITY.value,
251
+ title="Spec",
252
+ permalink="spec",
253
+ content_snippet="shared content",
254
+ row_id=77,
255
+ ),
256
+ ]
257
+
258
+ records = self.repo._build_chunk_records(rows)
259
+
260
+ assert len(records) == 1
261
+ assert records[0]["chunk_key"] == "entity:77:0"
262
+
240
263
 
241
264
  # --- SQLite SemanticSearchDisabledError ---
242
265