basic-memory 0.17.4__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 (431) hide show
  1. {basic_memory-0.17.4 → basic_memory-0.17.5}/.github/workflows/test.yml +3 -3
  2. basic_memory-0.17.5/.python-version +1 -0
  3. {basic_memory-0.17.4 → basic_memory-0.17.5}/CHANGELOG.md +11 -0
  4. {basic_memory-0.17.4 → basic_memory-0.17.5}/PKG-INFO +5 -2
  5. {basic_memory-0.17.4 → basic_memory-0.17.5}/pyproject.toml +7 -3
  6. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/__init__.py +1 -1
  7. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/env.py +12 -8
  8. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/6830751f5fb6_merge_multiple_heads.py +3 -3
  9. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/knowledge_router.py +1 -3
  10. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/project_router.py +1 -3
  11. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/core_commands.py +5 -6
  12. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/rclone_commands.py +1 -0
  13. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/upload_command.py +2 -2
  14. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/command_utils.py +6 -2
  15. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/db.py +5 -3
  16. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/format.py +2 -2
  17. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/import_chatgpt.py +3 -3
  18. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/import_claude_conversations.py +3 -3
  19. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/import_claude_projects.py +3 -3
  20. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/import_memory_json.py +3 -3
  21. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/project.py +19 -20
  22. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/tool.py +7 -7
  23. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/deps/projects.py +1 -3
  24. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/deps/repositories.py +6 -2
  25. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/deps/services.py +6 -2
  26. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/container.py +1 -3
  27. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/canvas.py +3 -1
  28. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/read_content.py +3 -1
  29. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/recent_activity.py +14 -4
  30. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/utils.py +6 -2
  31. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/write_note.py +3 -1
  32. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/models/knowledge.py +1 -3
  33. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/models/project.py +1 -3
  34. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/repository/entity_repository.py +1 -3
  35. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/repository/relation_repository.py +3 -3
  36. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/repository/repository.py +4 -3
  37. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/runtime.py +1 -1
  38. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/services/context_service.py +3 -1
  39. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/sync/sync_service.py +3 -1
  40. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/telemetry.py +87 -16
  41. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/mcp/test_lifespan_shutdown_sync_task_cancellation_integration.py +3 -1
  42. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/test_directory_router.py +0 -1
  43. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/test_management_router.py +0 -2
  44. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/test_project_router.py +4 -2
  45. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/test_relation_background_resolution.py +2 -0
  46. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/v2/test_knowledge_router.py +3 -1
  47. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/v2/test_project_router.py +7 -3
  48. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/cli/cloud/test_cloud_api_client_and_utils.py +9 -5
  49. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/cli/cloud/test_rclone_config_and_bmignore_filters.py +0 -2
  50. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/cli/cloud/test_upload_path.py +3 -3
  51. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/cli/test_auth_cli_auth.py +9 -4
  52. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/cli/test_cli_tool_exit.py +3 -1
  53. basic_memory-0.17.5/tests/cli/test_cli_tools.py +38 -0
  54. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/cli/test_cloud_authentication.py +0 -2
  55. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/clients/test_clients.py +0 -1
  56. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_async_client_modes.py +0 -2
  57. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_project_context.py +0 -2
  58. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_recent_activity_prompt_modes.py +16 -6
  59. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_server_lifespan_branches.py +0 -3
  60. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_tool_move_note.py +0 -2
  61. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_tool_project_management.py +0 -2
  62. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_tool_read_content.py +0 -2
  63. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_tool_recent_activity.py +1 -2
  64. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/repository/test_postgres_search_repository.py +9 -5
  65. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/schemas/test_relation_response_reference_resolution.py +0 -3
  66. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/services/test_initialization.py +12 -6
  67. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/services/test_initialization_cloud_mode_branches.py +5 -3
  68. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/services/test_project_service_operations.py +0 -2
  69. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/sync/test_watch_service_atomic_adds.py +0 -2
  70. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/sync/test_watch_service_reload.py +0 -2
  71. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/test_rclone_commands.py +56 -19
  72. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/test_runtime.py +0 -1
  73. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/test_telemetry.py +45 -23
  74. basic_memory-0.17.5/uv.lock +2704 -0
  75. basic_memory-0.17.4/.python-version +0 -1
  76. basic_memory-0.17.4/tests/cli/test_cli_tools.py +0 -500
  77. basic_memory-0.17.4/uv.lock +0 -2363
  78. {basic_memory-0.17.4 → basic_memory-0.17.5}/.claude/commands/release/beta.md +0 -0
  79. {basic_memory-0.17.4 → basic_memory-0.17.5}/.claude/commands/release/changelog.md +0 -0
  80. {basic_memory-0.17.4 → basic_memory-0.17.5}/.claude/commands/release/release-check.md +0 -0
  81. {basic_memory-0.17.4 → basic_memory-0.17.5}/.claude/commands/release/release.md +0 -0
  82. {basic_memory-0.17.4 → basic_memory-0.17.5}/.claude/commands/spec.md +0 -0
  83. {basic_memory-0.17.4 → basic_memory-0.17.5}/.claude/commands/test-live.md +0 -0
  84. {basic_memory-0.17.4 → basic_memory-0.17.5}/.claude/settings.json +0 -0
  85. {basic_memory-0.17.4 → basic_memory-0.17.5}/.dockerignore +0 -0
  86. {basic_memory-0.17.4 → basic_memory-0.17.5}/.env.example +0 -0
  87. {basic_memory-0.17.4 → basic_memory-0.17.5}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  88. {basic_memory-0.17.4 → basic_memory-0.17.5}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  89. {basic_memory-0.17.4 → basic_memory-0.17.5}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
  90. {basic_memory-0.17.4 → basic_memory-0.17.5}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  91. {basic_memory-0.17.4 → basic_memory-0.17.5}/.github/dependabot.yml +0 -0
  92. {basic_memory-0.17.4 → basic_memory-0.17.5}/.github/workflows/claude-code-review.yml +0 -0
  93. {basic_memory-0.17.4 → basic_memory-0.17.5}/.github/workflows/claude-issue-triage.yml +0 -0
  94. {basic_memory-0.17.4 → basic_memory-0.17.5}/.github/workflows/claude.yml +0 -0
  95. {basic_memory-0.17.4 → basic_memory-0.17.5}/.github/workflows/dev-release.yml +0 -0
  96. {basic_memory-0.17.4 → basic_memory-0.17.5}/.github/workflows/docker.yml +0 -0
  97. {basic_memory-0.17.4 → basic_memory-0.17.5}/.github/workflows/pr-title.yml +0 -0
  98. {basic_memory-0.17.4 → basic_memory-0.17.5}/.github/workflows/release.yml +0 -0
  99. {basic_memory-0.17.4 → basic_memory-0.17.5}/.gitignore +0 -0
  100. {basic_memory-0.17.4 → basic_memory-0.17.5}/CITATION.cff +0 -0
  101. {basic_memory-0.17.4 → basic_memory-0.17.5}/CLA.md +0 -0
  102. {basic_memory-0.17.4 → basic_memory-0.17.5}/CLAUDE.md +0 -0
  103. {basic_memory-0.17.4 → basic_memory-0.17.5}/CODE_OF_CONDUCT.md +0 -0
  104. {basic_memory-0.17.4 → basic_memory-0.17.5}/CONTRIBUTING.md +0 -0
  105. {basic_memory-0.17.4 → basic_memory-0.17.5}/Dockerfile +0 -0
  106. {basic_memory-0.17.4 → basic_memory-0.17.5}/LICENSE +0 -0
  107. {basic_memory-0.17.4 → basic_memory-0.17.5}/README.md +0 -0
  108. {basic_memory-0.17.4 → basic_memory-0.17.5}/SECURITY.md +0 -0
  109. {basic_memory-0.17.4 → basic_memory-0.17.5}/docker-compose-postgres.yml +0 -0
  110. {basic_memory-0.17.4 → basic_memory-0.17.5}/docker-compose.yml +0 -0
  111. {basic_memory-0.17.4 → basic_memory-0.17.5}/docs/ARCHITECTURE.md +0 -0
  112. {basic_memory-0.17.4 → basic_memory-0.17.5}/docs/Docker.md +0 -0
  113. {basic_memory-0.17.4 → basic_memory-0.17.5}/docs/ai-assistant-guide-extended.md +0 -0
  114. {basic_memory-0.17.4 → basic_memory-0.17.5}/docs/character-handling.md +0 -0
  115. {basic_memory-0.17.4 → basic_memory-0.17.5}/docs/cloud-cli.md +0 -0
  116. {basic_memory-0.17.4 → basic_memory-0.17.5}/docs/testing-coverage.md +0 -0
  117. {basic_memory-0.17.4 → basic_memory-0.17.5}/justfile +0 -0
  118. {basic_memory-0.17.4 → basic_memory-0.17.5}/llms-install.md +0 -0
  119. {basic_memory-0.17.4 → basic_memory-0.17.5}/smithery.yaml +0 -0
  120. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-1 Specification-Driven Development Process.md +0 -0
  121. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-10 Unified Deployment Workflow and Event Tracking.md +0 -0
  122. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-11 Basic Memory API Performance Optimization.md +0 -0
  123. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-12 OpenTelemetry Observability.md +0 -0
  124. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-13 CLI Authentication with Subscription Validation.md +0 -0
  125. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-14 Cloud Git Versioning & GitHub Backup.md +0 -0
  126. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-14- Cloud Git Versioning & GitHub Backup.md +0 -0
  127. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-15 Configuration Persistence via Tigris for Cloud Tenants.md +0 -0
  128. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-16 MCP Cloud Service Consolidation.md +0 -0
  129. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-17 Semantic Search with ChromaDB.md +0 -0
  130. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-18 AI Memory Management Tool.md +0 -0
  131. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-19 Sync Performance and Memory Optimization.md +0 -0
  132. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-2 Slash Commands Reference.md +0 -0
  133. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-20 Simplified Project-Scoped Rclone Sync.md +0 -0
  134. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-3 Agent Definitions.md +0 -0
  135. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-4 Notes Web UI Component Architecture.md +0 -0
  136. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-5 CLI Cloud Upload via WebDAV.md +0 -0
  137. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-6 Explicit Project Parameter Architecture.md +0 -0
  138. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-7 POC to spike Tigris Turso for local access to cloud data.md +0 -0
  139. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-8 TigrisFS Integration.md +0 -0
  140. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-9 Multi-Project Bidirectional Sync Architecture.md +0 -0
  141. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-9 Signed Header Tenant Information.md +0 -0
  142. {basic_memory-0.17.4 → basic_memory-0.17.5}/specs/SPEC-9-1 Follow-Ups- Conflict, Sync, and Observability.md +0 -0
  143. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/alembic.ini +0 -0
  144. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/migrations.py +0 -0
  145. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/script.py.mako +0 -0
  146. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/314f1ea54dc4_add_postgres_full_text_search_support_.py +0 -0
  147. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +0 -0
  148. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +0 -0
  149. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +0 -0
  150. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +0 -0
  151. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/9d9c1cb7d8f5_add_mtime_and_size_columns_to_entity_.py +0 -0
  152. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +0 -0
  153. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/a2b3c4d5e6f7_add_search_index_entity_cascade.py +0 -0
  154. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +0 -0
  155. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +0 -0
  156. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/e7e1f4367280_add_scan_watermark_tracking_to_project.py +0 -0
  157. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/f8a9b2c3d4e5_add_pg_trgm_for_fuzzy_link_resolution.py +0 -0
  158. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/alembic/versions/g9a0b3c4d5e6_add_external_id_to_project_and_entity.py +0 -0
  159. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/__init__.py +0 -0
  160. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/app.py +0 -0
  161. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/container.py +0 -0
  162. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/routers/__init__.py +0 -0
  163. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/routers/directory_router.py +0 -0
  164. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/routers/importer_router.py +0 -0
  165. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/routers/knowledge_router.py +0 -0
  166. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/routers/management_router.py +0 -0
  167. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/routers/memory_router.py +0 -0
  168. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/routers/project_router.py +0 -0
  169. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/routers/prompt_router.py +0 -0
  170. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/routers/resource_router.py +0 -0
  171. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/routers/search_router.py +0 -0
  172. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/routers/utils.py +0 -0
  173. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/template_loader.py +0 -0
  174. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/v2/__init__.py +0 -0
  175. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/__init__.py +0 -0
  176. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/directory_router.py +0 -0
  177. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/importer_router.py +0 -0
  178. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/memory_router.py +0 -0
  179. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/prompt_router.py +0 -0
  180. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/resource_router.py +0 -0
  181. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/api/v2/routers/search_router.py +0 -0
  182. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/__init__.py +0 -0
  183. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/app.py +0 -0
  184. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/auth.py +0 -0
  185. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/__init__.py +0 -0
  186. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/__init__.py +0 -0
  187. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/api_client.py +0 -0
  188. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/bisync_commands.py +0 -0
  189. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/cloud_utils.py +0 -0
  190. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/rclone_config.py +0 -0
  191. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/rclone_installer.py +0 -0
  192. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/cloud/upload.py +0 -0
  193. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/mcp.py +0 -0
  194. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/status.py +0 -0
  195. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/commands/telemetry.py +0 -0
  196. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/container.py +0 -0
  197. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/cli/main.py +0 -0
  198. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/config.py +0 -0
  199. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/db.py +0 -0
  200. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/deps/__init__.py +0 -0
  201. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/deps/config.py +0 -0
  202. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/deps/db.py +0 -0
  203. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/deps/importers.py +0 -0
  204. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/deps.py +0 -0
  205. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/file_utils.py +0 -0
  206. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/ignore_utils.py +0 -0
  207. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/importers/__init__.py +0 -0
  208. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/importers/base.py +0 -0
  209. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/importers/chatgpt_importer.py +0 -0
  210. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/importers/claude_conversations_importer.py +0 -0
  211. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/importers/claude_projects_importer.py +0 -0
  212. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/importers/memory_json_importer.py +0 -0
  213. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/importers/utils.py +0 -0
  214. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/markdown/__init__.py +0 -0
  215. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/markdown/entity_parser.py +0 -0
  216. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/markdown/markdown_processor.py +0 -0
  217. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/markdown/plugins.py +0 -0
  218. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/markdown/schemas.py +0 -0
  219. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/markdown/utils.py +0 -0
  220. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/__init__.py +0 -0
  221. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/async_client.py +0 -0
  222. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/clients/__init__.py +0 -0
  223. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/clients/directory.py +0 -0
  224. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/clients/knowledge.py +0 -0
  225. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/clients/memory.py +0 -0
  226. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/clients/project.py +0 -0
  227. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/clients/resource.py +0 -0
  228. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/clients/search.py +0 -0
  229. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/project_context.py +0 -0
  230. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/prompts/__init__.py +0 -0
  231. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/prompts/ai_assistant_guide.py +0 -0
  232. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/prompts/continue_conversation.py +0 -0
  233. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/prompts/recent_activity.py +0 -0
  234. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/prompts/search.py +0 -0
  235. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/prompts/utils.py +0 -0
  236. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/resources/ai_assistant_guide.md +0 -0
  237. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/resources/project_info.py +0 -0
  238. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/server.py +0 -0
  239. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/__init__.py +0 -0
  240. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/build_context.py +0 -0
  241. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/chatgpt_tools.py +0 -0
  242. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/delete_note.py +0 -0
  243. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/edit_note.py +0 -0
  244. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/list_directory.py +0 -0
  245. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/move_note.py +0 -0
  246. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/project_management.py +0 -0
  247. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/read_note.py +0 -0
  248. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/search.py +0 -0
  249. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/mcp/tools/view_note.py +0 -0
  250. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/models/__init__.py +0 -0
  251. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/models/base.py +0 -0
  252. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/models/search.py +0 -0
  253. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/project_resolver.py +0 -0
  254. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/repository/__init__.py +0 -0
  255. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/repository/observation_repository.py +0 -0
  256. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/repository/postgres_search_repository.py +0 -0
  257. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/repository/project_info_repository.py +0 -0
  258. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/repository/project_repository.py +0 -0
  259. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/repository/search_index_row.py +0 -0
  260. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/repository/search_repository.py +0 -0
  261. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/repository/search_repository_base.py +0 -0
  262. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/repository/sqlite_search_repository.py +0 -0
  263. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/schemas/__init__.py +0 -0
  264. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/schemas/base.py +0 -0
  265. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/schemas/cloud.py +0 -0
  266. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/schemas/delete.py +0 -0
  267. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/schemas/directory.py +0 -0
  268. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/schemas/importer.py +0 -0
  269. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/schemas/memory.py +0 -0
  270. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/schemas/project_info.py +0 -0
  271. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/schemas/prompt.py +0 -0
  272. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/schemas/request.py +0 -0
  273. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/schemas/response.py +0 -0
  274. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/schemas/search.py +0 -0
  275. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/schemas/sync_report.py +0 -0
  276. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/schemas/v2/__init__.py +0 -0
  277. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/schemas/v2/entity.py +0 -0
  278. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/schemas/v2/resource.py +0 -0
  279. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/services/__init__.py +0 -0
  280. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/services/directory_service.py +0 -0
  281. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/services/entity_service.py +0 -0
  282. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/services/exceptions.py +0 -0
  283. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/services/file_service.py +0 -0
  284. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/services/initialization.py +0 -0
  285. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/services/link_resolver.py +0 -0
  286. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/services/project_service.py +0 -0
  287. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/services/search_service.py +0 -0
  288. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/services/service.py +0 -0
  289. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/sync/__init__.py +0 -0
  290. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/sync/background_sync.py +0 -0
  291. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/sync/coordinator.py +0 -0
  292. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/sync/watch_service.py +0 -0
  293. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/templates/prompts/continue_conversation.hbs +0 -0
  294. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/templates/prompts/search.hbs +0 -0
  295. {basic_memory-0.17.4 → basic_memory-0.17.5}/src/basic_memory/utils.py +0 -0
  296. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/BENCHMARKS.md +0 -0
  297. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/cli/test_project_commands_integration.py +0 -0
  298. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/cli/test_version_integration.py +0 -0
  299. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/conftest.py +0 -0
  300. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/mcp/test_build_context_underscore.py +0 -0
  301. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/mcp/test_build_context_validation.py +0 -0
  302. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/mcp/test_chatgpt_tools_integration.py +0 -0
  303. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/mcp/test_default_project_mode_integration.py +0 -0
  304. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/mcp/test_delete_note_integration.py +0 -0
  305. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/mcp/test_edit_note_integration.py +0 -0
  306. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/mcp/test_list_directory_integration.py +0 -0
  307. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/mcp/test_move_note_integration.py +0 -0
  308. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/mcp/test_project_management_integration.py +0 -0
  309. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/mcp/test_project_state_sync_integration.py +0 -0
  310. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/mcp/test_read_content_integration.py +0 -0
  311. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/mcp/test_read_note_integration.py +0 -0
  312. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/mcp/test_search_integration.py +0 -0
  313. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/mcp/test_single_project_mcp_integration.py +0 -0
  314. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/mcp/test_write_note_integration.py +0 -0
  315. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/test_db_wal_mode.py +0 -0
  316. {basic_memory-0.17.4 → basic_memory-0.17.5}/test-int/test_disable_permalinks_integration.py +0 -0
  317. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/Non-MarkdownFileSupport.pdf +0 -0
  318. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/README.md +0 -0
  319. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/Screenshot.png +0 -0
  320. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/__init__.py +0 -0
  321. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/conftest.py +0 -0
  322. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/test_api_container.py +0 -0
  323. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/test_async_client.py +0 -0
  324. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/test_continue_conversation_template.py +0 -0
  325. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/test_importer_router.py +0 -0
  326. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/test_knowledge_router.py +0 -0
  327. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/test_memory_router.py +0 -0
  328. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/test_project_router_operations.py +0 -0
  329. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/test_prompt_router.py +0 -0
  330. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/test_resource_router.py +0 -0
  331. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/test_search_router.py +0 -0
  332. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/test_search_template.py +0 -0
  333. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/test_template_loader.py +0 -0
  334. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/test_template_loader_helpers.py +0 -0
  335. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/v2/__init__.py +0 -0
  336. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/v2/conftest.py +0 -0
  337. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/v2/test_directory_router.py +0 -0
  338. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/v2/test_importer_router.py +0 -0
  339. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/v2/test_memory_router.py +0 -0
  340. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/v2/test_prompt_router.py +0 -0
  341. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/v2/test_resource_router.py +0 -0
  342. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/api/v2/test_search_router.py +0 -0
  343. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/cli/conftest.py +0 -0
  344. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/cli/test_cli_container.py +0 -0
  345. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/cli/test_cli_exit.py +0 -0
  346. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/cli/test_ignore_utils.py +0 -0
  347. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/cli/test_import_chatgpt.py +0 -0
  348. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/cli/test_import_claude_conversations.py +0 -0
  349. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/cli/test_import_claude_projects.py +0 -0
  350. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/cli/test_import_memory_json.py +0 -0
  351. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/cli/test_project_add_with_local_path.py +0 -0
  352. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/cli/test_upload.py +0 -0
  353. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/conftest.py +0 -0
  354. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/db/test_issue_254_foreign_key_constraints.py +0 -0
  355. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/importers/test_conversation_indexing.py +0 -0
  356. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/importers/test_importer_base.py +0 -0
  357. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/importers/test_importer_utils.py +0 -0
  358. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/markdown/__init__.py +0 -0
  359. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/markdown/test_date_frontmatter_parsing.py +0 -0
  360. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/markdown/test_entity_parser.py +0 -0
  361. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/markdown/test_entity_parser_error_handling.py +0 -0
  362. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/markdown/test_markdown_plugins.py +0 -0
  363. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/markdown/test_markdown_processor.py +0 -0
  364. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/markdown/test_observation_edge_cases.py +0 -0
  365. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/markdown/test_parser_edge_cases.py +0 -0
  366. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/markdown/test_relation_edge_cases.py +0 -0
  367. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/markdown/test_task_detection.py +0 -0
  368. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/clients/__init__.py +0 -0
  369. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/conftest.py +0 -0
  370. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_mcp_container.py +0 -0
  371. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_obsidian_yaml_formatting.py +0 -0
  372. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_permalink_collision_file_overwrite.py +0 -0
  373. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_prompts.py +0 -0
  374. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_resources.py +0 -0
  375. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_tool_build_context.py +0 -0
  376. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_tool_canvas.py +0 -0
  377. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_tool_delete_note.py +0 -0
  378. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_tool_edit_note.py +0 -0
  379. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_tool_list_directory.py +0 -0
  380. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_tool_read_note.py +0 -0
  381. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_tool_resource.py +0 -0
  382. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_tool_search.py +0 -0
  383. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_tool_utils.py +0 -0
  384. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_tool_view_note.py +0 -0
  385. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_tool_write_note.py +0 -0
  386. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/test_tool_write_note_kebab_filenames.py +0 -0
  387. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/mcp/tools/test_chatgpt_tools.py +0 -0
  388. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/repository/test_entity_repository.py +0 -0
  389. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/repository/test_entity_repository_upsert.py +0 -0
  390. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/repository/test_entity_upsert_issue_187.py +0 -0
  391. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/repository/test_observation_repository.py +0 -0
  392. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/repository/test_project_info_repository.py +0 -0
  393. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/repository/test_project_repository.py +0 -0
  394. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/repository/test_relation_repository.py +0 -0
  395. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/repository/test_repository.py +0 -0
  396. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/repository/test_search_repository.py +0 -0
  397. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/repository/test_search_repository_edit_bug_fix.py +0 -0
  398. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/schemas/test_base_timeframe_minimum.py +0 -0
  399. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/schemas/test_memory_serialization.py +0 -0
  400. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/schemas/test_memory_url.py +0 -0
  401. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/schemas/test_memory_url_validation.py +0 -0
  402. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/schemas/test_schemas.py +0 -0
  403. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/schemas/test_search.py +0 -0
  404. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/services/test_context_service.py +0 -0
  405. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/services/test_directory_service.py +0 -0
  406. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/services/test_entity_service.py +0 -0
  407. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/services/test_entity_service_disable_permalinks.py +0 -0
  408. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/services/test_file_service.py +0 -0
  409. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/services/test_link_resolver.py +0 -0
  410. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/services/test_project_removal_bug.py +0 -0
  411. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/services/test_project_service.py +0 -0
  412. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/services/test_search_service.py +0 -0
  413. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/sync/test_character_conflicts.py +0 -0
  414. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/sync/test_coordinator.py +0 -0
  415. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/sync/test_sync_service.py +0 -0
  416. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/sync/test_sync_service_incremental.py +0 -0
  417. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/sync/test_sync_wikilink_issue.py +0 -0
  418. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/sync/test_tmp_files.py +0 -0
  419. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/sync/test_watch_service.py +0 -0
  420. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/sync/test_watch_service_edge_cases.py +0 -0
  421. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/test_config.py +0 -0
  422. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/test_deps.py +0 -0
  423. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/test_production_cascade_delete.py +0 -0
  424. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/test_project_resolver.py +0 -0
  425. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/utils/test_file_utils.py +0 -0
  426. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/utils/test_frontmatter_obsidian_compatible.py +0 -0
  427. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/utils/test_parse_tags.py +0 -0
  428. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/utils/test_permalink_formatting.py +0 -0
  429. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/utils/test_timezone_utils.py +0 -0
  430. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/utils/test_utf8_handling.py +0 -0
  431. {basic_memory-0.17.4 → basic_memory-0.17.5}/tests/utils/test_validate_project_path.py +0 -0
@@ -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,16 @@
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
+
3
14
  ## v0.17.4 (2026-01-05)
4
15
 
5
16
  ### Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basic-memory
3
- Version: 0.17.4
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
@@ -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.4"
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
 
@@ -414,9 +414,7 @@ async def move_entity(
414
414
 
415
415
  result = EntityResponseV2.model_validate(moved_entity)
416
416
 
417
- logger.info(
418
- f"API v2 response: moved external_id={entity_id} to '{data.destination_path}'"
419
- )
417
+ logger.info(f"API v2 response: moved external_id={entity_id} to '{data.destination_path}'")
420
418
 
421
419
  return result
422
420
 
@@ -264,9 +264,7 @@ async def delete_project_by_id(
264
264
  # Use is_default from database, not ConfigManager (which doesn't work in cloud mode)
265
265
  if old_project.is_default:
266
266
  available_projects = await project_service.list_projects()
267
- other_projects = [
268
- p.name for p in available_projects if p.external_id != project_id
269
- ]
267
+ other_projects = [p.name for p in available_projects if p.external_id != project_id]
270
268
  detail = f"Cannot delete default project '{old_project.name}'. "
271
269
  if other_projects:
272
270
  detail += ( # pragma: no cover
@@ -1,11 +1,10 @@
1
1
  """Core cloud commands for Basic Memory CLI."""
2
2
 
3
- import asyncio
4
-
5
3
  import typer
6
4
  from rich.console import Console
7
5
 
8
6
  from basic_memory.cli.app import cloud_app
7
+ from basic_memory.cli.commands.command_utils import run_with_cleanup
9
8
  from basic_memory.cli.auth import CLIAuth
10
9
  from basic_memory.config import ConfigManager
11
10
  from basic_memory.cli.commands.cloud.api_client import (
@@ -64,7 +63,7 @@ def login():
64
63
  )
65
64
  raise typer.Exit(1)
66
65
 
67
- asyncio.run(_login())
66
+ run_with_cleanup(_login())
68
67
 
69
68
 
70
69
  @cloud_app.command()
@@ -110,7 +109,7 @@ def status() -> None:
110
109
  console.print("\n[blue]Checking cloud instance health...[/blue]")
111
110
 
112
111
  # Make API request to check health
113
- response = asyncio.run(
112
+ response = run_with_cleanup(
114
113
  make_api_request(method="GET", url=f"{host_url}/proxy/health", headers=headers)
115
114
  )
116
115
 
@@ -156,12 +155,12 @@ def setup() -> None:
156
155
 
157
156
  # Step 2: Get tenant info
158
157
  console.print("\n[blue]Step 2: Getting tenant information...[/blue]")
159
- tenant_info = asyncio.run(get_mount_info())
158
+ tenant_info = run_with_cleanup(get_mount_info())
160
159
  console.print(f"[green]Found tenant: {tenant_info.tenant_id}[/green]")
161
160
 
162
161
  # Step 3: Generate credentials
163
162
  console.print("\n[blue]Step 3: Generating sync credentials...[/blue]")
164
- creds = asyncio.run(generate_mount_credentials(tenant_info.tenant_id))
163
+ creds = run_with_cleanup(generate_mount_credentials(tenant_info.tenant_id))
165
164
  console.print("[green]Generated secure credentials[/green]")
166
165
 
167
166
  # Step 4: Configure rclone remote
@@ -27,6 +27,7 @@ console = Console()
27
27
  # Minimum rclone version for --create-empty-src-dirs support
28
28
  MIN_RCLONE_VERSION_EMPTY_DIRS = (1, 64, 0)
29
29
 
30
+
30
31
  class RunResult(Protocol):
31
32
  returncode: int
32
33
  stdout: str
@@ -1,12 +1,12 @@
1
1
  """Upload CLI commands for basic-memory projects."""
2
2
 
3
- import asyncio
4
3
  from pathlib import Path
5
4
 
6
5
  import typer
7
6
  from rich.console import Console
8
7
 
9
8
  from basic_memory.cli.app import cloud_app
9
+ from basic_memory.cli.commands.command_utils import run_with_cleanup
10
10
  from basic_memory.cli.commands.cloud.cloud_utils import (
11
11
  create_cloud_project,
12
12
  project_exists,
@@ -121,4 +121,4 @@ def upload(
121
121
  console.print(f"[yellow]Warning: Sync failed: {e}[/yellow]")
122
122
  console.print("[dim]Files uploaded but may not be indexed yet[/dim]")
123
123
 
124
- asyncio.run(_upload())
124
+ run_with_cleanup(_upload())
@@ -14,6 +14,7 @@ from basic_memory.mcp.async_client import get_client
14
14
  from basic_memory.mcp.tools.utils import call_post, call_get
15
15
  from basic_memory.mcp.project_context import get_active_project
16
16
  from basic_memory.schemas import ProjectInfoResponse
17
+ from basic_memory.telemetry import shutdown_telemetry
17
18
 
18
19
  console = Console()
19
20
 
@@ -23,8 +24,8 @@ T = TypeVar("T")
23
24
  def run_with_cleanup(coro: Coroutine[Any, Any, T]) -> T:
24
25
  """Run an async coroutine with proper database cleanup.
25
26
 
26
- This helper ensures database connections are cleaned up before the event
27
- loop closes, preventing process hangs in CLI commands.
27
+ This helper ensures database connections and telemetry threads are cleaned up
28
+ before the event loop closes, preventing process hangs in CLI commands.
28
29
 
29
30
  Args:
30
31
  coro: The coroutine to run
@@ -38,6 +39,9 @@ def run_with_cleanup(coro: Coroutine[Any, Any, T]) -> T:
38
39
  return await coro
39
40
  finally:
40
41
  await db.shutdown_db()
42
+ # Shutdown telemetry to stop the OpenPanel background thread
43
+ # This prevents hangs on Python 3.14+ during thread shutdown
44
+ shutdown_telemetry()
41
45
 
42
46
  return asyncio.run(_with_cleanup())
43
47
 
@@ -1,6 +1,5 @@
1
1
  """Database management commands."""
2
2
 
3
- import asyncio
4
3
  from pathlib import Path
5
4
 
6
5
  import typer
@@ -10,6 +9,7 @@ from sqlalchemy.exc import OperationalError
10
9
 
11
10
  from basic_memory import db
12
11
  from basic_memory.cli.app import app
12
+ from basic_memory.cli.commands.command_utils import run_with_cleanup
13
13
  from basic_memory.config import ConfigManager
14
14
  from basic_memory.repository import ProjectRepository
15
15
  from basic_memory.services.initialization import reconcile_projects_with_config
@@ -81,7 +81,7 @@ def reset(
81
81
 
82
82
  # Create a new empty database (preserves project configuration)
83
83
  try:
84
- asyncio.run(db.run_migrations(app_config))
84
+ run_with_cleanup(db.run_migrations(app_config))
85
85
  except OperationalError as e:
86
86
  if "disk I/O error" in str(e) or "database is locked" in str(e):
87
87
  console.print(
@@ -99,5 +99,7 @@ def reset(
99
99
  console.print("[yellow]No projects configured. Skipping reindex.[/yellow]")
100
100
  else:
101
101
  console.print(f"Rebuilding search index for {len(projects)} project(s)...")
102
- asyncio.run(_reindex_projects(app_config))
102
+ # Note: _reindex_projects has its own cleanup, but run_with_cleanup
103
+ # ensures db.shutdown_db() is called even if _reindex_projects changes
104
+ run_with_cleanup(_reindex_projects(app_config))
103
105
  console.print("[green]Reindex complete[/green]")
@@ -1,6 +1,5 @@
1
1
  """Format command for basic-memory CLI."""
2
2
 
3
- import asyncio
4
3
  from pathlib import Path
5
4
  from typing import Annotated, Optional
6
5
 
@@ -10,6 +9,7 @@ from rich.console import Console
10
9
  from rich.progress import Progress, SpinnerColumn, TextColumn
11
10
 
12
11
  from basic_memory.cli.app import app
12
+ from basic_memory.cli.commands.command_utils import run_with_cleanup
13
13
  from basic_memory.config import ConfigManager, get_project_config
14
14
  from basic_memory.file_utils import format_file
15
15
 
@@ -189,7 +189,7 @@ def format(
189
189
  basic-memory format notes/ # Format all files in directory
190
190
  """
191
191
  try:
192
- asyncio.run(run_format(path, project))
192
+ run_with_cleanup(run_format(path, project))
193
193
  except Exception as e:
194
194
  if not isinstance(e, typer.Exit):
195
195
  logger.error(f"Error formatting files: {e}")
@@ -1,12 +1,12 @@
1
1
  """Import command for ChatGPT conversations."""
2
2
 
3
- import asyncio
4
3
  import json
5
4
  from pathlib import Path
6
5
  from typing import Annotated, Tuple
7
6
 
8
7
  import typer
9
8
  from basic_memory.cli.app import import_app
9
+ from basic_memory.cli.commands.command_utils import run_with_cleanup
10
10
  from basic_memory.config import ConfigManager, get_project_config
11
11
  from basic_memory.importers import ChatGPTImporter
12
12
  from basic_memory.markdown import EntityParser, MarkdownProcessor
@@ -53,7 +53,7 @@ def import_chatgpt(
53
53
  raise typer.Exit(1)
54
54
 
55
55
  # Get importer dependencies
56
- markdown_processor, file_service = asyncio.run(get_importer_dependencies())
56
+ markdown_processor, file_service = run_with_cleanup(get_importer_dependencies())
57
57
  config = get_project_config()
58
58
  # Process the file
59
59
  base_path = config.home / folder
@@ -63,7 +63,7 @@ def import_chatgpt(
63
63
  importer = ChatGPTImporter(config.home, markdown_processor, file_service)
64
64
  with conversations_json.open("r", encoding="utf-8") as file:
65
65
  json_data = json.load(file)
66
- result = asyncio.run(importer.import_data(json_data, folder))
66
+ result = run_with_cleanup(importer.import_data(json_data, folder))
67
67
 
68
68
  if not result.success: # pragma: no cover
69
69
  typer.echo(f"Error during import: {result.error_message}", err=True)
@@ -1,12 +1,12 @@
1
1
  """Import command for basic-memory CLI to import chat data from conversations2.json format."""
2
2
 
3
- import asyncio
4
3
  import json
5
4
  from pathlib import Path
6
5
  from typing import Annotated, Tuple
7
6
 
8
7
  import typer
9
8
  from basic_memory.cli.app import claude_app
9
+ from basic_memory.cli.commands.command_utils import run_with_cleanup
10
10
  from basic_memory.config import ConfigManager, get_project_config
11
11
  from basic_memory.importers.claude_conversations_importer import ClaudeConversationsImporter
12
12
  from basic_memory.markdown import EntityParser, MarkdownProcessor
@@ -54,7 +54,7 @@ def import_claude(
54
54
  raise typer.Exit(1)
55
55
 
56
56
  # Get importer dependencies
57
- markdown_processor, file_service = asyncio.run(get_importer_dependencies())
57
+ markdown_processor, file_service = run_with_cleanup(get_importer_dependencies())
58
58
 
59
59
  # Create the importer
60
60
  importer = ClaudeConversationsImporter(config.home, markdown_processor, file_service)
@@ -66,7 +66,7 @@ def import_claude(
66
66
  # Run the import
67
67
  with conversations_json.open("r", encoding="utf-8") as file:
68
68
  json_data = json.load(file)
69
- result = asyncio.run(importer.import_data(json_data, folder))
69
+ result = run_with_cleanup(importer.import_data(json_data, folder))
70
70
 
71
71
  if not result.success: # pragma: no cover
72
72
  typer.echo(f"Error during import: {result.error_message}", err=True)
@@ -1,12 +1,12 @@
1
1
  """Import command for basic-memory CLI to import project data from Claude.ai."""
2
2
 
3
- import asyncio
4
3
  import json
5
4
  from pathlib import Path
6
5
  from typing import Annotated, Tuple
7
6
 
8
7
  import typer
9
8
  from basic_memory.cli.app import claude_app
9
+ from basic_memory.cli.commands.command_utils import run_with_cleanup
10
10
  from basic_memory.config import ConfigManager, get_project_config
11
11
  from basic_memory.importers.claude_projects_importer import ClaudeProjectsImporter
12
12
  from basic_memory.markdown import EntityParser, MarkdownProcessor
@@ -53,7 +53,7 @@ def import_projects(
53
53
  raise typer.Exit(1)
54
54
 
55
55
  # Get importer dependencies
56
- markdown_processor, file_service = asyncio.run(get_importer_dependencies())
56
+ markdown_processor, file_service = run_with_cleanup(get_importer_dependencies())
57
57
 
58
58
  # Create the importer
59
59
  importer = ClaudeProjectsImporter(config.home, markdown_processor, file_service)
@@ -65,7 +65,7 @@ def import_projects(
65
65
  # Run the import
66
66
  with projects_json.open("r", encoding="utf-8") as file:
67
67
  json_data = json.load(file)
68
- result = asyncio.run(importer.import_data(json_data, base_folder))
68
+ result = run_with_cleanup(importer.import_data(json_data, base_folder))
69
69
 
70
70
  if not result.success: # pragma: no cover
71
71
  typer.echo(f"Error during import: {result.error_message}", err=True)
@@ -1,12 +1,12 @@
1
1
  """Import command for basic-memory CLI to import from JSON memory format."""
2
2
 
3
- import asyncio
4
3
  import json
5
4
  from pathlib import Path
6
5
  from typing import Annotated, Tuple
7
6
 
8
7
  import typer
9
8
  from basic_memory.cli.app import import_app
9
+ from basic_memory.cli.commands.command_utils import run_with_cleanup
10
10
  from basic_memory.config import ConfigManager, get_project_config
11
11
  from basic_memory.importers.memory_json_importer import MemoryJsonImporter
12
12
  from basic_memory.markdown import EntityParser, MarkdownProcessor
@@ -52,7 +52,7 @@ def memory_json(
52
52
  config = get_project_config()
53
53
  try:
54
54
  # Get importer dependencies
55
- markdown_processor, file_service = asyncio.run(get_importer_dependencies())
55
+ markdown_processor, file_service = run_with_cleanup(get_importer_dependencies())
56
56
 
57
57
  # Create the importer
58
58
  importer = MemoryJsonImporter(config.home, markdown_processor, file_service)
@@ -67,7 +67,7 @@ def memory_json(
67
67
  for line in file:
68
68
  json_data = json.loads(line)
69
69
  file_data.append(json_data)
70
- result = asyncio.run(importer.import_data(file_data, destination_folder))
70
+ result = run_with_cleanup(importer.import_data(file_data, destination_folder))
71
71
 
72
72
  if not result.success: # pragma: no cover
73
73
  typer.echo(f"Error during import: {result.error_message}", err=True)
@@ -1,6 +1,5 @@
1
1
  """Command module for basic-memory project management."""
2
2
 
3
- import asyncio
4
3
  import os
5
4
  from pathlib import Path
6
5
 
@@ -9,7 +8,7 @@ from rich.console import Console
9
8
  from rich.table import Table
10
9
 
11
10
  from basic_memory.cli.app import app
12
- from basic_memory.cli.commands.command_utils import get_project_info
11
+ from basic_memory.cli.commands.command_utils import get_project_info, run_with_cleanup
13
12
  from basic_memory.config import ConfigManager
14
13
  import json
15
14
  from datetime import datetime
@@ -56,7 +55,7 @@ def list_projects() -> None:
56
55
  return ProjectList.model_validate(response.json())
57
56
 
58
57
  try:
59
- result = asyncio.run(_list_projects())
58
+ result = run_with_cleanup(_list_projects())
60
59
  config = ConfigManager().config
61
60
 
62
61
  table = Table(title="Basic Memory Projects")
@@ -155,7 +154,7 @@ def add_project(
155
154
  return ProjectStatusResponse.model_validate(response.json())
156
155
 
157
156
  try:
158
- result = asyncio.run(_add_project())
157
+ result = run_with_cleanup(_add_project())
159
158
  console.print(f"[green]{result.message}[/green]")
160
159
 
161
160
  # Save local sync path to config if in cloud mode
@@ -212,7 +211,7 @@ def setup_project_sync(
212
211
 
213
212
  try:
214
213
  # Verify project exists on cloud
215
- asyncio.run(_verify_project_exists())
214
+ run_with_cleanup(_verify_project_exists())
216
215
 
217
216
  # Resolve and create local path
218
217
  resolved_path = Path(os.path.abspath(os.path.expanduser(local_path)))
@@ -279,7 +278,7 @@ def remove_project(
279
278
  has_bisync_state = bisync_state_path.exists()
280
279
 
281
280
  # Remove project from cloud/API
282
- result = asyncio.run(_remove_project())
281
+ result = run_with_cleanup(_remove_project())
283
282
  console.print(f"[green]{result.message}[/green]")
284
283
 
285
284
  # Clean up local sync directory if it exists and delete_notes is True
@@ -347,7 +346,7 @@ def set_default_project(
347
346
  return ProjectStatusResponse.model_validate(response.json())
348
347
 
349
348
  try:
350
- result = asyncio.run(_set_default())
349
+ result = run_with_cleanup(_set_default())
351
350
  console.print(f"[green]{result.message}[/green]")
352
351
  except Exception as e:
353
352
  console.print(f"[red]Error setting default project: {str(e)}[/red]")
@@ -372,7 +371,7 @@ def synchronize_projects() -> None:
372
371
  return ProjectStatusResponse.model_validate(response.json())
373
372
 
374
373
  try:
375
- result = asyncio.run(_sync_config())
374
+ result = run_with_cleanup(_sync_config())
376
375
  console.print(f"[green]{result.message}[/green]")
377
376
  except Exception as e: # pragma: no cover
378
377
  console.print(f"[red]Error synchronizing projects: {str(e)}[/red]")
@@ -407,7 +406,7 @@ def move_project(
407
406
  return ProjectStatusResponse.model_validate(response.json())
408
407
 
409
408
  try:
410
- result = asyncio.run(_move_project())
409
+ result = run_with_cleanup(_move_project())
411
410
  console.print(f"[green]{result.message}[/green]")
412
411
 
413
412
  # Show important file movement reminder
@@ -448,7 +447,7 @@ def sync_project_command(
448
447
 
449
448
  try:
450
449
  # Get tenant info for bucket name
451
- tenant_info = asyncio.run(get_mount_info())
450
+ tenant_info = run_with_cleanup(get_mount_info())
452
451
  bucket_name = tenant_info.bucket_name
453
452
 
454
453
  # Get project info
@@ -461,7 +460,7 @@ def sync_project_command(
461
460
  return proj
462
461
  return None
463
462
 
464
- project_data = asyncio.run(_get_project())
463
+ project_data = run_with_cleanup(_get_project())
465
464
  if not project_data:
466
465
  console.print(f"[red]Error: Project '{name}' not found[/red]")
467
466
  raise typer.Exit(1)
@@ -502,7 +501,7 @@ def sync_project_command(
502
501
  return response.json()
503
502
 
504
503
  try:
505
- result = asyncio.run(_trigger_db_sync())
504
+ result = run_with_cleanup(_trigger_db_sync())
506
505
  console.print(f"[dim]Database sync initiated: {result.get('message')}[/dim]")
507
506
  except Exception as e:
508
507
  console.print(f"[yellow]Warning: Could not trigger database sync: {e}[/yellow]")
@@ -539,7 +538,7 @@ def bisync_project_command(
539
538
 
540
539
  try:
541
540
  # Get tenant info for bucket name
542
- tenant_info = asyncio.run(get_mount_info())
541
+ tenant_info = run_with_cleanup(get_mount_info())
543
542
  bucket_name = tenant_info.bucket_name
544
543
 
545
544
  # Get project info
@@ -552,7 +551,7 @@ def bisync_project_command(
552
551
  return proj
553
552
  return None
554
553
 
555
- project_data = asyncio.run(_get_project())
554
+ project_data = run_with_cleanup(_get_project())
556
555
  if not project_data:
557
556
  console.print(f"[red]Error: Project '{name}' not found[/red]")
558
557
  raise typer.Exit(1)
@@ -600,7 +599,7 @@ def bisync_project_command(
600
599
  return response.json()
601
600
 
602
601
  try:
603
- result = asyncio.run(_trigger_db_sync())
602
+ result = run_with_cleanup(_trigger_db_sync())
604
603
  console.print(f"[dim]Database sync initiated: {result.get('message')}[/dim]")
605
604
  except Exception as e:
606
605
  console.print(f"[yellow]Warning: Could not trigger database sync: {e}[/yellow]")
@@ -633,7 +632,7 @@ def check_project_command(
633
632
 
634
633
  try:
635
634
  # Get tenant info for bucket name
636
- tenant_info = asyncio.run(get_mount_info())
635
+ tenant_info = run_with_cleanup(get_mount_info())
637
636
  bucket_name = tenant_info.bucket_name
638
637
 
639
638
  # Get project info
@@ -646,7 +645,7 @@ def check_project_command(
646
645
  return proj
647
646
  return None
648
647
 
649
- project_data = asyncio.run(_get_project())
648
+ project_data = run_with_cleanup(_get_project())
650
649
  if not project_data:
651
650
  console.print(f"[red]Error: Project '{name}' not found[/red]")
652
651
  raise typer.Exit(1)
@@ -734,7 +733,7 @@ def ls_project_command(
734
733
 
735
734
  try:
736
735
  # Get tenant info for bucket name
737
- tenant_info = asyncio.run(get_mount_info())
736
+ tenant_info = run_with_cleanup(get_mount_info())
738
737
  bucket_name = tenant_info.bucket_name
739
738
 
740
739
  # Get project info
@@ -747,7 +746,7 @@ def ls_project_command(
747
746
  return proj
748
747
  return None
749
748
 
750
- project_data = asyncio.run(_get_project())
749
+ project_data = run_with_cleanup(_get_project())
751
750
  if not project_data:
752
751
  console.print(f"[red]Error: Project '{name}' not found[/red]")
753
752
  raise typer.Exit(1)
@@ -784,7 +783,7 @@ def display_project_info(
784
783
  """Display detailed information and statistics about the current project."""
785
784
  try:
786
785
  # Get project info
787
- info = asyncio.run(get_project_info(name))
786
+ info = run_with_cleanup(get_project_info(name))
788
787
 
789
788
  if json_output:
790
789
  # Convert to JSON and print