basic-memory 0.17.9__tar.gz → 0.18.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (420) hide show
  1. {basic_memory-0.17.9 → basic_memory-0.18.0}/CHANGELOG.md +31 -0
  2. {basic_memory-0.17.9 → basic_memory-0.18.0}/CLAUDE.md +24 -4
  3. {basic_memory-0.17.9 → basic_memory-0.18.0}/PKG-INFO +18 -1
  4. {basic_memory-0.17.9 → basic_memory-0.18.0}/README.md +17 -0
  5. {basic_memory-0.17.9 → basic_memory-0.18.0}/server.json +2 -2
  6. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/__init__.py +1 -1
  7. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/routers/importer_router.py +12 -12
  8. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/routers/knowledge_router.py +46 -1
  9. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/v2/routers/importer_router.py +15 -15
  10. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/v2/routers/knowledge_router.py +105 -1
  11. basic_memory-0.18.0/src/basic_memory/cli/commands/mcp.py +80 -0
  12. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/project.py +136 -44
  13. basic_memory-0.18.0/src/basic_memory/cli/commands/routing.py +73 -0
  14. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/status.py +16 -2
  15. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/tool.py +155 -73
  16. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/file_utils.py +4 -4
  17. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/async_client.py +32 -2
  18. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/clients/knowledge.py +50 -1
  19. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/prompts/continue_conversation.py +1 -2
  20. basic_memory-0.18.0/src/basic_memory/mcp/prompts/recent_activity.py +100 -0
  21. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/prompts/search.py +1 -2
  22. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/prompts/utils.py +1 -2
  23. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/tools/canvas.py +11 -11
  24. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/tools/delete_note.py +94 -14
  25. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/tools/move_note.py +92 -11
  26. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/tools/search.py +1 -1
  27. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/tools/write_note.py +18 -18
  28. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/repository/entity_repository.py +12 -3
  29. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/schemas/base.py +7 -5
  30. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/schemas/request.py +24 -0
  31. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/schemas/response.py +68 -0
  32. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/schemas/v2/__init__.py +4 -0
  33. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/schemas/v2/entity.py +48 -0
  34. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/services/entity_service.py +175 -1
  35. basic_memory-0.18.0/src/basic_memory/services/link_resolver.py +251 -0
  36. basic_memory-0.18.0/test-int/cli/test_routing_integration.py +181 -0
  37. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/mcp/test_build_context_underscore.py +5 -5
  38. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/mcp/test_build_context_validation.py +2 -2
  39. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/mcp/test_chatgpt_tools_integration.py +10 -10
  40. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/mcp/test_default_project_mode_integration.py +9 -9
  41. basic_memory-0.18.0/test-int/mcp/test_delete_directory_integration.py +268 -0
  42. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/mcp/test_delete_note_integration.py +8 -8
  43. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/mcp/test_edit_note_integration.py +11 -11
  44. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/mcp/test_list_directory_integration.py +23 -23
  45. basic_memory-0.18.0/test-int/mcp/test_move_directory_integration.py +343 -0
  46. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/mcp/test_move_note_integration.py +14 -14
  47. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/mcp/test_project_management_integration.py +5 -5
  48. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/mcp/test_project_state_sync_integration.py +1 -1
  49. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/mcp/test_read_content_integration.py +8 -8
  50. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/mcp/test_read_note_integration.py +2 -2
  51. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/mcp/test_search_integration.py +20 -20
  52. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/mcp/test_single_project_mcp_integration.py +6 -6
  53. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/mcp/test_write_note_integration.py +13 -13
  54. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/test_disable_permalinks_integration.py +1 -1
  55. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/test_importer_router.py +11 -11
  56. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/test_knowledge_router.py +161 -44
  57. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/test_resource_router.py +7 -7
  58. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/test_search_router.py +1 -1
  59. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/v2/test_importer_router.py +16 -16
  60. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/v2/test_knowledge_router.py +237 -11
  61. basic_memory-0.18.0/tests/cli/test_routing.py +102 -0
  62. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/conftest.py +6 -6
  63. basic_memory-0.18.0/tests/mcp/test_async_client_force_local.py +79 -0
  64. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_obsidian_yaml_formatting.py +8 -8
  65. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_permalink_collision_file_overwrite.py +5 -5
  66. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_prompts.py +8 -6
  67. basic_memory-0.18.0/tests/mcp/test_recent_activity_prompt_modes.py +91 -0
  68. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_tool_canvas.py +6 -6
  69. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_tool_edit_note.py +16 -16
  70. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_tool_list_directory.py +3 -3
  71. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_tool_move_note.py +28 -28
  72. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_tool_read_content.py +1 -1
  73. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_tool_read_note.py +8 -8
  74. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_tool_recent_activity.py +2 -2
  75. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_tool_resource.py +3 -3
  76. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_tool_search.py +8 -8
  77. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_tool_view_note.py +12 -12
  78. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_tool_write_note.py +39 -39
  79. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_tool_write_note_kebab_filenames.py +20 -20
  80. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/tools/test_chatgpt_tools.py +3 -3
  81. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/repository/test_entity_repository.py +60 -0
  82. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/schemas/test_schemas.py +8 -8
  83. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/services/test_entity_service.py +53 -53
  84. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/services/test_entity_service_disable_permalinks.py +4 -4
  85. basic_memory-0.18.0/tests/services/test_link_resolver.py +831 -0
  86. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/sync/test_sync_service.py +4 -3
  87. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/utils/test_file_utils.py +19 -19
  88. basic_memory-0.17.9/src/basic_memory/cli/commands/mcp.py +0 -76
  89. basic_memory-0.17.9/src/basic_memory/mcp/prompts/recent_activity.py +0 -188
  90. basic_memory-0.17.9/src/basic_memory/services/link_resolver.py +0 -121
  91. basic_memory-0.17.9/tests/mcp/test_recent_activity_prompt_modes.py +0 -111
  92. basic_memory-0.17.9/tests/services/test_link_resolver.py +0 -359
  93. {basic_memory-0.17.9 → basic_memory-0.18.0}/.claude/commands/release/beta.md +0 -0
  94. {basic_memory-0.17.9 → basic_memory-0.18.0}/.claude/commands/release/changelog.md +0 -0
  95. {basic_memory-0.17.9 → basic_memory-0.18.0}/.claude/commands/release/release-check.md +0 -0
  96. {basic_memory-0.17.9 → basic_memory-0.18.0}/.claude/commands/release/release.md +0 -0
  97. {basic_memory-0.17.9 → basic_memory-0.18.0}/.claude/commands/spec.md +0 -0
  98. {basic_memory-0.17.9 → basic_memory-0.18.0}/.claude/commands/test-live.md +0 -0
  99. {basic_memory-0.17.9 → basic_memory-0.18.0}/.claude/settings.json +0 -0
  100. {basic_memory-0.17.9 → basic_memory-0.18.0}/.dockerignore +0 -0
  101. {basic_memory-0.17.9 → basic_memory-0.18.0}/.env.example +0 -0
  102. {basic_memory-0.17.9 → basic_memory-0.18.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  103. {basic_memory-0.17.9 → basic_memory-0.18.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  104. {basic_memory-0.17.9 → basic_memory-0.18.0}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
  105. {basic_memory-0.17.9 → basic_memory-0.18.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  106. {basic_memory-0.17.9 → basic_memory-0.18.0}/.github/dependabot.yml +0 -0
  107. {basic_memory-0.17.9 → basic_memory-0.18.0}/.github/workflows/claude-code-review.yml +0 -0
  108. {basic_memory-0.17.9 → basic_memory-0.18.0}/.github/workflows/claude-issue-triage.yml +0 -0
  109. {basic_memory-0.17.9 → basic_memory-0.18.0}/.github/workflows/claude.yml +0 -0
  110. {basic_memory-0.17.9 → basic_memory-0.18.0}/.github/workflows/dev-release.yml +0 -0
  111. {basic_memory-0.17.9 → basic_memory-0.18.0}/.github/workflows/docker.yml +0 -0
  112. {basic_memory-0.17.9 → basic_memory-0.18.0}/.github/workflows/pr-title.yml +0 -0
  113. {basic_memory-0.17.9 → basic_memory-0.18.0}/.github/workflows/release.yml +0 -0
  114. {basic_memory-0.17.9 → basic_memory-0.18.0}/.github/workflows/test.yml +0 -0
  115. {basic_memory-0.17.9 → basic_memory-0.18.0}/.gitignore +0 -0
  116. {basic_memory-0.17.9 → basic_memory-0.18.0}/.python-version +0 -0
  117. {basic_memory-0.17.9 → basic_memory-0.18.0}/CITATION.cff +0 -0
  118. {basic_memory-0.17.9 → basic_memory-0.18.0}/CLA.md +0 -0
  119. {basic_memory-0.17.9 → basic_memory-0.18.0}/CODE_OF_CONDUCT.md +0 -0
  120. {basic_memory-0.17.9 → basic_memory-0.18.0}/CONTRIBUTING.md +0 -0
  121. {basic_memory-0.17.9 → basic_memory-0.18.0}/Dockerfile +0 -0
  122. {basic_memory-0.17.9 → basic_memory-0.18.0}/LICENSE +0 -0
  123. {basic_memory-0.17.9 → basic_memory-0.18.0}/SECURITY.md +0 -0
  124. {basic_memory-0.17.9 → basic_memory-0.18.0}/docker-compose-postgres.yml +0 -0
  125. {basic_memory-0.17.9 → basic_memory-0.18.0}/docker-compose.yml +0 -0
  126. {basic_memory-0.17.9 → basic_memory-0.18.0}/docs/ARCHITECTURE.md +0 -0
  127. {basic_memory-0.17.9 → basic_memory-0.18.0}/docs/Docker.md +0 -0
  128. {basic_memory-0.17.9 → basic_memory-0.18.0}/docs/ai-assistant-guide-extended.md +0 -0
  129. {basic_memory-0.17.9 → basic_memory-0.18.0}/docs/character-handling.md +0 -0
  130. {basic_memory-0.17.9 → basic_memory-0.18.0}/docs/cloud-cli.md +0 -0
  131. {basic_memory-0.17.9 → basic_memory-0.18.0}/docs/testing-coverage.md +0 -0
  132. {basic_memory-0.17.9 → basic_memory-0.18.0}/justfile +0 -0
  133. {basic_memory-0.17.9 → basic_memory-0.18.0}/llms-install.md +0 -0
  134. {basic_memory-0.17.9 → basic_memory-0.18.0}/pyproject.toml +0 -0
  135. {basic_memory-0.17.9 → basic_memory-0.18.0}/smithery.yaml +0 -0
  136. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/alembic.ini +0 -0
  137. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/env.py +0 -0
  138. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/migrations.py +0 -0
  139. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/script.py.mako +0 -0
  140. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/versions/314f1ea54dc4_add_postgres_full_text_search_support_.py +0 -0
  141. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +0 -0
  142. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +0 -0
  143. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +0 -0
  144. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +0 -0
  145. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/versions/6830751f5fb6_merge_multiple_heads.py +0 -0
  146. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/versions/9d9c1cb7d8f5_add_mtime_and_size_columns_to_entity_.py +0 -0
  147. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +0 -0
  148. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/versions/a2b3c4d5e6f7_add_search_index_entity_cascade.py +0 -0
  149. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +0 -0
  150. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +0 -0
  151. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/versions/e7e1f4367280_add_scan_watermark_tracking_to_project.py +0 -0
  152. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/versions/f8a9b2c3d4e5_add_pg_trgm_for_fuzzy_link_resolution.py +0 -0
  153. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/alembic/versions/g9a0b3c4d5e6_add_external_id_to_project_and_entity.py +0 -0
  154. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/__init__.py +0 -0
  155. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/app.py +0 -0
  156. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/container.py +0 -0
  157. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/routers/__init__.py +0 -0
  158. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/routers/directory_router.py +0 -0
  159. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/routers/management_router.py +0 -0
  160. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/routers/memory_router.py +0 -0
  161. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/routers/project_router.py +0 -0
  162. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/routers/prompt_router.py +0 -0
  163. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/routers/resource_router.py +0 -0
  164. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/routers/search_router.py +0 -0
  165. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/routers/utils.py +0 -0
  166. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/template_loader.py +0 -0
  167. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/v2/__init__.py +0 -0
  168. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/v2/routers/__init__.py +0 -0
  169. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/v2/routers/directory_router.py +0 -0
  170. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/v2/routers/memory_router.py +0 -0
  171. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/v2/routers/project_router.py +0 -0
  172. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/v2/routers/prompt_router.py +0 -0
  173. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/v2/routers/resource_router.py +0 -0
  174. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/api/v2/routers/search_router.py +0 -0
  175. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/__init__.py +0 -0
  176. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/app.py +0 -0
  177. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/auth.py +0 -0
  178. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/__init__.py +0 -0
  179. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/cloud/__init__.py +0 -0
  180. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/cloud/api_client.py +0 -0
  181. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/cloud/bisync_commands.py +0 -0
  182. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/cloud/cloud_utils.py +0 -0
  183. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/cloud/core_commands.py +0 -0
  184. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/cloud/rclone_commands.py +0 -0
  185. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/cloud/rclone_config.py +0 -0
  186. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/cloud/rclone_installer.py +0 -0
  187. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/cloud/restore.py +0 -0
  188. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/cloud/schemas.py +0 -0
  189. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/cloud/snapshot.py +0 -0
  190. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/cloud/upload.py +0 -0
  191. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/cloud/upload_command.py +0 -0
  192. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/command_utils.py +0 -0
  193. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/db.py +0 -0
  194. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/format.py +0 -0
  195. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/import_chatgpt.py +0 -0
  196. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/import_claude_conversations.py +0 -0
  197. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/import_claude_projects.py +0 -0
  198. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/commands/import_memory_json.py +0 -0
  199. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/container.py +0 -0
  200. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/cli/main.py +0 -0
  201. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/config.py +0 -0
  202. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/db.py +0 -0
  203. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/deps/__init__.py +0 -0
  204. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/deps/config.py +0 -0
  205. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/deps/db.py +0 -0
  206. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/deps/importers.py +0 -0
  207. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/deps/projects.py +0 -0
  208. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/deps/repositories.py +0 -0
  209. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/deps/services.py +0 -0
  210. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/deps.py +0 -0
  211. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/ignore_utils.py +0 -0
  212. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/importers/__init__.py +0 -0
  213. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/importers/base.py +0 -0
  214. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/importers/chatgpt_importer.py +0 -0
  215. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/importers/claude_conversations_importer.py +0 -0
  216. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/importers/claude_projects_importer.py +0 -0
  217. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/importers/memory_json_importer.py +0 -0
  218. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/importers/utils.py +0 -0
  219. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/markdown/__init__.py +0 -0
  220. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/markdown/entity_parser.py +0 -0
  221. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/markdown/markdown_processor.py +0 -0
  222. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/markdown/plugins.py +0 -0
  223. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/markdown/schemas.py +0 -0
  224. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/markdown/utils.py +0 -0
  225. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/__init__.py +0 -0
  226. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/clients/__init__.py +0 -0
  227. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/clients/directory.py +0 -0
  228. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/clients/memory.py +0 -0
  229. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/clients/project.py +0 -0
  230. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/clients/resource.py +0 -0
  231. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/clients/search.py +0 -0
  232. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/container.py +0 -0
  233. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/project_context.py +0 -0
  234. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/prompts/__init__.py +0 -0
  235. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/prompts/ai_assistant_guide.py +0 -0
  236. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/resources/ai_assistant_guide.md +0 -0
  237. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/resources/project_info.py +0 -0
  238. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/server.py +0 -0
  239. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/tools/__init__.py +0 -0
  240. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/tools/build_context.py +0 -0
  241. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/tools/chatgpt_tools.py +0 -0
  242. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/tools/edit_note.py +0 -0
  243. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/tools/list_directory.py +0 -0
  244. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/tools/project_management.py +0 -0
  245. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/tools/read_content.py +0 -0
  246. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/tools/read_note.py +0 -0
  247. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/tools/recent_activity.py +0 -0
  248. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/tools/utils.py +0 -0
  249. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/mcp/tools/view_note.py +0 -0
  250. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/models/__init__.py +0 -0
  251. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/models/base.py +0 -0
  252. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/models/knowledge.py +0 -0
  253. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/models/project.py +0 -0
  254. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/models/search.py +0 -0
  255. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/project_resolver.py +0 -0
  256. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/repository/__init__.py +0 -0
  257. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/repository/observation_repository.py +0 -0
  258. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/repository/postgres_search_repository.py +0 -0
  259. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/repository/project_info_repository.py +0 -0
  260. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/repository/project_repository.py +0 -0
  261. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/repository/relation_repository.py +0 -0
  262. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/repository/repository.py +0 -0
  263. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/repository/search_index_row.py +0 -0
  264. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/repository/search_repository.py +0 -0
  265. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/repository/search_repository_base.py +0 -0
  266. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/repository/sqlite_search_repository.py +0 -0
  267. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/runtime.py +0 -0
  268. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/schemas/__init__.py +0 -0
  269. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/schemas/cloud.py +0 -0
  270. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/schemas/delete.py +0 -0
  271. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/schemas/directory.py +0 -0
  272. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/schemas/importer.py +0 -0
  273. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/schemas/memory.py +0 -0
  274. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/schemas/project_info.py +0 -0
  275. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/schemas/prompt.py +0 -0
  276. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/schemas/search.py +0 -0
  277. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/schemas/sync_report.py +0 -0
  278. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/schemas/v2/resource.py +0 -0
  279. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/services/__init__.py +0 -0
  280. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/services/context_service.py +0 -0
  281. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/services/directory_service.py +0 -0
  282. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/services/exceptions.py +0 -0
  283. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/services/file_service.py +0 -0
  284. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/services/initialization.py +0 -0
  285. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/services/project_service.py +0 -0
  286. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/services/search_service.py +0 -0
  287. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/services/service.py +0 -0
  288. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/sync/__init__.py +0 -0
  289. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/sync/background_sync.py +0 -0
  290. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/sync/coordinator.py +0 -0
  291. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/sync/sync_service.py +0 -0
  292. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/sync/watch_service.py +0 -0
  293. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/templates/prompts/continue_conversation.hbs +0 -0
  294. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/templates/prompts/search.hbs +0 -0
  295. {basic_memory-0.17.9 → basic_memory-0.18.0}/src/basic_memory/utils.py +0 -0
  296. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/BENCHMARKS.md +0 -0
  297. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/cli/test_project_commands_integration.py +0 -0
  298. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/cli/test_version_integration.py +0 -0
  299. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/conftest.py +0 -0
  300. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/mcp/test_lifespan_shutdown_sync_task_cancellation_integration.py +0 -0
  301. {basic_memory-0.17.9 → basic_memory-0.18.0}/test-int/test_db_wal_mode.py +0 -0
  302. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/Non-MarkdownFileSupport.pdf +0 -0
  303. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/README.md +0 -0
  304. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/Screenshot.png +0 -0
  305. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/__init__.py +0 -0
  306. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/conftest.py +0 -0
  307. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/test_api_container.py +0 -0
  308. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/test_async_client.py +0 -0
  309. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/test_continue_conversation_template.py +0 -0
  310. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/test_directory_router.py +0 -0
  311. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/test_management_router.py +0 -0
  312. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/test_memory_router.py +0 -0
  313. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/test_project_router.py +0 -0
  314. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/test_project_router_operations.py +0 -0
  315. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/test_prompt_router.py +0 -0
  316. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/test_relation_background_resolution.py +0 -0
  317. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/test_search_template.py +0 -0
  318. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/test_template_loader.py +0 -0
  319. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/test_template_loader_helpers.py +0 -0
  320. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/v2/__init__.py +0 -0
  321. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/v2/conftest.py +0 -0
  322. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/v2/test_directory_router.py +0 -0
  323. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/v2/test_memory_router.py +0 -0
  324. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/v2/test_project_router.py +0 -0
  325. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/v2/test_prompt_router.py +0 -0
  326. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/v2/test_resource_router.py +0 -0
  327. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/api/v2/test_search_router.py +0 -0
  328. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/cloud/test_cloud_api_client_and_utils.py +0 -0
  329. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/cloud/test_rclone_config_and_bmignore_filters.py +0 -0
  330. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/cloud/test_upload_path.py +0 -0
  331. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/conftest.py +0 -0
  332. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/test_auth_cli_auth.py +0 -0
  333. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/test_cli_container.py +0 -0
  334. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/test_cli_exit.py +0 -0
  335. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/test_cli_tool_exit.py +0 -0
  336. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/test_cli_tools.py +0 -0
  337. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/test_cloud_authentication.py +0 -0
  338. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/test_ignore_utils.py +0 -0
  339. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/test_import_chatgpt.py +0 -0
  340. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/test_import_claude_conversations.py +0 -0
  341. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/test_import_claude_projects.py +0 -0
  342. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/test_import_memory_json.py +0 -0
  343. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/test_project_add_with_local_path.py +0 -0
  344. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/test_restore_commands.py +0 -0
  345. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/test_snapshot_commands.py +0 -0
  346. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/cli/test_upload.py +0 -0
  347. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/db/test_issue_254_foreign_key_constraints.py +0 -0
  348. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/importers/test_conversation_indexing.py +0 -0
  349. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/importers/test_importer_base.py +0 -0
  350. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/importers/test_importer_utils.py +0 -0
  351. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/markdown/__init__.py +0 -0
  352. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/markdown/test_date_frontmatter_parsing.py +0 -0
  353. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/markdown/test_entity_parser.py +0 -0
  354. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/markdown/test_entity_parser_error_handling.py +0 -0
  355. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/markdown/test_markdown_plugins.py +0 -0
  356. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/markdown/test_markdown_processor.py +0 -0
  357. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/markdown/test_markdown_utils.py +0 -0
  358. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/markdown/test_observation_edge_cases.py +0 -0
  359. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/markdown/test_parser_edge_cases.py +0 -0
  360. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/markdown/test_relation_edge_cases.py +0 -0
  361. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/markdown/test_task_detection.py +0 -0
  362. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/clients/__init__.py +0 -0
  363. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/clients/test_clients.py +0 -0
  364. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/conftest.py +0 -0
  365. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_async_client_modes.py +0 -0
  366. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_mcp_container.py +0 -0
  367. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_project_context.py +0 -0
  368. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_resources.py +0 -0
  369. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_server_lifespan_branches.py +0 -0
  370. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_tool_build_context.py +0 -0
  371. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_tool_delete_note.py +0 -0
  372. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_tool_project_management.py +0 -0
  373. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/mcp/test_tool_utils.py +0 -0
  374. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/repository/test_entity_repository_upsert.py +0 -0
  375. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/repository/test_entity_upsert_issue_187.py +0 -0
  376. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/repository/test_observation_repository.py +0 -0
  377. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/repository/test_postgres_search_repository.py +0 -0
  378. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/repository/test_project_info_repository.py +0 -0
  379. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/repository/test_project_repository.py +0 -0
  380. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/repository/test_relation_repository.py +0 -0
  381. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/repository/test_repository.py +0 -0
  382. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/repository/test_search_repository.py +0 -0
  383. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/repository/test_search_repository_edit_bug_fix.py +0 -0
  384. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/schemas/test_base_timeframe_minimum.py +0 -0
  385. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/schemas/test_memory_serialization.py +0 -0
  386. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/schemas/test_memory_url.py +0 -0
  387. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/schemas/test_memory_url_validation.py +0 -0
  388. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/schemas/test_relation_response_reference_resolution.py +0 -0
  389. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/schemas/test_search.py +0 -0
  390. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/services/test_context_service.py +0 -0
  391. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/services/test_directory_service.py +0 -0
  392. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/services/test_file_service.py +0 -0
  393. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/services/test_initialization.py +0 -0
  394. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/services/test_initialization_cloud_mode_branches.py +0 -0
  395. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/services/test_project_removal_bug.py +0 -0
  396. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/services/test_project_service.py +0 -0
  397. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/services/test_project_service_operations.py +0 -0
  398. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/services/test_search_service.py +0 -0
  399. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/sync/test_character_conflicts.py +0 -0
  400. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/sync/test_coordinator.py +0 -0
  401. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/sync/test_sync_service_incremental.py +0 -0
  402. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/sync/test_sync_wikilink_issue.py +0 -0
  403. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/sync/test_tmp_files.py +0 -0
  404. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/sync/test_watch_service.py +0 -0
  405. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/sync/test_watch_service_atomic_adds.py +0 -0
  406. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/sync/test_watch_service_edge_cases.py +0 -0
  407. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/sync/test_watch_service_reload.py +0 -0
  408. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/test_config.py +0 -0
  409. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/test_deps.py +0 -0
  410. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/test_production_cascade_delete.py +0 -0
  411. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/test_project_resolver.py +0 -0
  412. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/test_rclone_commands.py +0 -0
  413. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/test_runtime.py +0 -0
  414. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/utils/test_frontmatter_obsidian_compatible.py +0 -0
  415. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/utils/test_parse_tags.py +0 -0
  416. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/utils/test_permalink_formatting.py +0 -0
  417. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/utils/test_timezone_utils.py +0 -0
  418. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/utils/test_utf8_handling.py +0 -0
  419. {basic_memory-0.17.9 → basic_memory-0.18.0}/tests/utils/test_validate_project_path.py +0 -0
  420. {basic_memory-0.17.9 → basic_memory-0.18.0}/uv.lock +0 -0
@@ -1,5 +1,36 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v0.18.0 (2026-01-28)
4
+
5
+ ### Features
6
+
7
+ - **#527**: Add context-aware wiki link resolution with source_path support
8
+ ([`0023e73`](https://github.com/basicmachines-co/basic-memory/commit/0023e73))
9
+ - Add `source_path` parameter to `resolve_link()` for context-aware resolution
10
+ - Relative path resolution: `[[nested/note]]` from `folder/file.md` → `folder/nested/note.md`
11
+ - Proximity-based resolution for duplicate titles (prefers notes in same folder)
12
+ - Strict mode to disable fuzzy search fallback for wiki links
13
+
14
+ - **#518**: Add directory support to move_note and delete_note tools
15
+ ([`0b20801`](https://github.com/basicmachines-co/basic-memory/commit/0b20801))
16
+ - Add `is_directory` parameter to `move_note` and `delete_note` MCP tools
17
+ - New `POST /move-directory` and delete directory API endpoints
18
+ - Rename `folder` → `directory` parameter across codebase for consistency
19
+
20
+ - **#522**: Local MCP cloud mode routing
21
+ ([`8730067`](https://github.com/basicmachines-co/basic-memory/commit/8730067))
22
+ - Add `--local` and `--cloud` CLI routing flags
23
+ - Local MCP server (`basic-memory mcp`) automatically uses local routing
24
+ - Enables simultaneous use of local Claude Desktop and cloud-based clients
25
+ - Environment variable `BASIC_MEMORY_FORCE_LOCAL=true` for global override
26
+
27
+ ### Bug Fixes
28
+
29
+ - **#524**: Fix MCP prompt rendering errors
30
+ ([`e14ba92`](https://github.com/basicmachines-co/basic-memory/commit/e14ba92))
31
+ - Fix "Error rendering prompt recent_activity" error
32
+ - Change `TimeFrame` to `str` in prompt type annotations for FastMCP compatibility
33
+
3
34
  ## v0.17.9 (2026-01-24)
4
35
 
5
36
  ### Bug Fixes
@@ -248,13 +248,13 @@ See SPEC-16 for full context manager refactor details.
248
248
  - Basic Memory exposes these MCP tools to LLMs:
249
249
 
250
250
  **Content Management:**
251
- - `write_note(title, content, folder, tags)` - Create/update markdown notes with semantic observations and relations
251
+ - `write_note(title, content, directory, tags)` - Create/update markdown notes with semantic observations and relations
252
252
  - `read_note(identifier, page, page_size)` - Read notes by title, permalink, or memory:// URL with knowledge graph awareness
253
253
  - `read_content(path)` - Read raw file content (text, images, binaries) without knowledge graph processing
254
254
  - `view_note(identifier, page, page_size)` - View notes as formatted artifacts for better readability
255
255
  - `edit_note(identifier, operation, content)` - Edit notes incrementally (append, prepend, find/replace, replace_section)
256
- - `move_note(identifier, destination_path)` - Move notes to new locations, updating database and maintaining links
257
- - `delete_note(identifier)` - Delete notes from the knowledge base
256
+ - `move_note(identifier, destination_path, is_directory)` - Move notes or directories to new locations, updating database and maintaining links
257
+ - `delete_note(identifier, is_directory)` - Delete notes or directories from the knowledge base
258
258
 
259
259
  **Knowledge Graph Navigation:**
260
260
  - `build_context(url, depth, timeframe)` - Navigate the knowledge graph via memory:// URLs for conversation continuity
@@ -270,7 +270,7 @@ See SPEC-16 for full context manager refactor details.
270
270
  - `delete_project(project_name)` - Delete a project from configuration
271
271
 
272
272
  **Visualization:**
273
- - `canvas(nodes, edges, title, folder)` - Generate Obsidian canvas files for knowledge graph visualization
273
+ - `canvas(nodes, edges, title, directory)` - Generate Obsidian canvas files for knowledge graph visualization
274
274
 
275
275
  **ChatGPT-Compatible Tools:**
276
276
  - `search(query)` - Search across knowledge base (OpenAI actions compatible)
@@ -310,6 +310,26 @@ Basic Memory now supports cloud synchronization and storage (requires active sub
310
310
  - Background relation resolution (non-blocking startup)
311
311
  - API performance optimizations (SPEC-11)
312
312
 
313
+ **CLI Routing Flags:**
314
+
315
+ When cloud mode is enabled, CLI commands route to the cloud API by default. Use `--local` and `--cloud` flags to override:
316
+
317
+ ```bash
318
+ # Force local routing (ignore cloud mode)
319
+ basic-memory status --local
320
+ basic-memory project list --local
321
+
322
+ # Force cloud routing (when cloud mode is disabled)
323
+ basic-memory status --cloud
324
+ basic-memory project info my-project --cloud
325
+ ```
326
+
327
+ Key behaviors:
328
+ - The local MCP server (`basic-memory mcp`) automatically uses local routing
329
+ - This allows simultaneous use of local Claude Desktop and cloud-based clients
330
+ - Some commands (like `project default`, `project sync-config`, `project move`) require `--local` in cloud mode since they modify local configuration
331
+ - Environment variable `BASIC_MEMORY_FORCE_LOCAL=true` forces local routing globally
332
+
313
333
  ## AI-Human Collaborative Development
314
334
 
315
335
  Basic Memory emerged from and enables a new kind of development process that combines human and AI capabilities. Instead
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basic-memory
3
- Version: 0.17.9
3
+ Version: 0.18.0
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
@@ -405,6 +405,22 @@ basic-memory cloud check
405
405
  basic-memory cloud mount
406
406
  ```
407
407
 
408
+ **Routing Flags** (for users with cloud subscriptions):
409
+
410
+ When cloud mode is enabled, CLI commands communicate with the cloud API by default. Use routing flags to override this:
411
+
412
+ ```bash
413
+ # Force local routing (useful for local MCP server while cloud mode is enabled)
414
+ basic-memory status --local
415
+ basic-memory project list --local
416
+
417
+ # Force cloud routing (when cloud mode is disabled but you want cloud access)
418
+ basic-memory status --cloud
419
+ basic-memory project info my-project --cloud
420
+ ```
421
+
422
+ The local MCP server (`basic-memory mcp`) automatically uses local routing, so you can use both local Claude Desktop and cloud-based clients simultaneously.
423
+
408
424
  4. In Claude Desktop, the LLM can now use these tools:
409
425
 
410
426
  **Content Management:**
@@ -481,6 +497,7 @@ Basic Memory uses [Loguru](https://github.com/Delgan/loguru) for logging. The lo
481
497
  |----------|---------|-------------|
482
498
  | `BASIC_MEMORY_LOG_LEVEL` | `INFO` | Log level: DEBUG, INFO, WARNING, ERROR |
483
499
  | `BASIC_MEMORY_CLOUD_MODE` | `false` | When `true`, API logs to stdout with structured context |
500
+ | `BASIC_MEMORY_FORCE_LOCAL` | `false` | When `true`, forces local API routing (ignores cloud mode) |
484
501
  | `BASIC_MEMORY_ENV` | `dev` | Set to `test` for test mode (stderr only) |
485
502
 
486
503
  ### Examples
@@ -357,6 +357,22 @@ basic-memory cloud check
357
357
  basic-memory cloud mount
358
358
  ```
359
359
 
360
+ **Routing Flags** (for users with cloud subscriptions):
361
+
362
+ When cloud mode is enabled, CLI commands communicate with the cloud API by default. Use routing flags to override this:
363
+
364
+ ```bash
365
+ # Force local routing (useful for local MCP server while cloud mode is enabled)
366
+ basic-memory status --local
367
+ basic-memory project list --local
368
+
369
+ # Force cloud routing (when cloud mode is disabled but you want cloud access)
370
+ basic-memory status --cloud
371
+ basic-memory project info my-project --cloud
372
+ ```
373
+
374
+ The local MCP server (`basic-memory mcp`) automatically uses local routing, so you can use both local Claude Desktop and cloud-based clients simultaneously.
375
+
360
376
  4. In Claude Desktop, the LLM can now use these tools:
361
377
 
362
378
  **Content Management:**
@@ -433,6 +449,7 @@ Basic Memory uses [Loguru](https://github.com/Delgan/loguru) for logging. The lo
433
449
  |----------|---------|-------------|
434
450
  | `BASIC_MEMORY_LOG_LEVEL` | `INFO` | Log level: DEBUG, INFO, WARNING, ERROR |
435
451
  | `BASIC_MEMORY_CLOUD_MODE` | `false` | When `true`, API logs to stdout with structured context |
452
+ | `BASIC_MEMORY_FORCE_LOCAL` | `false` | When `true`, forces local API routing (ignores cloud mode) |
436
453
  | `BASIC_MEMORY_ENV` | `dev` | Set to `test` for test mode (stderr only) |
437
454
 
438
455
  ### Examples
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/basicmachines-co/basic-memory.git",
7
7
  "source": "github"
8
8
  },
9
- "version": "0.17.9",
9
+ "version": "0.18.0",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "pypi",
13
13
  "identifier": "basic-memory",
14
- "version": "0.17.9",
14
+ "version": "0.18.0",
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.17.9"
4
+ __version__ = "0.18.0"
5
5
 
6
6
  # API version for FastAPI - independent of package version
7
7
  __api_version__ = "v0"
@@ -27,13 +27,13 @@ router = APIRouter(prefix="/import", tags=["import"])
27
27
  async def import_chatgpt(
28
28
  importer: ChatGPTImporterDep,
29
29
  file: UploadFile,
30
- folder: str = Form("conversations"),
30
+ directory: str = Form("conversations"),
31
31
  ) -> ChatImportResult:
32
32
  """Import conversations from ChatGPT JSON export.
33
33
 
34
34
  Args:
35
35
  file: The ChatGPT conversations.json file.
36
- folder: The folder to place the files in.
36
+ directory: The directory to place the files in.
37
37
  markdown_processor: MarkdownProcessor instance.
38
38
 
39
39
  Returns:
@@ -42,20 +42,20 @@ async def import_chatgpt(
42
42
  Raises:
43
43
  HTTPException: If import fails.
44
44
  """
45
- return await import_file(importer, file, folder)
45
+ return await import_file(importer, file, directory)
46
46
 
47
47
 
48
48
  @router.post("/claude/conversations", response_model=ChatImportResult)
49
49
  async def import_claude_conversations(
50
50
  importer: ClaudeConversationsImporterDep,
51
51
  file: UploadFile,
52
- folder: str = Form("conversations"),
52
+ directory: str = Form("conversations"),
53
53
  ) -> ChatImportResult:
54
54
  """Import conversations from Claude conversations.json export.
55
55
 
56
56
  Args:
57
57
  file: The Claude conversations.json file.
58
- folder: The folder to place the files in.
58
+ directory: The directory to place the files in.
59
59
  markdown_processor: MarkdownProcessor instance.
60
60
 
61
61
  Returns:
@@ -64,20 +64,20 @@ async def import_claude_conversations(
64
64
  Raises:
65
65
  HTTPException: If import fails.
66
66
  """
67
- return await import_file(importer, file, folder)
67
+ return await import_file(importer, file, directory)
68
68
 
69
69
 
70
70
  @router.post("/claude/projects", response_model=ProjectImportResult)
71
71
  async def import_claude_projects(
72
72
  importer: ClaudeProjectsImporterDep,
73
73
  file: UploadFile,
74
- folder: str = Form("projects"),
74
+ directory: str = Form("projects"),
75
75
  ) -> ProjectImportResult:
76
76
  """Import projects from Claude projects.json export.
77
77
 
78
78
  Args:
79
79
  file: The Claude projects.json file.
80
- base_folder: The base folder to place the files in.
80
+ directory: The directory to place the files in.
81
81
  markdown_processor: MarkdownProcessor instance.
82
82
 
83
83
  Returns:
@@ -86,20 +86,20 @@ async def import_claude_projects(
86
86
  Raises:
87
87
  HTTPException: If import fails.
88
88
  """
89
- return await import_file(importer, file, folder)
89
+ return await import_file(importer, file, directory)
90
90
 
91
91
 
92
92
  @router.post("/memory-json", response_model=EntityImportResult)
93
93
  async def import_memory_json(
94
94
  importer: MemoryJsonImporterDep,
95
95
  file: UploadFile,
96
- folder: str = Form("conversations"),
96
+ directory: str = Form("conversations"),
97
97
  ) -> EntityImportResult:
98
98
  """Import entities and relations from a memory.json file.
99
99
 
100
100
  Args:
101
101
  file: The memory.json file.
102
- destination_folder: Optional destination folder within the project.
102
+ directory: Optional destination directory within the project.
103
103
  markdown_processor: MarkdownProcessor instance.
104
104
 
105
105
  Returns:
@@ -116,7 +116,7 @@ async def import_memory_json(
116
116
  json_data = json.loads(line)
117
117
  file_data.append(json_data)
118
118
 
119
- result = await importer.import_data(file_data, folder)
119
+ result = await importer.import_data(file_data, directory)
120
120
  if not result.success: # pragma: no cover
121
121
  raise HTTPException(
122
122
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
@@ -29,7 +29,8 @@ from basic_memory.schemas import (
29
29
  DeleteEntitiesResponse,
30
30
  DeleteEntitiesRequest,
31
31
  )
32
- from basic_memory.schemas.request import EditEntityRequest, MoveEntityRequest
32
+ from basic_memory.schemas.request import EditEntityRequest, MoveEntityRequest, MoveDirectoryRequest
33
+ from basic_memory.schemas.response import DirectoryMoveResult
33
34
  from basic_memory.schemas.base import Permalink, Entity
34
35
 
35
36
  router = APIRouter(
@@ -231,6 +232,50 @@ async def move_entity(
231
232
  raise HTTPException(status_code=400, detail=str(e))
232
233
 
233
234
 
235
+ @router.post("/move-directory")
236
+ async def move_directory(
237
+ data: MoveDirectoryRequest,
238
+ background_tasks: BackgroundTasks,
239
+ entity_service: EntityServiceDep,
240
+ project_config: ProjectConfigDep,
241
+ app_config: AppConfigDep,
242
+ search_service: SearchServiceDep,
243
+ ) -> DirectoryMoveResult:
244
+ """Move all entities in a directory to a new location.
245
+
246
+ This endpoint moves all files within a source directory to a destination
247
+ directory, updating database records and optionally updating permalinks.
248
+ """
249
+ logger.info(
250
+ f"API request: endpoint='move_directory', source='{data.source_directory}', destination='{data.destination_directory}'"
251
+ )
252
+
253
+ try:
254
+ # Move the directory using the service
255
+ result = await entity_service.move_directory(
256
+ source_directory=data.source_directory,
257
+ destination_directory=data.destination_directory,
258
+ project_config=project_config,
259
+ app_config=app_config,
260
+ )
261
+
262
+ # Reindex moved entities
263
+ for file_path in result.moved_files:
264
+ entity = await entity_service.link_resolver.resolve_link(file_path)
265
+ if entity:
266
+ await search_service.index_entity(entity, background_tasks=background_tasks)
267
+
268
+ logger.info(
269
+ f"API response: endpoint='move_directory', "
270
+ f"total={result.total_files}, success={result.successful_moves}, failed={result.failed_moves}"
271
+ )
272
+ return result
273
+
274
+ except Exception as e:
275
+ logger.error(f"Error moving directory: {e}")
276
+ raise HTTPException(status_code=400, detail=str(e))
277
+
278
+
234
279
  ## Read endpoints
235
280
 
236
281
 
@@ -32,14 +32,14 @@ async def import_chatgpt(
32
32
  importer: ChatGPTImporterV2ExternalDep,
33
33
  file: UploadFile,
34
34
  project_id: str = Path(..., description="Project external UUID"),
35
- folder: str = Form("conversations"),
35
+ directory: str = Form("conversations"),
36
36
  ) -> ChatImportResult:
37
37
  """Import conversations from ChatGPT JSON export.
38
38
 
39
39
  Args:
40
40
  project_id: Project external UUID from URL path
41
41
  file: The ChatGPT conversations.json file.
42
- folder: The folder to place the files in.
42
+ directory: The directory to place the files in.
43
43
  importer: ChatGPT importer instance.
44
44
 
45
45
  Returns:
@@ -49,7 +49,7 @@ async def import_chatgpt(
49
49
  HTTPException: If import fails.
50
50
  """
51
51
  logger.info(f"V2 Importing ChatGPT conversations for project {project_id}")
52
- return await import_file(importer, file, folder)
52
+ return await import_file(importer, file, directory)
53
53
 
54
54
 
55
55
  @router.post("/claude/conversations", response_model=ChatImportResult)
@@ -57,14 +57,14 @@ async def import_claude_conversations(
57
57
  importer: ClaudeConversationsImporterV2ExternalDep,
58
58
  file: UploadFile,
59
59
  project_id: str = Path(..., description="Project external UUID"),
60
- folder: str = Form("conversations"),
60
+ directory: str = Form("conversations"),
61
61
  ) -> ChatImportResult:
62
62
  """Import conversations from Claude conversations.json export.
63
63
 
64
64
  Args:
65
65
  project_id: Project external UUID from URL path
66
66
  file: The Claude conversations.json file.
67
- folder: The folder to place the files in.
67
+ directory: The directory to place the files in.
68
68
  importer: Claude conversations importer instance.
69
69
 
70
70
  Returns:
@@ -74,7 +74,7 @@ async def import_claude_conversations(
74
74
  HTTPException: If import fails.
75
75
  """
76
76
  logger.info(f"V2 Importing Claude conversations for project {project_id}")
77
- return await import_file(importer, file, folder)
77
+ return await import_file(importer, file, directory)
78
78
 
79
79
 
80
80
  @router.post("/claude/projects", response_model=ProjectImportResult)
@@ -82,14 +82,14 @@ async def import_claude_projects(
82
82
  importer: ClaudeProjectsImporterV2ExternalDep,
83
83
  file: UploadFile,
84
84
  project_id: str = Path(..., description="Project external UUID"),
85
- folder: str = Form("projects"),
85
+ directory: str = Form("projects"),
86
86
  ) -> ProjectImportResult:
87
87
  """Import projects from Claude projects.json export.
88
88
 
89
89
  Args:
90
90
  project_id: Project external UUID from URL path
91
91
  file: The Claude projects.json file.
92
- folder: The base folder to place the files in.
92
+ directory: The base directory to place the files in.
93
93
  importer: Claude projects importer instance.
94
94
 
95
95
  Returns:
@@ -99,7 +99,7 @@ async def import_claude_projects(
99
99
  HTTPException: If import fails.
100
100
  """
101
101
  logger.info(f"V2 Importing Claude projects for project {project_id}")
102
- return await import_file(importer, file, folder)
102
+ return await import_file(importer, file, directory)
103
103
 
104
104
 
105
105
  @router.post("/memory-json", response_model=EntityImportResult)
@@ -107,14 +107,14 @@ async def import_memory_json(
107
107
  importer: MemoryJsonImporterV2ExternalDep,
108
108
  file: UploadFile,
109
109
  project_id: str = Path(..., description="Project external UUID"),
110
- folder: str = Form("conversations"),
110
+ directory: str = Form("conversations"),
111
111
  ) -> EntityImportResult:
112
112
  """Import entities and relations from a memory.json file.
113
113
 
114
114
  Args:
115
115
  project_id: Project external UUID from URL path
116
116
  file: The memory.json file.
117
- folder: Optional destination folder within the project.
117
+ directory: Optional destination directory within the project.
118
118
  importer: Memory JSON importer instance.
119
119
 
120
120
  Returns:
@@ -132,7 +132,7 @@ async def import_memory_json(
132
132
  json_data = json.loads(line)
133
133
  file_data.append(json_data)
134
134
 
135
- result = await importer.import_data(file_data, folder)
135
+ result = await importer.import_data(file_data, directory)
136
136
  if not result.success: # pragma: no cover
137
137
  raise HTTPException(
138
138
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
@@ -147,13 +147,13 @@ async def import_memory_json(
147
147
  return result
148
148
 
149
149
 
150
- async def import_file(importer: Importer, file: UploadFile, destination_folder: str):
150
+ async def import_file(importer: Importer, file: UploadFile, destination_directory: str):
151
151
  """Helper function to import a file using an importer instance.
152
152
 
153
153
  Args:
154
154
  importer: The importer instance to use
155
155
  file: The file to import
156
- destination_folder: Destination folder for imported content
156
+ destination_directory: Destination directory for imported content
157
157
 
158
158
  Returns:
159
159
  Import result from the importer
@@ -164,7 +164,7 @@ async def import_file(importer: Importer, file: UploadFile, destination_folder:
164
164
  try:
165
165
  # Process file
166
166
  json_data = json.load(file.file)
167
- result = await importer.import_data(json_data, destination_folder)
167
+ result = await importer.import_data(json_data, destination_directory)
168
168
  if not result.success: # pragma: no cover
169
169
  raise HTTPException(
170
170
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
@@ -31,7 +31,10 @@ from basic_memory.schemas.v2 import (
31
31
  EntityResolveResponse,
32
32
  EntityResponseV2,
33
33
  MoveEntityRequestV2,
34
+ MoveDirectoryRequestV2,
35
+ DeleteDirectoryRequestV2,
34
36
  )
37
+ from basic_memory.schemas.response import DirectoryMoveResult, DirectoryDeleteResult
35
38
 
36
39
  router = APIRouter(prefix="/knowledge", tags=["knowledge-v2"])
37
40
 
@@ -100,8 +103,12 @@ async def resolve_identifier(
100
103
  resolution_method = "external_id" if entity else "search"
101
104
 
102
105
  # If not found by external_id, try other resolution methods
106
+ # Pass source_path for context-aware resolution (prefers notes closer to source)
107
+ # Pass strict to control fuzzy search fallback (default False allows fuzzy matching)
103
108
  if not entity:
104
- entity = await link_resolver.resolve_link(data.identifier)
109
+ entity = await link_resolver.resolve_link(
110
+ data.identifier, source_path=data.source_path, strict=data.strict
111
+ )
105
112
  if entity:
106
113
  # Determine resolution method
107
114
  if entity.permalink == data.identifier:
@@ -423,3 +430,100 @@ async def move_entity(
423
430
  except Exception as e:
424
431
  logger.error(f"Error moving entity: {e}")
425
432
  raise HTTPException(status_code=400, detail=str(e))
433
+
434
+
435
+ ## Move directory endpoint
436
+
437
+
438
+ @router.post("/move-directory", response_model=DirectoryMoveResult)
439
+ async def move_directory(
440
+ data: MoveDirectoryRequestV2,
441
+ background_tasks: BackgroundTasks,
442
+ project_id: ProjectExternalIdPathDep,
443
+ entity_service: EntityServiceV2ExternalDep,
444
+ project_config: ProjectConfigV2ExternalDep,
445
+ app_config: AppConfigDep,
446
+ search_service: SearchServiceV2ExternalDep,
447
+ ) -> DirectoryMoveResult:
448
+ """Move all entities in a directory to a new location.
449
+
450
+ V2 API uses project external_id in the URL path for stable references.
451
+ Moves all files within a source directory to a destination directory,
452
+ updating database records and optionally updating permalinks.
453
+
454
+ Args:
455
+ project_id: Project external ID from URL path
456
+ data: Move request with source and destination directories
457
+
458
+ Returns:
459
+ DirectoryMoveResult with counts and details of moved files
460
+ """
461
+ logger.info(
462
+ f"API v2 request: move_directory source='{data.source_directory}', destination='{data.destination_directory}'"
463
+ )
464
+
465
+ try:
466
+ # Move the directory using the service
467
+ result = await entity_service.move_directory(
468
+ source_directory=data.source_directory,
469
+ destination_directory=data.destination_directory,
470
+ project_config=project_config,
471
+ app_config=app_config,
472
+ )
473
+
474
+ # Reindex moved entities
475
+ for file_path in result.moved_files:
476
+ entity = await entity_service.link_resolver.resolve_link(file_path)
477
+ if entity:
478
+ await search_service.index_entity(entity, background_tasks=background_tasks)
479
+
480
+ logger.info(
481
+ f"API v2 response: move_directory "
482
+ f"total={result.total_files}, success={result.successful_moves}, failed={result.failed_moves}"
483
+ )
484
+ return result
485
+
486
+ except Exception as e:
487
+ logger.error(f"Error moving directory: {e}")
488
+ raise HTTPException(status_code=400, detail=str(e))
489
+
490
+
491
+ ## Delete directory endpoint
492
+
493
+
494
+ @router.post("/delete-directory", response_model=DirectoryDeleteResult)
495
+ async def delete_directory(
496
+ data: DeleteDirectoryRequestV2,
497
+ project_id: ProjectExternalIdPathDep,
498
+ entity_service: EntityServiceV2ExternalDep,
499
+ ) -> DirectoryDeleteResult:
500
+ """Delete all entities in a directory.
501
+
502
+ V2 API uses project external_id in the URL path for stable references.
503
+ Deletes all files within a directory, updating database records and
504
+ removing files from the filesystem.
505
+
506
+ Args:
507
+ project_id: Project external ID from URL path
508
+ data: Delete request with directory path
509
+
510
+ Returns:
511
+ DirectoryDeleteResult with counts and details of deleted files
512
+ """
513
+ logger.info(f"API v2 request: delete_directory directory='{data.directory}'")
514
+
515
+ try:
516
+ # Delete the directory using the service
517
+ result = await entity_service.delete_directory(
518
+ directory=data.directory,
519
+ )
520
+
521
+ logger.info(
522
+ f"API v2 response: delete_directory "
523
+ f"total={result.total_files}, success={result.successful_deletes}, failed={result.failed_deletes}"
524
+ )
525
+ return result
526
+
527
+ except Exception as e:
528
+ logger.error(f"Error deleting directory: {e}")
529
+ raise HTTPException(status_code=400, detail=str(e))
@@ -0,0 +1,80 @@
1
+ """MCP server command with streamable HTTP transport."""
2
+
3
+ import os
4
+ import typer
5
+ from typing import Optional
6
+
7
+ from basic_memory.cli.app import app
8
+ from basic_memory.config import ConfigManager, init_mcp_logging
9
+
10
+ # Import mcp instance (has lifespan that handles initialization and file sync)
11
+ from basic_memory.mcp.server import mcp as mcp_server # pragma: no cover
12
+
13
+ # Import mcp tools to register them
14
+ import basic_memory.mcp.tools # noqa: F401 # pragma: no cover
15
+
16
+ # Import prompts to register them
17
+ import basic_memory.mcp.prompts # noqa: F401 # pragma: no cover
18
+ from loguru import logger
19
+
20
+
21
+ @app.command()
22
+ def mcp(
23
+ transport: str = typer.Option("stdio", help="Transport type: stdio, streamable-http, or sse"),
24
+ host: str = typer.Option(
25
+ "0.0.0.0", help="Host for HTTP transports (use 0.0.0.0 to allow external connections)"
26
+ ),
27
+ port: int = typer.Option(8000, help="Port for HTTP transports"),
28
+ path: str = typer.Option("/mcp", help="Path prefix for streamable-http transport"),
29
+ project: Optional[str] = typer.Option(None, help="Restrict MCP server to single project"),
30
+ ): # pragma: no cover
31
+ """Run the MCP server with configurable transport options.
32
+
33
+ This command starts an MCP server using one of three transport options:
34
+
35
+ - stdio: Standard I/O (good for local usage)
36
+ - streamable-http: Recommended for web deployments (default)
37
+ - sse: Server-Sent Events (for compatibility with existing clients)
38
+
39
+ Initialization, file sync, and cleanup are handled by the MCP server's lifespan.
40
+
41
+ Note: This command is available regardless of cloud mode setting.
42
+ Users who have cloud mode enabled can still use local MCP for Claude Code
43
+ and Claude Desktop while using cloud MCP for web and mobile access.
44
+ """
45
+ # Force local routing for local MCP server
46
+ # Why: The local MCP server should always talk to the local API, not the cloud proxy.
47
+ # Even when cloud_mode_enabled is True, stdio MCP runs locally and needs local API access.
48
+ os.environ["BASIC_MEMORY_FORCE_LOCAL"] = "true"
49
+
50
+ # Initialize logging for MCP (file only, stdout breaks protocol)
51
+ init_mcp_logging()
52
+
53
+ # Validate and set project constraint if specified
54
+ if project:
55
+ config_manager = ConfigManager()
56
+ project_name, _ = config_manager.get_project(project)
57
+ if not project_name:
58
+ typer.echo(f"No project found named: {project}", err=True)
59
+ raise typer.Exit(1)
60
+
61
+ # Set env var with validated project name
62
+ os.environ["BASIC_MEMORY_MCP_PROJECT"] = project_name
63
+ logger.info(f"MCP server constrained to project: {project_name}")
64
+
65
+ # Run the MCP server (blocks)
66
+ # Lifespan handles: initialization, migrations, file sync, cleanup
67
+ logger.info(f"Starting MCP server with {transport.upper()} transport")
68
+
69
+ if transport == "stdio":
70
+ mcp_server.run(
71
+ transport=transport,
72
+ )
73
+ elif transport == "streamable-http" or transport == "sse":
74
+ mcp_server.run(
75
+ transport=transport,
76
+ host=host,
77
+ port=port,
78
+ path=path,
79
+ log_level="INFO",
80
+ )