basic-memory 0.15.1__tar.gz → 0.15.2__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.15.1 → basic_memory-0.15.2}/CHANGELOG.md +45 -1
- {basic_memory-0.15.1 → basic_memory-0.15.2}/PKG-INFO +1 -1
- {basic_memory-0.15.1 → basic_memory-0.15.2}/docs/cloud-cli.md +73 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/pyproject.toml +1 -1
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/__init__.py +1 -1
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/cloud/__init__.py +2 -1
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/cloud/bisync_commands.py +4 -57
- basic_memory-0.15.2/src/basic_memory/cli/commands/cloud/cloud_utils.py +100 -0
- basic_memory-0.15.2/src/basic_memory/cli/commands/cloud/upload.py +128 -0
- basic_memory-0.15.2/src/basic_memory/cli/commands/cloud/upload_command.py +93 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/project.py +116 -101
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/cloud.py +7 -3
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/test_bisync_commands.py +10 -12
- basic_memory-0.15.2/tests/cli/test_cloud_utils.py +326 -0
- basic_memory-0.15.2/tests/cli/test_upload.py +328 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.claude/agents/python-developer.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.claude/agents/system-architect.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.claude/commands/release/beta.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.claude/commands/release/changelog.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.claude/commands/release/release-check.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.claude/commands/release/release.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.claude/commands/spec.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.claude/commands/test-live.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.dockerignore +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/dependabot.yml +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/workflows/claude-code-review.yml +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/workflows/claude-issue-triage.yml +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/workflows/claude.yml +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/workflows/dev-release.yml +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/workflows/docker.yml +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/workflows/pr-title.yml +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/workflows/release.yml +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.github/workflows/test.yml +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.gitignore +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/.python-version +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/CITATION.cff +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/CLA.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/CLAUDE.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/CODE_OF_CONDUCT.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/CONTRIBUTING.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/Dockerfile +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/LICENSE +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/README.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/SECURITY.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/docker-compose.yml +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/docs/Docker.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/docs/ai-assistant-guide-extended.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/docs/character-handling.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/justfile +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/llms-install.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/smithery.yaml +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-1 Specification-Driven Development Process.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-11 Basic Memory API Performance Optimization.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-13 CLI Authentication with Subscription Validation.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-14- Cloud Git Versioning & GitHub Backup.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-15 Configuration Persistence via Tigris for Cloud Tenants.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-16 MCP Cloud Service Consolidation.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-17 Semantic Search with ChromaDB.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-18 AI Memory Management Tool.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-2 Slash Commands Reference.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-3 Agent Definitions.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-5 CLI Cloud Upload via WebDAV.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-6 Explicit Project Parameter Architecture.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-7 POC to spike Tigris Turso for local access to cloud data.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-8 TigrisFS Integration.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-9 Multi-Project Bidirectional Sync Architecture.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/specs/SPEC-9-1 Follow-Ups- Conflict, Sync, and Observability.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/alembic.ini +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/env.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/migrations.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/script.py.mako +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/__init__.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/app.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/__init__.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/directory_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/importer_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/knowledge_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/management_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/memory_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/project_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/prompt_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/resource_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/search_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/routers/utils.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/api/template_loader.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/__init__.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/app.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/auth.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/__init__.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/cloud/api_client.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/cloud/core_commands.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/cloud/mount_commands.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/cloud/rclone_config.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/cloud/rclone_installer.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/command_utils.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/db.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/import_chatgpt.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/import_claude_conversations.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/import_claude_projects.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/import_memory_json.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/mcp.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/status.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/sync.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/tool.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/main.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/config.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/db.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/deps.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/file_utils.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/ignore_utils.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/importers/__init__.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/importers/base.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/importers/chatgpt_importer.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/importers/claude_conversations_importer.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/importers/claude_projects_importer.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/importers/memory_json_importer.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/importers/utils.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/markdown/__init__.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/markdown/entity_parser.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/markdown/markdown_processor.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/markdown/plugins.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/markdown/schemas.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/markdown/utils.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/__init__.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/async_client.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/project_context.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/prompts/__init__.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/prompts/ai_assistant_guide.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/prompts/continue_conversation.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/prompts/recent_activity.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/prompts/search.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/prompts/utils.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/resources/ai_assistant_guide.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/resources/project_info.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/server.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/__init__.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/build_context.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/canvas.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/chatgpt_tools.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/delete_note.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/edit_note.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/list_directory.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/move_note.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/project_management.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/read_content.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/read_note.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/recent_activity.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/search.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/sync_status.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/utils.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/view_note.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/mcp/tools/write_note.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/models/__init__.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/models/base.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/models/knowledge.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/models/project.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/models/search.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/repository/__init__.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/repository/entity_repository.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/repository/observation_repository.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/repository/project_info_repository.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/repository/project_repository.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/repository/relation_repository.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/repository/repository.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/repository/search_repository.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/__init__.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/base.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/delete.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/directory.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/importer.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/memory.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/project_info.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/prompt.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/request.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/response.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/search.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/schemas/sync_report.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/__init__.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/context_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/directory_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/entity_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/exceptions.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/file_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/initialization.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/link_resolver.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/project_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/search_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/services/sync_status_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/sync/__init__.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/sync/background_sync.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/sync/sync_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/sync/watch_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/templates/prompts/continue_conversation.hbs +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/templates/prompts/search.hbs +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/utils.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/BENCHMARKS.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/cli/test_project_commands_integration.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/cli/test_sync_commands_integration.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/cli/test_version_integration.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/conftest.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_build_context_underscore.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_build_context_validation.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_chatgpt_tools_integration.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_default_project_mode_integration.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_delete_note_integration.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_edit_note_integration.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_list_directory_integration.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_move_note_integration.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_project_management_integration.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_project_state_sync_integration.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_read_content_integration.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_read_note_integration.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_search_integration.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_single_project_mcp_integration.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/mcp/test_write_note_integration.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/test_db_wal_mode.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/test_disable_permalinks_integration.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/test-int/test_sync_performance_benchmark.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/Non-MarkdownFileSupport.pdf +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/Screenshot.png +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/__init__.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/conftest.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_async_client.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_continue_conversation_template.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_directory_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_importer_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_knowledge_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_management_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_memory_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_project_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_project_router_operations.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_prompt_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_relation_background_resolution.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_resource_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_search_router.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_search_template.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_template_loader.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/api/test_template_loader_helpers.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/conftest.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/test_cli_tools.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/test_cloud_authentication.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/test_ignore_utils.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/test_import_chatgpt.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/test_import_claude_conversations.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/test_import_claude_projects.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/cli/test_import_memory_json.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/conftest.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/db/test_issue_254_foreign_key_constraints.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/importers/test_importer_base.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/importers/test_importer_utils.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/markdown/__init__.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/markdown/test_entity_parser.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/markdown/test_markdown_plugins.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/markdown/test_markdown_processor.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/markdown/test_observation_edge_cases.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/markdown/test_parser_edge_cases.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/markdown/test_relation_edge_cases.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/markdown/test_task_detection.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/conftest.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_obsidian_yaml_formatting.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_permalink_collision_file_overwrite.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_prompts.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_resources.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_build_context.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_canvas.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_delete_note.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_edit_note.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_list_directory.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_move_note.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_read_content.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_read_note.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_recent_activity.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_resource.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_search.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_sync_status.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_utils.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_view_note.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/test_tool_write_note.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/mcp/tools/test_chatgpt_tools.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_entity_repository.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_entity_repository_upsert.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_observation_repository.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_project_info_repository.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_project_repository.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_relation_repository.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_repository.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_search_repository.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/repository/test_search_repository_edit_bug_fix.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/schemas/test_base_timeframe_minimum.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/schemas/test_memory_serialization.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/schemas/test_memory_url.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/schemas/test_memory_url_validation.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/schemas/test_schemas.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/schemas/test_search.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_context_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_directory_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_entity_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_entity_service_disable_permalinks.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_file_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_initialization.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_link_resolver.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_project_removal_bug.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_project_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_project_service_operations.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_search_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/services/test_sync_status_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/sync/test_character_conflicts.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/sync/test_sync_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/sync/test_sync_wikilink_issue.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/sync/test_tmp_files.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/sync/test_watch_service.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/sync/test_watch_service_edge_cases.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/sync/test_watch_service_reload.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/test_config.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/test_db_migration_deduplication.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/test_deps.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/test_production_cascade_delete.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/utils/test_file_utils.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/utils/test_frontmatter_obsidian_compatible.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/utils/test_parse_tags.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/utils/test_permalink_formatting.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/utils/test_utf8_handling.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/tests/utils/test_validate_project_path.py +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/uv.lock +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v0.15.0-RELEASE-DOCS.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/README.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/api-performance.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/background-relations.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/basic-memory-home.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/bug-fixes.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/chatgpt-integration.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/cloud-authentication.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/cloud-bisync.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/cloud-mode-usage.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/cloud-mount.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/default-project-mode.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/env-file-removal.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/env-var-overrides.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/explicit-project-parameter.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/gitignore-integration.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/project-root-env-var.md +0 -0
- {basic_memory-0.15.1 → basic_memory-0.15.2}/v15-docs/sqlite-performance.md +0 -0
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## v0.15.2 (2025-10-14)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- **#356**: Add WebDAV upload command for cloud projects
|
|
8
|
+
([`5258f45`](https://github.com/basicmachines-co/basic-memory/commit/5258f457))
|
|
9
|
+
- New `bm cloud upload` command for uploading local files/directories to cloud projects
|
|
10
|
+
- WebDAV-based file transfer with automatic directory creation
|
|
11
|
+
- Support for `.gitignore` and `.bmignore` pattern filtering
|
|
12
|
+
- Automatic project creation with `--create-project` flag
|
|
13
|
+
- Optional post-upload sync with `--sync` flag (enabled by default)
|
|
14
|
+
- Human-readable file size reporting (bytes, KB, MB)
|
|
15
|
+
- Comprehensive test coverage (28 unit tests)
|
|
16
|
+
|
|
17
|
+
### Migration Guide
|
|
18
|
+
|
|
19
|
+
No manual migration required. Upgrade with:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Update via uv
|
|
23
|
+
uv tool upgrade basic-memory
|
|
24
|
+
|
|
25
|
+
# Or install fresh
|
|
26
|
+
uv tool install basic-memory
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**What's New:**
|
|
30
|
+
- Upload local files to cloud projects with `bm cloud upload`
|
|
31
|
+
- Streamlined cloud project creation and management
|
|
32
|
+
- Better file filtering with gitignore integration
|
|
33
|
+
|
|
34
|
+
### Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Latest stable release
|
|
38
|
+
uv tool install basic-memory
|
|
39
|
+
|
|
40
|
+
# Update existing installation
|
|
41
|
+
uv tool upgrade basic-memory
|
|
42
|
+
|
|
43
|
+
# Docker
|
|
44
|
+
docker pull ghcr.io/basicmachines-co/basic-memory:v0.15.2
|
|
45
|
+
```
|
|
46
|
+
|
|
3
47
|
## v0.15.1 (2025-10-13)
|
|
4
48
|
|
|
5
49
|
### Performance Improvements
|
|
@@ -1728,4 +1772,4 @@ Co-authored-by: phernandez <phernandez@basicmachines.co>
|
|
|
1728
1772
|
### Chores
|
|
1729
1773
|
|
|
1730
1774
|
- Remove basic-foundation src ref in pyproject.toml
|
|
1731
|
-
([`29fce8b`](https://github.com/basicmachines-co/basic-memory/commit/29fce8b0b922d54d7799bf2534107ee6cfb961b8))
|
|
1775
|
+
([`29fce8b`](https://github.com/basicmachines-co/basic-memory/commit/29fce8b0b922d54d7799bf2534107ee6cfb961b8))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: basic-memory
|
|
3
|
-
Version: 0.15.
|
|
3
|
+
Version: 0.15.2
|
|
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
|
|
@@ -7,6 +7,7 @@ The Basic Memory Cloud CLI provides seamless integration between local and cloud
|
|
|
7
7
|
The cloud CLI enables you to:
|
|
8
8
|
- **Toggle cloud mode** with `bm cloud login` / `bm cloud logout`
|
|
9
9
|
- **Use regular commands in cloud mode**: `bm project`, `bm sync`, `bm tool` all work with cloud
|
|
10
|
+
- **Upload local files** directly to cloud projects via `bm cloud upload`
|
|
10
11
|
- **Bidirectional sync** with rclone bisync (recommended for most users)
|
|
11
12
|
- **Direct file access** via rclone mount (alternative workflow)
|
|
12
13
|
- **Integrity verification** with `bm cloud check`
|
|
@@ -160,6 +161,69 @@ bm project list
|
|
|
160
161
|
|
|
161
162
|
This Dropbox-like workflow means you don't need to manually coordinate projects between local and cloud.
|
|
162
163
|
|
|
164
|
+
### Uploading Local Files
|
|
165
|
+
|
|
166
|
+
You can directly upload local files or directories to cloud projects using `bm cloud upload`. This is useful for:
|
|
167
|
+
- Migrating existing local projects to the cloud
|
|
168
|
+
- Quickly uploading specific files or directories
|
|
169
|
+
- One-time bulk uploads without setting up sync
|
|
170
|
+
|
|
171
|
+
**Basic Usage:**
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# Upload a directory to existing project
|
|
175
|
+
bm cloud upload ~/my-notes --project research
|
|
176
|
+
|
|
177
|
+
# Upload a single file
|
|
178
|
+
bm cloud upload important-doc.md --project research
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Create Project On-the-Fly:**
|
|
182
|
+
|
|
183
|
+
If the target project doesn't exist yet, use `--create-project`:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# Upload and create project in one step
|
|
187
|
+
bm cloud upload ~/local-project --project new-research --create-project
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Skip Automatic Sync:**
|
|
191
|
+
|
|
192
|
+
By default, the command syncs the project after upload to index the files. To skip this:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# Upload without triggering sync
|
|
196
|
+
bm cloud upload ~/bulk-data --project archives --no-sync
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**File Filtering:**
|
|
200
|
+
|
|
201
|
+
The upload command respects `.bmignore` and `.gitignore` patterns, automatically excluding:
|
|
202
|
+
- Hidden files (`.git`, `.DS_Store`)
|
|
203
|
+
- Build artifacts (`node_modules`, `__pycache__`)
|
|
204
|
+
- Database files (`*.db`, `*.db-wal`)
|
|
205
|
+
- Environment files (`.env`)
|
|
206
|
+
|
|
207
|
+
To customize what gets uploaded, edit `~/.basic-memory/.bmignore`.
|
|
208
|
+
|
|
209
|
+
**Complete Example:**
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
# 1. Login to cloud
|
|
213
|
+
bm cloud login
|
|
214
|
+
|
|
215
|
+
# 2. Upload local project (creates project if needed)
|
|
216
|
+
bm cloud upload ~/Documents/research-notes --project research --create-project
|
|
217
|
+
|
|
218
|
+
# 3. Verify upload
|
|
219
|
+
bm project list
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Notes:**
|
|
223
|
+
- Files are uploaded directly via WebDAV (no sync setup required)
|
|
224
|
+
- Uploads are immediate and don't require bisync or mount
|
|
225
|
+
- Use this for migration or one-time uploads; use `bm sync` for ongoing synchronization
|
|
226
|
+
|
|
163
227
|
## File Synchronization
|
|
164
228
|
|
|
165
229
|
### The `bm sync` Command (Cloud Mode Aware)
|
|
@@ -628,6 +692,15 @@ bm cloud check # Full integrity check
|
|
|
628
692
|
bm cloud check --one-way # Faster one-way check
|
|
629
693
|
```
|
|
630
694
|
|
|
695
|
+
### File Upload
|
|
696
|
+
|
|
697
|
+
```bash
|
|
698
|
+
# Upload files/directories to cloud projects
|
|
699
|
+
bm cloud upload <path> --project <name> # Upload to existing project
|
|
700
|
+
bm cloud upload <path> -p <name> --create-project # Upload and create project
|
|
701
|
+
bm cloud upload <path> -p <name> --no-sync # Upload without syncing
|
|
702
|
+
```
|
|
703
|
+
|
|
631
704
|
### Direct File Access (Mount)
|
|
632
705
|
|
|
633
706
|
```bash
|
|
@@ -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.15.
|
|
4
|
+
__version__ = "0.15.2"
|
|
5
5
|
|
|
6
6
|
# API version for FastAPI - independent of package version
|
|
7
7
|
__api_version__ = "v0"
|
|
@@ -2,4 +2,5 @@
|
|
|
2
2
|
|
|
3
3
|
# Import all commands to register them with typer
|
|
4
4
|
from basic_memory.cli.commands.cloud.core_commands import * # noqa: F401,F403
|
|
5
|
-
from basic_memory.cli.commands.cloud.api_client import get_authenticated_headers # noqa: F401
|
|
5
|
+
from basic_memory.cli.commands.cloud.api_client import get_authenticated_headers, get_cloud_config # noqa: F401
|
|
6
|
+
from basic_memory.cli.commands.cloud.upload_command import * # noqa: F401,F403
|
{basic_memory-0.15.1 → basic_memory-0.15.2}/src/basic_memory/cli/commands/cloud/bisync_commands.py
RENAMED
|
@@ -12,6 +12,10 @@ from rich.console import Console
|
|
|
12
12
|
from rich.table import Table
|
|
13
13
|
|
|
14
14
|
from basic_memory.cli.commands.cloud.api_client import CloudAPIError, make_api_request
|
|
15
|
+
from basic_memory.cli.commands.cloud.cloud_utils import (
|
|
16
|
+
create_cloud_project,
|
|
17
|
+
fetch_cloud_projects,
|
|
18
|
+
)
|
|
15
19
|
from basic_memory.cli.commands.cloud.rclone_config import (
|
|
16
20
|
add_tenant_to_rclone_config,
|
|
17
21
|
)
|
|
@@ -21,11 +25,7 @@ from basic_memory.ignore_utils import get_bmignore_path, create_default_bmignore
|
|
|
21
25
|
from basic_memory.schemas.cloud import (
|
|
22
26
|
TenantMountInfo,
|
|
23
27
|
MountCredentials,
|
|
24
|
-
CloudProjectList,
|
|
25
|
-
CloudProjectCreateRequest,
|
|
26
|
-
CloudProjectCreateResponse,
|
|
27
28
|
)
|
|
28
|
-
from basic_memory.utils import generate_permalink
|
|
29
29
|
|
|
30
30
|
console = Console()
|
|
31
31
|
|
|
@@ -110,24 +110,6 @@ async def generate_mount_credentials(tenant_id: str) -> MountCredentials:
|
|
|
110
110
|
raise BisyncError(f"Failed to generate credentials: {e}") from e
|
|
111
111
|
|
|
112
112
|
|
|
113
|
-
async def fetch_cloud_projects() -> CloudProjectList:
|
|
114
|
-
"""Fetch list of projects from cloud API.
|
|
115
|
-
|
|
116
|
-
Returns:
|
|
117
|
-
CloudProjectList with projects from cloud
|
|
118
|
-
"""
|
|
119
|
-
try:
|
|
120
|
-
config_manager = ConfigManager()
|
|
121
|
-
config = config_manager.config
|
|
122
|
-
host_url = config.cloud_host.rstrip("/")
|
|
123
|
-
|
|
124
|
-
response = await make_api_request(method="GET", url=f"{host_url}/proxy/projects/projects")
|
|
125
|
-
|
|
126
|
-
return CloudProjectList.model_validate(response.json())
|
|
127
|
-
except Exception as e:
|
|
128
|
-
raise BisyncError(f"Failed to fetch cloud projects: {e}") from e
|
|
129
|
-
|
|
130
|
-
|
|
131
113
|
def scan_local_directories(sync_dir: Path) -> list[str]:
|
|
132
114
|
"""Scan local sync directory for project folders.
|
|
133
115
|
|
|
@@ -148,41 +130,6 @@ def scan_local_directories(sync_dir: Path) -> list[str]:
|
|
|
148
130
|
return directories
|
|
149
131
|
|
|
150
132
|
|
|
151
|
-
async def create_cloud_project(project_name: str) -> CloudProjectCreateResponse:
|
|
152
|
-
"""Create a new project on cloud.
|
|
153
|
-
|
|
154
|
-
Args:
|
|
155
|
-
project_name: Name of project to create
|
|
156
|
-
|
|
157
|
-
Returns:
|
|
158
|
-
CloudProjectCreateResponse with project details from API
|
|
159
|
-
"""
|
|
160
|
-
try:
|
|
161
|
-
config_manager = ConfigManager()
|
|
162
|
-
config = config_manager.config
|
|
163
|
-
host_url = config.cloud_host.rstrip("/")
|
|
164
|
-
|
|
165
|
-
# Use generate_permalink to ensure consistent naming
|
|
166
|
-
project_path = generate_permalink(project_name)
|
|
167
|
-
|
|
168
|
-
project_data = CloudProjectCreateRequest(
|
|
169
|
-
name=project_name,
|
|
170
|
-
path=project_path,
|
|
171
|
-
set_default=False,
|
|
172
|
-
)
|
|
173
|
-
|
|
174
|
-
response = await make_api_request(
|
|
175
|
-
method="POST",
|
|
176
|
-
url=f"{host_url}/proxy/projects/projects",
|
|
177
|
-
headers={"Content-Type": "application/json"},
|
|
178
|
-
json_data=project_data.model_dump(),
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
return CloudProjectCreateResponse.model_validate(response.json())
|
|
182
|
-
except Exception as e:
|
|
183
|
-
raise BisyncError(f"Failed to create cloud project '{project_name}': {e}") from e
|
|
184
|
-
|
|
185
|
-
|
|
186
133
|
def get_bisync_state_path(tenant_id: str) -> Path:
|
|
187
134
|
"""Get path to bisync state directory."""
|
|
188
135
|
return Path.home() / ".basic-memory" / "bisync-state" / tenant_id
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""Shared utilities for cloud operations."""
|
|
2
|
+
|
|
3
|
+
from basic_memory.cli.commands.cloud.api_client import make_api_request
|
|
4
|
+
from basic_memory.config import ConfigManager
|
|
5
|
+
from basic_memory.schemas.cloud import (
|
|
6
|
+
CloudProjectList,
|
|
7
|
+
CloudProjectCreateRequest,
|
|
8
|
+
CloudProjectCreateResponse,
|
|
9
|
+
)
|
|
10
|
+
from basic_memory.utils import generate_permalink
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CloudUtilsError(Exception):
|
|
14
|
+
"""Exception raised for cloud utility errors."""
|
|
15
|
+
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
async def fetch_cloud_projects() -> CloudProjectList:
|
|
20
|
+
"""Fetch list of projects from cloud API.
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
CloudProjectList with projects from cloud
|
|
24
|
+
"""
|
|
25
|
+
try:
|
|
26
|
+
config_manager = ConfigManager()
|
|
27
|
+
config = config_manager.config
|
|
28
|
+
host_url = config.cloud_host.rstrip("/")
|
|
29
|
+
|
|
30
|
+
response = await make_api_request(method="GET", url=f"{host_url}/proxy/projects/projects")
|
|
31
|
+
|
|
32
|
+
return CloudProjectList.model_validate(response.json())
|
|
33
|
+
except Exception as e:
|
|
34
|
+
raise CloudUtilsError(f"Failed to fetch cloud projects: {e}") from e
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
async def create_cloud_project(project_name: str) -> CloudProjectCreateResponse:
|
|
38
|
+
"""Create a new project on cloud.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
project_name: Name of project to create
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
CloudProjectCreateResponse with project details from API
|
|
45
|
+
"""
|
|
46
|
+
try:
|
|
47
|
+
config_manager = ConfigManager()
|
|
48
|
+
config = config_manager.config
|
|
49
|
+
host_url = config.cloud_host.rstrip("/")
|
|
50
|
+
|
|
51
|
+
# Use generate_permalink to ensure consistent naming
|
|
52
|
+
project_path = generate_permalink(project_name)
|
|
53
|
+
|
|
54
|
+
project_data = CloudProjectCreateRequest(
|
|
55
|
+
name=project_name,
|
|
56
|
+
path=project_path,
|
|
57
|
+
set_default=False,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
response = await make_api_request(
|
|
61
|
+
method="POST",
|
|
62
|
+
url=f"{host_url}/proxy/projects/projects",
|
|
63
|
+
headers={"Content-Type": "application/json"},
|
|
64
|
+
json_data=project_data.model_dump(),
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
return CloudProjectCreateResponse.model_validate(response.json())
|
|
68
|
+
except Exception as e:
|
|
69
|
+
raise CloudUtilsError(f"Failed to create cloud project '{project_name}': {e}") from e
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
async def sync_project(project_name: str) -> None:
|
|
73
|
+
"""Trigger sync for a specific project on cloud.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
project_name: Name of project to sync
|
|
77
|
+
"""
|
|
78
|
+
try:
|
|
79
|
+
from basic_memory.cli.commands.command_utils import run_sync
|
|
80
|
+
|
|
81
|
+
await run_sync(project=project_name)
|
|
82
|
+
except Exception as e:
|
|
83
|
+
raise CloudUtilsError(f"Failed to sync project '{project_name}': {e}") from e
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
async def project_exists(project_name: str) -> bool:
|
|
87
|
+
"""Check if a project exists on cloud.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
project_name: Name of project to check
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
True if project exists, False otherwise
|
|
94
|
+
"""
|
|
95
|
+
try:
|
|
96
|
+
projects = await fetch_cloud_projects()
|
|
97
|
+
project_names = {p.name for p in projects.projects}
|
|
98
|
+
return project_name in project_names
|
|
99
|
+
except Exception:
|
|
100
|
+
return False
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""WebDAV upload functionality for basic-memory projects."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import aiofiles
|
|
7
|
+
import httpx
|
|
8
|
+
|
|
9
|
+
from basic_memory.ignore_utils import load_gitignore_patterns, should_ignore_path
|
|
10
|
+
from basic_memory.mcp.async_client import get_client
|
|
11
|
+
from basic_memory.mcp.tools.utils import call_put
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
async def upload_path(local_path: Path, project_name: str) -> bool:
|
|
15
|
+
"""
|
|
16
|
+
Upload a file or directory to cloud project via WebDAV.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
local_path: Path to local file or directory
|
|
20
|
+
project_name: Name of cloud project (destination)
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
True if upload succeeded, False otherwise
|
|
24
|
+
"""
|
|
25
|
+
try:
|
|
26
|
+
# Resolve path
|
|
27
|
+
local_path = local_path.resolve()
|
|
28
|
+
|
|
29
|
+
# Check if path exists
|
|
30
|
+
if not local_path.exists():
|
|
31
|
+
print(f"Error: Path does not exist: {local_path}")
|
|
32
|
+
return False
|
|
33
|
+
|
|
34
|
+
# Get files to upload
|
|
35
|
+
if local_path.is_file():
|
|
36
|
+
files_to_upload = [(local_path, local_path.name)]
|
|
37
|
+
else:
|
|
38
|
+
files_to_upload = _get_files_to_upload(local_path)
|
|
39
|
+
|
|
40
|
+
if not files_to_upload:
|
|
41
|
+
print("No files found to upload")
|
|
42
|
+
return True
|
|
43
|
+
|
|
44
|
+
print(f"Found {len(files_to_upload)} file(s) to upload")
|
|
45
|
+
|
|
46
|
+
# Upload files using httpx
|
|
47
|
+
total_bytes = 0
|
|
48
|
+
|
|
49
|
+
async with get_client() as client:
|
|
50
|
+
for i, (file_path, relative_path) in enumerate(files_to_upload, 1):
|
|
51
|
+
# Build remote path: /webdav/{project_name}/{relative_path}
|
|
52
|
+
remote_path = f"/webdav/{project_name}/{relative_path}"
|
|
53
|
+
print(f"Uploading {relative_path} ({i}/{len(files_to_upload)})")
|
|
54
|
+
|
|
55
|
+
# Read file content asynchronously
|
|
56
|
+
async with aiofiles.open(file_path, "rb") as f:
|
|
57
|
+
content = await f.read()
|
|
58
|
+
|
|
59
|
+
# Upload via HTTP PUT to WebDAV endpoint
|
|
60
|
+
response = await call_put(client, remote_path, content=content)
|
|
61
|
+
response.raise_for_status()
|
|
62
|
+
|
|
63
|
+
total_bytes += file_path.stat().st_size
|
|
64
|
+
|
|
65
|
+
# Format size based on magnitude
|
|
66
|
+
if total_bytes < 1024:
|
|
67
|
+
size_str = f"{total_bytes} bytes"
|
|
68
|
+
elif total_bytes < 1024 * 1024:
|
|
69
|
+
size_str = f"{total_bytes / 1024:.1f} KB"
|
|
70
|
+
else:
|
|
71
|
+
size_str = f"{total_bytes / (1024 * 1024):.1f} MB"
|
|
72
|
+
|
|
73
|
+
print(f"✓ Upload complete: {len(files_to_upload)} file(s) ({size_str})")
|
|
74
|
+
return True
|
|
75
|
+
|
|
76
|
+
except httpx.HTTPStatusError as e:
|
|
77
|
+
print(f"Upload failed: HTTP {e.response.status_code} - {e.response.text}")
|
|
78
|
+
return False
|
|
79
|
+
except Exception as e:
|
|
80
|
+
print(f"Upload failed: {e}")
|
|
81
|
+
return False
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _get_files_to_upload(directory: Path) -> list[tuple[Path, str]]:
|
|
85
|
+
"""
|
|
86
|
+
Get list of files to upload from directory.
|
|
87
|
+
|
|
88
|
+
Uses .bmignore and .gitignore patterns for filtering.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
directory: Directory to scan
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
List of (absolute_path, relative_path) tuples
|
|
95
|
+
"""
|
|
96
|
+
files = []
|
|
97
|
+
|
|
98
|
+
# Load ignore patterns from .bmignore and .gitignore
|
|
99
|
+
ignore_patterns = load_gitignore_patterns(directory)
|
|
100
|
+
|
|
101
|
+
# Walk through directory
|
|
102
|
+
for root, dirs, filenames in os.walk(directory):
|
|
103
|
+
root_path = Path(root)
|
|
104
|
+
|
|
105
|
+
# Filter directories based on ignore patterns
|
|
106
|
+
filtered_dirs = []
|
|
107
|
+
for d in dirs:
|
|
108
|
+
dir_path = root_path / d
|
|
109
|
+
if not should_ignore_path(dir_path, directory, ignore_patterns):
|
|
110
|
+
filtered_dirs.append(d)
|
|
111
|
+
dirs[:] = filtered_dirs
|
|
112
|
+
|
|
113
|
+
# Process files
|
|
114
|
+
for filename in filenames:
|
|
115
|
+
file_path = root_path / filename
|
|
116
|
+
|
|
117
|
+
# Check if file should be ignored
|
|
118
|
+
if should_ignore_path(file_path, directory, ignore_patterns):
|
|
119
|
+
continue
|
|
120
|
+
|
|
121
|
+
# Calculate relative path for remote
|
|
122
|
+
rel_path = file_path.relative_to(directory)
|
|
123
|
+
# Use forward slashes for WebDAV paths
|
|
124
|
+
remote_path = str(rel_path).replace("\\", "/")
|
|
125
|
+
|
|
126
|
+
files.append((file_path, remote_path))
|
|
127
|
+
|
|
128
|
+
return files
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""Upload CLI commands for basic-memory projects."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
|
|
9
|
+
from basic_memory.cli.app import cloud_app
|
|
10
|
+
from basic_memory.cli.commands.cloud.cloud_utils import (
|
|
11
|
+
create_cloud_project,
|
|
12
|
+
project_exists,
|
|
13
|
+
sync_project,
|
|
14
|
+
)
|
|
15
|
+
from basic_memory.cli.commands.cloud.upload import upload_path
|
|
16
|
+
|
|
17
|
+
console = Console()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@cloud_app.command("upload")
|
|
21
|
+
def upload(
|
|
22
|
+
path: Path = typer.Argument(
|
|
23
|
+
...,
|
|
24
|
+
help="Path to local file or directory to upload",
|
|
25
|
+
exists=True,
|
|
26
|
+
readable=True,
|
|
27
|
+
resolve_path=True,
|
|
28
|
+
),
|
|
29
|
+
project: str = typer.Option(
|
|
30
|
+
...,
|
|
31
|
+
"--project",
|
|
32
|
+
"-p",
|
|
33
|
+
help="Cloud project name (destination)",
|
|
34
|
+
),
|
|
35
|
+
create_project: bool = typer.Option(
|
|
36
|
+
False,
|
|
37
|
+
"--create-project",
|
|
38
|
+
"-c",
|
|
39
|
+
help="Create project if it doesn't exist",
|
|
40
|
+
),
|
|
41
|
+
sync: bool = typer.Option(
|
|
42
|
+
True,
|
|
43
|
+
"--sync/--no-sync",
|
|
44
|
+
help="Sync project after upload (default: true)",
|
|
45
|
+
),
|
|
46
|
+
) -> None:
|
|
47
|
+
"""Upload local files or directories to cloud project via WebDAV.
|
|
48
|
+
|
|
49
|
+
Examples:
|
|
50
|
+
bm cloud upload ~/my-notes --project research
|
|
51
|
+
bm cloud upload notes.md --project research --create-project
|
|
52
|
+
bm cloud upload ~/docs --project work --no-sync
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
async def _upload():
|
|
56
|
+
# Check if project exists
|
|
57
|
+
if not await project_exists(project):
|
|
58
|
+
if create_project:
|
|
59
|
+
console.print(f"[blue]Creating cloud project '{project}'...[/blue]")
|
|
60
|
+
try:
|
|
61
|
+
await create_cloud_project(project)
|
|
62
|
+
console.print(f"[green]✓ Created project '{project}'[/green]")
|
|
63
|
+
except Exception as e:
|
|
64
|
+
console.print(f"[red]Failed to create project: {e}[/red]")
|
|
65
|
+
raise typer.Exit(1)
|
|
66
|
+
else:
|
|
67
|
+
console.print(
|
|
68
|
+
f"[red]Project '{project}' does not exist.[/red]\n"
|
|
69
|
+
f"[yellow]Options:[/yellow]\n"
|
|
70
|
+
f" 1. Create it first: bm project add {project}\n"
|
|
71
|
+
f" 2. Use --create-project flag to create automatically"
|
|
72
|
+
)
|
|
73
|
+
raise typer.Exit(1)
|
|
74
|
+
|
|
75
|
+
# Perform upload
|
|
76
|
+
console.print(f"[blue]Uploading {path} to project '{project}'...[/blue]")
|
|
77
|
+
success = await upload_path(path, project)
|
|
78
|
+
if not success:
|
|
79
|
+
console.print("[red]Upload failed[/red]")
|
|
80
|
+
raise typer.Exit(1)
|
|
81
|
+
|
|
82
|
+
console.print(f"[green]✅ Successfully uploaded to '{project}'[/green]")
|
|
83
|
+
|
|
84
|
+
# Sync project if requested
|
|
85
|
+
if sync:
|
|
86
|
+
console.print(f"[blue]Syncing project '{project}'...[/blue]")
|
|
87
|
+
try:
|
|
88
|
+
await sync_project(project)
|
|
89
|
+
except Exception as e:
|
|
90
|
+
console.print(f"[yellow]Warning: Sync failed: {e}[/yellow]")
|
|
91
|
+
console.print("[dim]Files uploaded but may not be indexed yet[/dim]")
|
|
92
|
+
|
|
93
|
+
asyncio.run(_upload())
|