basic-memory 0.14.2__tar.gz → 0.14.3__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.

Potentially problematic release.


This version of basic-memory might be problematic. Click here for more details.

Files changed (288) hide show
  1. {basic_memory-0.14.2 → basic_memory-0.14.3}/CONTRIBUTING.md +6 -1
  2. {basic_memory-0.14.2 → basic_memory-0.14.3}/PKG-INFO +2 -2
  3. basic_memory-0.14.3/docs/character-handling.md +241 -0
  4. {basic_memory-0.14.2 → basic_memory-0.14.3}/justfile +4 -1
  5. {basic_memory-0.14.2 → basic_memory-0.14.3}/pyproject.toml +2 -2
  6. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/__init__.py +1 -1
  7. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/alembic/env.py +3 -1
  8. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/api/app.py +4 -1
  9. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/api/routers/management_router.py +3 -1
  10. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/api/routers/project_router.py +21 -13
  11. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/cli/app.py +3 -3
  12. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/cli/commands/__init__.py +1 -2
  13. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/cli/commands/db.py +5 -5
  14. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/cli/commands/import_chatgpt.py +3 -2
  15. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/cli/commands/import_claude_conversations.py +3 -1
  16. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/cli/commands/import_claude_projects.py +3 -1
  17. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/cli/commands/import_memory_json.py +5 -2
  18. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/cli/commands/mcp.py +3 -15
  19. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/cli/commands/project.py +41 -0
  20. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/cli/commands/status.py +4 -1
  21. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/cli/commands/sync.py +10 -2
  22. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/cli/main.py +0 -1
  23. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/config.py +46 -31
  24. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/db.py +2 -6
  25. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/deps.py +3 -2
  26. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/importers/chatgpt_importer.py +19 -9
  27. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/importers/memory_json_importer.py +22 -7
  28. basic_memory-0.14.3/src/basic_memory/mcp/async_client.py +28 -0
  29. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/project_session.py +6 -4
  30. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/prompts/__init__.py +0 -2
  31. basic_memory-0.14.3/src/basic_memory/mcp/server.py +46 -0
  32. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/tools/move_note.py +24 -12
  33. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/tools/read_content.py +16 -0
  34. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/tools/read_note.py +12 -0
  35. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/tools/sync_status.py +3 -2
  36. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/tools/write_note.py +9 -1
  37. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/models/project.py +3 -3
  38. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/repository/project_repository.py +18 -0
  39. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/schemas/importer.py +1 -0
  40. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/services/entity_service.py +49 -3
  41. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/services/initialization.py +0 -75
  42. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/services/project_service.py +85 -28
  43. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/sync/background_sync.py +4 -3
  44. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/sync/sync_service.py +50 -1
  45. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/utils.py +105 -4
  46. {basic_memory-0.14.2 → basic_memory-0.14.3}/test-int/conftest.py +25 -38
  47. {basic_memory-0.14.2 → basic_memory-0.14.3}/test-int/mcp/test_build_context_validation.py +7 -6
  48. {basic_memory-0.14.2 → basic_memory-0.14.3}/test-int/mcp/test_delete_note_integration.py +37 -29
  49. {basic_memory-0.14.2 → basic_memory-0.14.3}/test-int/mcp/test_edit_note_integration.py +28 -28
  50. {basic_memory-0.14.2 → basic_memory-0.14.3}/test-int/mcp/test_list_directory_integration.py +20 -20
  51. {basic_memory-0.14.2 → basic_memory-0.14.3}/test-int/mcp/test_move_note_integration.py +43 -87
  52. {basic_memory-0.14.2 → basic_memory-0.14.3}/test-int/mcp/test_project_management_integration.py +82 -79
  53. {basic_memory-0.14.2 → basic_memory-0.14.3}/test-int/mcp/test_project_state_sync_integration.py +28 -25
  54. {basic_memory-0.14.2 → basic_memory-0.14.3}/test-int/mcp/test_read_content_integration.py +6 -6
  55. {basic_memory-0.14.2 → basic_memory-0.14.3}/test-int/mcp/test_read_note_integration.py +6 -6
  56. {basic_memory-0.14.2 → basic_memory-0.14.3}/test-int/mcp/test_search_integration.py +15 -15
  57. {basic_memory-0.14.2 → basic_memory-0.14.3}/test-int/mcp/test_write_note_integration.py +25 -25
  58. basic_memory-0.14.3/tests/api/test_async_client.py +36 -0
  59. basic_memory-0.14.3/tests/api/test_project_router.py +394 -0
  60. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/cli/test_import_chatgpt.py +3 -1
  61. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/cli/test_import_claude_conversations.py +3 -1
  62. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/cli/test_import_claude_projects.py +4 -1
  63. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/cli/test_import_memory_json.py +40 -0
  64. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/cli/test_project_commands.py +38 -0
  65. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/cli/test_sync.py +11 -20
  66. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/conftest.py +3 -42
  67. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/mcp/conftest.py +0 -2
  68. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/mcp/test_tool_move_note.py +264 -0
  69. basic_memory-0.14.3/tests/mcp/test_tool_read_content.py +459 -0
  70. basic_memory-0.14.3/tests/mcp/test_tool_read_note.py +619 -0
  71. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/mcp/test_tool_write_note.py +394 -0
  72. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/repository/test_project_repository.py +28 -0
  73. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/services/test_initialization.py +0 -176
  74. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/services/test_project_service.py +127 -15
  75. basic_memory-0.14.3/tests/sync/test_character_conflicts.py +341 -0
  76. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/test_db_migration_deduplication.py +4 -6
  77. basic_memory-0.14.3/tests/utils/test_validate_project_path.py +413 -0
  78. {basic_memory-0.14.2 → basic_memory-0.14.3}/uv.lock +401 -216
  79. basic_memory-0.14.2/src/basic_memory/cli/commands/auth.py +0 -136
  80. basic_memory-0.14.2/src/basic_memory/mcp/async_client.py +0 -8
  81. basic_memory-0.14.2/src/basic_memory/mcp/auth_provider.py +0 -270
  82. basic_memory-0.14.2/src/basic_memory/mcp/external_auth_provider.py +0 -321
  83. basic_memory-0.14.2/src/basic_memory/mcp/prompts/sync_status.py +0 -112
  84. basic_memory-0.14.2/src/basic_memory/mcp/server.py +0 -109
  85. basic_memory-0.14.2/src/basic_memory/mcp/supabase_auth_provider.py +0 -463
  86. basic_memory-0.14.2/src/basic_memory/services/migration_service.py +0 -168
  87. basic_memory-0.14.2/test-int/cli/test_reset_integration.py +0 -158
  88. basic_memory-0.14.2/tests/api/test_project_router.py +0 -198
  89. basic_memory-0.14.2/tests/cli/test_auth_commands.py +0 -352
  90. basic_memory-0.14.2/tests/mcp/test_auth_provider.py +0 -313
  91. basic_memory-0.14.2/tests/mcp/test_server.py +0 -144
  92. basic_memory-0.14.2/tests/mcp/test_tool_read_note.py +0 -296
  93. {basic_memory-0.14.2 → basic_memory-0.14.3}/.claude/commands/release/beta.md +0 -0
  94. {basic_memory-0.14.2 → basic_memory-0.14.3}/.claude/commands/release/changelog.md +0 -0
  95. {basic_memory-0.14.2 → basic_memory-0.14.3}/.claude/commands/release/release-check.md +0 -0
  96. {basic_memory-0.14.2 → basic_memory-0.14.3}/.claude/commands/release/release.md +0 -0
  97. {basic_memory-0.14.2 → basic_memory-0.14.3}/.claude/commands/test-live.md +0 -0
  98. {basic_memory-0.14.2 → basic_memory-0.14.3}/.dockerignore +0 -0
  99. {basic_memory-0.14.2 → basic_memory-0.14.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  100. {basic_memory-0.14.2 → basic_memory-0.14.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  101. {basic_memory-0.14.2 → basic_memory-0.14.3}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
  102. {basic_memory-0.14.2 → basic_memory-0.14.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  103. {basic_memory-0.14.2 → basic_memory-0.14.3}/.github/dependabot.yml +0 -0
  104. {basic_memory-0.14.2 → basic_memory-0.14.3}/.github/workflows/claude.yml +0 -0
  105. {basic_memory-0.14.2 → basic_memory-0.14.3}/.github/workflows/dev-release.yml +0 -0
  106. {basic_memory-0.14.2 → basic_memory-0.14.3}/.github/workflows/docker.yml +0 -0
  107. {basic_memory-0.14.2 → basic_memory-0.14.3}/.github/workflows/pr-title.yml +0 -0
  108. {basic_memory-0.14.2 → basic_memory-0.14.3}/.github/workflows/release.yml +0 -0
  109. {basic_memory-0.14.2 → basic_memory-0.14.3}/.github/workflows/test.yml +0 -0
  110. {basic_memory-0.14.2 → basic_memory-0.14.3}/.gitignore +0 -0
  111. {basic_memory-0.14.2 → basic_memory-0.14.3}/.python-version +0 -0
  112. {basic_memory-0.14.2 → basic_memory-0.14.3}/CHANGELOG.md +0 -0
  113. {basic_memory-0.14.2 → basic_memory-0.14.3}/CITATION.cff +0 -0
  114. {basic_memory-0.14.2 → basic_memory-0.14.3}/CLA.md +0 -0
  115. {basic_memory-0.14.2 → basic_memory-0.14.3}/CLAUDE.md +0 -0
  116. {basic_memory-0.14.2 → basic_memory-0.14.3}/CODE_OF_CONDUCT.md +0 -0
  117. {basic_memory-0.14.2 → basic_memory-0.14.3}/Dockerfile +0 -0
  118. {basic_memory-0.14.2 → basic_memory-0.14.3}/LICENSE +0 -0
  119. {basic_memory-0.14.2 → basic_memory-0.14.3}/README.md +0 -0
  120. {basic_memory-0.14.2 → basic_memory-0.14.3}/SECURITY.md +0 -0
  121. {basic_memory-0.14.2 → basic_memory-0.14.3}/docker-compose.yml +0 -0
  122. {basic_memory-0.14.2 → basic_memory-0.14.3}/docs/AI Assistant Guide.md +0 -0
  123. {basic_memory-0.14.2 → basic_memory-0.14.3}/docs/Docker.md +0 -0
  124. {basic_memory-0.14.2 → basic_memory-0.14.3}/llms-install.md +0 -0
  125. {basic_memory-0.14.2 → basic_memory-0.14.3}/memory.json +0 -0
  126. {basic_memory-0.14.2 → basic_memory-0.14.3}/smithery.yaml +0 -0
  127. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/alembic/alembic.ini +0 -0
  128. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/alembic/migrations.py +0 -0
  129. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/alembic/script.py.mako +0 -0
  130. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +0 -0
  131. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +0 -0
  132. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +0 -0
  133. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +0 -0
  134. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +0 -0
  135. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +0 -0
  136. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/api/__init__.py +0 -0
  137. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/api/routers/__init__.py +0 -0
  138. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/api/routers/directory_router.py +0 -0
  139. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/api/routers/importer_router.py +0 -0
  140. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/api/routers/knowledge_router.py +0 -0
  141. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/api/routers/memory_router.py +0 -0
  142. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/api/routers/prompt_router.py +0 -0
  143. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/api/routers/resource_router.py +0 -0
  144. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/api/routers/search_router.py +0 -0
  145. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/api/routers/utils.py +0 -0
  146. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/api/template_loader.py +0 -0
  147. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/cli/__init__.py +0 -0
  148. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/cli/commands/tool.py +0 -0
  149. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/file_utils.py +0 -0
  150. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/importers/__init__.py +0 -0
  151. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/importers/base.py +0 -0
  152. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/importers/claude_conversations_importer.py +0 -0
  153. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/importers/claude_projects_importer.py +0 -0
  154. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/importers/utils.py +0 -0
  155. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/markdown/__init__.py +0 -0
  156. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/markdown/entity_parser.py +0 -0
  157. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/markdown/markdown_processor.py +0 -0
  158. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/markdown/plugins.py +0 -0
  159. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/markdown/schemas.py +0 -0
  160. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/markdown/utils.py +0 -0
  161. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/__init__.py +0 -0
  162. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/prompts/ai_assistant_guide.py +0 -0
  163. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/prompts/continue_conversation.py +0 -0
  164. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/prompts/recent_activity.py +0 -0
  165. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/prompts/search.py +0 -0
  166. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/prompts/utils.py +0 -0
  167. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/resources/ai_assistant_guide.md +0 -0
  168. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/resources/project_info.py +0 -0
  169. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/tools/__init__.py +0 -0
  170. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/tools/build_context.py +0 -0
  171. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/tools/canvas.py +0 -0
  172. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/tools/delete_note.py +0 -0
  173. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/tools/edit_note.py +0 -0
  174. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/tools/list_directory.py +0 -0
  175. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/tools/project_management.py +0 -0
  176. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/tools/recent_activity.py +0 -0
  177. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/tools/search.py +0 -0
  178. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/tools/utils.py +0 -0
  179. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/mcp/tools/view_note.py +0 -0
  180. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/models/__init__.py +0 -0
  181. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/models/base.py +0 -0
  182. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/models/knowledge.py +0 -0
  183. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/models/search.py +0 -0
  184. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/repository/__init__.py +0 -0
  185. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/repository/entity_repository.py +0 -0
  186. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/repository/observation_repository.py +0 -0
  187. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/repository/project_info_repository.py +0 -0
  188. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/repository/relation_repository.py +0 -0
  189. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/repository/repository.py +0 -0
  190. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/repository/search_repository.py +0 -0
  191. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/schemas/__init__.py +0 -0
  192. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/schemas/base.py +0 -0
  193. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/schemas/delete.py +0 -0
  194. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/schemas/directory.py +0 -0
  195. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/schemas/memory.py +0 -0
  196. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/schemas/project_info.py +0 -0
  197. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/schemas/prompt.py +0 -0
  198. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/schemas/request.py +0 -0
  199. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/schemas/response.py +0 -0
  200. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/schemas/search.py +0 -0
  201. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/services/__init__.py +0 -0
  202. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/services/context_service.py +0 -0
  203. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/services/directory_service.py +0 -0
  204. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/services/exceptions.py +0 -0
  205. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/services/file_service.py +0 -0
  206. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/services/link_resolver.py +0 -0
  207. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/services/search_service.py +0 -0
  208. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/services/service.py +0 -0
  209. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/services/sync_status_service.py +0 -0
  210. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/sync/__init__.py +0 -0
  211. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/sync/watch_service.py +0 -0
  212. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/templates/prompts/continue_conversation.hbs +0 -0
  213. {basic_memory-0.14.2 → basic_memory-0.14.3}/src/basic_memory/templates/prompts/search.hbs +0 -0
  214. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/Non-MarkdownFileSupport.pdf +0 -0
  215. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/Screenshot.png +0 -0
  216. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/__init__.py +0 -0
  217. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/api/conftest.py +0 -0
  218. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/api/test_continue_conversation_template.py +0 -0
  219. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/api/test_directory_router.py +0 -0
  220. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/api/test_importer_router.py +0 -0
  221. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/api/test_knowledge_router.py +0 -0
  222. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/api/test_management_router.py +0 -0
  223. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/api/test_memory_router.py +0 -0
  224. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/api/test_project_router_operations.py +0 -0
  225. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/api/test_prompt_router.py +0 -0
  226. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/api/test_resource_router.py +0 -0
  227. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/api/test_search_router.py +0 -0
  228. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/api/test_search_template.py +0 -0
  229. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/api/test_template_loader.py +0 -0
  230. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/api/test_template_loader_helpers.py +0 -0
  231. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/cli/conftest.py +0 -0
  232. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/cli/test_cli_tools.py +0 -0
  233. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/cli/test_project_info.py +0 -0
  234. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/cli/test_status.py +0 -0
  235. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/cli/test_version.py +0 -0
  236. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/importers/test_importer_base.py +0 -0
  237. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/importers/test_importer_utils.py +0 -0
  238. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/markdown/__init__.py +0 -0
  239. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/markdown/test_entity_parser.py +0 -0
  240. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/markdown/test_markdown_plugins.py +0 -0
  241. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/markdown/test_markdown_processor.py +0 -0
  242. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/markdown/test_observation_edge_cases.py +0 -0
  243. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/markdown/test_parser_edge_cases.py +0 -0
  244. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/markdown/test_relation_edge_cases.py +0 -0
  245. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/markdown/test_task_detection.py +0 -0
  246. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/mcp/test_prompts.py +0 -0
  247. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/mcp/test_resource_project_info.py +0 -0
  248. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/mcp/test_resources.py +0 -0
  249. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/mcp/test_tool_build_context.py +0 -0
  250. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/mcp/test_tool_canvas.py +0 -0
  251. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/mcp/test_tool_delete_note.py +0 -0
  252. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/mcp/test_tool_edit_note.py +0 -0
  253. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/mcp/test_tool_list_directory.py +0 -0
  254. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/mcp/test_tool_recent_activity.py +0 -0
  255. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/mcp/test_tool_resource.py +0 -0
  256. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/mcp/test_tool_search.py +0 -0
  257. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/mcp/test_tool_sync_status.py +0 -0
  258. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/mcp/test_tool_utils.py +0 -0
  259. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/mcp/test_tool_view_note.py +0 -0
  260. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/repository/test_entity_repository.py +0 -0
  261. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/repository/test_entity_repository_upsert.py +0 -0
  262. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/repository/test_observation_repository.py +0 -0
  263. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/repository/test_project_info_repository.py +0 -0
  264. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/repository/test_relation_repository.py +0 -0
  265. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/repository/test_repository.py +0 -0
  266. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/repository/test_search_repository.py +0 -0
  267. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/schemas/test_memory_url.py +0 -0
  268. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/schemas/test_memory_url_validation.py +0 -0
  269. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/schemas/test_schemas.py +0 -0
  270. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/schemas/test_search.py +0 -0
  271. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/services/test_context_service.py +0 -0
  272. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/services/test_directory_service.py +0 -0
  273. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/services/test_entity_service.py +0 -0
  274. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/services/test_file_service.py +0 -0
  275. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/services/test_link_resolver.py +0 -0
  276. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/services/test_project_service_operations.py +0 -0
  277. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/services/test_search_service.py +0 -0
  278. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/services/test_sync_status_service.py +0 -0
  279. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/sync/test_sync_service.py +0 -0
  280. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/sync/test_sync_wikilink_issue.py +0 -0
  281. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/sync/test_tmp_files.py +0 -0
  282. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/sync/test_watch_service.py +0 -0
  283. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/sync/test_watch_service_edge_cases.py +0 -0
  284. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/test_config.py +0 -0
  285. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/utils/test_file_utils.py +0 -0
  286. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/utils/test_parse_tags.py +0 -0
  287. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/utils/test_permalink_formatting.py +0 -0
  288. {basic_memory-0.14.2 → basic_memory-0.14.3}/tests/utils/test_utf8_handling.py +0 -0
@@ -27,7 +27,12 @@ project and how to get started as a developer.
27
27
 
28
28
  > **Note**: Basic Memory uses [just](https://just.systems) as a modern command runner. Install with `brew install just` or `cargo install just`.
29
29
 
30
- 3. **Run the Tests**:
30
+ 3. **Activate the Virtual Environment**
31
+ ```bash
32
+ source .venv/bin/activate
33
+ ```
34
+
35
+ 4. **Run the Tests**:
31
36
  ```bash
32
37
  # Run all tests
33
38
  just test
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basic-memory
3
- Version: 0.14.2
3
+ Version: 0.14.3
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
@@ -13,7 +13,7 @@ Requires-Dist: aiosqlite>=0.20.0
13
13
  Requires-Dist: alembic>=1.14.1
14
14
  Requires-Dist: dateparser>=1.2.0
15
15
  Requires-Dist: fastapi[standard]>=0.115.8
16
- Requires-Dist: fastmcp<2.10.0,>=2.3.4
16
+ Requires-Dist: fastmcp==2.10.2
17
17
  Requires-Dist: greenlet>=3.1.1
18
18
  Requires-Dist: icecream>=2.1.3
19
19
  Requires-Dist: loguru>=0.7.3
@@ -0,0 +1,241 @@
1
+ # Character Handling and Conflict Resolution
2
+
3
+ Basic Memory handles various character encoding scenarios and file naming conventions to provide consistent permalink generation and conflict resolution. This document explains how the system works and how to resolve common character-related issues.
4
+
5
+ ## Overview
6
+
7
+ Basic Memory uses a sophisticated system to generate permalinks from file paths while maintaining consistency across different operating systems and character encodings. The system normalizes file paths and generates unique permalinks to prevent conflicts.
8
+
9
+ ## Character Normalization Rules
10
+
11
+ ### 1. Permalink Generation
12
+
13
+ When Basic Memory processes a file path, it applies these normalization rules:
14
+
15
+ ```
16
+ Original: "Finance/My Investment Strategy.md"
17
+ Permalink: "finance/my-investment-strategy"
18
+ ```
19
+
20
+ **Transformation process:**
21
+ 1. Remove file extension (`.md`)
22
+ 2. Convert to lowercase (case-insensitive)
23
+ 3. Replace spaces with hyphens
24
+ 4. Replace underscores with hyphens
25
+ 5. Handle international characters (transliteration for Latin, preservation for non-Latin)
26
+ 6. Convert camelCase to kebab-case
27
+
28
+ ### 2. International Character Support
29
+
30
+ **Latin characters with diacritics** are transliterated:
31
+ - `ø` → `o` (Søren → soren)
32
+ - `ü` → `u` (Müller → muller)
33
+ - `é` → `e` (Café → cafe)
34
+ - `ñ` → `n` (Niño → nino)
35
+
36
+ **Non-Latin characters** are preserved:
37
+ - Chinese: `中文/测试文档.md` → `中文/测试文档`
38
+ - Japanese: `日本語/文書.md` → `日本語/文書`
39
+
40
+ ## Common Conflict Scenarios
41
+
42
+ ### 1. Hyphen vs Space Conflicts
43
+
44
+ **Problem:** Files with existing hyphens conflict with generated permalinks from spaces.
45
+
46
+ **Example:**
47
+ ```
48
+ File 1: "basic memory bug.md" → permalink: "basic-memory-bug"
49
+ File 2: "basic-memory-bug.md" → permalink: "basic-memory-bug" (CONFLICT!)
50
+ ```
51
+
52
+ **Resolution:** The system automatically resolves this by adding suffixes:
53
+ ```
54
+ File 1: "basic memory bug.md" → permalink: "basic-memory-bug"
55
+ File 2: "basic-memory-bug.md" → permalink: "basic-memory-bug-1"
56
+ ```
57
+
58
+ **Best Practice:** Choose consistent naming conventions within your project.
59
+
60
+ ### 2. Case Sensitivity Conflicts
61
+
62
+ **Problem:** Different case variations that normalize to the same permalink.
63
+
64
+ **Example on macOS:**
65
+ ```
66
+ Directory: Finance/investment.md
67
+ Directory: finance/investment.md (different on filesystem, same permalink)
68
+ ```
69
+
70
+ **Resolution:** Basic Memory detects case conflicts and prevents them during sync operations with helpful error messages.
71
+
72
+ **Best Practice:** Use consistent casing for directory and file names.
73
+
74
+ ### 3. Character Encoding Conflicts
75
+
76
+ **Problem:** Different Unicode normalizations of the same logical character.
77
+
78
+ **Example:**
79
+ ```
80
+ File 1: "café.md" (é as single character)
81
+ File 2: "café.md" (e + combining accent)
82
+ ```
83
+
84
+ **Resolution:** Basic Memory normalizes Unicode characters using NFD normalization to detect these conflicts.
85
+
86
+ ### 4. Forward Slash Conflicts
87
+
88
+ **Problem:** Forward slashes in frontmatter or file names interpreted as path separators.
89
+
90
+ **Example:**
91
+ ```yaml
92
+ ---
93
+ permalink: finance/investment/strategy
94
+ ---
95
+ ```
96
+
97
+ **Resolution:** Basic Memory validates frontmatter permalinks and warns about path separator conflicts.
98
+
99
+ ## Error Messages and Troubleshooting
100
+
101
+ ### "UNIQUE constraint failed: entity.file_path, entity.project_id"
102
+
103
+ **Cause:** Two entities trying to use the same file path within a project.
104
+
105
+ **Common scenarios:**
106
+ 1. File move operation where destination is already occupied
107
+ 2. Case sensitivity differences on macOS
108
+ 3. Character encoding conflicts
109
+ 4. Concurrent file operations
110
+
111
+ **Resolution steps:**
112
+ 1. Check for duplicate file names with different cases
113
+ 2. Look for files with similar names but different character encodings
114
+ 3. Rename conflicting files to have unique names
115
+ 4. Run sync again after resolving conflicts
116
+
117
+ ### "File path conflict detected during move"
118
+
119
+ **Cause:** Enhanced conflict detection preventing potential database integrity violations.
120
+
121
+ **What this means:** The system detected that moving a file would create a conflict before attempting the database operation.
122
+
123
+ **Resolution:** Follow the specific guidance in the error message, which will indicate the type of conflict detected.
124
+
125
+ ## Best Practices
126
+
127
+ ### 1. File Naming Conventions
128
+
129
+ **Recommended patterns:**
130
+ - Use consistent casing (prefer lowercase)
131
+ - Use hyphens instead of spaces for multi-word files
132
+ - Avoid special characters that could conflict with path separators
133
+ - Be consistent with directory structure casing
134
+
135
+ **Examples:**
136
+ ```
137
+ ✅ Good:
138
+ - finance/investment-strategy.md
139
+ - projects/basic-memory-features.md
140
+ - docs/api-reference.md
141
+
142
+ ❌ Problematic:
143
+ - Finance/Investment Strategy.md (mixed case, spaces)
144
+ - finance/Investment Strategy.md (inconsistent case)
145
+ - docs/API/Reference.md (mixed case directories)
146
+ ```
147
+
148
+ ### 2. Permalink Management
149
+
150
+ **Custom permalinks in frontmatter:**
151
+ ```yaml
152
+ ---
153
+ type: knowledge
154
+ permalink: custom-permalink-name
155
+ ---
156
+ ```
157
+
158
+ **Guidelines:**
159
+ - Use lowercase permalinks
160
+ - Use hyphens for word separation
161
+ - Avoid path separators unless creating sub-paths
162
+ - Ensure uniqueness within your project
163
+
164
+ ### 3. Directory Structure
165
+
166
+ **Consistent casing:**
167
+ ```
168
+ ✅ Good:
169
+ finance/
170
+ investment-strategies.md
171
+ portfolio-management.md
172
+
173
+ ❌ Problematic:
174
+ Finance/ (capital F)
175
+ investment-strategies.md
176
+ finance/ (lowercase f)
177
+ portfolio-management.md
178
+ ```
179
+
180
+ ## Migration and Cleanup
181
+
182
+ ### Identifying Conflicts
183
+
184
+ Use Basic Memory's built-in conflict detection:
185
+
186
+ ```bash
187
+ # Sync will report conflicts
188
+ basic-memory sync
189
+
190
+ # Check sync status for warnings
191
+ basic-memory status
192
+ ```
193
+
194
+ ### Resolving Existing Conflicts
195
+
196
+ 1. **Identify conflicting files** from sync error messages
197
+ 2. **Choose consistent naming convention** for your project
198
+ 3. **Rename files** to follow the convention
199
+ 4. **Re-run sync** to verify resolution
200
+
201
+ ### Bulk Renaming Strategy
202
+
203
+ For projects with many conflicts:
204
+
205
+ 1. **Backup your project** before making changes
206
+ 2. **Standardize on lowercase** file and directory names
207
+ 3. **Replace spaces with hyphens** in file names
208
+ 4. **Use consistent character encoding** (UTF-8)
209
+ 5. **Test sync after each batch** of changes
210
+
211
+ ## System Enhancements
212
+
213
+ ### Recent Improvements (v0.13+)
214
+
215
+ 1. **Enhanced conflict detection** before database operations
216
+ 2. **Improved error messages** with specific resolution guidance
217
+ 3. **Character normalization utilities** for consistent handling
218
+ 4. **File swap detection** for complex move scenarios
219
+ 5. **Proactive conflict warnings** during permalink resolution
220
+
221
+ ### Monitoring and Logging
222
+
223
+ The system now provides detailed logging for conflict resolution:
224
+
225
+ ```
226
+ DEBUG: Detected potential file path conflicts for 'Finance/Investment.md': ['finance/investment.md']
227
+ WARNING: File path conflict detected during move: entity_id=123 trying to move from 'old.md' to 'new.md'
228
+ ```
229
+
230
+ These logs help identify and resolve conflicts before they cause sync failures.
231
+
232
+ ## Support and Resources
233
+
234
+ If you encounter character-related conflicts not covered in this guide:
235
+
236
+ 1. **Check the logs** for specific conflict details
237
+ 2. **Review error messages** for resolution guidance
238
+ 3. **Report issues** with examples of the conflicting files
239
+ 4. **Consider the file naming best practices** outlined above
240
+
241
+ The Basic Memory system is designed to handle most character conflicts automatically while providing clear guidance for manual resolution when needed.
@@ -3,6 +3,9 @@
3
3
  # Install dependencies
4
4
  install:
5
5
  pip install -e ".[dev]"
6
+ uv sync
7
+ @echo ""
8
+ @echo "💡 Remember to activate the virtual environment by running: source .venv/bin/activate"
6
9
 
7
10
  # Run unit tests in parallel
8
11
  test-unit:
@@ -179,4 +182,4 @@ beta version:
179
182
 
180
183
  # List all available recipes
181
184
  default:
182
- @just --list
185
+ @just --list
@@ -30,7 +30,7 @@ dependencies = [
30
30
  "alembic>=1.14.1",
31
31
  "pillow>=11.1.0",
32
32
  "pybars3>=0.9.7",
33
- "fastmcp>=2.3.4,<2.10.0",
33
+ "fastmcp==2.10.2",
34
34
  "pyjwt>=2.10.1",
35
35
  "python-dotenv>=1.1.0",
36
36
  "pytest-aio>=1.9.0",
@@ -52,7 +52,7 @@ build-backend = "hatchling.build"
52
52
 
53
53
  [tool.pytest.ini_options]
54
54
  pythonpath = ["src", "tests"]
55
- addopts = "--cov=basic_memory --cov-report term-missing -ra -q"
55
+ addopts = "--cov=basic_memory --cov-report term-missing"
56
56
  testpaths = ["tests"]
57
57
  asyncio_mode = "strict"
58
58
  asyncio_default_fixture_loop_scope = "function"
@@ -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.14.2"
4
+ __version__ = "0.14.3"
5
5
 
6
6
  # API version for FastAPI - independent of package version
7
7
  __api_version__ = "v0"
@@ -8,17 +8,19 @@ from sqlalchemy import pool
8
8
 
9
9
  from alembic import context
10
10
 
11
+ from basic_memory.config import ConfigManager
12
+
11
13
  # set config.env to "test" for pytest to prevent logging to file in utils.setup_logging()
12
14
  os.environ["BASIC_MEMORY_ENV"] = "test"
13
15
 
14
16
  # Import after setting environment variable # noqa: E402
15
- from basic_memory.config import app_config # noqa: E402
16
17
  from basic_memory.models import Base # noqa: E402
17
18
 
18
19
  # this is the Alembic Config object, which provides
19
20
  # access to the values within the .ini file in use.
20
21
  config = context.config
21
22
 
23
+ app_config = ConfigManager().config
22
24
  # Set the SQLAlchemy URL from our app config
23
25
  sqlalchemy_url = f"sqlite:///{app_config.database_path}"
24
26
  config.set_main_option("sqlalchemy.url", sqlalchemy_url)
@@ -20,15 +20,18 @@ from basic_memory.api.routers import (
20
20
  search,
21
21
  prompt_router,
22
22
  )
23
- from basic_memory.config import app_config
23
+ from basic_memory.config import ConfigManager
24
24
  from basic_memory.services.initialization import initialize_app, initialize_file_sync
25
25
 
26
26
 
27
27
  @asynccontextmanager
28
28
  async def lifespan(app: FastAPI): # pragma: no cover
29
29
  """Lifecycle manager for the FastAPI app."""
30
+
31
+ app_config = ConfigManager().config
30
32
  # Initialize app and database
31
33
  logger.info("Starting Basic Memory API")
34
+ print(f"fastapi {app_config.projects}")
32
35
  await initialize_app(app_config)
33
36
 
34
37
  logger.info(f"Sync changes enabled: {app_config.sync_changes}")
@@ -6,7 +6,7 @@ from fastapi import APIRouter, Request
6
6
  from loguru import logger
7
7
  from pydantic import BaseModel
8
8
 
9
- from basic_memory.config import app_config
9
+ from basic_memory.config import ConfigManager
10
10
  from basic_memory.deps import SyncServiceDep, ProjectRepositoryDep
11
11
 
12
12
  router = APIRouter(prefix="/management", tags=["management"])
@@ -41,6 +41,8 @@ async def start_watch_service(
41
41
  # Watch service is already running
42
42
  return WatchStatusResponse(running=True)
43
43
 
44
+ app_config = ConfigManager().config
45
+
44
46
  # Create and start a new watch service
45
47
  logger.info("Starting watch service via management API")
46
48
 
@@ -1,5 +1,6 @@
1
1
  """Router for project management."""
2
2
 
3
+ import os
3
4
  from fastapi import APIRouter, HTTPException, Path, Body
4
5
  from typing import Optional
5
6
 
@@ -32,40 +33,47 @@ async def get_project_info(
32
33
  @project_router.patch("/{name}", response_model=ProjectStatusResponse)
33
34
  async def update_project(
34
35
  project_service: ProjectServiceDep,
35
- project_name: str = Path(..., description="Name of the project to update"),
36
- path: Optional[str] = Body(None, description="New path for the project"),
36
+ name: str = Path(..., description="Name of the project to update"),
37
+ path: Optional[str] = Body(None, description="New absolute path for the project"),
37
38
  is_active: Optional[bool] = Body(None, description="Status of the project (active/inactive)"),
38
39
  ) -> ProjectStatusResponse:
39
40
  """Update a project's information in configuration and database.
40
41
 
41
42
  Args:
42
- project_name: The name of the project to update
43
- path: Optional new path for the project
43
+ name: The name of the project to update
44
+ path: Optional new absolute path for the project
44
45
  is_active: Optional status update for the project
45
46
 
46
47
  Returns:
47
48
  Response confirming the project was updated
48
49
  """
49
- try: # pragma: no cover
50
+ try:
51
+ # Validate that path is absolute if provided
52
+ if path and not os.path.isabs(path):
53
+ raise HTTPException(status_code=400, detail="Path must be absolute")
54
+
50
55
  # Get original project info for the response
51
56
  old_project_info = ProjectItem(
52
- name=project_name,
53
- path=project_service.projects.get(project_name, ""),
57
+ name=name,
58
+ path=project_service.projects.get(name, ""),
54
59
  )
55
60
 
56
- await project_service.update_project(project_name, updated_path=path, is_active=is_active)
61
+ if path:
62
+ await project_service.move_project(name, path)
63
+ elif is_active is not None:
64
+ await project_service.update_project(name, is_active=is_active)
57
65
 
58
66
  # Get updated project info
59
- updated_path = path if path else project_service.projects.get(project_name, "")
67
+ updated_path = path if path else project_service.projects.get(name, "")
60
68
 
61
69
  return ProjectStatusResponse(
62
- message=f"Project '{project_name}' updated successfully",
70
+ message=f"Project '{name}' updated successfully",
63
71
  status="success",
64
- default=(project_name == project_service.default_project),
72
+ default=(name == project_service.default_project),
65
73
  old_project=old_project_info,
66
- new_project=ProjectItem(name=project_name, path=updated_path),
74
+ new_project=ProjectItem(name=name, path=updated_path),
67
75
  )
68
- except ValueError as e: # pragma: no cover
76
+ except ValueError as e:
69
77
  raise HTTPException(status_code=400, detail=str(e))
70
78
 
71
79
 
@@ -2,7 +2,7 @@ from typing import Optional
2
2
 
3
3
  import typer
4
4
 
5
- from basic_memory.config import get_project_config
5
+ from basic_memory.config import get_project_config, ConfigManager
6
6
  from basic_memory.mcp.project_session import session
7
7
 
8
8
 
@@ -10,8 +10,8 @@ def version_callback(value: bool) -> None:
10
10
  """Show version and exit."""
11
11
  if value: # pragma: no cover
12
12
  import basic_memory
13
- from basic_memory.config import config
14
13
 
14
+ config = get_project_config()
15
15
  typer.echo(f"Basic Memory version: {basic_memory.__version__}")
16
16
  typer.echo(f"Current project: {config.project}")
17
17
  typer.echo(f"Project path: {config.home}")
@@ -44,9 +44,9 @@ def app_callback(
44
44
 
45
45
  # Run initialization for every command unless --version was specified
46
46
  if not version and ctx.invoked_subcommand is not None:
47
- from basic_memory.config import app_config
48
47
  from basic_memory.services.initialization import ensure_initialization
49
48
 
49
+ app_config = ConfigManager().config
50
50
  ensure_initialization(app_config)
51
51
 
52
52
  # Initialize MCP session with the specified project or default
@@ -1,10 +1,9 @@
1
1
  """CLI commands for basic-memory."""
2
2
 
3
- from . import auth, status, sync, db, import_memory_json, mcp, import_claude_conversations
3
+ from . import status, sync, db, import_memory_json, mcp, import_claude_conversations
4
4
  from . import import_claude_projects, import_chatgpt, tool, project
5
5
 
6
6
  __all__ = [
7
- "auth",
8
7
  "status",
9
8
  "sync",
10
9
  "db",
@@ -1,14 +1,13 @@
1
1
  """Database management commands."""
2
2
 
3
3
  import asyncio
4
- from pathlib import Path
5
4
 
6
5
  import typer
7
6
  from loguru import logger
8
7
 
9
8
  from basic_memory import db
10
9
  from basic_memory.cli.app import app
11
- from basic_memory.config import app_config, config_manager
10
+ from basic_memory.config import ConfigManager, BasicMemoryConfig, save_basic_memory_config
12
11
 
13
12
 
14
13
  @app.command()
@@ -18,6 +17,8 @@ def reset(
18
17
  """Reset database (drop all tables and recreate)."""
19
18
  if typer.confirm("This will delete all data in your db. Are you sure?"):
20
19
  logger.info("Resetting database...")
20
+ config_manager = ConfigManager()
21
+ app_config = config_manager.config
21
22
  # Get database path
22
23
  db_path = app_config.app_database_path
23
24
 
@@ -27,9 +28,8 @@ def reset(
27
28
  logger.info(f"Database file deleted: {db_path}")
28
29
 
29
30
  # Reset project configuration
30
- config_manager.config.projects = {"main": str(Path.home() / "basic-memory")}
31
- config_manager.config.default_project = "main"
32
- config_manager.save_config(config_manager.config)
31
+ config = BasicMemoryConfig()
32
+ save_basic_memory_config(config_manager.config_file, config)
33
33
  logger.info("Project configuration reset to default")
34
34
 
35
35
  # Create a new empty database
@@ -7,7 +7,7 @@ from typing import Annotated
7
7
 
8
8
  import typer
9
9
  from basic_memory.cli.app import import_app
10
- from basic_memory.config import config
10
+ from basic_memory.config import get_project_config
11
11
  from basic_memory.importers import ChatGPTImporter
12
12
  from basic_memory.markdown import EntityParser, MarkdownProcessor
13
13
  from loguru import logger
@@ -19,6 +19,7 @@ console = Console()
19
19
 
20
20
  async def get_markdown_processor() -> MarkdownProcessor:
21
21
  """Get MarkdownProcessor instance."""
22
+ config = get_project_config()
22
23
  entity_parser = EntityParser(config.home)
23
24
  return MarkdownProcessor(entity_parser)
24
25
 
@@ -49,7 +50,7 @@ def import_chatgpt(
49
50
 
50
51
  # Get markdown processor
51
52
  markdown_processor = asyncio.run(get_markdown_processor())
52
-
53
+ config = get_project_config()
53
54
  # Process the file
54
55
  base_path = config.home / folder
55
56
  console.print(f"\nImporting chats from {conversations_json}...writing to {base_path}")
@@ -7,7 +7,7 @@ from typing import Annotated
7
7
 
8
8
  import typer
9
9
  from basic_memory.cli.app import claude_app
10
- from basic_memory.config import config
10
+ from basic_memory.config import get_project_config
11
11
  from basic_memory.importers.claude_conversations_importer import ClaudeConversationsImporter
12
12
  from basic_memory.markdown import EntityParser, MarkdownProcessor
13
13
  from loguru import logger
@@ -19,6 +19,7 @@ console = Console()
19
19
 
20
20
  async def get_markdown_processor() -> MarkdownProcessor:
21
21
  """Get MarkdownProcessor instance."""
22
+ config = get_project_config()
22
23
  entity_parser = EntityParser(config.home)
23
24
  return MarkdownProcessor(entity_parser)
24
25
 
@@ -42,6 +43,7 @@ def import_claude(
42
43
  After importing, run 'basic-memory sync' to index the new files.
43
44
  """
44
45
 
46
+ config = get_project_config()
45
47
  try:
46
48
  if not conversations_json.exists():
47
49
  typer.echo(f"Error: File not found: {conversations_json}", err=True)
@@ -7,7 +7,7 @@ from typing import Annotated
7
7
 
8
8
  import typer
9
9
  from basic_memory.cli.app import claude_app
10
- from basic_memory.config import config
10
+ from basic_memory.config import get_project_config
11
11
  from basic_memory.importers.claude_projects_importer import ClaudeProjectsImporter
12
12
  from basic_memory.markdown import EntityParser, MarkdownProcessor
13
13
  from loguru import logger
@@ -19,6 +19,7 @@ console = Console()
19
19
 
20
20
  async def get_markdown_processor() -> MarkdownProcessor:
21
21
  """Get MarkdownProcessor instance."""
22
+ config = get_project_config()
22
23
  entity_parser = EntityParser(config.home)
23
24
  return MarkdownProcessor(entity_parser)
24
25
 
@@ -41,6 +42,7 @@ def import_projects(
41
42
 
42
43
  After importing, run 'basic-memory sync' to index the new files.
43
44
  """
45
+ config = get_project_config()
44
46
  try:
45
47
  if not projects_json.exists():
46
48
  typer.echo(f"Error: File not found: {projects_json}", err=True)
@@ -7,7 +7,7 @@ from typing import Annotated
7
7
 
8
8
  import typer
9
9
  from basic_memory.cli.app import import_app
10
- from basic_memory.config import config
10
+ from basic_memory.config import get_project_config
11
11
  from basic_memory.importers.memory_json_importer import MemoryJsonImporter
12
12
  from basic_memory.markdown import EntityParser, MarkdownProcessor
13
13
  from loguru import logger
@@ -19,6 +19,7 @@ console = Console()
19
19
 
20
20
  async def get_markdown_processor() -> MarkdownProcessor:
21
21
  """Get MarkdownProcessor instance."""
22
+ config = get_project_config()
22
23
  entity_parser = EntityParser(config.home)
23
24
  return MarkdownProcessor(entity_parser)
24
25
 
@@ -46,6 +47,7 @@ def memory_json(
46
47
  typer.echo(f"Error: File not found: {json_path}", err=True)
47
48
  raise typer.Exit(1)
48
49
 
50
+ config = get_project_config()
49
51
  try:
50
52
  # Get markdown processor
51
53
  markdown_processor = asyncio.run(get_markdown_processor())
@@ -74,7 +76,8 @@ def memory_json(
74
76
  Panel(
75
77
  f"[green]Import complete![/green]\n\n"
76
78
  f"Created {result.entities} entities\n"
77
- f"Added {result.relations} relations",
79
+ f"Added {result.relations} relations\n"
80
+ f"Skipped {result.skipped_entities} entities\n",
78
81
  expand=False,
79
82
  )
80
83
  )
@@ -4,6 +4,7 @@ import asyncio
4
4
  import typer
5
5
 
6
6
  from basic_memory.cli.app import app
7
+ from basic_memory.config import ConfigManager
7
8
 
8
9
  # Import mcp instance
9
10
  from basic_memory.mcp.server import mcp as mcp_server # pragma: no cover
@@ -34,26 +35,13 @@ def mcp(
34
35
  - sse: Server-Sent Events (for compatibility with existing clients)
35
36
  """
36
37
 
37
- # Check if OAuth is enabled
38
- import os
39
-
40
- auth_enabled = os.getenv("FASTMCP_AUTH_ENABLED", "false").lower() == "true"
41
- if auth_enabled:
42
- logger.info("OAuth authentication is ENABLED")
43
- logger.info(f"Issuer URL: {os.getenv('FASTMCP_AUTH_ISSUER_URL', 'http://localhost:8000')}")
44
- if os.getenv("FASTMCP_AUTH_REQUIRED_SCOPES"):
45
- logger.info(f"Required scopes: {os.getenv('FASTMCP_AUTH_REQUIRED_SCOPES')}")
46
- else:
47
- logger.info("OAuth authentication is DISABLED")
48
-
49
- from basic_memory.config import app_config
50
38
  from basic_memory.services.initialization import initialize_file_sync
51
39
 
52
- # Start the MCP server with the specified transport
53
-
54
40
  # Use unified thread-based sync approach for both transports
55
41
  import threading
56
42
 
43
+ app_config = ConfigManager().config
44
+
57
45
  def run_file_sync():
58
46
  """Run file sync in a separate thread with its own event loop."""
59
47
  loop = asyncio.new_event_loop()