basic-memory 0.16.3__tar.gz → 0.17.1__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.16.3 → basic_memory-0.17.1}/CHANGELOG.md +90 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/CLAUDE.md +75 -12
- {basic_memory-0.16.3 → basic_memory-0.17.1}/PKG-INFO +38 -1
- {basic_memory-0.16.3 → basic_memory-0.17.1}/README.md +33 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/justfile +12 -3
- {basic_memory-0.16.3 → basic_memory-0.17.1}/pyproject.toml +4 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/__init__.py +1 -1
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/alembic/env.py +6 -2
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/alembic/versions/f8a9b2c3d4e5_add_pg_trgm_for_fuzzy_link_resolution.py +116 -76
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/app.py +12 -4
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/routers/project_router.py +2 -2
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/v2/routers/knowledge_router.py +1 -3
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/v2/routers/project_router.py +79 -1
- basic_memory-0.17.1/src/basic_memory/cli/app.py +84 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/__init__.py +3 -1
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/cloud/rclone_commands.py +46 -1
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/command_utils.py +27 -1
- basic_memory-0.17.1/src/basic_memory/cli/commands/format.py +198 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/import_chatgpt.py +3 -2
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/import_claude_conversations.py +3 -2
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/import_claude_projects.py +3 -2
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/import_memory_json.py +3 -2
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/mcp.py +5 -25
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/project.py +22 -9
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/status.py +3 -2
- basic_memory-0.17.1/src/basic_memory/cli/commands/telemetry.py +81 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/main.py +7 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/config.py +50 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/db.py +16 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/deps.py +20 -8
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/file_utils.py +196 -3
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/importers/utils.py +5 -2
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/markdown/entity_parser.py +6 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/markdown/markdown_processor.py +22 -4
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/async_client.py +1 -0
- basic_memory-0.17.1/src/basic_memory/mcp/server.py +81 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/tools/build_context.py +3 -3
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/tools/canvas.py +34 -12
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/tools/chatgpt_tools.py +3 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/tools/delete_note.py +20 -3
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/tools/edit_note.py +7 -3
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/tools/list_directory.py +3 -2
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/tools/move_note.py +16 -10
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/tools/project_management.py +6 -5
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/tools/read_content.py +13 -3
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/tools/read_note.py +24 -12
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/tools/recent_activity.py +4 -4
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/tools/search.py +3 -2
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/tools/utils.py +28 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/tools/view_note.py +2 -1
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/tools/write_note.py +33 -10
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/repository/project_repository.py +13 -1
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/schemas/base.py +1 -1
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/schemas/v2/__init__.py +5 -1
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/schemas/v2/entity.py +34 -1
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/services/entity_service.py +8 -1
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/services/file_service.py +32 -5
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/services/initialization.py +43 -26
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/sync/sync_service.py +36 -2
- basic_memory-0.17.1/src/basic_memory/telemetry.py +249 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/utils.py +3 -1
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/conftest.py +9 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/mcp/test_lifespan_shutdown_sync_task_cancellation_integration.py +0 -2
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/mcp/test_project_management_integration.py +48 -22
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/mcp/test_project_state_sync_integration.py +2 -2
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/v2/test_knowledge_router.py +1 -1
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/v2/test_project_router.py +83 -0
- basic_memory-0.17.1/tests/cli/test_cli_exit.py +48 -0
- basic_memory-0.17.1/tests/cli/test_cli_tool_exit.py +85 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/cli/test_cli_tools.py +6 -6
- basic_memory-0.17.1/tests/importers/test_conversation_indexing.py +114 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/importers/test_importer_utils.py +3 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/markdown/test_entity_parser.py +8 -5
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_tool_move_note.py +15 -21
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_tool_read_content.py +124 -93
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_tool_read_note.py +17 -37
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_tool_view_note.py +18 -11
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/schemas/test_schemas.py +42 -0
- basic_memory-0.17.1/tests/services/test_initialization.py +122 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/sync/test_sync_service.py +62 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/test_config.py +113 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/test_rclone_commands.py +172 -6
- basic_memory-0.17.1/tests/test_telemetry.py +276 -0
- basic_memory-0.17.1/tests/utils/test_file_utils.py +550 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/uv.lock +135 -3
- basic_memory-0.16.3/.claude/agents/python-developer.md +0 -154
- basic_memory-0.16.3/.claude/agents/system-architect.md +0 -126
- basic_memory-0.16.3/src/basic_memory/cli/app.py +0 -57
- basic_memory-0.16.3/src/basic_memory/mcp/server.py +0 -9
- basic_memory-0.16.3/tests/services/test_initialization.py +0 -248
- basic_memory-0.16.3/tests/utils/test_file_utils.py +0 -216
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.claude/commands/release/beta.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.claude/commands/release/changelog.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.claude/commands/release/release-check.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.claude/commands/release/release.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.claude/commands/spec.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.claude/commands/test-live.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.claude/settings.json +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.dockerignore +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.env.example +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.github/dependabot.yml +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.github/workflows/claude-code-review.yml +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.github/workflows/claude-issue-triage.yml +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.github/workflows/claude.yml +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.github/workflows/dev-release.yml +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.github/workflows/docker.yml +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.github/workflows/pr-title.yml +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.github/workflows/release.yml +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.github/workflows/test.yml +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.gitignore +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/.python-version +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/CITATION.cff +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/CLA.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/CODE_OF_CONDUCT.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/CONTRIBUTING.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/Dockerfile +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/LICENSE +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/SECURITY.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/docker-compose-postgres.yml +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/docker-compose.yml +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/docs/Docker.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/docs/ai-assistant-guide-extended.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/docs/character-handling.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/docs/cloud-cli.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/llms-install.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/smithery.yaml +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-1 Specification-Driven Development Process.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-10 Unified Deployment Workflow and Event Tracking.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-11 Basic Memory API Performance Optimization.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-12 OpenTelemetry Observability.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-13 CLI Authentication with Subscription Validation.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-14 Cloud Git Versioning & GitHub Backup.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-14- Cloud Git Versioning & GitHub Backup.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-15 Configuration Persistence via Tigris for Cloud Tenants.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-16 MCP Cloud Service Consolidation.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-17 Semantic Search with ChromaDB.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-18 AI Memory Management Tool.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-19 Sync Performance and Memory Optimization.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-2 Slash Commands Reference.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-20 Simplified Project-Scoped Rclone Sync.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-3 Agent Definitions.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-4 Notes Web UI Component Architecture.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-5 CLI Cloud Upload via WebDAV.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-6 Explicit Project Parameter Architecture.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-7 POC to spike Tigris Turso for local access to cloud data.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-8 TigrisFS Integration.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-9 Multi-Project Bidirectional Sync Architecture.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-9 Signed Header Tenant Information.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/specs/SPEC-9-1 Follow-Ups- Conflict, Sync, and Observability.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/alembic/alembic.ini +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/alembic/migrations.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/alembic/script.py.mako +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/alembic/versions/314f1ea54dc4_add_postgres_full_text_search_support_.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/alembic/versions/9d9c1cb7d8f5_add_mtime_and_size_columns_to_entity_.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/alembic/versions/a2b3c4d5e6f7_add_search_index_entity_cascade.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/alembic/versions/e7e1f4367280_add_scan_watermark_tracking_to_project.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/routers/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/routers/directory_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/routers/importer_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/routers/knowledge_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/routers/management_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/routers/memory_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/routers/prompt_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/routers/resource_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/routers/search_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/routers/utils.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/template_loader.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/v2/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/v2/routers/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/v2/routers/directory_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/v2/routers/importer_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/v2/routers/memory_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/v2/routers/prompt_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/v2/routers/resource_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/api/v2/routers/search_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/auth.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/cloud/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/cloud/api_client.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/cloud/bisync_commands.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/cloud/cloud_utils.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/cloud/core_commands.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/cloud/rclone_config.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/cloud/rclone_installer.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/cloud/upload.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/cloud/upload_command.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/db.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/cli/commands/tool.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/ignore_utils.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/importers/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/importers/base.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/importers/chatgpt_importer.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/importers/claude_conversations_importer.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/importers/claude_projects_importer.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/importers/memory_json_importer.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/markdown/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/markdown/plugins.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/markdown/schemas.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/markdown/utils.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/project_context.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/prompts/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/prompts/ai_assistant_guide.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/prompts/continue_conversation.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/prompts/recent_activity.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/prompts/search.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/prompts/utils.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/resources/ai_assistant_guide.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/resources/project_info.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/mcp/tools/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/models/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/models/base.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/models/knowledge.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/models/project.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/models/search.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/repository/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/repository/entity_repository.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/repository/observation_repository.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/repository/postgres_search_repository.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/repository/project_info_repository.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/repository/relation_repository.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/repository/repository.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/repository/search_index_row.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/repository/search_repository.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/repository/search_repository_base.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/repository/sqlite_search_repository.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/schemas/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/schemas/cloud.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/schemas/delete.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/schemas/directory.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/schemas/importer.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/schemas/memory.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/schemas/project_info.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/schemas/prompt.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/schemas/request.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/schemas/response.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/schemas/search.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/schemas/sync_report.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/schemas/v2/resource.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/services/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/services/context_service.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/services/directory_service.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/services/exceptions.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/services/link_resolver.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/services/project_service.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/services/search_service.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/services/service.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/sync/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/sync/background_sync.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/sync/watch_service.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/templates/prompts/continue_conversation.hbs +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/src/basic_memory/templates/prompts/search.hbs +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/BENCHMARKS.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/cli/test_project_commands_integration.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/cli/test_version_integration.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/mcp/test_build_context_underscore.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/mcp/test_build_context_validation.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/mcp/test_chatgpt_tools_integration.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/mcp/test_default_project_mode_integration.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/mcp/test_delete_note_integration.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/mcp/test_edit_note_integration.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/mcp/test_list_directory_integration.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/mcp/test_move_note_integration.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/mcp/test_read_content_integration.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/mcp/test_read_note_integration.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/mcp/test_search_integration.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/mcp/test_single_project_mcp_integration.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/mcp/test_write_note_integration.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/test_db_wal_mode.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/test-int/test_disable_permalinks_integration.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/Non-MarkdownFileSupport.pdf +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/README.md +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/Screenshot.png +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/conftest.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/test_async_client.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/test_continue_conversation_template.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/test_directory_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/test_importer_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/test_knowledge_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/test_management_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/test_memory_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/test_project_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/test_project_router_operations.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/test_prompt_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/test_relation_background_resolution.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/test_resource_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/test_search_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/test_search_template.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/test_template_loader.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/test_template_loader_helpers.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/v2/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/v2/conftest.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/v2/test_directory_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/v2/test_importer_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/v2/test_memory_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/v2/test_prompt_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/v2/test_resource_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/api/v2/test_search_router.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/cli/conftest.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/cli/test_cloud_authentication.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/cli/test_ignore_utils.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/cli/test_import_chatgpt.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/cli/test_import_claude_conversations.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/cli/test_import_claude_projects.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/cli/test_import_memory_json.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/cli/test_project_add_with_local_path.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/cli/test_upload.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/conftest.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/db/test_issue_254_foreign_key_constraints.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/importers/test_importer_base.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/markdown/__init__.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/markdown/test_date_frontmatter_parsing.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/markdown/test_entity_parser_error_handling.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/markdown/test_markdown_plugins.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/markdown/test_markdown_processor.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/markdown/test_observation_edge_cases.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/markdown/test_parser_edge_cases.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/markdown/test_relation_edge_cases.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/markdown/test_task_detection.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/conftest.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_obsidian_yaml_formatting.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_permalink_collision_file_overwrite.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_prompts.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_resources.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_tool_build_context.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_tool_canvas.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_tool_delete_note.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_tool_edit_note.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_tool_list_directory.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_tool_recent_activity.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_tool_resource.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_tool_search.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_tool_utils.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_tool_write_note.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/test_tool_write_note_kebab_filenames.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/mcp/tools/test_chatgpt_tools.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/repository/test_entity_repository.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/repository/test_entity_repository_upsert.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/repository/test_entity_upsert_issue_187.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/repository/test_observation_repository.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/repository/test_project_info_repository.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/repository/test_project_repository.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/repository/test_relation_repository.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/repository/test_repository.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/repository/test_search_repository.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/repository/test_search_repository_edit_bug_fix.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/schemas/test_base_timeframe_minimum.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/schemas/test_memory_serialization.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/schemas/test_memory_url.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/schemas/test_memory_url_validation.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/schemas/test_search.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/services/test_context_service.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/services/test_directory_service.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/services/test_entity_service.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/services/test_entity_service_disable_permalinks.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/services/test_file_service.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/services/test_link_resolver.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/services/test_project_removal_bug.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/services/test_project_service.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/services/test_project_service_operations.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/services/test_search_service.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/sync/test_character_conflicts.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/sync/test_sync_service_incremental.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/sync/test_sync_wikilink_issue.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/sync/test_tmp_files.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/sync/test_watch_service.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/sync/test_watch_service_edge_cases.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/sync/test_watch_service_reload.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/test_deps.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/test_production_cascade_delete.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/utils/test_frontmatter_obsidian_compatible.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/utils/test_parse_tags.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/utils/test_permalink_formatting.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/utils/test_timezone_utils.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/utils/test_utf8_handling.py +0 -0
- {basic_memory-0.16.3 → basic_memory-0.17.1}/tests/utils/test_validate_project_path.py +0 -0
|
@@ -1,5 +1,95 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## v0.17.1 (2025-12-29)
|
|
4
|
+
|
|
5
|
+
### Bug Fixes
|
|
6
|
+
|
|
7
|
+
- **#482**: Only set BASIC_MEMORY_ENV=test during pytest runs
|
|
8
|
+
([`98fbd60`](https://github.com/basicmachines-co/basic-memory/commit/98fbd60))
|
|
9
|
+
- Fixes environment variable pollution affecting alembic migrations
|
|
10
|
+
- Test environment detection now scoped to pytest execution only
|
|
11
|
+
|
|
12
|
+
## v0.17.0 (2025-12-28)
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
- **#478**: Add anonymous usage telemetry with Homebrew-style opt-out
|
|
17
|
+
([`856737f`](https://github.com/basicmachines-co/basic-memory/commit/856737f))
|
|
18
|
+
- Privacy-respecting anonymous usage analytics
|
|
19
|
+
- Easy opt-out via `BASIC_MEMORY_NO_ANALYTICS=1` environment variable
|
|
20
|
+
- Helps improve Basic Memory based on real usage patterns
|
|
21
|
+
|
|
22
|
+
- **#474**: Add auto-format files on save with built-in Python formatter
|
|
23
|
+
([`1fd680c`](https://github.com/basicmachines-co/basic-memory/commit/1fd680c))
|
|
24
|
+
- Automatic markdown formatting on file save
|
|
25
|
+
- Built-in Python formatter for consistent code style
|
|
26
|
+
- Configurable formatting options
|
|
27
|
+
|
|
28
|
+
- **#447**: Complete Phase 2 of API v2 migration - MCP tools use v2 endpoints
|
|
29
|
+
([`1a74d85`](https://github.com/basicmachines-co/basic-memory/commit/1a74d85))
|
|
30
|
+
- All MCP tools now use optimized v2 API endpoints
|
|
31
|
+
- Improved performance for knowledge graph operations
|
|
32
|
+
- Foundation for future API enhancements
|
|
33
|
+
|
|
34
|
+
### Bug Fixes
|
|
35
|
+
|
|
36
|
+
- Fix UTF-8 BOM handling in frontmatter parsing
|
|
37
|
+
([`85684f8`](https://github.com/basicmachines-co/basic-memory/commit/85684f8))
|
|
38
|
+
- Handles files with UTF-8 byte order marks correctly
|
|
39
|
+
- Prevents frontmatter parsing failures
|
|
40
|
+
|
|
41
|
+
- **#475**: Handle null titles in ChatGPT import
|
|
42
|
+
([`14ce5a3`](https://github.com/basicmachines-co/basic-memory/commit/14ce5a3))
|
|
43
|
+
- Gracefully handles conversations without titles
|
|
44
|
+
- Improved import robustness
|
|
45
|
+
|
|
46
|
+
- Remove MaxLen constraint from observation content
|
|
47
|
+
([`45d6caf`](https://github.com/basicmachines-co/basic-memory/commit/45d6caf))
|
|
48
|
+
- Allows longer observation content without truncation
|
|
49
|
+
- Removes arbitrary 2000 character limit
|
|
50
|
+
|
|
51
|
+
- Handle FileNotFoundError gracefully during sync
|
|
52
|
+
([`1652f86`](https://github.com/basicmachines-co/basic-memory/commit/1652f86))
|
|
53
|
+
- Prevents sync failures when files are deleted during sync
|
|
54
|
+
- More resilient file watching
|
|
55
|
+
|
|
56
|
+
- Use canonical project names in API response messages
|
|
57
|
+
([`c23927d`](https://github.com/basicmachines-co/basic-memory/commit/c23927d))
|
|
58
|
+
- Consistent project name formatting in all responses
|
|
59
|
+
|
|
60
|
+
- Suppress CLI warnings for cleaner output
|
|
61
|
+
([`d71c6e8`](https://github.com/basicmachines-co/basic-memory/commit/d71c6e8))
|
|
62
|
+
- Cleaner terminal output without spurious warnings
|
|
63
|
+
|
|
64
|
+
- Prevent DEBUG logs from appearing on CLI stdout
|
|
65
|
+
([`63b9849`](https://github.com/basicmachines-co/basic-memory/commit/63b9849))
|
|
66
|
+
- Debug logging no longer pollutes CLI output
|
|
67
|
+
|
|
68
|
+
- **#473**: Detect rclone version for --create-empty-src-dirs support
|
|
69
|
+
([`622d37e`](https://github.com/basicmachines-co/basic-memory/commit/622d37e))
|
|
70
|
+
- Automatic rclone version detection for compatibility
|
|
71
|
+
- Prevents errors on older rclone versions
|
|
72
|
+
|
|
73
|
+
- **#471**: Prevent CLI commands from hanging on exit
|
|
74
|
+
([`916baf8`](https://github.com/basicmachines-co/basic-memory/commit/916baf8))
|
|
75
|
+
- Fixes CLI hang on shutdown
|
|
76
|
+
- Proper async cleanup
|
|
77
|
+
|
|
78
|
+
- Add cloud_mode check to initialize_app()
|
|
79
|
+
([`ef7adb7`](https://github.com/basicmachines-co/basic-memory/commit/ef7adb7))
|
|
80
|
+
- Correct initialization for cloud deployments
|
|
81
|
+
|
|
82
|
+
### Internal
|
|
83
|
+
|
|
84
|
+
- Centralize test environment detection in config.is_test_env
|
|
85
|
+
([`3cd9178`](https://github.com/basicmachines-co/basic-memory/commit/3cd9178))
|
|
86
|
+
- Unified test environment detection
|
|
87
|
+
- Disables analytics in test environments
|
|
88
|
+
|
|
89
|
+
- Make test-int-postgres compatible with macOS
|
|
90
|
+
([`95937c6`](https://github.com/basicmachines-co/basic-memory/commit/95937c6))
|
|
91
|
+
- Cross-platform PostgreSQL testing support
|
|
92
|
+
|
|
3
93
|
## v0.16.3 (2025-12-20)
|
|
4
94
|
|
|
5
95
|
### Features
|
|
@@ -58,11 +58,69 @@ See the [README.md](README.md) file for a project overview.
|
|
|
58
58
|
- Follow the repository pattern for data access
|
|
59
59
|
- Tools communicate to api routers via the httpx ASGI client (in process)
|
|
60
60
|
|
|
61
|
+
### Code Change Guidelines
|
|
62
|
+
|
|
63
|
+
- **Full file read before edits**: Before editing any file, read it in full first to ensure complete context; partial reads lead to corrupted edits
|
|
64
|
+
- **Minimize diffs**: Prefer the smallest change that satisfies the request. Avoid unrelated refactors or style rewrites unless necessary for correctness
|
|
65
|
+
- **No speculative getattr**: Never use `getattr(obj, "attr", default)` when unsure about attribute names. Check the class definition or source code first
|
|
66
|
+
- **Fail fast**: Write code with fail-fast logic by default. Do not swallow exceptions with errors or warnings
|
|
67
|
+
- **No fallback logic**: Do not add fallback logic unless explicitly told to and agreed with the user
|
|
68
|
+
- **No guessing**: Do not say "The issue is..." before you actually know what the issue is. Investigate first.
|
|
69
|
+
|
|
70
|
+
### Literate Programming Style
|
|
71
|
+
|
|
72
|
+
Code should tell a story. Comments must explain the "why" and narrative flow, not just the "what".
|
|
73
|
+
|
|
74
|
+
**Section Headers:**
|
|
75
|
+
For files with multiple phases of logic, add section headers so the control flow reads like chapters:
|
|
76
|
+
```python
|
|
77
|
+
# --- Authentication ---
|
|
78
|
+
# ... auth logic ...
|
|
79
|
+
|
|
80
|
+
# --- Data Validation ---
|
|
81
|
+
# ... validation logic ...
|
|
82
|
+
|
|
83
|
+
# --- Business Logic ---
|
|
84
|
+
# ... core logic ...
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Decision Point Comments:**
|
|
88
|
+
For conditionals that materially change behavior (gates, fallbacks, retries, feature flags), add comments with:
|
|
89
|
+
- **Trigger**: what condition causes this branch
|
|
90
|
+
- **Why**: the rationale (cost, correctness, UX, determinism)
|
|
91
|
+
- **Outcome**: what changes downstream
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
# Trigger: project has no active sync watcher
|
|
95
|
+
# Why: avoid duplicate file system watchers consuming resources
|
|
96
|
+
# Outcome: starts new watcher, registers in active_watchers dict
|
|
97
|
+
if project_id not in active_watchers:
|
|
98
|
+
start_watcher(project_id)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Constraint Comments:**
|
|
102
|
+
If code exists because of a constraint (async requirements, rate limits, schema compatibility), explain the constraint near the code:
|
|
103
|
+
```python
|
|
104
|
+
# SQLite requires WAL mode for concurrent read/write access
|
|
105
|
+
connection.execute("PRAGMA journal_mode=WAL")
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**What NOT to Comment:**
|
|
109
|
+
Avoid comments that restate obvious code:
|
|
110
|
+
```python
|
|
111
|
+
# Bad - restates code
|
|
112
|
+
counter += 1 # increment counter
|
|
113
|
+
|
|
114
|
+
# Good - explains why
|
|
115
|
+
counter += 1 # track retries for backoff calculation
|
|
116
|
+
```
|
|
117
|
+
|
|
61
118
|
### Codebase Architecture
|
|
62
119
|
|
|
63
120
|
- `/alembic` - Alembic db migrations
|
|
64
121
|
- `/api` - FastAPI implementation of REST endpoints
|
|
65
122
|
- `/cli` - Typer command-line interface
|
|
123
|
+
- `/importers` - Import functionality for Claude, ChatGPT, and other sources
|
|
66
124
|
- `/markdown` - Markdown parsing and processing
|
|
67
125
|
- `/mcp` - Model Context Protocol server implementation
|
|
68
126
|
- `/models` - SQLAlchemy ORM models
|
|
@@ -140,22 +198,26 @@ See SPEC-16 for full context manager refactor details.
|
|
|
140
198
|
### Basic Memory Commands
|
|
141
199
|
|
|
142
200
|
**Local Commands:**
|
|
143
|
-
-
|
|
201
|
+
- Check sync status: `basic-memory status`
|
|
144
202
|
- Import from Claude: `basic-memory import claude conversations`
|
|
145
203
|
- Import from ChatGPT: `basic-memory import chatgpt`
|
|
146
204
|
- Import from Memory JSON: `basic-memory import memory-json`
|
|
147
|
-
-
|
|
148
|
-
-
|
|
149
|
-
|
|
150
|
-
|
|
205
|
+
- Tool access: `basic-memory tool` (provides CLI access to MCP tools)
|
|
206
|
+
- Continue: `basic-memory tool continue-conversation --topic="search"`
|
|
207
|
+
|
|
208
|
+
**Project Management:**
|
|
209
|
+
- List projects: `basic-memory project list`
|
|
210
|
+
- Add project: `basic-memory project add "name" ~/path`
|
|
211
|
+
- Project info: `basic-memory project info`
|
|
212
|
+
- One-way sync (local -> cloud): `basic-memory project sync`
|
|
213
|
+
- Bidirectional sync: `basic-memory project bisync`
|
|
214
|
+
- Integrity check: `basic-memory project check`
|
|
151
215
|
|
|
152
216
|
**Cloud Commands (requires subscription):**
|
|
153
217
|
- Authenticate: `basic-memory cloud login`
|
|
154
218
|
- Logout: `basic-memory cloud logout`
|
|
155
|
-
-
|
|
156
|
-
-
|
|
157
|
-
- Mount cloud storage: `basic-memory cloud mount`
|
|
158
|
-
- Unmount cloud storage: `basic-memory cloud unmount`
|
|
219
|
+
- Check cloud status: `basic-memory cloud status`
|
|
220
|
+
- Setup cloud sync: `basic-memory cloud setup`
|
|
159
221
|
|
|
160
222
|
### MCP Capabilities
|
|
161
223
|
|
|
@@ -182,18 +244,19 @@ See SPEC-16 for full context manager refactor details.
|
|
|
182
244
|
- `list_memory_projects()` - List all available projects with their status
|
|
183
245
|
- `create_memory_project(project_name, project_path, set_default)` - Create new Basic Memory projects
|
|
184
246
|
- `delete_project(project_name)` - Delete a project from configuration
|
|
185
|
-
- `get_current_project()` - Get current project information and stats
|
|
186
|
-
- `sync_status()` - Check file synchronization and background operation status
|
|
187
247
|
|
|
188
248
|
**Visualization:**
|
|
189
249
|
- `canvas(nodes, edges, title, folder)` - Generate Obsidian canvas files for knowledge graph visualization
|
|
190
250
|
|
|
251
|
+
**ChatGPT-Compatible Tools:**
|
|
252
|
+
- `search(query)` - Search across knowledge base (OpenAI actions compatible)
|
|
253
|
+
- `fetch(id)` - Fetch full content of a search result document
|
|
254
|
+
|
|
191
255
|
- MCP Prompts for better AI interaction:
|
|
192
256
|
- `ai_assistant_guide()` - Guidance on effectively using Basic Memory tools for AI assistants
|
|
193
257
|
- `continue_conversation(topic, timeframe)` - Continue previous conversations with relevant historical context
|
|
194
258
|
- `search(query, after_date)` - Search with detailed, formatted results for better context understanding
|
|
195
259
|
- `recent_activity(timeframe)` - View recently changed items with formatted output
|
|
196
|
-
- `json_canvas_spec()` - Full JSON Canvas specification for Obsidian visualization
|
|
197
260
|
|
|
198
261
|
### Cloud Features (v0.15.0+)
|
|
199
262
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: basic-memory
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.17.1
|
|
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
|
|
@@ -20,7 +20,11 @@ Requires-Dist: greenlet>=3.1.1
|
|
|
20
20
|
Requires-Dist: loguru>=0.7.3
|
|
21
21
|
Requires-Dist: markdown-it-py>=3.0.0
|
|
22
22
|
Requires-Dist: mcp>=1.2.0
|
|
23
|
+
Requires-Dist: mdformat-frontmatter>=2.0.8
|
|
24
|
+
Requires-Dist: mdformat-gfm>=0.3.7
|
|
25
|
+
Requires-Dist: mdformat>=0.7.22
|
|
23
26
|
Requires-Dist: nest-asyncio>=1.6.0
|
|
27
|
+
Requires-Dist: openpanel>=0.0.1
|
|
24
28
|
Requires-Dist: pillow>=11.1.0
|
|
25
29
|
Requires-Dist: psycopg==3.3.1
|
|
26
30
|
Requires-Dist: pybars3>=0.9.7
|
|
@@ -508,6 +512,39 @@ tail -f ~/.basic-memory/basic-memory.log
|
|
|
508
512
|
BASIC_MEMORY_CLOUD_MODE=true uvicorn basic_memory.api.app:app
|
|
509
513
|
```
|
|
510
514
|
|
|
515
|
+
## Telemetry
|
|
516
|
+
|
|
517
|
+
Basic Memory collects anonymous usage statistics to help improve the software. This follows the [Homebrew model](https://docs.brew.sh/Analytics) - telemetry is on by default with easy opt-out.
|
|
518
|
+
|
|
519
|
+
**What we collect:**
|
|
520
|
+
- App version, Python version, OS, architecture
|
|
521
|
+
- Feature usage (which MCP tools and CLI commands are used)
|
|
522
|
+
- Error types (sanitized - no file paths or personal data)
|
|
523
|
+
|
|
524
|
+
**What we NEVER collect:**
|
|
525
|
+
- Note content, file names, or paths
|
|
526
|
+
- Personal information
|
|
527
|
+
- IP addresses
|
|
528
|
+
|
|
529
|
+
**Opting out:**
|
|
530
|
+
```bash
|
|
531
|
+
# Disable telemetry
|
|
532
|
+
basic-memory telemetry disable
|
|
533
|
+
|
|
534
|
+
# Check status
|
|
535
|
+
basic-memory telemetry status
|
|
536
|
+
|
|
537
|
+
# Re-enable
|
|
538
|
+
basic-memory telemetry enable
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
Or set the environment variable:
|
|
542
|
+
```bash
|
|
543
|
+
export BASIC_MEMORY_TELEMETRY_ENABLED=false
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
For more details, see the [Telemetry documentation](https://basicmemory.com/telemetry).
|
|
547
|
+
|
|
511
548
|
## Development
|
|
512
549
|
|
|
513
550
|
### Running Tests
|
|
@@ -466,6 +466,39 @@ tail -f ~/.basic-memory/basic-memory.log
|
|
|
466
466
|
BASIC_MEMORY_CLOUD_MODE=true uvicorn basic_memory.api.app:app
|
|
467
467
|
```
|
|
468
468
|
|
|
469
|
+
## Telemetry
|
|
470
|
+
|
|
471
|
+
Basic Memory collects anonymous usage statistics to help improve the software. This follows the [Homebrew model](https://docs.brew.sh/Analytics) - telemetry is on by default with easy opt-out.
|
|
472
|
+
|
|
473
|
+
**What we collect:**
|
|
474
|
+
- App version, Python version, OS, architecture
|
|
475
|
+
- Feature usage (which MCP tools and CLI commands are used)
|
|
476
|
+
- Error types (sanitized - no file paths or personal data)
|
|
477
|
+
|
|
478
|
+
**What we NEVER collect:**
|
|
479
|
+
- Note content, file names, or paths
|
|
480
|
+
- Personal information
|
|
481
|
+
- IP addresses
|
|
482
|
+
|
|
483
|
+
**Opting out:**
|
|
484
|
+
```bash
|
|
485
|
+
# Disable telemetry
|
|
486
|
+
basic-memory telemetry disable
|
|
487
|
+
|
|
488
|
+
# Check status
|
|
489
|
+
basic-memory telemetry status
|
|
490
|
+
|
|
491
|
+
# Re-enable
|
|
492
|
+
basic-memory telemetry enable
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
Or set the environment variable:
|
|
496
|
+
```bash
|
|
497
|
+
export BASIC_MEMORY_TELEMETRY_ENABLED=false
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
For more details, see the [Telemetry documentation](https://basicmemory.com/telemetry).
|
|
501
|
+
|
|
469
502
|
## Development
|
|
470
503
|
|
|
471
504
|
### Running Tests
|
|
@@ -37,11 +37,11 @@ test-postgres: test-unit-postgres test-int-postgres
|
|
|
37
37
|
|
|
38
38
|
# Run unit tests against SQLite
|
|
39
39
|
test-unit-sqlite:
|
|
40
|
-
uv run pytest -p pytest_mock -v --no-cov tests
|
|
40
|
+
BASIC_MEMORY_ENV=test uv run pytest -p pytest_mock -v --no-cov tests
|
|
41
41
|
|
|
42
42
|
# Run unit tests against Postgres
|
|
43
43
|
test-unit-postgres:
|
|
44
|
-
BASIC_MEMORY_TEST_POSTGRES=1 uv run pytest -p pytest_mock -v --no-cov tests
|
|
44
|
+
BASIC_MEMORY_ENV=test BASIC_MEMORY_TEST_POSTGRES=1 uv run pytest -p pytest_mock -v --no-cov tests
|
|
45
45
|
|
|
46
46
|
# Run integration tests against SQLite
|
|
47
47
|
test-int-sqlite:
|
|
@@ -51,7 +51,16 @@ test-int-sqlite:
|
|
|
51
51
|
# Note: Uses timeout due to FastMCP Client + asyncpg cleanup hang (tests pass, process hangs on exit)
|
|
52
52
|
# See: https://github.com/jlowin/fastmcp/issues/1311
|
|
53
53
|
test-int-postgres:
|
|
54
|
-
|
|
54
|
+
#!/usr/bin/env bash
|
|
55
|
+
set -euo pipefail
|
|
56
|
+
# Use gtimeout (macOS/Homebrew) or timeout (Linux)
|
|
57
|
+
TIMEOUT_CMD=$(command -v gtimeout || command -v timeout || echo "")
|
|
58
|
+
if [[ -n "$TIMEOUT_CMD" ]]; then
|
|
59
|
+
$TIMEOUT_CMD --signal=KILL 600 bash -c 'BASIC_MEMORY_TEST_POSTGRES=1 uv run pytest -p pytest_mock -v --no-cov test-int' || test $? -eq 137
|
|
60
|
+
else
|
|
61
|
+
echo "⚠️ No timeout command found, running without timeout..."
|
|
62
|
+
BASIC_MEMORY_TEST_POSTGRES=1 uv run pytest -p pytest_mock -v --no-cov test-int
|
|
63
|
+
fi
|
|
55
64
|
|
|
56
65
|
# Reset Postgres test database (drops and recreates schema)
|
|
57
66
|
# Useful when Alembic migration state gets out of sync during development
|
|
@@ -38,6 +38,10 @@ dependencies = [
|
|
|
38
38
|
"nest-asyncio>=1.6.0", # For Alembic migrations with Postgres
|
|
39
39
|
"pytest-asyncio>=1.2.0",
|
|
40
40
|
"psycopg==3.3.1",
|
|
41
|
+
"mdformat>=0.7.22",
|
|
42
|
+
"mdformat-gfm>=0.3.7",
|
|
43
|
+
"mdformat-frontmatter>=2.0.8",
|
|
44
|
+
"openpanel>=0.0.1", # Anonymous usage telemetry (Homebrew-style opt-out)
|
|
41
45
|
]
|
|
42
46
|
|
|
43
47
|
|
|
@@ -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.
|
|
4
|
+
__version__ = "0.17.1"
|
|
5
5
|
|
|
6
6
|
# API version for FastAPI - independent of package version
|
|
7
7
|
__api_version__ = "v0"
|
|
@@ -21,8 +21,12 @@ from alembic import context
|
|
|
21
21
|
|
|
22
22
|
from basic_memory.config import ConfigManager
|
|
23
23
|
|
|
24
|
-
#
|
|
25
|
-
|
|
24
|
+
# Trigger: only set test env when actually running under pytest
|
|
25
|
+
# Why: alembic/env.py is imported during normal operations (MCP server startup, migrations)
|
|
26
|
+
# but we only want test behavior during actual test runs
|
|
27
|
+
# Outcome: prevents is_test_env from returning True in production, enabling watch service
|
|
28
|
+
if os.getenv("PYTEST_CURRENT_TEST") is not None:
|
|
29
|
+
os.environ["BASIC_MEMORY_ENV"] = "test"
|
|
26
30
|
|
|
27
31
|
# Import after setting environment variable # noqa: E402
|
|
28
32
|
from basic_memory.models import Base # noqa: E402
|
|
@@ -10,6 +10,42 @@ from typing import Sequence, Union
|
|
|
10
10
|
|
|
11
11
|
import sqlalchemy as sa
|
|
12
12
|
from alembic import op
|
|
13
|
+
from sqlalchemy import text
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def column_exists(connection, table: str, column: str) -> bool:
|
|
17
|
+
"""Check if a column exists in a table (idempotent migration support)."""
|
|
18
|
+
if connection.dialect.name == "postgresql":
|
|
19
|
+
result = connection.execute(
|
|
20
|
+
text(
|
|
21
|
+
"SELECT 1 FROM information_schema.columns "
|
|
22
|
+
"WHERE table_name = :table AND column_name = :column"
|
|
23
|
+
),
|
|
24
|
+
{"table": table, "column": column},
|
|
25
|
+
)
|
|
26
|
+
return result.fetchone() is not None
|
|
27
|
+
else:
|
|
28
|
+
# SQLite
|
|
29
|
+
result = connection.execute(text(f"PRAGMA table_info({table})"))
|
|
30
|
+
columns = [row[1] for row in result]
|
|
31
|
+
return column in columns
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def index_exists(connection, index_name: str) -> bool:
|
|
35
|
+
"""Check if an index exists (idempotent migration support)."""
|
|
36
|
+
if connection.dialect.name == "postgresql":
|
|
37
|
+
result = connection.execute(
|
|
38
|
+
text("SELECT 1 FROM pg_indexes WHERE indexname = :index_name"),
|
|
39
|
+
{"index_name": index_name},
|
|
40
|
+
)
|
|
41
|
+
return result.fetchone() is not None
|
|
42
|
+
else:
|
|
43
|
+
# SQLite
|
|
44
|
+
result = connection.execute(
|
|
45
|
+
text("SELECT 1 FROM sqlite_master WHERE type='index' AND name = :index_name"),
|
|
46
|
+
{"index_name": index_name},
|
|
47
|
+
)
|
|
48
|
+
return result.fetchone() is not None
|
|
13
49
|
|
|
14
50
|
|
|
15
51
|
# revision identifiers, used by Alembic.
|
|
@@ -36,101 +72,105 @@ def upgrade() -> None:
|
|
|
36
72
|
# Add project_id to relation table
|
|
37
73
|
# -------------------------------------------------------------------------
|
|
38
74
|
|
|
39
|
-
# Step 1: Add project_id column as nullable first
|
|
40
|
-
|
|
75
|
+
# Step 1: Add project_id column as nullable first (idempotent)
|
|
76
|
+
if not column_exists(connection, "relation", "project_id"):
|
|
77
|
+
op.add_column("relation", sa.Column("project_id", sa.Integer(), nullable=True))
|
|
41
78
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
FROM entity
|
|
48
|
-
WHERE relation.from_id = entity.id
|
|
49
|
-
""")
|
|
50
|
-
else:
|
|
51
|
-
# SQLite syntax
|
|
52
|
-
op.execute("""
|
|
53
|
-
UPDATE relation
|
|
54
|
-
SET project_id = (
|
|
55
|
-
SELECT entity.project_id
|
|
79
|
+
# Step 2: Backfill project_id from entity.project_id via from_id
|
|
80
|
+
if dialect == "postgresql":
|
|
81
|
+
op.execute("""
|
|
82
|
+
UPDATE relation
|
|
83
|
+
SET project_id = entity.project_id
|
|
56
84
|
FROM entity
|
|
57
|
-
WHERE
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
batch_op.alter_column("project_id", nullable=False)
|
|
75
|
-
batch_op.create_foreign_key(
|
|
85
|
+
WHERE relation.from_id = entity.id
|
|
86
|
+
""")
|
|
87
|
+
else:
|
|
88
|
+
# SQLite syntax
|
|
89
|
+
op.execute("""
|
|
90
|
+
UPDATE relation
|
|
91
|
+
SET project_id = (
|
|
92
|
+
SELECT entity.project_id
|
|
93
|
+
FROM entity
|
|
94
|
+
WHERE entity.id = relation.from_id
|
|
95
|
+
)
|
|
96
|
+
""")
|
|
97
|
+
|
|
98
|
+
# Step 3: Make project_id NOT NULL and add foreign key
|
|
99
|
+
if dialect == "postgresql":
|
|
100
|
+
op.alter_column("relation", "project_id", nullable=False)
|
|
101
|
+
op.create_foreign_key(
|
|
76
102
|
"fk_relation_project_id",
|
|
103
|
+
"relation",
|
|
77
104
|
"project",
|
|
78
105
|
["project_id"],
|
|
79
106
|
["id"],
|
|
80
107
|
)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
108
|
+
else:
|
|
109
|
+
# SQLite requires batch operations for ALTER COLUMN
|
|
110
|
+
with op.batch_alter_table("relation") as batch_op:
|
|
111
|
+
batch_op.alter_column("project_id", nullable=False)
|
|
112
|
+
batch_op.create_foreign_key(
|
|
113
|
+
"fk_relation_project_id",
|
|
114
|
+
"project",
|
|
115
|
+
["project_id"],
|
|
116
|
+
["id"],
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# Step 4: Create index on relation.project_id (idempotent)
|
|
120
|
+
if not index_exists(connection, "ix_relation_project_id"):
|
|
121
|
+
op.create_index("ix_relation_project_id", "relation", ["project_id"])
|
|
84
122
|
|
|
85
123
|
# -------------------------------------------------------------------------
|
|
86
124
|
# Add project_id to observation table
|
|
87
125
|
# -------------------------------------------------------------------------
|
|
88
126
|
|
|
89
|
-
# Step 1: Add project_id column as nullable first
|
|
90
|
-
|
|
127
|
+
# Step 1: Add project_id column as nullable first (idempotent)
|
|
128
|
+
if not column_exists(connection, "observation", "project_id"):
|
|
129
|
+
op.add_column("observation", sa.Column("project_id", sa.Integer(), nullable=True))
|
|
91
130
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
FROM entity
|
|
98
|
-
WHERE observation.entity_id = entity.id
|
|
99
|
-
""")
|
|
100
|
-
else:
|
|
101
|
-
# SQLite syntax
|
|
102
|
-
op.execute("""
|
|
103
|
-
UPDATE observation
|
|
104
|
-
SET project_id = (
|
|
105
|
-
SELECT entity.project_id
|
|
131
|
+
# Step 2: Backfill project_id from entity.project_id via entity_id
|
|
132
|
+
if dialect == "postgresql":
|
|
133
|
+
op.execute("""
|
|
134
|
+
UPDATE observation
|
|
135
|
+
SET project_id = entity.project_id
|
|
106
136
|
FROM entity
|
|
107
|
-
WHERE
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
batch_op.alter_column("project_id", nullable=False)
|
|
125
|
-
batch_op.create_foreign_key(
|
|
137
|
+
WHERE observation.entity_id = entity.id
|
|
138
|
+
""")
|
|
139
|
+
else:
|
|
140
|
+
# SQLite syntax
|
|
141
|
+
op.execute("""
|
|
142
|
+
UPDATE observation
|
|
143
|
+
SET project_id = (
|
|
144
|
+
SELECT entity.project_id
|
|
145
|
+
FROM entity
|
|
146
|
+
WHERE entity.id = observation.entity_id
|
|
147
|
+
)
|
|
148
|
+
""")
|
|
149
|
+
|
|
150
|
+
# Step 3: Make project_id NOT NULL and add foreign key
|
|
151
|
+
if dialect == "postgresql":
|
|
152
|
+
op.alter_column("observation", "project_id", nullable=False)
|
|
153
|
+
op.create_foreign_key(
|
|
126
154
|
"fk_observation_project_id",
|
|
155
|
+
"observation",
|
|
127
156
|
"project",
|
|
128
157
|
["project_id"],
|
|
129
158
|
["id"],
|
|
130
159
|
)
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
160
|
+
else:
|
|
161
|
+
# SQLite requires batch operations for ALTER COLUMN
|
|
162
|
+
with op.batch_alter_table("observation") as batch_op:
|
|
163
|
+
batch_op.alter_column("project_id", nullable=False)
|
|
164
|
+
batch_op.create_foreign_key(
|
|
165
|
+
"fk_observation_project_id",
|
|
166
|
+
"project",
|
|
167
|
+
["project_id"],
|
|
168
|
+
["id"],
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# Step 4: Create index on observation.project_id (idempotent)
|
|
172
|
+
if not index_exists(connection, "ix_observation_project_id"):
|
|
173
|
+
op.create_index("ix_observation_project_id", "observation", ["project_id"])
|
|
134
174
|
|
|
135
175
|
# Postgres-specific: pg_trgm and GIN indexes
|
|
136
176
|
if dialect == "postgresql":
|
|
@@ -53,12 +53,20 @@ async def lifespan(app: FastAPI): # pragma: no cover
|
|
|
53
53
|
app.state.session_maker = session_maker
|
|
54
54
|
logger.info("Database connections cached in app state")
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
if app_config.sync_changes:
|
|
56
|
+
# Start file sync if enabled
|
|
57
|
+
if app_config.sync_changes and not app_config.is_test_env:
|
|
58
|
+
logger.info(f"Sync changes enabled: {app_config.sync_changes}")
|
|
59
|
+
|
|
58
60
|
# start file sync task in background
|
|
59
|
-
|
|
61
|
+
async def _file_sync_runner() -> None:
|
|
62
|
+
await initialize_file_sync(app_config)
|
|
63
|
+
|
|
64
|
+
app.state.sync_task = asyncio.create_task(_file_sync_runner())
|
|
60
65
|
else:
|
|
61
|
-
|
|
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.")
|
|
62
70
|
app.state.sync_task = None
|
|
63
71
|
|
|
64
72
|
# proceed with startup
|
|
@@ -274,7 +274,7 @@ async def add_project(
|
|
|
274
274
|
raise HTTPException(status_code=500, detail="Failed to retrieve newly created project")
|
|
275
275
|
|
|
276
276
|
return ProjectStatusResponse( # pyright: ignore [reportCallIssue]
|
|
277
|
-
message=f"Project '{
|
|
277
|
+
message=f"Project '{new_project.name}' added successfully",
|
|
278
278
|
status="success",
|
|
279
279
|
default=project_data.set_default,
|
|
280
280
|
new_project=ProjectItem(
|
|
@@ -329,7 +329,7 @@ async def remove_project(
|
|
|
329
329
|
await project_service.remove_project(name, delete_notes=delete_notes)
|
|
330
330
|
|
|
331
331
|
return ProjectStatusResponse(
|
|
332
|
-
message=f"Project '{name}' removed successfully",
|
|
332
|
+
message=f"Project '{old_project.name}' removed successfully",
|
|
333
333
|
status="success",
|
|
334
334
|
default=False,
|
|
335
335
|
old_project=ProjectItem(
|