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