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