basic-memory 0.17.3__tar.gz → 0.17.5__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 (434) hide show
  1. {basic_memory-0.17.3 → basic_memory-0.17.5}/.github/workflows/claude-code-review.yml +1 -0
  2. {basic_memory-0.17.3 → basic_memory-0.17.5}/.github/workflows/test.yml +3 -3
  3. basic_memory-0.17.5/.python-version +1 -0
  4. {basic_memory-0.17.3 → basic_memory-0.17.5}/CHANGELOG.md +31 -0
  5. {basic_memory-0.17.3 → basic_memory-0.17.5}/CLAUDE.md +26 -4
  6. {basic_memory-0.17.3 → basic_memory-0.17.5}/PKG-INFO +5 -2
  7. basic_memory-0.17.5/docs/ARCHITECTURE.md +412 -0
  8. {basic_memory-0.17.3 → basic_memory-0.17.5}/pyproject.toml +7 -3
  9. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/__init__.py +1 -1
  10. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/env.py +12 -8
  11. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/6830751f5fb6_merge_multiple_heads.py +3 -3
  12. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/app.py +21 -33
  13. basic_memory-0.17.5/src/basic_memory/api/container.py +133 -0
  14. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/knowledge_router.py +3 -5
  15. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/project_router.py +2 -4
  16. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/app.py +11 -5
  17. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/core_commands.py +5 -6
  18. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/rclone_commands.py +1 -0
  19. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/upload_command.py +2 -2
  20. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/command_utils.py +31 -5
  21. basic_memory-0.17.5/src/basic_memory/cli/commands/db.py +105 -0
  22. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/format.py +2 -2
  23. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/import_chatgpt.py +3 -3
  24. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/import_claude_conversations.py +3 -3
  25. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/import_claude_projects.py +3 -3
  26. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/import_memory_json.py +3 -3
  27. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/project.py +19 -20
  28. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/tool.py +7 -7
  29. basic_memory-0.17.5/src/basic_memory/cli/container.py +84 -0
  30. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/db.py +31 -7
  31. basic_memory-0.17.5/src/basic_memory/deps/__init__.py +293 -0
  32. basic_memory-0.17.5/src/basic_memory/deps/config.py +26 -0
  33. basic_memory-0.17.5/src/basic_memory/deps/db.py +56 -0
  34. basic_memory-0.17.5/src/basic_memory/deps/importers.py +200 -0
  35. basic_memory-0.17.5/src/basic_memory/deps/projects.py +236 -0
  36. basic_memory-0.17.5/src/basic_memory/deps/repositories.py +183 -0
  37. basic_memory-0.17.5/src/basic_memory/deps/services.py +484 -0
  38. basic_memory-0.17.5/src/basic_memory/deps.py +16 -0
  39. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/importers/chatgpt_importer.py +1 -1
  40. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/importers/claude_conversations_importer.py +1 -1
  41. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/importers/claude_projects_importer.py +1 -1
  42. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/importers/memory_json_importer.py +1 -1
  43. basic_memory-0.17.5/src/basic_memory/mcp/clients/__init__.py +28 -0
  44. basic_memory-0.17.5/src/basic_memory/mcp/clients/directory.py +70 -0
  45. basic_memory-0.17.5/src/basic_memory/mcp/clients/knowledge.py +176 -0
  46. basic_memory-0.17.5/src/basic_memory/mcp/clients/memory.py +120 -0
  47. basic_memory-0.17.5/src/basic_memory/mcp/clients/project.py +89 -0
  48. basic_memory-0.17.5/src/basic_memory/mcp/clients/resource.py +71 -0
  49. basic_memory-0.17.5/src/basic_memory/mcp/clients/search.py +65 -0
  50. basic_memory-0.17.5/src/basic_memory/mcp/container.py +108 -0
  51. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/project_context.py +36 -34
  52. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/server.py +15 -29
  53. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/build_context.py +12 -12
  54. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/canvas.py +3 -1
  55. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/delete_note.py +8 -7
  56. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/edit_note.py +10 -9
  57. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/list_directory.py +5 -16
  58. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/move_note.py +19 -25
  59. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/project_management.py +22 -17
  60. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/read_content.py +3 -1
  61. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/read_note.py +11 -13
  62. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/recent_activity.py +14 -4
  63. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/search.py +9 -7
  64. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/utils.py +6 -2
  65. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/write_note.py +15 -13
  66. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/models/knowledge.py +1 -3
  67. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/models/project.py +1 -3
  68. basic_memory-0.17.5/src/basic_memory/project_resolver.py +222 -0
  69. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/repository/entity_repository.py +2 -4
  70. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/repository/relation_repository.py +3 -3
  71. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/repository/repository.py +4 -3
  72. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/repository/search_repository.py +10 -3
  73. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/repository/sqlite_search_repository.py +4 -6
  74. basic_memory-0.17.5/src/basic_memory/runtime.py +61 -0
  75. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/services/context_service.py +3 -1
  76. basic_memory-0.17.5/src/basic_memory/sync/__init__.py +7 -0
  77. basic_memory-0.17.5/src/basic_memory/sync/coordinator.py +160 -0
  78. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/sync/sync_service.py +3 -1
  79. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/telemetry.py +87 -16
  80. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/mcp/test_lifespan_shutdown_sync_task_cancellation_integration.py +24 -11
  81. basic_memory-0.17.5/tests/api/test_api_container.py +62 -0
  82. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/test_directory_router.py +0 -1
  83. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/test_management_router.py +0 -2
  84. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/test_project_router.py +4 -2
  85. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/test_relation_background_resolution.py +2 -0
  86. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/v2/test_knowledge_router.py +3 -1
  87. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/v2/test_project_router.py +7 -3
  88. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/cli/cloud/test_cloud_api_client_and_utils.py +9 -5
  89. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/cli/cloud/test_rclone_config_and_bmignore_filters.py +0 -2
  90. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/cli/cloud/test_upload_path.py +3 -3
  91. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/cli/test_auth_cli_auth.py +9 -4
  92. basic_memory-0.17.5/tests/cli/test_cli_container.py +96 -0
  93. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/cli/test_cli_tool_exit.py +3 -1
  94. basic_memory-0.17.5/tests/cli/test_cli_tools.py +38 -0
  95. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/cli/test_cloud_authentication.py +0 -2
  96. basic_memory-0.17.5/tests/mcp/clients/__init__.py +0 -0
  97. basic_memory-0.17.5/tests/mcp/clients/test_clients.py +311 -0
  98. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_async_client_modes.py +0 -2
  99. basic_memory-0.17.5/tests/mcp/test_mcp_container.py +93 -0
  100. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_project_context.py +0 -2
  101. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_recent_activity_prompt_modes.py +16 -6
  102. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_server_lifespan_branches.py +0 -3
  103. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_tool_move_note.py +11 -6
  104. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_tool_project_management.py +0 -2
  105. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_tool_read_content.py +0 -2
  106. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_tool_read_note.py +15 -11
  107. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_tool_recent_activity.py +1 -2
  108. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_tool_search.py +20 -6
  109. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/repository/test_postgres_search_repository.py +9 -5
  110. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/repository/test_search_repository.py +42 -0
  111. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/schemas/test_relation_response_reference_resolution.py +0 -3
  112. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/services/test_initialization.py +12 -6
  113. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/services/test_initialization_cloud_mode_branches.py +5 -3
  114. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/services/test_project_service_operations.py +0 -2
  115. basic_memory-0.17.5/tests/sync/test_coordinator.py +135 -0
  116. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/sync/test_watch_service_atomic_adds.py +0 -2
  117. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/sync/test_watch_service_reload.py +0 -2
  118. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/test_deps.py +26 -0
  119. basic_memory-0.17.5/tests/test_project_resolver.py +209 -0
  120. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/test_rclone_commands.py +56 -19
  121. basic_memory-0.17.5/tests/test_runtime.py +52 -0
  122. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/test_telemetry.py +45 -23
  123. basic_memory-0.17.5/uv.lock +2704 -0
  124. basic_memory-0.17.3/.python-version +0 -1
  125. basic_memory-0.17.3/src/basic_memory/cli/commands/db.py +0 -44
  126. basic_memory-0.17.3/src/basic_memory/deps.py +0 -1014
  127. basic_memory-0.17.3/src/basic_memory/sync/__init__.py +0 -6
  128. basic_memory-0.17.3/tests/cli/test_cli_tools.py +0 -500
  129. basic_memory-0.17.3/uv.lock +0 -2363
  130. {basic_memory-0.17.3 → basic_memory-0.17.5}/.claude/commands/release/beta.md +0 -0
  131. {basic_memory-0.17.3 → basic_memory-0.17.5}/.claude/commands/release/changelog.md +0 -0
  132. {basic_memory-0.17.3 → basic_memory-0.17.5}/.claude/commands/release/release-check.md +0 -0
  133. {basic_memory-0.17.3 → basic_memory-0.17.5}/.claude/commands/release/release.md +0 -0
  134. {basic_memory-0.17.3 → basic_memory-0.17.5}/.claude/commands/spec.md +0 -0
  135. {basic_memory-0.17.3 → basic_memory-0.17.5}/.claude/commands/test-live.md +0 -0
  136. {basic_memory-0.17.3 → basic_memory-0.17.5}/.claude/settings.json +0 -0
  137. {basic_memory-0.17.3 → basic_memory-0.17.5}/.dockerignore +0 -0
  138. {basic_memory-0.17.3 → basic_memory-0.17.5}/.env.example +0 -0
  139. {basic_memory-0.17.3 → basic_memory-0.17.5}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  140. {basic_memory-0.17.3 → basic_memory-0.17.5}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  141. {basic_memory-0.17.3 → basic_memory-0.17.5}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
  142. {basic_memory-0.17.3 → basic_memory-0.17.5}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  143. {basic_memory-0.17.3 → basic_memory-0.17.5}/.github/dependabot.yml +0 -0
  144. {basic_memory-0.17.3 → basic_memory-0.17.5}/.github/workflows/claude-issue-triage.yml +0 -0
  145. {basic_memory-0.17.3 → basic_memory-0.17.5}/.github/workflows/claude.yml +0 -0
  146. {basic_memory-0.17.3 → basic_memory-0.17.5}/.github/workflows/dev-release.yml +0 -0
  147. {basic_memory-0.17.3 → basic_memory-0.17.5}/.github/workflows/docker.yml +0 -0
  148. {basic_memory-0.17.3 → basic_memory-0.17.5}/.github/workflows/pr-title.yml +0 -0
  149. {basic_memory-0.17.3 → basic_memory-0.17.5}/.github/workflows/release.yml +0 -0
  150. {basic_memory-0.17.3 → basic_memory-0.17.5}/.gitignore +0 -0
  151. {basic_memory-0.17.3 → basic_memory-0.17.5}/CITATION.cff +0 -0
  152. {basic_memory-0.17.3 → basic_memory-0.17.5}/CLA.md +0 -0
  153. {basic_memory-0.17.3 → basic_memory-0.17.5}/CODE_OF_CONDUCT.md +0 -0
  154. {basic_memory-0.17.3 → basic_memory-0.17.5}/CONTRIBUTING.md +0 -0
  155. {basic_memory-0.17.3 → basic_memory-0.17.5}/Dockerfile +0 -0
  156. {basic_memory-0.17.3 → basic_memory-0.17.5}/LICENSE +0 -0
  157. {basic_memory-0.17.3 → basic_memory-0.17.5}/README.md +0 -0
  158. {basic_memory-0.17.3 → basic_memory-0.17.5}/SECURITY.md +0 -0
  159. {basic_memory-0.17.3 → basic_memory-0.17.5}/docker-compose-postgres.yml +0 -0
  160. {basic_memory-0.17.3 → basic_memory-0.17.5}/docker-compose.yml +0 -0
  161. {basic_memory-0.17.3 → basic_memory-0.17.5}/docs/Docker.md +0 -0
  162. {basic_memory-0.17.3 → basic_memory-0.17.5}/docs/ai-assistant-guide-extended.md +0 -0
  163. {basic_memory-0.17.3 → basic_memory-0.17.5}/docs/character-handling.md +0 -0
  164. {basic_memory-0.17.3 → basic_memory-0.17.5}/docs/cloud-cli.md +0 -0
  165. {basic_memory-0.17.3 → basic_memory-0.17.5}/docs/testing-coverage.md +0 -0
  166. {basic_memory-0.17.3 → basic_memory-0.17.5}/justfile +0 -0
  167. {basic_memory-0.17.3 → basic_memory-0.17.5}/llms-install.md +0 -0
  168. {basic_memory-0.17.3 → basic_memory-0.17.5}/smithery.yaml +0 -0
  169. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-1 Specification-Driven Development Process.md +0 -0
  170. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-10 Unified Deployment Workflow and Event Tracking.md +0 -0
  171. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-11 Basic Memory API Performance Optimization.md +0 -0
  172. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-12 OpenTelemetry Observability.md +0 -0
  173. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-13 CLI Authentication with Subscription Validation.md +0 -0
  174. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-14 Cloud Git Versioning & GitHub Backup.md +0 -0
  175. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-14- Cloud Git Versioning & GitHub Backup.md +0 -0
  176. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-15 Configuration Persistence via Tigris for Cloud Tenants.md +0 -0
  177. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-16 MCP Cloud Service Consolidation.md +0 -0
  178. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-17 Semantic Search with ChromaDB.md +0 -0
  179. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-18 AI Memory Management Tool.md +0 -0
  180. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-19 Sync Performance and Memory Optimization.md +0 -0
  181. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-2 Slash Commands Reference.md +0 -0
  182. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-20 Simplified Project-Scoped Rclone Sync.md +0 -0
  183. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-3 Agent Definitions.md +0 -0
  184. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-4 Notes Web UI Component Architecture.md +0 -0
  185. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-5 CLI Cloud Upload via WebDAV.md +0 -0
  186. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-6 Explicit Project Parameter Architecture.md +0 -0
  187. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-7 POC to spike Tigris Turso for local access to cloud data.md +0 -0
  188. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-8 TigrisFS Integration.md +0 -0
  189. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-9 Multi-Project Bidirectional Sync Architecture.md +0 -0
  190. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-9 Signed Header Tenant Information.md +0 -0
  191. {basic_memory-0.17.3 → basic_memory-0.17.5}/specs/SPEC-9-1 Follow-Ups- Conflict, Sync, and Observability.md +0 -0
  192. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/alembic.ini +0 -0
  193. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/migrations.py +0 -0
  194. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/script.py.mako +0 -0
  195. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/314f1ea54dc4_add_postgres_full_text_search_support_.py +0 -0
  196. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +0 -0
  197. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +0 -0
  198. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +0 -0
  199. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +0 -0
  200. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/9d9c1cb7d8f5_add_mtime_and_size_columns_to_entity_.py +0 -0
  201. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +0 -0
  202. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/a2b3c4d5e6f7_add_search_index_entity_cascade.py +0 -0
  203. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +0 -0
  204. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +0 -0
  205. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/e7e1f4367280_add_scan_watermark_tracking_to_project.py +0 -0
  206. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/f8a9b2c3d4e5_add_pg_trgm_for_fuzzy_link_resolution.py +0 -0
  207. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/g9a0b3c4d5e6_add_external_id_to_project_and_entity.py +0 -0
  208. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/__init__.py +0 -0
  209. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/routers/__init__.py +0 -0
  210. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/routers/directory_router.py +0 -0
  211. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/routers/importer_router.py +0 -0
  212. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/routers/knowledge_router.py +0 -0
  213. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/routers/management_router.py +0 -0
  214. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/routers/memory_router.py +0 -0
  215. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/routers/project_router.py +0 -0
  216. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/routers/prompt_router.py +0 -0
  217. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/routers/resource_router.py +0 -0
  218. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/routers/search_router.py +0 -0
  219. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/routers/utils.py +0 -0
  220. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/template_loader.py +0 -0
  221. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/v2/__init__.py +0 -0
  222. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/__init__.py +0 -0
  223. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/directory_router.py +0 -0
  224. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/importer_router.py +0 -0
  225. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/memory_router.py +0 -0
  226. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/prompt_router.py +0 -0
  227. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/resource_router.py +0 -0
  228. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/search_router.py +0 -0
  229. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/__init__.py +0 -0
  230. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/auth.py +0 -0
  231. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/__init__.py +0 -0
  232. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/__init__.py +0 -0
  233. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/api_client.py +0 -0
  234. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/bisync_commands.py +0 -0
  235. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/cloud_utils.py +0 -0
  236. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/rclone_config.py +0 -0
  237. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/rclone_installer.py +0 -0
  238. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/upload.py +0 -0
  239. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/mcp.py +0 -0
  240. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/status.py +0 -0
  241. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/commands/telemetry.py +0 -0
  242. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/cli/main.py +0 -0
  243. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/config.py +0 -0
  244. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/file_utils.py +0 -0
  245. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/ignore_utils.py +0 -0
  246. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/importers/__init__.py +0 -0
  247. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/importers/base.py +0 -0
  248. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/importers/utils.py +0 -0
  249. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/markdown/__init__.py +0 -0
  250. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/markdown/entity_parser.py +0 -0
  251. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/markdown/markdown_processor.py +0 -0
  252. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/markdown/plugins.py +0 -0
  253. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/markdown/schemas.py +0 -0
  254. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/markdown/utils.py +0 -0
  255. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/__init__.py +0 -0
  256. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/async_client.py +0 -0
  257. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/prompts/__init__.py +0 -0
  258. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/prompts/ai_assistant_guide.py +0 -0
  259. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/prompts/continue_conversation.py +0 -0
  260. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/prompts/recent_activity.py +0 -0
  261. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/prompts/search.py +0 -0
  262. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/prompts/utils.py +0 -0
  263. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/resources/ai_assistant_guide.md +0 -0
  264. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/resources/project_info.py +0 -0
  265. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/__init__.py +0 -0
  266. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/chatgpt_tools.py +0 -0
  267. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/view_note.py +0 -0
  268. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/models/__init__.py +0 -0
  269. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/models/base.py +0 -0
  270. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/models/search.py +0 -0
  271. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/repository/__init__.py +0 -0
  272. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/repository/observation_repository.py +0 -0
  273. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/repository/postgres_search_repository.py +0 -0
  274. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/repository/project_info_repository.py +0 -0
  275. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/repository/project_repository.py +0 -0
  276. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/repository/search_index_row.py +0 -0
  277. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/repository/search_repository_base.py +0 -0
  278. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/schemas/__init__.py +0 -0
  279. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/schemas/base.py +0 -0
  280. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/schemas/cloud.py +0 -0
  281. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/schemas/delete.py +0 -0
  282. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/schemas/directory.py +0 -0
  283. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/schemas/importer.py +0 -0
  284. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/schemas/memory.py +0 -0
  285. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/schemas/project_info.py +0 -0
  286. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/schemas/prompt.py +0 -0
  287. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/schemas/request.py +0 -0
  288. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/schemas/response.py +0 -0
  289. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/schemas/search.py +0 -0
  290. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/schemas/sync_report.py +0 -0
  291. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/schemas/v2/__init__.py +0 -0
  292. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/schemas/v2/entity.py +0 -0
  293. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/schemas/v2/resource.py +0 -0
  294. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/services/__init__.py +0 -0
  295. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/services/directory_service.py +0 -0
  296. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/services/entity_service.py +0 -0
  297. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/services/exceptions.py +0 -0
  298. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/services/file_service.py +0 -0
  299. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/services/initialization.py +0 -0
  300. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/services/link_resolver.py +0 -0
  301. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/services/project_service.py +0 -0
  302. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/services/search_service.py +0 -0
  303. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/services/service.py +0 -0
  304. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/sync/background_sync.py +0 -0
  305. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/sync/watch_service.py +0 -0
  306. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/templates/prompts/continue_conversation.hbs +0 -0
  307. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/templates/prompts/search.hbs +0 -0
  308. {basic_memory-0.17.3 → basic_memory-0.17.5}/src/basic_memory/utils.py +0 -0
  309. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/BENCHMARKS.md +0 -0
  310. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/cli/test_project_commands_integration.py +0 -0
  311. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/cli/test_version_integration.py +0 -0
  312. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/conftest.py +0 -0
  313. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/mcp/test_build_context_underscore.py +0 -0
  314. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/mcp/test_build_context_validation.py +0 -0
  315. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/mcp/test_chatgpt_tools_integration.py +0 -0
  316. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/mcp/test_default_project_mode_integration.py +0 -0
  317. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/mcp/test_delete_note_integration.py +0 -0
  318. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/mcp/test_edit_note_integration.py +0 -0
  319. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/mcp/test_list_directory_integration.py +0 -0
  320. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/mcp/test_move_note_integration.py +0 -0
  321. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/mcp/test_project_management_integration.py +0 -0
  322. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/mcp/test_project_state_sync_integration.py +0 -0
  323. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/mcp/test_read_content_integration.py +0 -0
  324. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/mcp/test_read_note_integration.py +0 -0
  325. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/mcp/test_search_integration.py +0 -0
  326. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/mcp/test_single_project_mcp_integration.py +0 -0
  327. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/mcp/test_write_note_integration.py +0 -0
  328. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/test_db_wal_mode.py +0 -0
  329. {basic_memory-0.17.3 → basic_memory-0.17.5}/test-int/test_disable_permalinks_integration.py +0 -0
  330. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/Non-MarkdownFileSupport.pdf +0 -0
  331. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/README.md +0 -0
  332. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/Screenshot.png +0 -0
  333. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/__init__.py +0 -0
  334. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/conftest.py +0 -0
  335. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/test_async_client.py +0 -0
  336. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/test_continue_conversation_template.py +0 -0
  337. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/test_importer_router.py +0 -0
  338. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/test_knowledge_router.py +0 -0
  339. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/test_memory_router.py +0 -0
  340. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/test_project_router_operations.py +0 -0
  341. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/test_prompt_router.py +0 -0
  342. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/test_resource_router.py +0 -0
  343. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/test_search_router.py +0 -0
  344. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/test_search_template.py +0 -0
  345. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/test_template_loader.py +0 -0
  346. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/test_template_loader_helpers.py +0 -0
  347. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/v2/__init__.py +0 -0
  348. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/v2/conftest.py +0 -0
  349. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/v2/test_directory_router.py +0 -0
  350. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/v2/test_importer_router.py +0 -0
  351. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/v2/test_memory_router.py +0 -0
  352. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/v2/test_prompt_router.py +0 -0
  353. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/v2/test_resource_router.py +0 -0
  354. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/api/v2/test_search_router.py +0 -0
  355. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/cli/conftest.py +0 -0
  356. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/cli/test_cli_exit.py +0 -0
  357. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/cli/test_ignore_utils.py +0 -0
  358. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/cli/test_import_chatgpt.py +0 -0
  359. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/cli/test_import_claude_conversations.py +0 -0
  360. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/cli/test_import_claude_projects.py +0 -0
  361. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/cli/test_import_memory_json.py +0 -0
  362. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/cli/test_project_add_with_local_path.py +0 -0
  363. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/cli/test_upload.py +0 -0
  364. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/conftest.py +0 -0
  365. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/db/test_issue_254_foreign_key_constraints.py +0 -0
  366. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/importers/test_conversation_indexing.py +0 -0
  367. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/importers/test_importer_base.py +0 -0
  368. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/importers/test_importer_utils.py +0 -0
  369. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/markdown/__init__.py +0 -0
  370. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/markdown/test_date_frontmatter_parsing.py +0 -0
  371. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/markdown/test_entity_parser.py +0 -0
  372. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/markdown/test_entity_parser_error_handling.py +0 -0
  373. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/markdown/test_markdown_plugins.py +0 -0
  374. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/markdown/test_markdown_processor.py +0 -0
  375. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/markdown/test_observation_edge_cases.py +0 -0
  376. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/markdown/test_parser_edge_cases.py +0 -0
  377. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/markdown/test_relation_edge_cases.py +0 -0
  378. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/markdown/test_task_detection.py +0 -0
  379. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/conftest.py +0 -0
  380. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_obsidian_yaml_formatting.py +0 -0
  381. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_permalink_collision_file_overwrite.py +0 -0
  382. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_prompts.py +0 -0
  383. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_resources.py +0 -0
  384. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_tool_build_context.py +0 -0
  385. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_tool_canvas.py +0 -0
  386. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_tool_delete_note.py +0 -0
  387. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_tool_edit_note.py +0 -0
  388. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_tool_list_directory.py +0 -0
  389. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_tool_resource.py +0 -0
  390. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_tool_utils.py +0 -0
  391. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_tool_view_note.py +0 -0
  392. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_tool_write_note.py +0 -0
  393. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/test_tool_write_note_kebab_filenames.py +0 -0
  394. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/mcp/tools/test_chatgpt_tools.py +0 -0
  395. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/repository/test_entity_repository.py +0 -0
  396. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/repository/test_entity_repository_upsert.py +0 -0
  397. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/repository/test_entity_upsert_issue_187.py +0 -0
  398. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/repository/test_observation_repository.py +0 -0
  399. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/repository/test_project_info_repository.py +0 -0
  400. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/repository/test_project_repository.py +0 -0
  401. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/repository/test_relation_repository.py +0 -0
  402. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/repository/test_repository.py +0 -0
  403. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/repository/test_search_repository_edit_bug_fix.py +0 -0
  404. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/schemas/test_base_timeframe_minimum.py +0 -0
  405. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/schemas/test_memory_serialization.py +0 -0
  406. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/schemas/test_memory_url.py +0 -0
  407. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/schemas/test_memory_url_validation.py +0 -0
  408. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/schemas/test_schemas.py +0 -0
  409. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/schemas/test_search.py +0 -0
  410. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/services/test_context_service.py +0 -0
  411. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/services/test_directory_service.py +0 -0
  412. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/services/test_entity_service.py +0 -0
  413. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/services/test_entity_service_disable_permalinks.py +0 -0
  414. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/services/test_file_service.py +0 -0
  415. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/services/test_link_resolver.py +0 -0
  416. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/services/test_project_removal_bug.py +0 -0
  417. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/services/test_project_service.py +0 -0
  418. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/services/test_search_service.py +0 -0
  419. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/sync/test_character_conflicts.py +0 -0
  420. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/sync/test_sync_service.py +0 -0
  421. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/sync/test_sync_service_incremental.py +0 -0
  422. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/sync/test_sync_wikilink_issue.py +0 -0
  423. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/sync/test_tmp_files.py +0 -0
  424. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/sync/test_watch_service.py +0 -0
  425. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/sync/test_watch_service_edge_cases.py +0 -0
  426. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/test_config.py +0 -0
  427. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/test_production_cascade_delete.py +0 -0
  428. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/utils/test_file_utils.py +0 -0
  429. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/utils/test_frontmatter_obsidian_compatible.py +0 -0
  430. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/utils/test_parse_tags.py +0 -0
  431. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/utils/test_permalink_formatting.py +0 -0
  432. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/utils/test_timezone_utils.py +0 -0
  433. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/utils/test_utf8_handling.py +0 -0
  434. {basic_memory-0.17.3 → basic_memory-0.17.5}/tests/utils/test_validate_project_path.py +0 -0
@@ -54,6 +54,7 @@ jobs:
54
54
  - [ ] Unit tests for new functions/methods
55
55
  - [ ] Integration tests for new MCP tools
56
56
  - [ ] Test coverage for edge cases
57
+ - [ ] **100% test coverage maintained** (use `# pragma: no cover` only for truly hard-to-test code)
57
58
  - [ ] Documentation updated (README, docstrings)
58
59
  - [ ] CLAUDE.md updated if conventions change
59
60
 
@@ -19,7 +19,7 @@ jobs:
19
19
  fail-fast: false
20
20
  matrix:
21
21
  os: [ubuntu-latest, windows-latest]
22
- python-version: [ "3.12", "3.13" ]
22
+ python-version: [ "3.12", "3.13", "3.14" ]
23
23
  runs-on: ${{ matrix.os }}
24
24
 
25
25
  steps:
@@ -75,7 +75,7 @@ jobs:
75
75
  strategy:
76
76
  fail-fast: false
77
77
  matrix:
78
- python-version: [ "3.12", "3.13" ]
78
+ python-version: [ "3.12", "3.13", "3.14" ]
79
79
  runs-on: ubuntu-latest
80
80
 
81
81
  # Note: No services section needed - testcontainers handles Postgres in Docker
@@ -164,4 +164,4 @@ jobs:
164
164
  uses: actions/upload-artifact@v4
165
165
  with:
166
166
  name: htmlcov
167
- path: htmlcov/
167
+ path: htmlcov/
@@ -0,0 +1 @@
1
+ 3.14
@@ -1,5 +1,36 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v0.17.5 (2026-01-11)
4
+
5
+ ### Bug Fixes
6
+
7
+ - **#505**: Prevent CLI commands from hanging on exit (Python 3.14 compatibility)
8
+ ([`863e0a4`](https://github.com/basicmachines-co/basic-memory/commit/863e0a4))
9
+ - Skip `nest_asyncio` on Python 3.14+ where it causes event loop issues
10
+ - Simplify CLI test infrastructure for cross-version compatibility
11
+ - Update pyright to 1.1.408 for Python 3.14 support
12
+ - Fix SQLAlchemy rowcount typing for Python 3.14
13
+
14
+ ## v0.17.4 (2026-01-05)
15
+
16
+ ### Bug Fixes
17
+
18
+ - **#503**: Preserve search index across server restarts
19
+ ([`26f7e98`](https://github.com/basicmachines-co/basic-memory/commit/26f7e98))
20
+ - Fixes critical bug where search index was wiped on every MCP server restart
21
+ - Bug was introduced in v0.16.3, affecting v0.16.3-v0.17.3
22
+ - **User action**: Run `basic-memory reset` once after updating to rebuild search index
23
+
24
+ ### Internal
25
+
26
+ - **#502**: Major architecture refactor with composition roots and typed API clients
27
+ ([`5947f04`](https://github.com/basicmachines-co/basic-memory/commit/5947f04))
28
+ - Add composition roots for API, MCP, and CLI entrypoints
29
+ - Split deps.py into feature-scoped modules (config, db, projects, repositories, services, importers)
30
+ - Add ProjectResolver for unified project selection
31
+ - Add SyncCoordinator for centralized sync/watch lifecycle
32
+ - Introduce typed API clients for MCP tools (KnowledgeClient, SearchClient, MemoryClient, etc.)
33
+
3
34
  ## v0.17.3 (2026-01-03)
4
35
 
5
36
  ### Features
@@ -117,17 +117,38 @@ counter += 1 # track retries for backoff calculation
117
117
 
118
118
  ### Codebase Architecture
119
119
 
120
+ See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for detailed architecture documentation.
121
+
122
+ **Directory Structure:**
120
123
  - `/alembic` - Alembic db migrations
121
- - `/api` - FastAPI implementation of REST endpoints
122
- - `/cli` - Typer command-line interface
124
+ - `/api` - FastAPI REST endpoints + `container.py` composition root
125
+ - `/cli` - Typer CLI + `container.py` composition root
126
+ - `/deps` - Feature-scoped FastAPI dependencies (config, db, projects, repositories, services, importers)
123
127
  - `/importers` - Import functionality for Claude, ChatGPT, and other sources
124
128
  - `/markdown` - Markdown parsing and processing
125
- - `/mcp` - Model Context Protocol server implementation
129
+ - `/mcp` - MCP server + `container.py` composition root + `clients/` typed API clients
126
130
  - `/models` - SQLAlchemy ORM models
127
131
  - `/repository` - Data access layer
128
132
  - `/schemas` - Pydantic models for validation
129
133
  - `/services` - Business logic layer
130
- - `/sync` - File synchronization services
134
+ - `/sync` - File synchronization services + `coordinator.py` for lifecycle management
135
+
136
+ **Composition Roots:**
137
+ Each entrypoint (API, MCP, CLI) has a composition root that:
138
+ - Reads `ConfigManager` (the only place that reads global config)
139
+ - Resolves runtime mode via `RuntimeMode` enum (TEST > CLOUD > LOCAL)
140
+ - Provides dependencies to downstream code explicitly
141
+
142
+ **Typed API Clients (MCP):**
143
+ MCP tools use typed clients in `mcp/clients/` to communicate with the API:
144
+ - `KnowledgeClient` - Entity CRUD operations
145
+ - `SearchClient` - Search operations
146
+ - `MemoryClient` - Context building
147
+ - `DirectoryClient` - Directory listing
148
+ - `ResourceClient` - Resource reading
149
+ - `ProjectClient` - Project management
150
+
151
+ Flow: MCP Tool → Typed Client → HTTP API → Router → Service → Repository
131
152
 
132
153
  ### Development Notes
133
154
 
@@ -146,6 +167,7 @@ counter += 1 # track retries for backoff calculation
146
167
  - CI runs SQLite and Postgres tests in parallel for faster feedback
147
168
  - Performance benchmarks are in `test-int/test_sync_performance_benchmark.py`
148
169
  - Use pytest markers: `@pytest.mark.benchmark` for benchmarks, `@pytest.mark.slow` for slow tests
170
+ - **Coverage must stay at 100%**: Write tests for new code. Only use `# pragma: no cover` when tests would require excessive mocking (e.g., TYPE_CHECKING blocks, error handlers that need failure injection, runtime-mode-dependent code paths)
149
171
 
150
172
  ### Async Client Pattern (Important!)
151
173
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basic-memory
3
- Version: 0.17.3
3
+ Version: 0.17.5
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
@@ -12,11 +12,13 @@ Requires-Python: >=3.12
12
12
  Requires-Dist: aiofiles>=24.1.0
13
13
  Requires-Dist: aiosqlite>=0.20.0
14
14
  Requires-Dist: alembic>=1.14.1
15
+ Requires-Dist: anyio>=4.10.0
15
16
  Requires-Dist: asyncpg>=0.30.0
16
17
  Requires-Dist: dateparser>=1.2.0
17
18
  Requires-Dist: fastapi[standard]>=0.115.8
18
19
  Requires-Dist: fastmcp==2.12.3
19
20
  Requires-Dist: greenlet>=3.1.1
21
+ Requires-Dist: httpx>=0.28.0
20
22
  Requires-Dist: loguru>=0.7.3
21
23
  Requires-Dist: markdown-it-py>=3.0.0
22
24
  Requires-Dist: mcp>=1.23.1
@@ -29,7 +31,7 @@ Requires-Dist: pillow>=11.1.0
29
31
  Requires-Dist: psycopg==3.3.1
30
32
  Requires-Dist: pybars3>=0.9.7
31
33
  Requires-Dist: pydantic-settings>=2.6.1
32
- Requires-Dist: pydantic[email,timezone]>=2.10.3
34
+ Requires-Dist: pydantic[email,timezone]>=2.12.0
33
35
  Requires-Dist: pyjwt>=2.10.1
34
36
  Requires-Dist: pyright>=1.1.390
35
37
  Requires-Dist: pytest-aio>=1.9.0
@@ -38,6 +40,7 @@ Requires-Dist: python-dotenv>=1.1.0
38
40
  Requires-Dist: python-frontmatter>=1.1.0
39
41
  Requires-Dist: pyyaml>=6.0.1
40
42
  Requires-Dist: rich>=13.9.4
43
+ Requires-Dist: sniffio>=1.3.1
41
44
  Requires-Dist: sqlalchemy>=2.0.0
42
45
  Requires-Dist: typer>=0.9.0
43
46
  Requires-Dist: unidecode>=1.3.8
@@ -0,0 +1,412 @@
1
+ # Basic Memory Architecture
2
+
3
+ This document describes the architectural patterns and composition structure of Basic Memory.
4
+
5
+ ## Overview
6
+
7
+ Basic Memory is a local-first knowledge management system with three entrypoints:
8
+ - **API** - FastAPI REST server for HTTP access
9
+ - **MCP** - Model Context Protocol server for LLM integration
10
+ - **CLI** - Typer command-line interface
11
+
12
+ Each entrypoint uses a **composition root** pattern to manage configuration and dependencies.
13
+
14
+ ## Composition Roots
15
+
16
+ ### What is a Composition Root?
17
+
18
+ A composition root is the single place in an application where dependencies are wired together. In Basic Memory, each entrypoint has its own composition root that:
19
+
20
+ 1. Reads configuration from `ConfigManager`
21
+ 2. Resolves runtime mode (cloud/local/test)
22
+ 3. Creates and provides dependencies to downstream code
23
+
24
+ **Key principle**: Only composition roots read global configuration. All other modules receive configuration explicitly.
25
+
26
+ ### Container Structure
27
+
28
+ Each entrypoint has a container dataclass in its package:
29
+
30
+ ```
31
+ src/basic_memory/
32
+ ├── api/
33
+ │ └── container.py # ApiContainer
34
+ ├── mcp/
35
+ │ └── container.py # McpContainer
36
+ ├── cli/
37
+ │ └── container.py # CliContainer
38
+ └── runtime.py # RuntimeMode enum and resolver
39
+ ```
40
+
41
+ ### Container Pattern
42
+
43
+ All containers follow the same structure:
44
+
45
+ ```python
46
+ @dataclass
47
+ class Container:
48
+ config: BasicMemoryConfig
49
+ mode: RuntimeMode
50
+
51
+ @classmethod
52
+ def create(cls) -> "Container":
53
+ """Create container by reading ConfigManager."""
54
+ config = ConfigManager().config
55
+ mode = resolve_runtime_mode(
56
+ cloud_mode_enabled=config.cloud_mode_enabled,
57
+ is_test_env=config.is_test_env,
58
+ )
59
+ return cls(config=config, mode=mode)
60
+
61
+ @property
62
+ def some_computed_property(self) -> bool:
63
+ """Derived values based on config and mode."""
64
+ return self.mode.is_local and self.config.some_setting
65
+
66
+ # Module-level singleton
67
+ _container: Container | None = None
68
+
69
+ def get_container() -> Container:
70
+ if _container is None:
71
+ raise RuntimeError("Container not initialized")
72
+ return _container
73
+
74
+ def set_container(container: Container) -> None:
75
+ global _container
76
+ _container = container
77
+ ```
78
+
79
+ ### Runtime Mode Resolution
80
+
81
+ The `RuntimeMode` enum centralizes mode detection:
82
+
83
+ ```python
84
+ class RuntimeMode(Enum):
85
+ LOCAL = "local"
86
+ CLOUD = "cloud"
87
+ TEST = "test"
88
+
89
+ @property
90
+ def is_cloud(self) -> bool:
91
+ return self == RuntimeMode.CLOUD
92
+
93
+ @property
94
+ def is_local(self) -> bool:
95
+ return self == RuntimeMode.LOCAL
96
+
97
+ @property
98
+ def is_test(self) -> bool:
99
+ return self == RuntimeMode.TEST
100
+ ```
101
+
102
+ Resolution follows this precedence: **TEST > CLOUD > LOCAL**
103
+
104
+ ```python
105
+ def resolve_runtime_mode(cloud_mode_enabled: bool, is_test_env: bool) -> RuntimeMode:
106
+ if is_test_env:
107
+ return RuntimeMode.TEST
108
+ if cloud_mode_enabled:
109
+ return RuntimeMode.CLOUD
110
+ return RuntimeMode.LOCAL
111
+ ```
112
+
113
+ ## Dependencies Package
114
+
115
+ ### Structure
116
+
117
+ The `deps/` package provides FastAPI dependencies organized by feature:
118
+
119
+ ```
120
+ src/basic_memory/deps/
121
+ ├── __init__.py # Re-exports for backwards compatibility
122
+ ├── config.py # Configuration access
123
+ ├── db.py # Database/session management
124
+ ├── projects.py # Project resolution
125
+ ├── repositories.py # Data access layer
126
+ ├── services.py # Business logic layer
127
+ └── importers.py # Import functionality
128
+ ```
129
+
130
+ ### Usage in Routers
131
+
132
+ ```python
133
+ from basic_memory.deps.services import get_entity_service
134
+ from basic_memory.deps.projects import get_project_config
135
+
136
+ @router.get("/entities/{id}")
137
+ async def get_entity(
138
+ id: int,
139
+ entity_service: EntityService = Depends(get_entity_service),
140
+ project: ProjectConfig = Depends(get_project_config),
141
+ ):
142
+ return await entity_service.get(id)
143
+ ```
144
+
145
+ ### Backwards Compatibility
146
+
147
+ The old `deps.py` file still exists as a thin re-export shim:
148
+
149
+ ```python
150
+ # deps.py - backwards compatibility shim
151
+ from basic_memory.deps import *
152
+ ```
153
+
154
+ New code should import from specific submodules (`basic_memory.deps.services`) for clarity.
155
+
156
+ ## MCP Tools Architecture
157
+
158
+ ### Typed API Clients
159
+
160
+ MCP tools communicate with the API through typed clients that encapsulate HTTP paths and response validation:
161
+
162
+ ```
163
+ src/basic_memory/mcp/clients/
164
+ ├── __init__.py # Re-exports all clients
165
+ ├── base.py # BaseClient with common logic
166
+ ├── knowledge.py # KnowledgeClient - entity CRUD
167
+ ├── search.py # SearchClient - search operations
168
+ ├── memory.py # MemoryClient - context building
169
+ ├── directory.py # DirectoryClient - directory listing
170
+ ├── resource.py # ResourceClient - resource reading
171
+ └── project.py # ProjectClient - project management
172
+ ```
173
+
174
+ ### Client Pattern
175
+
176
+ Each client encapsulates API paths and validates responses:
177
+
178
+ ```python
179
+ class KnowledgeClient(BaseClient):
180
+ """Client for knowledge/entity operations."""
181
+
182
+ async def resolve_entity(self, identifier: str) -> int:
183
+ """Resolve identifier to entity ID."""
184
+ response = await call_get(
185
+ self.http_client,
186
+ f"{self._base_path}/resolve/{identifier}",
187
+ )
188
+ return int(response.text)
189
+
190
+ async def get_entity(self, entity_id: int) -> EntityResponse:
191
+ """Get entity by ID."""
192
+ response = await call_get(
193
+ self.http_client,
194
+ f"{self._base_path}/entities/{entity_id}",
195
+ )
196
+ return EntityResponse.model_validate(response.json())
197
+ ```
198
+
199
+ ### Tool → Client → API Flow
200
+
201
+ ```
202
+ MCP Tool (thin adapter)
203
+
204
+ Typed Client (encapsulates paths, validates responses)
205
+
206
+ HTTP API (FastAPI router)
207
+
208
+ Service Layer (business logic)
209
+
210
+ Repository Layer (data access)
211
+ ```
212
+
213
+ Example tool using typed client:
214
+
215
+ ```python
216
+ @mcp.tool()
217
+ async def search_notes(query: str, project: str | None = None) -> SearchResponse:
218
+ async with get_client() as client:
219
+ active_project = await get_active_project(client, project)
220
+
221
+ # Import client inside function to avoid circular imports
222
+ from basic_memory.mcp.clients import SearchClient
223
+
224
+ search_client = SearchClient(client, active_project.external_id)
225
+ return await search_client.search(query)
226
+ ```
227
+
228
+ ## Sync Coordination
229
+
230
+ ### SyncCoordinator
231
+
232
+ The `SyncCoordinator` centralizes sync/watch lifecycle management:
233
+
234
+ ```python
235
+ @dataclass
236
+ class SyncCoordinator:
237
+ """Coordinates file sync and watch operations."""
238
+
239
+ status: SyncStatus = SyncStatus.NOT_STARTED
240
+ sync_task: asyncio.Task | None = None
241
+ watch_service: WatchService | None = None
242
+
243
+ async def start(self, ...):
244
+ """Start sync and watch operations."""
245
+
246
+ async def stop(self):
247
+ """Stop all sync operations gracefully."""
248
+
249
+ def get_status_info(self) -> dict:
250
+ """Get current sync status for observability."""
251
+ ```
252
+
253
+ ### Status Enum
254
+
255
+ ```python
256
+ class SyncStatus(Enum):
257
+ NOT_STARTED = "not_started"
258
+ STARTING = "starting"
259
+ RUNNING = "running"
260
+ STOPPING = "stopping"
261
+ STOPPED = "stopped"
262
+ ERROR = "error"
263
+ ```
264
+
265
+ ## Project Resolution
266
+
267
+ ### ProjectResolver
268
+
269
+ Unified project selection across all entrypoints:
270
+
271
+ ```python
272
+ class ProjectResolver:
273
+ """Resolves which project to use based on context."""
274
+
275
+ def resolve(
276
+ self,
277
+ explicit_project: str | None = None,
278
+ ) -> ResolvedProject:
279
+ """Resolve project using three-tier hierarchy:
280
+ 1. Explicit project parameter
281
+ 2. Default project from config
282
+ 3. Single available project
283
+ """
284
+ ```
285
+
286
+ ### Resolution Modes
287
+
288
+ ```python
289
+ class ResolutionMode(Enum):
290
+ EXPLICIT = "explicit" # User specified project
291
+ DEFAULT = "default" # Using configured default
292
+ SINGLE_PROJECT = "single" # Only one project exists
293
+ FALLBACK = "fallback" # Using first available
294
+ ```
295
+
296
+ ## Testing Patterns
297
+
298
+ ### Container Testing
299
+
300
+ Each container has corresponding tests:
301
+
302
+ ```
303
+ tests/
304
+ ├── api/test_api_container.py
305
+ ├── mcp/test_mcp_container.py
306
+ └── cli/test_cli_container.py
307
+ ```
308
+
309
+ Tests verify:
310
+ - Container creation from config
311
+ - Runtime mode properties
312
+ - Container accessor functions (get/set)
313
+
314
+ ### Mocking Typed Clients
315
+
316
+ When testing MCP tools, mock at the client level:
317
+
318
+ ```python
319
+ def test_search_notes(monkeypatch):
320
+ import basic_memory.mcp.clients as clients_mod
321
+
322
+ class MockSearchClient:
323
+ async def search(self, query):
324
+ return SearchResponse(results=[...])
325
+
326
+ monkeypatch.setattr(clients_mod, "SearchClient", MockSearchClient)
327
+ ```
328
+
329
+ ## Design Principles
330
+
331
+ ### 1. Explicit Dependencies
332
+
333
+ Modules receive configuration explicitly rather than reading globals:
334
+
335
+ ```python
336
+ # Good - explicit injection
337
+ async def sync_files(config: BasicMemoryConfig):
338
+ ...
339
+
340
+ # Avoid - hidden global access
341
+ async def sync_files():
342
+ config = ConfigManager().config # Hidden coupling
343
+ ```
344
+
345
+ ### 2. Single Responsibility
346
+
347
+ Each layer has a clear responsibility:
348
+ - **Containers**: Wire dependencies
349
+ - **Clients**: Encapsulate HTTP communication
350
+ - **Services**: Business logic
351
+ - **Repositories**: Data access
352
+ - **Tools/Routers**: Thin adapters
353
+
354
+ ### 3. Deferred Imports
355
+
356
+ To avoid circular imports, typed clients are imported inside functions:
357
+
358
+ ```python
359
+ async def my_tool():
360
+ async with get_client() as client:
361
+ # Import here to avoid circular dependency
362
+ from basic_memory.mcp.clients import KnowledgeClient
363
+
364
+ knowledge_client = KnowledgeClient(client, project_id)
365
+ ```
366
+
367
+ ### 4. Backwards Compatibility
368
+
369
+ When refactoring, maintain backwards compatibility via shims:
370
+
371
+ ```python
372
+ # Old module becomes a shim
373
+ from basic_memory.new_location import *
374
+
375
+ # Docstring explains migration path
376
+ """
377
+ DEPRECATED: Import from basic_memory.new_location instead.
378
+ This shim will be removed in a future version.
379
+ """
380
+ ```
381
+
382
+ ## File Organization
383
+
384
+ ```
385
+ src/basic_memory/
386
+ ├── api/
387
+ │ ├── container.py # API composition root
388
+ │ ├── routers/ # FastAPI routers
389
+ │ └── ...
390
+ ├── mcp/
391
+ │ ├── container.py # MCP composition root
392
+ │ ├── clients/ # Typed API clients
393
+ │ ├── tools/ # MCP tool definitions
394
+ │ └── server.py # MCP server setup
395
+ ├── cli/
396
+ │ ├── container.py # CLI composition root
397
+ │ ├── app.py # Typer app
398
+ │ └── commands/ # CLI command groups
399
+ ├── deps/
400
+ │ ├── config.py # Config dependencies
401
+ │ ├── db.py # Database dependencies
402
+ │ ├── projects.py # Project dependencies
403
+ │ ├── repositories.py # Repository dependencies
404
+ │ ├── services.py # Service dependencies
405
+ │ └── importers.py # Importer dependencies
406
+ ├── sync/
407
+ │ ├── coordinator.py # SyncCoordinator
408
+ │ └── ...
409
+ ├── runtime.py # RuntimeMode resolution
410
+ ├── project_resolver.py # Unified project selection
411
+ └── config.py # Configuration management
412
+ ```
@@ -14,7 +14,7 @@ dependencies = [
14
14
  "typer>=0.9.0",
15
15
  "aiosqlite>=0.20.0",
16
16
  "greenlet>=3.1.1",
17
- "pydantic[email,timezone]>=2.10.3",
17
+ "pydantic[email,timezone]>=2.12.0",
18
18
  "mcp>=1.23.1",
19
19
  "pydantic-settings>=2.6.1",
20
20
  "loguru>=0.7.3",
@@ -29,7 +29,7 @@ dependencies = [
29
29
  "alembic>=1.14.1",
30
30
  "pillow>=11.1.0",
31
31
  "pybars3>=0.9.7",
32
- "fastmcp==2.12.3", # Pinned - 2.14.x breaks MCP tools visibility (issue #463)
32
+ "fastmcp==2.12.3", # Pinned - 2.14.x breaks MCP tools visibility (issue #463)
33
33
  "pyjwt>=2.10.1",
34
34
  "python-dotenv>=1.1.0",
35
35
  "pytest-aio>=1.9.0",
@@ -41,7 +41,10 @@ dependencies = [
41
41
  "mdformat>=0.7.22",
42
42
  "mdformat-gfm>=0.3.7",
43
43
  "mdformat-frontmatter>=2.0.8",
44
- "openpanel>=0.0.1", # Anonymous usage telemetry (Homebrew-style opt-out)
44
+ "openpanel>=0.0.1", # Anonymous usage telemetry (Homebrew-style opt-out)
45
+ "sniffio>=1.3.1",
46
+ "anyio>=4.10.0",
47
+ "httpx>=0.28.0",
45
48
  ]
46
49
 
47
50
 
@@ -88,6 +91,7 @@ dev = [
88
91
  "freezegun>=1.5.5",
89
92
  "testcontainers[postgres]>=4.0.0",
90
93
  "psycopg>=3.2.0",
94
+ "pyright>=1.1.408",
91
95
  ]
92
96
 
93
97
  [tool.hatch.version]
@@ -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.3"
4
+ __version__ = "0.17.5"
5
5
 
6
6
  # API version for FastAPI - independent of package version
7
7
  __api_version__ = "v0"
@@ -5,14 +5,18 @@ import os
5
5
  from logging.config import fileConfig
6
6
 
7
7
  # Allow nested event loops (needed for pytest-asyncio and other async contexts)
8
- # Note: nest_asyncio doesn't work with uvloop, so we handle that case separately
9
- try:
10
- import nest_asyncio
11
-
12
- nest_asyncio.apply()
13
- except (ImportError, ValueError):
14
- # nest_asyncio not available or can't patch this loop type (e.g., uvloop)
15
- pass
8
+ # Note: nest_asyncio doesn't work with uvloop or Python 3.14+, so we handle those cases separately
9
+ import sys
10
+
11
+ if sys.version_info < (3, 14):
12
+ try:
13
+ import nest_asyncio
14
+
15
+ nest_asyncio.apply()
16
+ except (ImportError, ValueError):
17
+ # nest_asyncio not available or can't patch this loop type (e.g., uvloop)
18
+ pass
19
+ # For Python 3.14+, we rely on the thread-based fallback in run_migrations_online()
16
20
 
17
21
  from sqlalchemy import engine_from_config, pool
18
22
  from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
@@ -5,13 +5,13 @@ Revises: a2b3c4d5e6f7, g9a0b3c4d5e6
5
5
  Create Date: 2025-12-29 12:46:46.476268
6
6
 
7
7
  """
8
- from typing import Sequence, Union
9
8
 
9
+ from typing import Sequence, Union
10
10
 
11
11
 
12
12
  # revision identifiers, used by Alembic.
13
- revision: str = '6830751f5fb6'
14
- down_revision: Union[str, Sequence[str], None] = ('a2b3c4d5e6f7', 'g9a0b3c4d5e6')
13
+ revision: str = "6830751f5fb6"
14
+ down_revision: Union[str, Sequence[str], None] = ("a2b3c4d5e6f7", "g9a0b3c4d5e6")
15
15
  branch_labels: Union[str, Sequence[str], None] = None
16
16
  depends_on: Union[str, Sequence[str], None] = None
17
17