basic-memory 0.19.0__tar.gz → 0.19.1__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 (634) hide show
  1. {basic_memory-0.19.0 → basic_memory-0.19.1}/CHANGELOG.md +17 -0
  2. {basic_memory-0.19.0 → basic_memory-0.19.1}/PKG-INFO +13 -1
  3. {basic_memory-0.19.0 → basic_memory-0.19.1}/README.md +12 -0
  4. {basic_memory-0.19.0 → basic_memory-0.19.1}/server.json +2 -2
  5. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/__init__.py +1 -1
  6. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/api/v2/routers/knowledge_router.py +48 -0
  7. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/delete_note.py +1 -1
  8. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/edit_note.py +19 -5
  9. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/move_note.py +21 -2
  10. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schemas/base.py +5 -3
  11. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schemas/request.py +18 -3
  12. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schemas/v2/__init__.py +8 -0
  13. basic_memory-0.19.1/src/basic_memory/schemas/v2/graph.py +31 -0
  14. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/services/entity_service.py +75 -0
  15. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/cli/test_cli_tool_edit_note_integration.py +1 -1
  16. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_delete_note_integration.py +30 -5
  17. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_edit_note_integration.py +78 -0
  18. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_move_note_integration.py +53 -0
  19. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_delete_note.py +27 -3
  20. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_edit_note.py +160 -1
  21. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_move_note.py +25 -0
  22. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/schemas/test_schemas.py +43 -3
  23. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/services/test_entity_service.py +261 -0
  24. {basic_memory-0.19.0 → basic_memory-0.19.1}/uv.lock +9 -3
  25. {basic_memory-0.19.0 → basic_memory-0.19.1}/.claude/commands/release/beta.md +0 -0
  26. {basic_memory-0.19.0 → basic_memory-0.19.1}/.claude/commands/release/changelog.md +0 -0
  27. {basic_memory-0.19.0 → basic_memory-0.19.1}/.claude/commands/release/release-check.md +0 -0
  28. {basic_memory-0.19.0 → basic_memory-0.19.1}/.claude/commands/release/release.md +0 -0
  29. {basic_memory-0.19.0 → basic_memory-0.19.1}/.claude/commands/spec.md +0 -0
  30. {basic_memory-0.19.0 → basic_memory-0.19.1}/.claude/commands/test-live.md +0 -0
  31. {basic_memory-0.19.0 → basic_memory-0.19.1}/.claude/settings.json +0 -0
  32. {basic_memory-0.19.0 → basic_memory-0.19.1}/.dockerignore +0 -0
  33. {basic_memory-0.19.0 → basic_memory-0.19.1}/.env.example +0 -0
  34. {basic_memory-0.19.0 → basic_memory-0.19.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  35. {basic_memory-0.19.0 → basic_memory-0.19.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  36. {basic_memory-0.19.0 → basic_memory-0.19.1}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
  37. {basic_memory-0.19.0 → basic_memory-0.19.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  38. {basic_memory-0.19.0 → basic_memory-0.19.1}/.github/dependabot.yml +0 -0
  39. {basic_memory-0.19.0 → basic_memory-0.19.1}/.github/workflows/claude-code-review.yml +0 -0
  40. {basic_memory-0.19.0 → basic_memory-0.19.1}/.github/workflows/claude-issue-triage.yml +0 -0
  41. {basic_memory-0.19.0 → basic_memory-0.19.1}/.github/workflows/claude.yml +0 -0
  42. {basic_memory-0.19.0 → basic_memory-0.19.1}/.github/workflows/dev-release.yml +0 -0
  43. {basic_memory-0.19.0 → basic_memory-0.19.1}/.github/workflows/docker.yml +0 -0
  44. {basic_memory-0.19.0 → basic_memory-0.19.1}/.github/workflows/pr-title.yml +0 -0
  45. {basic_memory-0.19.0 → basic_memory-0.19.1}/.github/workflows/release.yml +0 -0
  46. {basic_memory-0.19.0 → basic_memory-0.19.1}/.github/workflows/test.yml +0 -0
  47. {basic_memory-0.19.0 → basic_memory-0.19.1}/.gitignore +0 -0
  48. {basic_memory-0.19.0 → basic_memory-0.19.1}/.python-version +0 -0
  49. {basic_memory-0.19.0 → basic_memory-0.19.1}/AGENTS.md +0 -0
  50. {basic_memory-0.19.0 → basic_memory-0.19.1}/CITATION.cff +0 -0
  51. {basic_memory-0.19.0 → basic_memory-0.19.1}/CLA.md +0 -0
  52. {basic_memory-0.19.0 → basic_memory-0.19.1}/CLAUDE.md +0 -0
  53. {basic_memory-0.19.0 → basic_memory-0.19.1}/CODE_OF_CONDUCT.md +0 -0
  54. {basic_memory-0.19.0 → basic_memory-0.19.1}/CONTRIBUTING.md +0 -0
  55. {basic_memory-0.19.0 → basic_memory-0.19.1}/Dockerfile +0 -0
  56. {basic_memory-0.19.0 → basic_memory-0.19.1}/LICENSE +0 -0
  57. {basic_memory-0.19.0 → basic_memory-0.19.1}/NOTE-FORMAT.md +0 -0
  58. {basic_memory-0.19.0 → basic_memory-0.19.1}/SECURITY.md +0 -0
  59. {basic_memory-0.19.0 → basic_memory-0.19.1}/docker-compose-postgres.yml +0 -0
  60. {basic_memory-0.19.0 → basic_memory-0.19.1}/docker-compose.yml +0 -0
  61. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/ARCHITECTURE.md +0 -0
  62. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/Docker.md +0 -0
  63. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/NOTE-FORMAT.md +0 -0
  64. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/SPEC-PER-PROJECT-ROUTING.md +0 -0
  65. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/ai-assistant-guide-extended.md +0 -0
  66. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/character-handling.md +0 -0
  67. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/cloud-cli.md +0 -0
  68. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/cloud-semantic-search-value.md +0 -0
  69. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/mcp-ui-bakeoff-instructions.md +0 -0
  70. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/metadata-search.md +0 -0
  71. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/post-v0.18.0-test-plan.md +0 -0
  72. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/releases/v0.19.0.md +0 -0
  73. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/semantic-search-test-log.md +0 -0
  74. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/semantic-search.md +0 -0
  75. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/specs/SPEC-LOCAL-PLUS-PUBLISH.md +0 -0
  76. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/specs/SPEC-SCHEMA-IMPL.md +0 -0
  77. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/specs/SPEC-SCHEMA.md +0 -0
  78. {basic_memory-0.19.0 → basic_memory-0.19.1}/docs/testing-coverage.md +0 -0
  79. {basic_memory-0.19.0 → basic_memory-0.19.1}/justfile +0 -0
  80. {basic_memory-0.19.0 → basic_memory-0.19.1}/llms-install.md +0 -0
  81. {basic_memory-0.19.0 → basic_memory-0.19.1}/pyproject.toml +0 -0
  82. {basic_memory-0.19.0 → basic_memory-0.19.1}/smithery.yaml +0 -0
  83. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/alembic.ini +0 -0
  84. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/env.py +0 -0
  85. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/migrations.py +0 -0
  86. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/script.py.mako +0 -0
  87. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/314f1ea54dc4_add_postgres_full_text_search_support_.py +0 -0
  88. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +0 -0
  89. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +0 -0
  90. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +0 -0
  91. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +0 -0
  92. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/6830751f5fb6_merge_multiple_heads.py +0 -0
  93. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/9d9c1cb7d8f5_add_mtime_and_size_columns_to_entity_.py +0 -0
  94. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +0 -0
  95. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/a2b3c4d5e6f7_add_search_index_entity_cascade.py +0 -0
  96. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +0 -0
  97. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +0 -0
  98. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/d7e8f9a0b1c2_add_structured_metadata_indexes.py +0 -0
  99. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/e7e1f4367280_add_scan_watermark_tracking_to_project.py +0 -0
  100. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/f8a9b2c3d4e5_add_pg_trgm_for_fuzzy_link_resolution.py +0 -0
  101. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/g9a0b3c4d5e6_add_external_id_to_project_and_entity.py +0 -0
  102. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/h1b2c3d4e5f6_add_postgres_vector_search_tables.py +0 -0
  103. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/i2c3d4e5f6g7_auto_backfill_semantic_embeddings.py +0 -0
  104. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/j3d4e5f6g7h8_rename_entity_type_to_note_type.py +0 -0
  105. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/alembic/versions/k4e5f6g7h8i9_add_created_by_and_last_updated_by_to_entity.py +0 -0
  106. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/api/__init__.py +0 -0
  107. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/api/app.py +0 -0
  108. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/api/container.py +0 -0
  109. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/api/template_loader.py +0 -0
  110. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/api/v2/__init__.py +0 -0
  111. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/api/v2/routers/__init__.py +0 -0
  112. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/api/v2/routers/directory_router.py +0 -0
  113. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/api/v2/routers/importer_router.py +0 -0
  114. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/api/v2/routers/memory_router.py +0 -0
  115. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/api/v2/routers/project_router.py +0 -0
  116. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/api/v2/routers/prompt_router.py +0 -0
  117. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/api/v2/routers/resource_router.py +0 -0
  118. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/api/v2/routers/schema_router.py +0 -0
  119. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/api/v2/routers/search_router.py +0 -0
  120. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/api/v2/utils.py +0 -0
  121. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/__init__.py +0 -0
  122. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/analytics.py +0 -0
  123. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/app.py +0 -0
  124. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/auth.py +0 -0
  125. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/__init__.py +0 -0
  126. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/cloud/__init__.py +0 -0
  127. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/cloud/api_client.py +0 -0
  128. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/cloud/bisync_commands.py +0 -0
  129. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/cloud/cloud_utils.py +0 -0
  130. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/cloud/core_commands.py +0 -0
  131. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/cloud/project_sync.py +0 -0
  132. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/cloud/rclone_commands.py +0 -0
  133. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/cloud/rclone_config.py +0 -0
  134. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/cloud/rclone_installer.py +0 -0
  135. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/cloud/restore.py +0 -0
  136. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/cloud/schemas.py +0 -0
  137. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/cloud/snapshot.py +0 -0
  138. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/cloud/upload.py +0 -0
  139. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/cloud/upload_command.py +0 -0
  140. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/cloud/workspace.py +0 -0
  141. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/command_utils.py +0 -0
  142. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/db.py +0 -0
  143. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/doctor.py +0 -0
  144. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/format.py +0 -0
  145. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/import_chatgpt.py +0 -0
  146. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/import_claude_conversations.py +0 -0
  147. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/import_claude_projects.py +0 -0
  148. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/import_memory_json.py +0 -0
  149. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/mcp.py +0 -0
  150. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/project.py +0 -0
  151. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/routing.py +0 -0
  152. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/schema.py +0 -0
  153. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/status.py +0 -0
  154. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/commands/tool.py +0 -0
  155. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/container.py +0 -0
  156. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/main.py +0 -0
  157. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/cli/promo.py +0 -0
  158. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/config.py +0 -0
  159. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/db.py +0 -0
  160. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/deps/__init__.py +0 -0
  161. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/deps/config.py +0 -0
  162. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/deps/db.py +0 -0
  163. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/deps/importers.py +0 -0
  164. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/deps/projects.py +0 -0
  165. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/deps/repositories.py +0 -0
  166. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/deps/services.py +0 -0
  167. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/deps.py +0 -0
  168. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/file_utils.py +0 -0
  169. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/ignore_utils.py +0 -0
  170. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/importers/__init__.py +0 -0
  171. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/importers/base.py +0 -0
  172. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/importers/chatgpt_importer.py +0 -0
  173. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/importers/claude_conversations_importer.py +0 -0
  174. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/importers/claude_projects_importer.py +0 -0
  175. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/importers/memory_json_importer.py +0 -0
  176. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/importers/utils.py +0 -0
  177. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/markdown/__init__.py +0 -0
  178. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/markdown/entity_parser.py +0 -0
  179. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/markdown/markdown_processor.py +0 -0
  180. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/markdown/plugins.py +0 -0
  181. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/markdown/schemas.py +0 -0
  182. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/markdown/utils.py +0 -0
  183. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/__init__.py +0 -0
  184. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/async_client.py +0 -0
  185. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/clients/__init__.py +0 -0
  186. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/clients/directory.py +0 -0
  187. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/clients/knowledge.py +0 -0
  188. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/clients/memory.py +0 -0
  189. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/clients/project.py +0 -0
  190. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/clients/resource.py +0 -0
  191. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/clients/schema.py +0 -0
  192. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/clients/search.py +0 -0
  193. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/container.py +0 -0
  194. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/formatting.py +0 -0
  195. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/project_context.py +0 -0
  196. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/prompts/__init__.py +0 -0
  197. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/prompts/ai_assistant_guide.py +0 -0
  198. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/prompts/continue_conversation.py +0 -0
  199. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/prompts/recent_activity.py +0 -0
  200. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/prompts/search.py +0 -0
  201. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/prompts/utils.py +0 -0
  202. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/resources/__init__.py +0 -0
  203. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/resources/ai_assistant_guide.md +0 -0
  204. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/resources/cloud_info.md +0 -0
  205. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/resources/project_info.py +0 -0
  206. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/resources/release_notes.md +0 -0
  207. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/resources/ui.py +0 -0
  208. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/server.py +0 -0
  209. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/__init__.py +0 -0
  210. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/build_context.py +0 -0
  211. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/canvas.py +0 -0
  212. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/chatgpt_tools.py +0 -0
  213. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/cloud_info.py +0 -0
  214. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/list_directory.py +0 -0
  215. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/project_management.py +0 -0
  216. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/read_content.py +0 -0
  217. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/read_note.py +0 -0
  218. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/recent_activity.py +0 -0
  219. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/release_notes.py +0 -0
  220. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/schema.py +0 -0
  221. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/search.py +0 -0
  222. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/ui_sdk.py +0 -0
  223. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/utils.py +0 -0
  224. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/view_note.py +0 -0
  225. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/workspaces.py +0 -0
  226. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/tools/write_note.py +0 -0
  227. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/ui/__init__.py +0 -0
  228. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/ui/html/note-preview-mcp-ui.html +0 -0
  229. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/ui/html/note-preview-tool-ui.html +0 -0
  230. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/ui/html/note-preview-vanilla.html +0 -0
  231. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/ui/html/search-results-mcp-ui.html +0 -0
  232. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/ui/html/search-results-tool-ui.html +0 -0
  233. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/ui/html/search-results-vanilla.html +0 -0
  234. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/ui/sdk.py +0 -0
  235. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/mcp/ui/templates.py +0 -0
  236. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/models/__init__.py +0 -0
  237. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/models/base.py +0 -0
  238. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/models/knowledge.py +0 -0
  239. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/models/project.py +0 -0
  240. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/models/search.py +0 -0
  241. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/project_resolver.py +0 -0
  242. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/__init__.py +0 -0
  243. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/embedding_provider.py +0 -0
  244. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/embedding_provider_factory.py +0 -0
  245. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/entity_repository.py +0 -0
  246. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/fastembed_provider.py +0 -0
  247. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/metadata_filters.py +0 -0
  248. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/observation_repository.py +0 -0
  249. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/openai_provider.py +0 -0
  250. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/postgres_search_repository.py +0 -0
  251. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/project_info_repository.py +0 -0
  252. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/project_repository.py +0 -0
  253. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/relation_repository.py +0 -0
  254. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/repository.py +0 -0
  255. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/search_index_row.py +0 -0
  256. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/search_repository.py +0 -0
  257. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/search_repository_base.py +0 -0
  258. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/semantic_errors.py +0 -0
  259. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/repository/sqlite_search_repository.py +0 -0
  260. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/runtime.py +0 -0
  261. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schema/__init__.py +0 -0
  262. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schema/diff.py +0 -0
  263. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schema/inference.py +0 -0
  264. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schema/parser.py +0 -0
  265. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schema/resolver.py +0 -0
  266. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schema/validator.py +0 -0
  267. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schemas/__init__.py +0 -0
  268. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schemas/cloud.py +0 -0
  269. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schemas/delete.py +0 -0
  270. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schemas/directory.py +0 -0
  271. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schemas/importer.py +0 -0
  272. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schemas/memory.py +0 -0
  273. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schemas/project_info.py +0 -0
  274. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schemas/prompt.py +0 -0
  275. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schemas/response.py +0 -0
  276. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schemas/schema.py +0 -0
  277. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schemas/search.py +0 -0
  278. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schemas/sync_report.py +0 -0
  279. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schemas/v2/entity.py +0 -0
  280. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/schemas/v2/resource.py +0 -0
  281. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/services/__init__.py +0 -0
  282. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/services/context_service.py +0 -0
  283. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/services/directory_service.py +0 -0
  284. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/services/exceptions.py +0 -0
  285. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/services/file_service.py +0 -0
  286. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/services/initialization.py +0 -0
  287. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/services/link_resolver.py +0 -0
  288. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/services/project_service.py +0 -0
  289. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/services/search_service.py +0 -0
  290. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/services/service.py +0 -0
  291. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/sync/__init__.py +0 -0
  292. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/sync/background_sync.py +0 -0
  293. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/sync/coordinator.py +0 -0
  294. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/sync/sync_service.py +0 -0
  295. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/sync/watch_service.py +0 -0
  296. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/templates/prompts/continue_conversation.hbs +0 -0
  297. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/templates/prompts/search.hbs +0 -0
  298. {basic_memory-0.19.0 → basic_memory-0.19.1}/src/basic_memory/utils.py +0 -0
  299. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/BENCHMARKS.md +0 -0
  300. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/cli/test_cli_tool_json_failure_integration.py +0 -0
  301. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/cli/test_cli_tool_json_integration.py +0 -0
  302. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/cli/test_project_commands_integration.py +0 -0
  303. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/cli/test_routing_integration.py +0 -0
  304. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/cli/test_search_notes_meta_integration.py +0 -0
  305. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/cli/test_version_integration.py +0 -0
  306. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/compare_search_benchmarks.py +0 -0
  307. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/conftest.py +0 -0
  308. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-01.md +0 -0
  309. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-02.md +0 -0
  310. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-03.md +0 -0
  311. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-04.md +0 -0
  312. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-05.md +0 -0
  313. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-06.md +0 -0
  314. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-07.md +0 -0
  315. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-08.md +0 -0
  316. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-09.md +0 -0
  317. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-10.md +0 -0
  318. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-11.md +0 -0
  319. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-12.md +0 -0
  320. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-13.md +0 -0
  321. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-14.md +0 -0
  322. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-15.md +0 -0
  323. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-16.md +0 -0
  324. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-17.md +0 -0
  325. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-18.md +0 -0
  326. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-19.md +0 -0
  327. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/people/drift-person-20.md +0 -0
  328. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/drift/schema/Person.md +0 -0
  329. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/edge-cases/array-single.md +0 -0
  330. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/edge-cases/empty-note.md +0 -0
  331. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/edge-cases/explicit-overrides-type.md +0 -0
  332. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/edge-cases/inline-and-type.md +0 -0
  333. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/edge-cases/no-frontmatter.md +0 -0
  334. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/edge-cases/relation-only.md +0 -0
  335. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/edge-cases/type-no-schema.md +0 -0
  336. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/edge-cases/unicode-fields.md +0 -0
  337. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/ada-lovelace.md +0 -0
  338. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/alan-turing.md +0 -0
  339. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/anders-hejlsberg.md +0 -0
  340. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/andrej-karpathy.md +0 -0
  341. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/barbara-liskov.md +0 -0
  342. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/bjarne-stroustrup.md +0 -0
  343. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/brendan-eich.md +0 -0
  344. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/claude-shannon.md +0 -0
  345. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/dennis-ritchie.md +0 -0
  346. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/dijkstra.md +0 -0
  347. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/donald-knuth.md +0 -0
  348. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/fei-fei-li.md +0 -0
  349. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/geoffrey-hinton.md +0 -0
  350. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/grace-hopper.md +0 -0
  351. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/guido-van-rossum.md +0 -0
  352. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/james-gosling.md +0 -0
  353. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/john-carmack.md +0 -0
  354. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/ken-thompson.md +0 -0
  355. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/larry-page.md +0 -0
  356. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/leslie-lamport.md +0 -0
  357. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/linus-torvalds.md +0 -0
  358. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/margaret-hamilton.md +0 -0
  359. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/rasmus-lerdorf.md +0 -0
  360. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/richard-stallman.md +0 -0
  361. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/rob-pike.md +0 -0
  362. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/satoshi-nakamoto.md +0 -0
  363. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/tim-berners-lee.md +0 -0
  364. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/vint-cerf.md +0 -0
  365. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/yann-lecun.md +0 -0
  366. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/inference/people/yukihiro-matsumoto.md +0 -0
  367. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/schemas/Book.md +0 -0
  368. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/schemas/Meeting.md +0 -0
  369. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/schemas/Person.md +0 -0
  370. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/schemas/SoftwareProject.md +0 -0
  371. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/schemas/StrictSchema.md +0 -0
  372. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/valid/basic-memory.md +0 -0
  373. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/valid/explicit-ref-note.md +0 -0
  374. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/valid/no-schema-note.md +0 -0
  375. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/valid/paul-graham.md +0 -0
  376. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/valid/rich-hickey.md +0 -0
  377. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/valid/standup-2024-01-15.md +0 -0
  378. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/warnings/extra-observations.md +0 -0
  379. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/warnings/missing-multiple.md +0 -0
  380. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/warnings/missing-required.md +0 -0
  381. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/fixtures/schema/warnings/wrong-enum-value.md +0 -0
  382. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_build_context_underscore.py +0 -0
  383. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_build_context_validation.py +0 -0
  384. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_chatgpt_tools_integration.py +0 -0
  385. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_default_project_mode_integration.py +0 -0
  386. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_delete_directory_integration.py +0 -0
  387. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_lifespan_shutdown_sync_task_cancellation_integration.py +0 -0
  388. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_list_directory_integration.py +0 -0
  389. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_move_directory_integration.py +0 -0
  390. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_output_format_json_integration.py +0 -0
  391. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_pagination_integration.py +0 -0
  392. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_permalink_collision_integration.py +0 -0
  393. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_project_management_integration.py +0 -0
  394. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_project_state_sync_integration.py +0 -0
  395. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_read_content_integration.py +0 -0
  396. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_read_note_integration.py +0 -0
  397. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_search_integration.py +0 -0
  398. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_single_project_mcp_integration.py +0 -0
  399. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_smoke_integration.py +0 -0
  400. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_ui_sdk_integration.py +0 -0
  401. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/mcp/test_write_note_integration.py +0 -0
  402. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/semantic/__init__.py +0 -0
  403. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/semantic/conftest.py +0 -0
  404. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/semantic/corpus.py +0 -0
  405. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/semantic/metrics.py +0 -0
  406. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/semantic/report.py +0 -0
  407. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/semantic/test_multiterm_semantic_queries.py +0 -0
  408. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/semantic/test_search_diagnostics.py +0 -0
  409. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/semantic/test_semantic_coverage.py +0 -0
  410. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/semantic/test_semantic_quality.py +0 -0
  411. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/test_db_wal_mode.py +0 -0
  412. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/test_disable_permalinks_integration.py +0 -0
  413. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/test_schema/__init__.py +0 -0
  414. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/test_schema/conftest.py +0 -0
  415. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/test_schema/helpers.py +0 -0
  416. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/test_schema/test_diff_integration.py +0 -0
  417. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/test_schema/test_inference_integration.py +0 -0
  418. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/test_schema/test_parser_integration.py +0 -0
  419. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/test_schema/test_validator_integration.py +0 -0
  420. {basic_memory-0.19.0 → basic_memory-0.19.1}/test-int/test_search_performance_benchmark.py +0 -0
  421. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/Non-MarkdownFileSupport.pdf +0 -0
  422. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/README.md +0 -0
  423. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/Screenshot.png +0 -0
  424. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/__init__.py +0 -0
  425. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/api/v2/__init__.py +0 -0
  426. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/api/v2/conftest.py +0 -0
  427. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/api/v2/test_directory_router.py +0 -0
  428. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/api/v2/test_importer_router.py +0 -0
  429. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/api/v2/test_knowledge_router.py +0 -0
  430. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/api/v2/test_memory_router.py +0 -0
  431. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/api/v2/test_project_router.py +0 -0
  432. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/api/v2/test_prompt_router.py +0 -0
  433. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/api/v2/test_resource_router.py +0 -0
  434. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/api/v2/test_schema_router.py +0 -0
  435. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/api/v2/test_search_router.py +0 -0
  436. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/cloud/test_cloud_api_client_and_utils.py +0 -0
  437. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/cloud/test_rclone_config_and_bmignore_filters.py +0 -0
  438. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/cloud/test_upload_command_routing.py +0 -0
  439. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/cloud/test_upload_path.py +0 -0
  440. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/conftest.py +0 -0
  441. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_analytics.py +0 -0
  442. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_auth_cli_auth.py +0 -0
  443. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_cli_container.py +0 -0
  444. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_cli_exit.py +0 -0
  445. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_cli_schema.py +0 -0
  446. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_cli_tool_exit.py +0 -0
  447. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_cli_tool_json_output.py +0 -0
  448. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_cli_tools.py +0 -0
  449. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_cloud_authentication.py +0 -0
  450. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_cloud_promo.py +0 -0
  451. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_cloud_status.py +0 -0
  452. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_db_reset_exit.py +0 -0
  453. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_ignore_utils.py +0 -0
  454. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_import_chatgpt.py +0 -0
  455. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_import_claude_conversations.py +0 -0
  456. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_import_claude_projects.py +0 -0
  457. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_import_memory_json.py +0 -0
  458. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_json_output.py +0 -0
  459. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_project_add_with_local_path.py +0 -0
  460. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_project_info_errors.py +0 -0
  461. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_project_list_and_ls.py +0 -0
  462. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_project_set_cloud_local.py +0 -0
  463. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_restore_commands.py +0 -0
  464. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_routing.py +0 -0
  465. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_snapshot_commands.py +0 -0
  466. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_upload.py +0 -0
  467. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/cli/test_workspace_commands.py +0 -0
  468. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/conftest.py +0 -0
  469. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/db/test_issue_254_foreign_key_constraints.py +0 -0
  470. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/importers/test_conversation_indexing.py +0 -0
  471. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/importers/test_importer_base.py +0 -0
  472. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/importers/test_importer_utils.py +0 -0
  473. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/markdown/__init__.py +0 -0
  474. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/markdown/test_date_frontmatter_parsing.py +0 -0
  475. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/markdown/test_entity_parser.py +0 -0
  476. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/markdown/test_entity_parser_error_handling.py +0 -0
  477. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/markdown/test_markdown_plugins.py +0 -0
  478. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/markdown/test_markdown_processor.py +0 -0
  479. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/markdown/test_markdown_utils.py +0 -0
  480. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/markdown/test_observation_edge_cases.py +0 -0
  481. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/markdown/test_parser_edge_cases.py +0 -0
  482. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/markdown/test_relation_edge_cases.py +0 -0
  483. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/markdown/test_task_detection.py +0 -0
  484. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/clients/__init__.py +0 -0
  485. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/clients/test_clients.py +0 -0
  486. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/conftest.py +0 -0
  487. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_async_client_force_local.py +0 -0
  488. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_async_client_modes.py +0 -0
  489. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_client_schema.py +0 -0
  490. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_mcp_container.py +0 -0
  491. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_obsidian_yaml_formatting.py +0 -0
  492. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_permalink_collision_file_overwrite.py +0 -0
  493. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_project_context.py +0 -0
  494. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_prompt_tool_delegation.py +0 -0
  495. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_prompts.py +0 -0
  496. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_recent_activity_prompt_modes.py +0 -0
  497. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_resources.py +0 -0
  498. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_server_lifespan_branches.py +0 -0
  499. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_build_context.py +0 -0
  500. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_canvas.py +0 -0
  501. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_cloud_discovery.py +0 -0
  502. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_contracts.py +0 -0
  503. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_json_output_modes.py +0 -0
  504. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_list_directory.py +0 -0
  505. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_project_management.py +0 -0
  506. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_read_content.py +0 -0
  507. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_read_note.py +0 -0
  508. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_recent_activity.py +0 -0
  509. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_resource.py +0 -0
  510. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_schema.py +0 -0
  511. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_search.py +0 -0
  512. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_utils.py +0 -0
  513. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_utils_cloud_auth.py +0 -0
  514. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_view_note.py +0 -0
  515. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_workspace_management.py +0 -0
  516. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_write_note.py +0 -0
  517. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_write_note_kebab_filenames.py +0 -0
  518. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_tool_write_note_metadata.py +0 -0
  519. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_ui_resources.py +0 -0
  520. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_ui_sdk.py +0 -0
  521. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/test_ui_templates.py +0 -0
  522. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/mcp/tools/test_chatgpt_tools.py +0 -0
  523. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_distance_to_similarity.py +0 -0
  524. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_entity_repository.py +0 -0
  525. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_entity_repository_upsert.py +0 -0
  526. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_entity_upsert_issue_187.py +0 -0
  527. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_fastembed_provider.py +0 -0
  528. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_hybrid_fusion.py +0 -0
  529. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_metadata_filters.py +0 -0
  530. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_metadata_filters_edge_cases.py +0 -0
  531. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_observation_repository.py +0 -0
  532. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_openai_provider.py +0 -0
  533. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_postgres_search_repository.py +0 -0
  534. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_postgres_search_repository_unit.py +0 -0
  535. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_project_info_repository.py +0 -0
  536. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_project_repository.py +0 -0
  537. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_relation_repository.py +0 -0
  538. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_repository.py +0 -0
  539. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_search_index_row.py +0 -0
  540. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_search_repository.py +0 -0
  541. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_search_repository_edit_bug_fix.py +0 -0
  542. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_search_text_with_metadata_filters.py +0 -0
  543. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_semantic_search_base.py +0 -0
  544. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_sqlite_vector_search_repository.py +0 -0
  545. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_vector_pagination.py +0 -0
  546. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/repository/test_vector_threshold.py +0 -0
  547. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/schema/__init__.py +0 -0
  548. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/schema/test_diff.py +0 -0
  549. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/schema/test_inference.py +0 -0
  550. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/schema/test_parser.py +0 -0
  551. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/schema/test_resolver.py +0 -0
  552. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/schema/test_validator.py +0 -0
  553. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/schemas/test_base_timeframe_minimum.py +0 -0
  554. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/schemas/test_memory_serialization.py +0 -0
  555. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/schemas/test_memory_url.py +0 -0
  556. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/schemas/test_memory_url_validation.py +0 -0
  557. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/schemas/test_relation_response_reference_resolution.py +0 -0
  558. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/schemas/test_search.py +0 -0
  559. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/services/test_context_service.py +0 -0
  560. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/services/test_directory_service.py +0 -0
  561. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/services/test_entity_service_disable_permalinks.py +0 -0
  562. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/services/test_file_service.py +0 -0
  563. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/services/test_initialization.py +0 -0
  564. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/services/test_initialization_cloud_mode_branches.py +0 -0
  565. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/services/test_link_resolver.py +0 -0
  566. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/services/test_project_removal_bug.py +0 -0
  567. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/services/test_project_service.py +0 -0
  568. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/services/test_project_service_cloud_info.py +0 -0
  569. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/services/test_project_service_embedding_status.py +0 -0
  570. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/services/test_project_service_operations.py +0 -0
  571. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/services/test_search_service.py +0 -0
  572. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/services/test_semantic_search.py +0 -0
  573. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/services/test_task_scheduler_semantic.py +0 -0
  574. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/sync/test_character_conflicts.py +0 -0
  575. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/sync/test_coordinator.py +0 -0
  576. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/sync/test_sync_service.py +0 -0
  577. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/sync/test_sync_service_incremental.py +0 -0
  578. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/sync/test_sync_wikilink_issue.py +0 -0
  579. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/sync/test_tmp_files.py +0 -0
  580. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/sync/test_watch_service.py +0 -0
  581. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/sync/test_watch_service_atomic_adds.py +0 -0
  582. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/sync/test_watch_service_edge_cases.py +0 -0
  583. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/sync/test_watch_service_reload.py +0 -0
  584. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/sync/test_watch_service_stress.py +0 -0
  585. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/test_config.py +0 -0
  586. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/test_deps.py +0 -0
  587. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/test_production_cascade_delete.py +0 -0
  588. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/test_project_resolver.py +0 -0
  589. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/test_rclone_commands.py +0 -0
  590. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/test_runtime.py +0 -0
  591. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/utils/test_file_utils.py +0 -0
  592. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/utils/test_frontmatter_obsidian_compatible.py +0 -0
  593. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/utils/test_parse_tags.py +0 -0
  594. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/utils/test_permalink_formatting.py +0 -0
  595. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/utils/test_timezone_utils.py +0 -0
  596. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/utils/test_utf8_handling.py +0 -0
  597. {basic_memory-0.19.0 → basic_memory-0.19.1}/tests/utils/test_validate_project_path.py +0 -0
  598. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/.gitignore +0 -0
  599. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/build.mjs +0 -0
  600. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/package-lock.json +0 -0
  601. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/package.json +0 -0
  602. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/data-table/_adapter.tsx +0 -0
  603. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/data-table/data-table.tsx +0 -0
  604. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/data-table/error-boundary.tsx +0 -0
  605. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/data-table/formatters.tsx +0 -0
  606. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/data-table/index.tsx +0 -0
  607. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/data-table/schema.ts +0 -0
  608. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/data-table/types.ts +0 -0
  609. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/data-table/utilities.ts +0 -0
  610. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/shared/_adapter.tsx +0 -0
  611. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/shared/action-buttons.tsx +0 -0
  612. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/shared/actions-config.ts +0 -0
  613. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/shared/error-boundary.tsx +0 -0
  614. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/shared/index.ts +0 -0
  615. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/shared/media/aspect-ratio.ts +0 -0
  616. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/shared/media/format-utils.ts +0 -0
  617. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/shared/media/index.ts +0 -0
  618. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/shared/media/overlay-gradient.ts +0 -0
  619. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/shared/media/sanitize-href.ts +0 -0
  620. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/shared/parse.ts +0 -0
  621. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/shared/schema.ts +0 -0
  622. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/shared/use-action-buttons.tsx +0 -0
  623. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/shared/use-copy-to-clipboard.ts +0 -0
  624. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/tool-ui/shared/utils.ts +0 -0
  625. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/ui/accordion.tsx +0 -0
  626. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/ui/badge.tsx +0 -0
  627. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/ui/button.tsx +0 -0
  628. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/ui/dropdown-menu.tsx +0 -0
  629. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/ui/table.tsx +0 -0
  630. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/components/ui/tooltip.tsx +0 -0
  631. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/note-preview.tsx +0 -0
  632. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/search-results.tsx +0 -0
  633. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/src/styles.css +0 -0
  634. {basic_memory-0.19.0 → basic_memory-0.19.1}/ui/tool-ui-react/tailwind.config.js +0 -0
@@ -2,6 +2,23 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## v0.19.1 (2026-03-08)
6
+
7
+ ### Bug Fixes
8
+
9
+ - **#649**: Enforce strict entity resolution in destructive MCP tools (`edit_note`, `move_note`, `delete_note`)
10
+ - Prevents fuzzy-match fallback from silently editing/moving/deleting the wrong note
11
+ - DST-related timeframe validation fix (round instead of truncate days)
12
+
13
+ ### Features
14
+
15
+ - **#648**: Add `insert_before_section` and `insert_after_section` edit operations
16
+ - Add `GET /knowledge/graph` endpoint for full graph visualization
17
+
18
+ ### Dependencies
19
+
20
+ - Bump authlib from 1.6.6 to 1.6.7
21
+
5
22
  ## v0.19.0 (2026-03-07)
6
23
 
7
24
  ### Highlights
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basic-memory
3
- Version: 0.19.0
3
+ Version: 0.19.1
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
@@ -74,6 +74,18 @@ Basic Memory lets you build persistent knowledge through natural conversations w
74
74
  Claude, while keeping everything in simple Markdown files on your computer. It uses the Model Context Protocol (MCP) to
75
75
  enable any compatible LLM to read and write to your local knowledge base.
76
76
 
77
+ ## What's New in v0.19.0
78
+
79
+ - **Semantic Vector Search** — find notes by meaning, not just keywords. Combines full-text and vector similarity for hybrid search with FastEmbed embeddings.
80
+ - **Schema System** — infer, validate, and diff the structure of your knowledge base with `schema_infer`, `schema_validate`, and `schema_diff` tools.
81
+ - **Per-Project Cloud Routing** — route individual projects through the cloud while others stay local, using API key authentication (`basic-memory project set-cloud`).
82
+ - **FastMCP 3.0** — upgraded to FastMCP 3.0 with tool annotations for better client integration.
83
+ - **CLI Overhaul** — JSON output mode (`--json`) for scripting, workspace-aware commands, and an htop-inspired project dashboard.
84
+ - **Smarter Editing** — `edit_note` append/prepend auto-creates notes if they don't exist; `write_note` has an overwrite guard to prevent accidental data loss.
85
+ - **Richer Search Results** — matched chunk text returned in search results for better context.
86
+
87
+ See the full [CHANGELOG](CHANGELOG.md) for details.
88
+
77
89
  - Website: [basicmemory.com](https://basicmemory.com?utm_source=github&utm_medium=referral&utm_campaign=readme)
78
90
  - Documentation: [docs.basicmemory.com](https://docs.basicmemory.com?utm_source=github&utm_medium=referral&utm_campaign=readme)
79
91
  - Community: [Discord](https://discord.gg/tyvKNccgqN?utm_source=github&utm_medium=referral&utm_campaign=readme)
@@ -23,6 +23,18 @@ Basic Memory lets you build persistent knowledge through natural conversations w
23
23
  Claude, while keeping everything in simple Markdown files on your computer. It uses the Model Context Protocol (MCP) to
24
24
  enable any compatible LLM to read and write to your local knowledge base.
25
25
 
26
+ ## What's New in v0.19.0
27
+
28
+ - **Semantic Vector Search** — find notes by meaning, not just keywords. Combines full-text and vector similarity for hybrid search with FastEmbed embeddings.
29
+ - **Schema System** — infer, validate, and diff the structure of your knowledge base with `schema_infer`, `schema_validate`, and `schema_diff` tools.
30
+ - **Per-Project Cloud Routing** — route individual projects through the cloud while others stay local, using API key authentication (`basic-memory project set-cloud`).
31
+ - **FastMCP 3.0** — upgraded to FastMCP 3.0 with tool annotations for better client integration.
32
+ - **CLI Overhaul** — JSON output mode (`--json`) for scripting, workspace-aware commands, and an htop-inspired project dashboard.
33
+ - **Smarter Editing** — `edit_note` append/prepend auto-creates notes if they don't exist; `write_note` has an overwrite guard to prevent accidental data loss.
34
+ - **Richer Search Results** — matched chunk text returned in search results for better context.
35
+
36
+ See the full [CHANGELOG](CHANGELOG.md) for details.
37
+
26
38
  - Website: [basicmemory.com](https://basicmemory.com?utm_source=github&utm_medium=referral&utm_campaign=readme)
27
39
  - Documentation: [docs.basicmemory.com](https://docs.basicmemory.com?utm_source=github&utm_medium=referral&utm_campaign=readme)
28
40
  - Community: [Discord](https://discord.gg/tyvKNccgqN?utm_source=github&utm_medium=referral&utm_campaign=readme)
@@ -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.0",
9
+ "version": "0.19.1",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "pypi",
13
13
  "identifier": "basic-memory",
14
- "version": "0.19.0",
14
+ "version": "0.19.1",
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.0"
4
+ __version__ = "0.19.1"
5
5
 
6
6
  # API version for FastAPI - independent of package version
7
7
  __api_version__ = "v0"
@@ -20,6 +20,7 @@ from basic_memory.deps import (
20
20
  ProjectConfigV2ExternalDep,
21
21
  AppConfigDep,
22
22
  EntityRepositoryV2ExternalDep,
23
+ RelationRepositoryV2ExternalDep,
23
24
  ProjectExternalIdPathDep,
24
25
  TaskSchedulerDep,
25
26
  FileServiceV2ExternalDep,
@@ -31,6 +32,9 @@ from basic_memory.schemas.v2 import (
31
32
  EntityResolveRequest,
32
33
  EntityResolveResponse,
33
34
  EntityResponseV2,
35
+ GraphEdge,
36
+ GraphNode,
37
+ GraphResponse,
34
38
  MoveEntityRequestV2,
35
39
  MoveDirectoryRequestV2,
36
40
  DeleteDirectoryRequestV2,
@@ -56,6 +60,50 @@ def _schedule_vector_sync_if_enabled(
56
60
  )
57
61
 
58
62
 
63
+ ## Graph endpoint
64
+
65
+
66
+ @router.get("/graph", response_model=GraphResponse)
67
+ async def get_graph(
68
+ project_id: ProjectExternalIdPathDep,
69
+ entity_repository: EntityRepositoryV2ExternalDep,
70
+ relation_repository: RelationRepositoryV2ExternalDep,
71
+ ) -> GraphResponse:
72
+ """Return all entities and resolved relations for knowledge graph visualization.
73
+
74
+ Returns a flat node/edge structure optimized for rendering with graph libraries.
75
+ Only includes resolved relations (where to_id is not null).
76
+ """
77
+ logger.info("API v2 request: get_graph")
78
+
79
+ # Fetch all entities for this project
80
+ entities = await entity_repository.find_all(use_load_options=False)
81
+ nodes = [
82
+ GraphNode(
83
+ external_id=entity.external_id,
84
+ title=entity.title,
85
+ note_type=entity.note_type,
86
+ file_path=entity.file_path,
87
+ )
88
+ for entity in entities
89
+ ]
90
+
91
+ # Fetch all resolved relations (to_id is not null) with eager-loaded entities
92
+ relations = await relation_repository.find_all()
93
+ edges = [
94
+ GraphEdge(
95
+ from_id=relation.from_entity.external_id,
96
+ to_id=relation.to_entity.external_id,
97
+ relation_type=relation.relation_type,
98
+ )
99
+ for relation in relations
100
+ if relation.to_entity is not None
101
+ ]
102
+
103
+ logger.info(f"API v2 response: graph with {len(nodes)} nodes and {len(edges)} edges")
104
+ return GraphResponse(nodes=nodes, edges=edges)
105
+
106
+
59
107
  ## Resolution endpoint
60
108
 
61
109
 
@@ -318,7 +318,7 @@ delete_note("path/to/file.md")
318
318
  note_file_path = None
319
319
  try:
320
320
  # Resolve identifier to entity ID
321
- entity_id = await knowledge_client.resolve_entity(identifier)
321
+ entity_id = await knowledge_client.resolve_entity(identifier, strict=True)
322
322
  if output_format == "json":
323
323
  entity = await knowledge_client.get_entity(entity_id)
324
324
  note_title = entity.title
@@ -158,7 +158,7 @@ Error editing note '{identifier}': {error_message}
158
158
 
159
159
 
160
160
  @mcp.tool(
161
- description="Edit an existing markdown note using various operations like append, prepend, find_replace, or replace_section.",
161
+ description="Edit an existing markdown note using various operations like append, prepend, find_replace, replace_section, insert_before_section, or insert_after_section.",
162
162
  annotations={"destructiveHint": False, "openWorldHint": False},
163
163
  )
164
164
  async def edit_note(
@@ -190,6 +190,8 @@ async def edit_note(
190
190
  - "prepend": Add content to the beginning of the note (creates the note if it doesn't exist)
191
191
  - "find_replace": Replace occurrences of find_text with content (note must exist)
192
192
  - "replace_section": Replace content under a specific markdown header (note must exist)
193
+ - "insert_before_section": Insert content before a section heading without consuming it (note must exist)
194
+ - "insert_after_section": Insert content after a section heading without consuming it (note must exist)
193
195
  content: The content to add or use for replacement
194
196
  project: Project name to edit in. Optional - server will resolve using hierarchy.
195
197
  If unknown, use list_memory_projects() to discover available projects.
@@ -257,7 +259,14 @@ async def edit_note(
257
259
  logger.info("MCP tool call", tool="edit_note", identifier=identifier, operation=operation)
258
260
 
259
261
  # Validate operation
260
- valid_operations = ["append", "prepend", "find_replace", "replace_section"]
262
+ valid_operations = [
263
+ "append",
264
+ "prepend",
265
+ "find_replace",
266
+ "replace_section",
267
+ "insert_before_section",
268
+ "insert_after_section",
269
+ ]
261
270
  if operation not in valid_operations:
262
271
  raise ValueError(
263
272
  f"Invalid operation '{operation}'. Must be one of: {', '.join(valid_operations)}"
@@ -266,8 +275,9 @@ async def edit_note(
266
275
  # Validate required parameters for specific operations
267
276
  if operation == "find_replace" and not find_text:
268
277
  raise ValueError("find_text parameter is required for find_replace operation")
269
- if operation == "replace_section" and not section:
270
- raise ValueError("section parameter is required for replace_section operation")
278
+ section_ops = ("replace_section", "insert_before_section", "insert_after_section")
279
+ if operation in section_ops and not section:
280
+ raise ValueError("section parameter is required for section-based operations")
271
281
 
272
282
  # Use the PATCH endpoint to edit the entity
273
283
  try:
@@ -283,7 +293,7 @@ async def edit_note(
283
293
 
284
294
  # Try to resolve the entity; for append/prepend, create it if not found
285
295
  try:
286
- entity_id = await knowledge_client.resolve_entity(identifier)
296
+ entity_id = await knowledge_client.resolve_entity(identifier, strict=True)
287
297
  except Exception as resolve_error:
288
298
  # Trigger: entity does not exist yet
289
299
  # Why: append/prepend can meaningfully create a new note from the content,
@@ -389,6 +399,10 @@ async def edit_note(
389
399
  summary.append("operation: Find and replace operation completed")
390
400
  elif operation == "replace_section":
391
401
  summary.append(f"operation: Replaced content under section '{section}'")
402
+ elif operation == "insert_before_section":
403
+ summary.append(f"operation: Inserted content before section '{section}'")
404
+ elif operation == "insert_after_section":
405
+ summary.append(f"operation: Inserted content after section '{section}'")
392
406
 
393
407
  # Count observations by category (reuse logic from write_note)
394
408
  categories = {}
@@ -6,6 +6,7 @@ from typing import Optional, Literal
6
6
 
7
7
  from loguru import logger
8
8
  from fastmcp import Context
9
+ from mcp.server.fastmcp.exceptions import ToolError
9
10
 
10
11
  from basic_memory.mcp.server import mcp
11
12
  from basic_memory.mcp.project_context import get_project_client
@@ -637,7 +638,7 @@ move_note("path/to/file.md", "{destination_path}/file.md")
637
638
  """Resolve and cache the source entity ID for the duration of this move."""
638
639
  nonlocal resolved_entity_id
639
640
  if resolved_entity_id is None:
640
- resolved_entity_id = await knowledge_client.resolve_entity(identifier)
641
+ resolved_entity_id = await knowledge_client.resolve_entity(identifier, strict=True)
641
642
  return resolved_entity_id
642
643
 
643
644
  try:
@@ -645,8 +646,26 @@ move_note("path/to/file.md", "{destination_path}/file.md")
645
646
  source_entity = await knowledge_client.get_entity(resolved_entity_id)
646
647
  if "." in source_entity.file_path:
647
648
  source_ext = source_entity.file_path.split(".")[-1]
649
+ except ToolError as e:
650
+ # Trigger: strict=True resolve_entity raised because the entity was not found.
651
+ # Why: fail fast with a formatted error instead of silently falling through
652
+ # to extension defaults and failing later with a confusing message.
653
+ # Outcome: move_note returns a user-facing not-found error immediately.
654
+ logger.error(f"Move failed for '{identifier}' to '{destination_path}': {e}")
655
+ if output_format == "json":
656
+ return {
657
+ "moved": False,
658
+ "title": None,
659
+ "permalink": None,
660
+ "file_path": None,
661
+ "source": identifier,
662
+ "destination": destination_path,
663
+ "error": str(e),
664
+ }
665
+ return _format_move_error_response(str(e), identifier, destination_path)
648
666
  except Exception as e:
649
- # If we can't fetch source metadata, continue with extension defaults.
667
+ # If we can't fetch source metadata (e.g. get_entity or file_path parsing fails),
668
+ # continue with extension defaults — the entity was at least resolved.
650
669
  logger.debug(f"Could not fetch source entity for extension check: {e}")
651
670
 
652
671
  # --- Resolve destination_folder into destination_path ---
@@ -140,10 +140,12 @@ def validate_timeframe(timeframe: str) -> str:
140
140
  if parsed > now:
141
141
  raise ValueError("Timeframe cannot be in the future") # pragma: no cover
142
142
 
143
- # Could format the duration back to our standard format
144
- days = (now - parsed).days
143
+ # Round to nearest day to handle DST transitions where an hour shift
144
+ # can cause e.g. "7d" to compute as 6 days + 23 hours
145
+ total_seconds = (now - parsed).total_seconds()
146
+ days = round(total_seconds / 86400)
145
147
 
146
- # Could enforce reasonable limits
148
+ # Enforce reasonable limits
147
149
  if days > 365:
148
150
  raise ValueError("Timeframe should be <= 1 year")
149
151
 
@@ -65,7 +65,14 @@ class EditEntityRequest(BaseModel):
65
65
  Supports various operation types for different editing scenarios.
66
66
  """
67
67
 
68
- operation: Literal["append", "prepend", "find_replace", "replace_section"]
68
+ operation: Literal[
69
+ "append",
70
+ "prepend",
71
+ "find_replace",
72
+ "replace_section",
73
+ "insert_before_section",
74
+ "insert_after_section",
75
+ ]
69
76
  content: str
70
77
  section: Optional[str] = None
71
78
  find_text: Optional[str] = None
@@ -75,8 +82,16 @@ class EditEntityRequest(BaseModel):
75
82
  @classmethod
76
83
  def validate_section_for_replace_section(cls, v, info):
77
84
  """Ensure section is provided for replace_section operation."""
78
- if info.data.get("operation") == "replace_section" and not v:
79
- raise ValueError("section parameter is required for replace_section operation")
85
+ if (
86
+ info.data.get("operation")
87
+ in (
88
+ "replace_section",
89
+ "insert_before_section",
90
+ "insert_after_section",
91
+ )
92
+ and not v
93
+ ):
94
+ raise ValueError("section parameter is required for section-based operations")
80
95
  return v
81
96
 
82
97
  @field_validator("find_text")
@@ -10,6 +10,11 @@ from basic_memory.schemas.v2.entity import (
10
10
  ProjectResolveRequest,
11
11
  ProjectResolveResponse,
12
12
  )
13
+ from basic_memory.schemas.v2.graph import (
14
+ GraphEdge,
15
+ GraphNode,
16
+ GraphResponse,
17
+ )
13
18
  from basic_memory.schemas.v2.resource import (
14
19
  CreateResourceRequest,
15
20
  UpdateResourceRequest,
@@ -25,6 +30,9 @@ __all__ = [
25
30
  "DeleteDirectoryRequestV2",
26
31
  "ProjectResolveRequest",
27
32
  "ProjectResolveResponse",
33
+ "GraphEdge",
34
+ "GraphNode",
35
+ "GraphResponse",
28
36
  "CreateResourceRequest",
29
37
  "UpdateResourceRequest",
30
38
  "ResourceResponse",
@@ -0,0 +1,31 @@
1
+ """Graph visualization schemas for the knowledge graph endpoint."""
2
+
3
+ from typing import Optional
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+
8
+ class GraphNode(BaseModel):
9
+ """A node in the knowledge graph visualization."""
10
+
11
+ external_id: str = Field(..., description="Entity external ID (UUID)")
12
+ title: str = Field(..., description="Entity title")
13
+ note_type: Optional[str] = Field(None, description="Note type (e.g., note, spec, task)")
14
+ file_path: str = Field(..., description="Relative file path")
15
+
16
+
17
+ class GraphEdge(BaseModel):
18
+ """An edge in the knowledge graph visualization."""
19
+
20
+ from_id: str = Field(..., description="External ID of source entity")
21
+ to_id: str = Field(..., description="External ID of target entity")
22
+ relation_type: str = Field(..., description="Type of relation")
23
+
24
+
25
+ class GraphResponse(BaseModel):
26
+ """Complete knowledge graph for visualization."""
27
+
28
+ nodes: list[GraphNode] = Field(default_factory=list, description="All entities as nodes")
29
+ edges: list[GraphEdge] = Field(
30
+ default_factory=list, description="All resolved relations as edges"
31
+ )
@@ -888,6 +888,14 @@ class EntityService(BaseService[EntityModel]):
888
888
  raise ValueError("section cannot be empty or whitespace only")
889
889
  return self.replace_section_content(current_content, section, content)
890
890
 
891
+ elif operation in ("insert_before_section", "insert_after_section"):
892
+ if not section:
893
+ raise ValueError("section is required for insert section operations")
894
+ if not section.strip():
895
+ raise ValueError("section cannot be empty or whitespace only")
896
+ position = "before" if operation == "insert_before_section" else "after"
897
+ return self.insert_relative_to_section(current_content, section, content, position)
898
+
891
899
  else:
892
900
  raise ValueError(f"Unsupported operation: {operation}")
893
901
 
@@ -979,6 +987,73 @@ class EntityService(BaseService[EntityModel]):
979
987
 
980
988
  return "\n".join(result_lines)
981
989
 
990
+ def insert_relative_to_section(
991
+ self,
992
+ current_content: str,
993
+ section_header: str,
994
+ new_content: str,
995
+ position: str,
996
+ ) -> str:
997
+ """Insert content before or after a section heading without consuming it.
998
+
999
+ Unlike replace_section_content, this preserves the section heading and its
1000
+ existing content. The new content is inserted immediately before or after
1001
+ the heading line.
1002
+
1003
+ Args:
1004
+ current_content: The current markdown content
1005
+ section_header: The section header to anchor on (e.g., "## Section Name")
1006
+ new_content: The content to insert
1007
+ position: "before" to insert above the heading, "after" to insert below it
1008
+
1009
+ Returns:
1010
+ The updated content with new_content inserted relative to the heading
1011
+
1012
+ Raises:
1013
+ ValueError: If the section header is not found or appears more than once
1014
+ """
1015
+ # Normalize the section header (ensure it starts with #)
1016
+ if not section_header.startswith("#"):
1017
+ section_header = "## " + section_header
1018
+
1019
+ lines = current_content.split("\n")
1020
+ matching_indices = [
1021
+ i for i, line in enumerate(lines) if line.strip() == section_header.strip()
1022
+ ]
1023
+
1024
+ if len(matching_indices) == 0:
1025
+ raise ValueError(
1026
+ f"Section '{section_header}' not found in document. "
1027
+ f"Use replace_section to create a new section."
1028
+ )
1029
+ if len(matching_indices) > 1:
1030
+ raise ValueError(
1031
+ f"Multiple sections found with header '{section_header}'. "
1032
+ f"Section insertion requires unique headers."
1033
+ )
1034
+
1035
+ idx = matching_indices[0]
1036
+
1037
+ if position == "before":
1038
+ # Insert new content before the section heading
1039
+ before = lines[:idx]
1040
+ after = lines[idx:]
1041
+ # Ensure blank line separation
1042
+ insert_lines = new_content.rstrip("\n").split("\n")
1043
+ if before and before[-1].strip() != "":
1044
+ insert_lines = [""] + insert_lines
1045
+ return "\n".join(before + insert_lines + [""] + after)
1046
+ else:
1047
+ # Insert new content after the section heading line
1048
+ before = lines[: idx + 1]
1049
+ after = lines[idx + 1 :]
1050
+ insert_lines = new_content.rstrip("\n").split("\n")
1051
+ # Ensure blank line separation so inserted text doesn't merge
1052
+ # with existing section content into a single paragraph
1053
+ if after and after[0].strip() != "":
1054
+ insert_lines = insert_lines + [""]
1055
+ return "\n".join(before + insert_lines + after)
1056
+
982
1057
  def _prepend_after_frontmatter(self, current_content: str, content: str) -> str:
983
1058
  """Prepend content after frontmatter, preserving frontmatter structure."""
984
1059
 
@@ -208,7 +208,7 @@ def test_edit_note_replace_section_fails_without_section(
208
208
  )
209
209
 
210
210
  assert result.exit_code != 0
211
- assert "section parameter is required for replace_section operation" in result.output
211
+ assert "section parameter is required for section-based operations" in result.output
212
212
 
213
213
 
214
214
  def test_edit_note_append_creates_nonexistent_note_cli(
@@ -307,8 +307,13 @@ async def test_delete_note_by_file_path(mcp_server, app, test_project):
307
307
 
308
308
 
309
309
  @pytest.mark.asyncio
310
- async def test_delete_note_case_insensitive(mcp_server, app, test_project):
311
- """Test that note deletion is case insensitive for titles."""
310
+ async def test_delete_note_rejects_case_mismatch(mcp_server, app, test_project):
311
+ """Test that delete_note with wrong case does not fuzzy-match to an existing note.
312
+
313
+ Strict resolution (#649) prevents destructive operations from silently
314
+ resolving to a different note via fuzzy search. Case-mismatched titles
315
+ should be rejected, not resolved to the nearest match.
316
+ """
312
317
 
313
318
  async with Client(mcp_server) as client:
314
319
  # Create a note with mixed case
@@ -323,7 +328,7 @@ async def test_delete_note_case_insensitive(mcp_server, app, test_project):
323
328
  },
324
329
  )
325
330
 
326
- # Try to delete with different case
331
+ # Try to delete with different case — should NOT find the note
327
332
  delete_result = await client.call_tool(
328
333
  "delete_note",
329
334
  {
@@ -332,8 +337,28 @@ async def test_delete_note_case_insensitive(mcp_server, app, test_project):
332
337
  },
333
338
  )
334
339
 
335
- # Should return True for successful deletion
336
- assert "true" in delete_result.content[0].text.lower()
340
+ # Should return False (not found) — strict mode rejects fuzzy matches
341
+ assert "false" in delete_result.content[0].text.lower()
342
+
343
+ # Verify the note still exists using the exact title
344
+ read_result = await client.call_tool(
345
+ "read_note",
346
+ {
347
+ "project": test_project.name,
348
+ "identifier": "CamelCase Note Title",
349
+ },
350
+ )
351
+ assert "Testing case sensitivity" in read_result.content[0].text
352
+
353
+ # Delete with exact title should succeed
354
+ delete_result2 = await client.call_tool(
355
+ "delete_note",
356
+ {
357
+ "project": test_project.name,
358
+ "identifier": "CamelCase Note Title",
359
+ },
360
+ )
361
+ assert "true" in delete_result2.content[0].text.lower()
337
362
 
338
363
 
339
364
  @pytest.mark.asyncio
@@ -710,3 +710,81 @@ async def test_edit_note_using_different_identifiers(mcp_server, app, test_proje
710
710
  assert "Edited by title." in content
711
711
  assert "Edited by permalink." in content
712
712
  assert "Edited by folder/title." in content
713
+
714
+
715
+ @pytest.mark.asyncio
716
+ async def test_edit_note_append_autocreate_does_not_fuzzy_match(mcp_server, app, test_project):
717
+ """Reproduces #649: edit_note append must auto-create, not fuzzy-match to an existing note.
718
+
719
+ Creates two notes, then attempts to append to a nonexistent identifier.
720
+ The tool should create a new note, and neither existing note should be modified.
721
+ """
722
+
723
+ async with Client(mcp_server) as client:
724
+ # Create two notes that could be fuzzy-matched
725
+ await client.call_tool(
726
+ "write_note",
727
+ {
728
+ "project": test_project.name,
729
+ "title": "Routing Test A",
730
+ "directory": "test",
731
+ "content": "# Routing Test A\n\nContent A.",
732
+ },
733
+ )
734
+ await client.call_tool(
735
+ "write_note",
736
+ {
737
+ "project": test_project.name,
738
+ "title": "Routing Test B",
739
+ "directory": "test",
740
+ "content": "# Routing Test B\n\nContent B.",
741
+ },
742
+ )
743
+
744
+ # Attempt to edit a nonexistent note — should error, not silently edit A or B
745
+ edit_result = await client.call_tool(
746
+ "edit_note",
747
+ {
748
+ "project": test_project.name,
749
+ "identifier": "Routing Test NONEXISTENT",
750
+ "operation": "append",
751
+ "content": "\n\nThis should NOT appear in any note.",
752
+ },
753
+ )
754
+
755
+ edit_text = edit_result.content[0].text
756
+ # append to nonexistent creates a new note — verify it did NOT edit A or B
757
+ assert "Created note (append)" in edit_text
758
+ assert "fileCreated: true" in edit_text
759
+
760
+ # Verify neither A nor B was modified
761
+ read_a = await client.call_tool(
762
+ "read_note",
763
+ {"project": test_project.name, "identifier": "Routing Test A"},
764
+ )
765
+ content_a = read_a.content[0].text
766
+ assert "Content A" in content_a
767
+ assert "This should NOT appear" not in content_a
768
+
769
+ read_b = await client.call_tool(
770
+ "read_note",
771
+ {"project": test_project.name, "identifier": "Routing Test B"},
772
+ )
773
+ content_b = read_b.content[0].text
774
+ assert "Content B" in content_b
775
+ assert "This should NOT appear" not in content_b
776
+
777
+ # Now test find_replace on nonexistent — should error
778
+ edit_result2 = await client.call_tool(
779
+ "edit_note",
780
+ {
781
+ "project": test_project.name,
782
+ "identifier": "Routing Test NONEXISTENT AGAIN",
783
+ "operation": "find_replace",
784
+ "content": "replaced",
785
+ "find_text": "Content",
786
+ },
787
+ )
788
+
789
+ error_text = edit_result2.content[0].text
790
+ assert "Edit Failed" in error_text