basic-memory 0.19.1__tar.gz → 0.19.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.
- {basic_memory-0.19.1 → basic_memory-0.19.2}/CHANGELOG.md +12 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/PKG-INFO +1 -1
- {basic_memory-0.19.1 → basic_memory-0.19.2}/server.json +2 -2
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/__init__.py +1 -1
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/canvas.py +5 -3
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/search.py +12 -2
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/write_note.py +4 -3
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/search_repository_base.py +24 -9
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/project_service.py +70 -44
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/utils.py +63 -3
- basic_memory-0.19.2/test-int/mcp/test_string_params_integration.py +167 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_semantic_search_base.py +23 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_project_service_embedding_status.py +41 -0
- basic_memory-0.19.2/tests/test_coerce.py +58 -0
- basic_memory-0.19.2/tests/utils/test_setup_logging.py +162 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.claude/commands/release/beta.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.claude/commands/release/changelog.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.claude/commands/release/release-check.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.claude/commands/release/release.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.claude/commands/spec.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.claude/commands/test-live.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.claude/settings.json +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.dockerignore +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.env.example +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/dependabot.yml +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/workflows/claude-code-review.yml +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/workflows/claude-issue-triage.yml +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/workflows/claude.yml +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/workflows/dev-release.yml +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/workflows/docker.yml +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/workflows/pr-title.yml +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/workflows/release.yml +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.github/workflows/test.yml +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.gitignore +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/.python-version +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/AGENTS.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/CITATION.cff +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/CLA.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/CLAUDE.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/CODE_OF_CONDUCT.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/CONTRIBUTING.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/Dockerfile +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/LICENSE +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/NOTE-FORMAT.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/README.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/SECURITY.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docker-compose-postgres.yml +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docker-compose.yml +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/ARCHITECTURE.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/Docker.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/NOTE-FORMAT.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/SPEC-PER-PROJECT-ROUTING.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/ai-assistant-guide-extended.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/character-handling.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/cloud-cli.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/cloud-semantic-search-value.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/mcp-ui-bakeoff-instructions.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/metadata-search.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/post-v0.18.0-test-plan.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/releases/v0.19.0.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/semantic-search-test-log.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/semantic-search.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/specs/SPEC-LOCAL-PLUS-PUBLISH.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/specs/SPEC-SCHEMA-IMPL.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/specs/SPEC-SCHEMA.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/docs/testing-coverage.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/justfile +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/llms-install.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/pyproject.toml +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/smithery.yaml +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/alembic.ini +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/env.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/migrations.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/script.py.mako +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/314f1ea54dc4_add_postgres_full_text_search_support_.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/6830751f5fb6_merge_multiple_heads.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/9d9c1cb7d8f5_add_mtime_and_size_columns_to_entity_.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/a2b3c4d5e6f7_add_search_index_entity_cascade.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/d7e8f9a0b1c2_add_structured_metadata_indexes.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/e7e1f4367280_add_scan_watermark_tracking_to_project.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/f8a9b2c3d4e5_add_pg_trgm_for_fuzzy_link_resolution.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/g9a0b3c4d5e6_add_external_id_to_project_and_entity.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/h1b2c3d4e5f6_add_postgres_vector_search_tables.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/i2c3d4e5f6g7_auto_backfill_semantic_embeddings.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/j3d4e5f6g7h8_rename_entity_type_to_note_type.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/alembic/versions/k4e5f6g7h8i9_add_created_by_and_last_updated_by_to_entity.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/app.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/container.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/template_loader.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/directory_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/importer_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/knowledge_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/memory_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/project_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/prompt_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/resource_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/schema_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/routers/search_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/api/v2/utils.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/analytics.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/app.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/auth.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/api_client.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/bisync_commands.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/cloud_utils.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/core_commands.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/project_sync.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/rclone_commands.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/rclone_config.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/rclone_installer.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/restore.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/schemas.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/snapshot.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/upload.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/upload_command.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/cloud/workspace.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/command_utils.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/db.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/doctor.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/format.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/import_chatgpt.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/import_claude_conversations.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/import_claude_projects.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/import_memory_json.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/mcp.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/project.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/routing.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/schema.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/status.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/commands/tool.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/container.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/main.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/cli/promo.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/config.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/db.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/deps/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/deps/config.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/deps/db.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/deps/importers.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/deps/projects.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/deps/repositories.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/deps/services.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/deps.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/file_utils.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/ignore_utils.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/importers/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/importers/base.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/importers/chatgpt_importer.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/importers/claude_conversations_importer.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/importers/claude_projects_importer.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/importers/memory_json_importer.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/importers/utils.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/markdown/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/markdown/entity_parser.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/markdown/markdown_processor.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/markdown/plugins.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/markdown/schemas.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/markdown/utils.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/async_client.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/clients/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/clients/directory.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/clients/knowledge.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/clients/memory.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/clients/project.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/clients/resource.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/clients/schema.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/clients/search.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/container.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/formatting.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/project_context.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/prompts/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/prompts/ai_assistant_guide.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/prompts/continue_conversation.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/prompts/recent_activity.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/prompts/search.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/prompts/utils.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/resources/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/resources/ai_assistant_guide.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/resources/cloud_info.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/resources/project_info.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/resources/release_notes.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/resources/ui.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/server.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/build_context.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/chatgpt_tools.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/cloud_info.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/delete_note.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/edit_note.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/list_directory.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/move_note.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/project_management.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/read_content.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/read_note.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/recent_activity.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/release_notes.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/schema.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/ui_sdk.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/utils.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/view_note.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/tools/workspaces.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/html/note-preview-mcp-ui.html +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/html/note-preview-tool-ui.html +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/html/note-preview-vanilla.html +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/html/search-results-mcp-ui.html +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/html/search-results-tool-ui.html +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/html/search-results-vanilla.html +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/sdk.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/mcp/ui/templates.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/models/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/models/base.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/models/knowledge.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/models/project.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/models/search.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/project_resolver.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/embedding_provider.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/embedding_provider_factory.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/entity_repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/fastembed_provider.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/metadata_filters.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/observation_repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/openai_provider.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/postgres_search_repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/project_info_repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/project_repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/relation_repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/search_index_row.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/search_repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/semantic_errors.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/sqlite_search_repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/runtime.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schema/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schema/diff.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schema/inference.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schema/parser.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schema/resolver.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schema/validator.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/base.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/cloud.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/delete.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/directory.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/importer.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/memory.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/project_info.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/prompt.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/request.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/response.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/schema.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/search.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/sync_report.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/v2/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/v2/entity.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/v2/graph.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/schemas/v2/resource.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/context_service.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/directory_service.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/entity_service.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/exceptions.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/file_service.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/initialization.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/link_resolver.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/search_service.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/services/service.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/sync/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/sync/background_sync.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/sync/coordinator.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/sync/sync_service.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/sync/watch_service.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/templates/prompts/continue_conversation.hbs +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/templates/prompts/search.hbs +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/BENCHMARKS.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/cli/test_cli_tool_edit_note_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/cli/test_cli_tool_json_failure_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/cli/test_cli_tool_json_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/cli/test_project_commands_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/cli/test_routing_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/cli/test_search_notes_meta_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/cli/test_version_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/compare_search_benchmarks.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/conftest.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-01.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-02.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-03.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-04.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-05.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-06.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-07.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-08.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-09.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-10.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-11.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-12.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-13.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-14.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-15.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-16.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-17.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-18.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-19.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/people/drift-person-20.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/drift/schema/Person.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/edge-cases/array-single.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/edge-cases/empty-note.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/edge-cases/explicit-overrides-type.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/edge-cases/inline-and-type.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/edge-cases/no-frontmatter.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/edge-cases/relation-only.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/edge-cases/type-no-schema.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/edge-cases/unicode-fields.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/ada-lovelace.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/alan-turing.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/anders-hejlsberg.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/andrej-karpathy.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/barbara-liskov.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/bjarne-stroustrup.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/brendan-eich.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/claude-shannon.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/dennis-ritchie.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/dijkstra.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/donald-knuth.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/fei-fei-li.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/geoffrey-hinton.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/grace-hopper.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/guido-van-rossum.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/james-gosling.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/john-carmack.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/ken-thompson.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/larry-page.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/leslie-lamport.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/linus-torvalds.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/margaret-hamilton.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/rasmus-lerdorf.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/richard-stallman.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/rob-pike.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/satoshi-nakamoto.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/tim-berners-lee.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/vint-cerf.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/yann-lecun.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/inference/people/yukihiro-matsumoto.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/schemas/Book.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/schemas/Meeting.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/schemas/Person.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/schemas/SoftwareProject.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/schemas/StrictSchema.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/valid/basic-memory.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/valid/explicit-ref-note.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/valid/no-schema-note.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/valid/paul-graham.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/valid/rich-hickey.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/valid/standup-2024-01-15.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/warnings/extra-observations.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/warnings/missing-multiple.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/warnings/missing-required.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/fixtures/schema/warnings/wrong-enum-value.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_build_context_underscore.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_build_context_validation.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_chatgpt_tools_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_default_project_mode_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_delete_directory_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_delete_note_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_edit_note_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_lifespan_shutdown_sync_task_cancellation_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_list_directory_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_move_directory_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_move_note_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_output_format_json_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_pagination_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_permalink_collision_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_project_management_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_project_state_sync_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_read_content_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_read_note_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_search_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_single_project_mcp_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_smoke_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_ui_sdk_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/mcp/test_write_note_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/conftest.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/corpus.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/metrics.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/report.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/test_multiterm_semantic_queries.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/test_search_diagnostics.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/test_semantic_coverage.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/semantic/test_semantic_quality.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_db_wal_mode.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_disable_permalinks_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_schema/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_schema/conftest.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_schema/helpers.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_schema/test_diff_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_schema/test_inference_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_schema/test_parser_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_schema/test_validator_integration.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/test-int/test_search_performance_benchmark.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/Non-MarkdownFileSupport.pdf +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/README.md +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/Screenshot.png +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/conftest.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_directory_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_importer_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_knowledge_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_memory_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_project_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_prompt_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_resource_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_schema_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/api/v2/test_search_router.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/cloud/test_cloud_api_client_and_utils.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/cloud/test_rclone_config_and_bmignore_filters.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/cloud/test_upload_command_routing.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/cloud/test_upload_path.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/conftest.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_analytics.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_auth_cli_auth.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cli_container.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cli_exit.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cli_schema.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cli_tool_exit.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cli_tool_json_output.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cli_tools.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cloud_authentication.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cloud_promo.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_cloud_status.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_db_reset_exit.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_ignore_utils.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_import_chatgpt.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_import_claude_conversations.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_import_claude_projects.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_import_memory_json.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_json_output.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_project_add_with_local_path.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_project_info_errors.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_project_list_and_ls.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_project_set_cloud_local.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_restore_commands.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_routing.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_snapshot_commands.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_upload.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/cli/test_workspace_commands.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/conftest.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/db/test_issue_254_foreign_key_constraints.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/importers/test_conversation_indexing.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/importers/test_importer_base.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/importers/test_importer_utils.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_date_frontmatter_parsing.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_entity_parser.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_entity_parser_error_handling.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_markdown_plugins.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_markdown_processor.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_markdown_utils.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_observation_edge_cases.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_parser_edge_cases.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_relation_edge_cases.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/markdown/test_task_detection.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/clients/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/clients/test_clients.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/conftest.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_async_client_force_local.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_async_client_modes.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_client_schema.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_mcp_container.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_obsidian_yaml_formatting.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_permalink_collision_file_overwrite.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_project_context.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_prompt_tool_delegation.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_prompts.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_recent_activity_prompt_modes.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_resources.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_server_lifespan_branches.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_build_context.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_canvas.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_cloud_discovery.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_contracts.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_delete_note.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_edit_note.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_json_output_modes.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_list_directory.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_move_note.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_project_management.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_read_content.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_read_note.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_recent_activity.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_resource.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_schema.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_search.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_utils.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_utils_cloud_auth.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_view_note.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_workspace_management.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_write_note.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_write_note_kebab_filenames.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_tool_write_note_metadata.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_ui_resources.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_ui_sdk.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/test_ui_templates.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/mcp/tools/test_chatgpt_tools.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_distance_to_similarity.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_entity_repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_entity_repository_upsert.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_entity_upsert_issue_187.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_fastembed_provider.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_hybrid_fusion.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_metadata_filters.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_metadata_filters_edge_cases.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_observation_repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_openai_provider.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_postgres_search_repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_postgres_search_repository_unit.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_project_info_repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_project_repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_relation_repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_search_index_row.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_search_repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_search_repository_edit_bug_fix.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_search_text_with_metadata_filters.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_sqlite_vector_search_repository.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_vector_pagination.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/repository/test_vector_threshold.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schema/__init__.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schema/test_diff.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schema/test_inference.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schema/test_parser.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schema/test_resolver.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schema/test_validator.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schemas/test_base_timeframe_minimum.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schemas/test_memory_serialization.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schemas/test_memory_url.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schemas/test_memory_url_validation.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schemas/test_relation_response_reference_resolution.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schemas/test_schemas.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/schemas/test_search.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_context_service.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_directory_service.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_entity_service.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_entity_service_disable_permalinks.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_file_service.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_initialization.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_initialization_cloud_mode_branches.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_link_resolver.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_project_removal_bug.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_project_service.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_project_service_cloud_info.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_project_service_operations.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_search_service.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_semantic_search.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/services/test_task_scheduler_semantic.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_character_conflicts.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_coordinator.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_sync_service.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_sync_service_incremental.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_sync_wikilink_issue.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_tmp_files.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_watch_service.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_watch_service_atomic_adds.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_watch_service_edge_cases.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_watch_service_reload.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/sync/test_watch_service_stress.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/test_config.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/test_deps.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/test_production_cascade_delete.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/test_project_resolver.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/test_rclone_commands.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/test_runtime.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/utils/test_file_utils.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/utils/test_frontmatter_obsidian_compatible.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/utils/test_parse_tags.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/utils/test_permalink_formatting.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/utils/test_timezone_utils.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/utils/test_utf8_handling.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/tests/utils/test_validate_project_path.py +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/.gitignore +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/build.mjs +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/package-lock.json +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/package.json +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/data-table/_adapter.tsx +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/data-table/data-table.tsx +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/data-table/error-boundary.tsx +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/data-table/formatters.tsx +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/data-table/index.tsx +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/data-table/schema.ts +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/data-table/types.ts +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/data-table/utilities.ts +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/_adapter.tsx +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/action-buttons.tsx +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/actions-config.ts +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/error-boundary.tsx +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/index.ts +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/media/aspect-ratio.ts +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/media/format-utils.ts +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/media/index.ts +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/media/overlay-gradient.ts +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/media/sanitize-href.ts +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/parse.ts +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/schema.ts +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/use-action-buttons.tsx +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/use-copy-to-clipboard.ts +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/tool-ui/shared/utils.ts +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/ui/accordion.tsx +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/ui/badge.tsx +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/ui/button.tsx +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/ui/dropdown-menu.tsx +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/ui/table.tsx +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/components/ui/tooltip.tsx +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/note-preview.tsx +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/search-results.tsx +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/src/styles.css +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/ui/tool-ui-react/tailwind.config.js +0 -0
- {basic_memory-0.19.1 → basic_memory-0.19.2}/uv.lock +0 -0
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## v0.19.2 (2026-03-09)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- **#657**: Coerce string params to list/dict in MCP tools
|
|
10
|
+
- MCP clients that serialize `list`/`dict` arguments as JSON strings no longer fail Pydantic validation
|
|
11
|
+
- Adds `BeforeValidator` coercion to `search_notes` (`entity_types`, `note_types`, `tags`, `metadata_filters`), `write_note` (`metadata`), and `canvas` (`nodes`, `edges`)
|
|
12
|
+
- **#655**: Handle SQLite and Windows semantic search regressions
|
|
13
|
+
- Fix embedding status query for non-semantic SQLite databases
|
|
14
|
+
- Windows-safe log file rotation with per-process log filenames
|
|
15
|
+
- Robust `setup_logging` that handles all environments cleanly
|
|
16
|
+
|
|
5
17
|
## v0.19.1 (2026-03-08)
|
|
6
18
|
|
|
7
19
|
### Bug Fixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: basic-memory
|
|
3
|
-
Version: 0.19.
|
|
3
|
+
Version: 0.19.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
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"url": "https://github.com/basicmachines-co/basic-memory.git",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.19.
|
|
9
|
+
"version": "0.19.2",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "pypi",
|
|
13
13
|
"identifier": "basic-memory",
|
|
14
|
-
"version": "0.19.
|
|
14
|
+
"version": "0.19.2",
|
|
15
15
|
"runtimeHint": "uvx",
|
|
16
16
|
"runtimeArguments": [
|
|
17
17
|
{"type": "positional", "value": "basic-memory"},
|
|
@@ -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.19.
|
|
4
|
+
__version__ = "0.19.2"
|
|
5
5
|
|
|
6
6
|
# API version for FastAPI - independent of package version
|
|
7
7
|
__api_version__ = "v0"
|
|
@@ -4,12 +4,14 @@ This tool creates Obsidian canvas files (.canvas) using the JSON Canvas 1.0 spec
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
import json
|
|
7
|
-
from typing import Dict, List, Any, Optional
|
|
7
|
+
from typing import Annotated, Dict, List, Any, Optional
|
|
8
8
|
|
|
9
9
|
from loguru import logger
|
|
10
10
|
from fastmcp import Context
|
|
11
|
+
from pydantic import BeforeValidator
|
|
11
12
|
|
|
12
13
|
from basic_memory.mcp.project_context import get_project_client
|
|
14
|
+
from basic_memory.utils import coerce_list
|
|
13
15
|
from basic_memory.mcp.server import mcp
|
|
14
16
|
from basic_memory.mcp.tools.utils import call_put, call_post, resolve_entity_id
|
|
15
17
|
|
|
@@ -19,8 +21,8 @@ from basic_memory.mcp.tools.utils import call_put, call_post, resolve_entity_id
|
|
|
19
21
|
annotations={"destructiveHint": False, "idempotentHint": True, "openWorldHint": False},
|
|
20
22
|
)
|
|
21
23
|
async def canvas(
|
|
22
|
-
nodes: List[Dict[str, Any]],
|
|
23
|
-
edges: List[Dict[str, Any]],
|
|
24
|
+
nodes: Annotated[List[Dict[str, Any]], BeforeValidator(coerce_list)],
|
|
25
|
+
edges: Annotated[List[Dict[str, Any]], BeforeValidator(coerce_list)],
|
|
24
26
|
title: str,
|
|
25
27
|
directory: str,
|
|
26
28
|
project: Optional[str] = None,
|
|
@@ -6,8 +6,10 @@ from typing import Annotated, List, Optional, Dict, Any, Literal
|
|
|
6
6
|
|
|
7
7
|
from loguru import logger
|
|
8
8
|
from fastmcp import Context
|
|
9
|
+
from pydantic import BeforeValidator
|
|
9
10
|
|
|
10
11
|
from basic_memory.config import ConfigManager
|
|
12
|
+
from basic_memory.utils import coerce_dict, coerce_list
|
|
11
13
|
from basic_memory.mcp.container import get_container
|
|
12
14
|
from basic_memory.mcp.project_context import (
|
|
13
15
|
detect_project_from_url_prefix,
|
|
@@ -307,18 +309,26 @@ async def search_notes(
|
|
|
307
309
|
output_format: Literal["text", "json"] = "text",
|
|
308
310
|
note_types: Annotated[
|
|
309
311
|
List[str] | None,
|
|
312
|
+
BeforeValidator(coerce_list),
|
|
310
313
|
"Filter by the 'type' field in note frontmatter (e.g. 'note', 'chapter', 'person'). "
|
|
311
314
|
"Case-insensitive.",
|
|
312
315
|
] = None,
|
|
313
316
|
entity_types: Annotated[
|
|
314
317
|
List[str] | None,
|
|
318
|
+
BeforeValidator(coerce_list),
|
|
315
319
|
"Filter by knowledge graph item type: 'entity' (whole notes), 'observation', or "
|
|
316
320
|
"'relation'. Defaults to 'entity'. Do NOT pass schema/frontmatter types like "
|
|
317
321
|
"'Chapter' here — use note_types instead.",
|
|
318
322
|
] = None,
|
|
319
323
|
after_date: Optional[str] = None,
|
|
320
|
-
metadata_filters:
|
|
321
|
-
|
|
324
|
+
metadata_filters: Annotated[
|
|
325
|
+
Dict[str, Any] | None,
|
|
326
|
+
BeforeValidator(coerce_dict),
|
|
327
|
+
] = None,
|
|
328
|
+
tags: Annotated[
|
|
329
|
+
List[str] | None,
|
|
330
|
+
BeforeValidator(coerce_list),
|
|
331
|
+
] = None,
|
|
322
332
|
status: Optional[str] = None,
|
|
323
333
|
min_similarity: Optional[float] = None,
|
|
324
334
|
context: Context | None = None,
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
"""Write note tool for Basic Memory MCP server."""
|
|
2
2
|
|
|
3
3
|
import textwrap
|
|
4
|
-
from typing import List, Union, Optional, Literal
|
|
4
|
+
from typing import Annotated, List, Union, Optional, Literal
|
|
5
5
|
|
|
6
6
|
from loguru import logger
|
|
7
|
+
from pydantic import BeforeValidator
|
|
7
8
|
|
|
8
9
|
from basic_memory.config import ConfigManager
|
|
9
10
|
from basic_memory.mcp.project_context import get_project_client, add_project_metadata
|
|
10
11
|
from basic_memory.mcp.server import mcp
|
|
11
12
|
from fastmcp import Context
|
|
12
13
|
from basic_memory.schemas.base import Entity
|
|
13
|
-
from basic_memory.utils import parse_tags, validate_project_path
|
|
14
|
+
from basic_memory.utils import coerce_dict, parse_tags, validate_project_path
|
|
14
15
|
|
|
15
16
|
# Define TagType as a Union that can accept either a string or a list of strings or None
|
|
16
17
|
TagType = Union[List[str], str, None]
|
|
@@ -28,7 +29,7 @@ async def write_note(
|
|
|
28
29
|
workspace: Optional[str] = None,
|
|
29
30
|
tags: list[str] | str | None = None,
|
|
30
31
|
note_type: str = "note",
|
|
31
|
-
metadata: dict | None = None,
|
|
32
|
+
metadata: Annotated[dict | None, BeforeValidator(coerce_dict)] = None,
|
|
32
33
|
overwrite: bool | None = None,
|
|
33
34
|
output_format: Literal["text", "json"] = "text",
|
|
34
35
|
context: Context | None = None,
|
{basic_memory-0.19.1 → basic_memory-0.19.2}/src/basic_memory/repository/search_repository_base.py
RENAMED
|
@@ -451,21 +451,36 @@ class SearchRepositoryBase(ABC):
|
|
|
451
451
|
return "\n\n".join(part for part in row_parts if part)
|
|
452
452
|
|
|
453
453
|
def _build_chunk_records(self, rows) -> list[dict[str, str]]:
|
|
454
|
-
|
|
454
|
+
records_by_key: dict[str, dict[str, str]] = {}
|
|
455
|
+
duplicate_chunk_keys = 0
|
|
455
456
|
for row in rows:
|
|
456
457
|
source_text = self._compose_row_source_text(row)
|
|
457
458
|
chunks = self._split_text_into_chunks(source_text)
|
|
458
459
|
for chunk_index, chunk_text in enumerate(chunks):
|
|
459
460
|
chunk_key = f"{row.type}:{row.id}:{chunk_index}"
|
|
460
461
|
source_hash = hashlib.sha256(chunk_text.encode("utf-8")).hexdigest()
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
462
|
+
# Trigger: SQLite FTS5 can accumulate duplicate logical rows for the
|
|
463
|
+
# same search_index id because it does not enforce relational uniqueness.
|
|
464
|
+
# Why: duplicate chunk keys would schedule duplicate writes for the same
|
|
465
|
+
# chunk row and eventually trip UNIQUE(rowid) in search_vector_embeddings.
|
|
466
|
+
# Outcome: collapse chunk work to one deterministic record per chunk key.
|
|
467
|
+
if chunk_key in records_by_key:
|
|
468
|
+
duplicate_chunk_keys += 1
|
|
469
|
+
records_by_key[chunk_key] = {
|
|
470
|
+
"chunk_key": chunk_key,
|
|
471
|
+
"chunk_text": chunk_text,
|
|
472
|
+
"source_hash": source_hash,
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if duplicate_chunk_keys:
|
|
476
|
+
logger.warning(
|
|
477
|
+
"Collapsed duplicate vector chunk keys before embedding sync: "
|
|
478
|
+
"project_id={project_id} duplicate_chunk_keys={duplicate_chunk_keys}",
|
|
479
|
+
project_id=self.project_id,
|
|
480
|
+
duplicate_chunk_keys=duplicate_chunk_keys,
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
return list(records_by_key.values())
|
|
469
484
|
|
|
470
485
|
# --- Text splitting ---
|
|
471
486
|
|
|
@@ -11,6 +11,7 @@ from typing import TYPE_CHECKING, Dict, Optional, Sequence
|
|
|
11
11
|
|
|
12
12
|
from loguru import logger
|
|
13
13
|
from sqlalchemy import text
|
|
14
|
+
from sqlalchemy.exc import OperationalError as SAOperationalError
|
|
14
15
|
|
|
15
16
|
from basic_memory.models import Project
|
|
16
17
|
from basic_memory.repository.project_repository import ProjectRepository
|
|
@@ -1004,56 +1005,81 @@ class ProjectService:
|
|
|
1004
1005
|
)
|
|
1005
1006
|
total_indexed_entities = si_result.scalar() or 0
|
|
1006
1007
|
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
total_chunks = chunks_result.scalar() or 0
|
|
1012
|
-
|
|
1013
|
-
entities_with_chunks_result = await self.repository.execute_query(
|
|
1014
|
-
text(
|
|
1015
|
-
"SELECT COUNT(DISTINCT entity_id) FROM search_vector_chunks "
|
|
1016
|
-
"WHERE project_id = :project_id"
|
|
1017
|
-
),
|
|
1018
|
-
{"project_id": project_id},
|
|
1019
|
-
)
|
|
1020
|
-
total_entities_with_chunks = entities_with_chunks_result.scalar() or 0
|
|
1021
|
-
|
|
1022
|
-
# Embeddings count — join pattern differs between SQLite and Postgres
|
|
1023
|
-
if is_postgres:
|
|
1024
|
-
embeddings_sql = text(
|
|
1025
|
-
"SELECT COUNT(*) FROM search_vector_chunks c "
|
|
1026
|
-
"JOIN search_vector_embeddings e ON e.chunk_id = c.id "
|
|
1027
|
-
"WHERE c.project_id = :project_id"
|
|
1028
|
-
)
|
|
1029
|
-
else:
|
|
1030
|
-
embeddings_sql = text(
|
|
1031
|
-
"SELECT COUNT(*) FROM search_vector_chunks c "
|
|
1032
|
-
"JOIN search_vector_embeddings e ON e.rowid = c.id "
|
|
1033
|
-
"WHERE c.project_id = :project_id"
|
|
1008
|
+
try:
|
|
1009
|
+
chunks_result = await self.repository.execute_query(
|
|
1010
|
+
text("SELECT COUNT(*) FROM search_vector_chunks WHERE project_id = :project_id"),
|
|
1011
|
+
{"project_id": project_id},
|
|
1034
1012
|
)
|
|
1013
|
+
total_chunks = chunks_result.scalar() or 0
|
|
1035
1014
|
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1015
|
+
entities_with_chunks_result = await self.repository.execute_query(
|
|
1016
|
+
text(
|
|
1017
|
+
"SELECT COUNT(DISTINCT entity_id) FROM search_vector_chunks "
|
|
1018
|
+
"WHERE project_id = :project_id"
|
|
1019
|
+
),
|
|
1020
|
+
{"project_id": project_id},
|
|
1021
|
+
)
|
|
1022
|
+
total_entities_with_chunks = entities_with_chunks_result.scalar() or 0
|
|
1023
|
+
|
|
1024
|
+
# Embeddings count — join pattern differs between SQLite and Postgres
|
|
1025
|
+
if is_postgres:
|
|
1026
|
+
embeddings_sql = text(
|
|
1027
|
+
"SELECT COUNT(*) FROM search_vector_chunks c "
|
|
1028
|
+
"JOIN search_vector_embeddings e ON e.chunk_id = c.id "
|
|
1029
|
+
"WHERE c.project_id = :project_id"
|
|
1030
|
+
)
|
|
1031
|
+
else:
|
|
1032
|
+
embeddings_sql = text(
|
|
1033
|
+
"SELECT COUNT(*) FROM search_vector_chunks c "
|
|
1034
|
+
"JOIN search_vector_embeddings e ON e.rowid = c.id "
|
|
1035
|
+
"WHERE c.project_id = :project_id"
|
|
1036
|
+
)
|
|
1040
1037
|
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
orphan_sql = text(
|
|
1044
|
-
"SELECT COUNT(*) FROM search_vector_chunks c "
|
|
1045
|
-
"LEFT JOIN search_vector_embeddings e ON e.chunk_id = c.id "
|
|
1046
|
-
"WHERE c.project_id = :project_id AND e.chunk_id IS NULL"
|
|
1038
|
+
embeddings_result = await self.repository.execute_query(
|
|
1039
|
+
embeddings_sql, {"project_id": project_id}
|
|
1047
1040
|
)
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1041
|
+
total_embeddings = embeddings_result.scalar() or 0
|
|
1042
|
+
|
|
1043
|
+
# Orphaned chunks (chunks without embeddings — indicates interrupted indexing)
|
|
1044
|
+
if is_postgres:
|
|
1045
|
+
orphan_sql = text(
|
|
1046
|
+
"SELECT COUNT(*) FROM search_vector_chunks c "
|
|
1047
|
+
"LEFT JOIN search_vector_embeddings e ON e.chunk_id = c.id "
|
|
1048
|
+
"WHERE c.project_id = :project_id AND e.chunk_id IS NULL"
|
|
1049
|
+
)
|
|
1050
|
+
else:
|
|
1051
|
+
orphan_sql = text(
|
|
1052
|
+
"SELECT COUNT(*) FROM search_vector_chunks c "
|
|
1053
|
+
"LEFT JOIN search_vector_embeddings e ON e.rowid = c.id "
|
|
1054
|
+
"WHERE c.project_id = :project_id AND e.rowid IS NULL"
|
|
1055
|
+
)
|
|
1056
|
+
|
|
1057
|
+
orphan_result = await self.repository.execute_query(
|
|
1058
|
+
orphan_sql, {"project_id": project_id}
|
|
1053
1059
|
)
|
|
1060
|
+
orphaned_chunks = orphan_result.scalar() or 0
|
|
1061
|
+
except SAOperationalError as exc:
|
|
1062
|
+
# Trigger: sqlite_master can list vec0 virtual tables even when sqlite-vec
|
|
1063
|
+
# is not loaded in the current Python runtime.
|
|
1064
|
+
# Why: project info should degrade gracefully instead of crashing on stats queries.
|
|
1065
|
+
# Outcome: report vector tables as unavailable and point the user to install the
|
|
1066
|
+
# missing dependency before rebuilding embeddings.
|
|
1067
|
+
if is_postgres or "no such module: vec0" not in str(exc).lower():
|
|
1068
|
+
raise
|
|
1054
1069
|
|
|
1055
|
-
|
|
1056
|
-
|
|
1070
|
+
return EmbeddingStatus(
|
|
1071
|
+
semantic_search_enabled=True,
|
|
1072
|
+
embedding_provider=provider,
|
|
1073
|
+
embedding_model=model,
|
|
1074
|
+
embedding_dimensions=dimensions,
|
|
1075
|
+
total_indexed_entities=total_indexed_entities,
|
|
1076
|
+
vector_tables_exist=False,
|
|
1077
|
+
reindex_recommended=True,
|
|
1078
|
+
reindex_reason=(
|
|
1079
|
+
"SQLite vector tables exist but sqlite-vec is unavailable in this Python "
|
|
1080
|
+
"environment — install/update basic-memory, then run: bm reindex --embeddings"
|
|
1081
|
+
),
|
|
1082
|
+
)
|
|
1057
1083
|
|
|
1058
1084
|
# --- Reindex recommendation logic (priority order) ---
|
|
1059
1085
|
reindex_recommended = False
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Utility functions for basic-memory."""
|
|
2
2
|
|
|
3
|
+
import json
|
|
3
4
|
import os
|
|
4
5
|
|
|
5
6
|
import logging
|
|
@@ -7,7 +8,7 @@ import re
|
|
|
7
8
|
import sys
|
|
8
9
|
from datetime import datetime, timezone
|
|
9
10
|
from pathlib import Path
|
|
10
|
-
from typing import Protocol, Union, runtime_checkable, List, Optional
|
|
11
|
+
from typing import Any, Protocol, Union, runtime_checkable, List, Optional
|
|
11
12
|
|
|
12
13
|
from loguru import logger
|
|
13
14
|
from unidecode import unidecode
|
|
@@ -66,6 +67,7 @@ class PathLike(Protocol):
|
|
|
66
67
|
# In type annotations, use Union[Path, str] instead of FilePath for now
|
|
67
68
|
# This preserves compatibility with existing code while we migrate
|
|
68
69
|
FilePath = Union[Path, str]
|
|
70
|
+
WINDOWS_LOG_FILE_RETENTION = 5
|
|
69
71
|
|
|
70
72
|
|
|
71
73
|
def generate_permalink(file_path: Union[Path, str, PathLike], split_extension: bool = True) -> str:
|
|
@@ -250,7 +252,7 @@ def setup_logging(
|
|
|
250
252
|
log_to_file: bool = False,
|
|
251
253
|
log_to_stdout: bool = False,
|
|
252
254
|
structured_context: bool = False,
|
|
253
|
-
) -> None:
|
|
255
|
+
) -> None:
|
|
254
256
|
"""Configure logging with explicit settings.
|
|
255
257
|
|
|
256
258
|
This function provides a simple, explicit interface for configuring logging.
|
|
@@ -273,8 +275,14 @@ def setup_logging(
|
|
|
273
275
|
|
|
274
276
|
# Add file handler with rotation
|
|
275
277
|
if log_to_file:
|
|
276
|
-
|
|
278
|
+
# Trigger: Windows does not allow renaming an open file held by another process.
|
|
279
|
+
# Why: multiple basic-memory processes can share the same log directory at once.
|
|
280
|
+
# Outcome: use per-process log files on Windows so log rotation stays local.
|
|
281
|
+
log_filename = f"basic-memory-{os.getpid()}.log" if os.name == "nt" else "basic-memory.log"
|
|
282
|
+
log_path = Path.home() / ".basic-memory" / log_filename
|
|
277
283
|
log_path.parent.mkdir(parents=True, exist_ok=True)
|
|
284
|
+
if os.name == "nt":
|
|
285
|
+
_cleanup_windows_log_files(log_path.parent, log_path.name)
|
|
278
286
|
# Keep logging synchronous (enqueue=False) to avoid background logging threads.
|
|
279
287
|
# Background threads are a common source of "hang on exit" issues in CLI/test runs.
|
|
280
288
|
logger.add(
|
|
@@ -308,6 +316,28 @@ def setup_logging(
|
|
|
308
316
|
logging.getLogger("watchfiles.main").setLevel(logging.WARNING)
|
|
309
317
|
|
|
310
318
|
|
|
319
|
+
def _cleanup_windows_log_files(log_dir: Path, current_log_name: str) -> None:
|
|
320
|
+
"""Trim stale per-process Windows log files so the directory stays bounded."""
|
|
321
|
+
stale_logs = [
|
|
322
|
+
path
|
|
323
|
+
for path in log_dir.glob("basic-memory-*.log*")
|
|
324
|
+
if path.is_file() and path.name != current_log_name
|
|
325
|
+
]
|
|
326
|
+
|
|
327
|
+
if len(stale_logs) <= WINDOWS_LOG_FILE_RETENTION - 1:
|
|
328
|
+
return
|
|
329
|
+
|
|
330
|
+
# Trigger: per-process log filenames avoid Windows rename contention but fragment retention.
|
|
331
|
+
# Why: loguru retention applies per sink, not across the whole basic-memory log directory.
|
|
332
|
+
# Outcome: keep only the newest stale PID logs so repeated CLI/server launches stay bounded.
|
|
333
|
+
stale_logs.sort(key=lambda path: path.stat().st_mtime, reverse=True)
|
|
334
|
+
for stale_log in stale_logs[WINDOWS_LOG_FILE_RETENTION - 1 :]:
|
|
335
|
+
try:
|
|
336
|
+
stale_log.unlink()
|
|
337
|
+
except OSError:
|
|
338
|
+
logger.debug("Failed to delete stale Windows log file: {path}", path=stale_log)
|
|
339
|
+
|
|
340
|
+
|
|
311
341
|
def parse_tags(tags: Union[List[str], str, None]) -> List[str]:
|
|
312
342
|
"""Parse tags from various input formats into a consistent list.
|
|
313
343
|
|
|
@@ -356,6 +386,36 @@ def parse_tags(tags: Union[List[str], str, None]) -> List[str]:
|
|
|
356
386
|
return []
|
|
357
387
|
|
|
358
388
|
|
|
389
|
+
def coerce_list(v: Any) -> Any:
|
|
390
|
+
"""Coerce string input to list for MCP clients that serialize lists as strings."""
|
|
391
|
+
if v is None:
|
|
392
|
+
return v
|
|
393
|
+
if isinstance(v, str):
|
|
394
|
+
try:
|
|
395
|
+
parsed = json.loads(v)
|
|
396
|
+
if isinstance(parsed, list):
|
|
397
|
+
return parsed
|
|
398
|
+
except (json.JSONDecodeError, TypeError):
|
|
399
|
+
pass
|
|
400
|
+
# Single string value — wrap in a list
|
|
401
|
+
return [v]
|
|
402
|
+
return v
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
def coerce_dict(v: Any) -> Any:
|
|
406
|
+
"""Coerce string input to dict for MCP clients that serialize dicts as strings."""
|
|
407
|
+
if v is None:
|
|
408
|
+
return v
|
|
409
|
+
if isinstance(v, str):
|
|
410
|
+
try:
|
|
411
|
+
parsed = json.loads(v)
|
|
412
|
+
if isinstance(parsed, dict):
|
|
413
|
+
return parsed
|
|
414
|
+
except (json.JSONDecodeError, TypeError):
|
|
415
|
+
pass
|
|
416
|
+
return v
|
|
417
|
+
|
|
418
|
+
|
|
359
419
|
def normalize_newlines(multiline: str) -> str:
|
|
360
420
|
"""Replace any \r\n, \r, or \n with the native newline.
|
|
361
421
|
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""Integration tests for MCP tools accepting string-serialized list/dict params.
|
|
2
|
+
|
|
3
|
+
Goes through the full FastMCP Client → validate_call → tool function path,
|
|
4
|
+
which is where Pydantic rejects strings for list/dict params.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
from fastmcp import Client
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.mark.asyncio
|
|
12
|
+
async def test_search_notes_entity_types_as_string(mcp_server, app, test_project):
|
|
13
|
+
"""search_notes should accept entity_types as a JSON string via MCP protocol."""
|
|
14
|
+
async with Client(mcp_server) as client:
|
|
15
|
+
await client.call_tool(
|
|
16
|
+
"write_note",
|
|
17
|
+
{
|
|
18
|
+
"project": test_project.name,
|
|
19
|
+
"title": "Entity Type Coerce Test",
|
|
20
|
+
"directory": "test",
|
|
21
|
+
"content": "# Test\nContent for entity type coercion",
|
|
22
|
+
},
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# MCP client sends entity_types as a string
|
|
26
|
+
result = await client.call_tool(
|
|
27
|
+
"search_notes",
|
|
28
|
+
{
|
|
29
|
+
"project": test_project.name,
|
|
30
|
+
"query": "coercion",
|
|
31
|
+
"entity_types": '["entity"]',
|
|
32
|
+
},
|
|
33
|
+
)
|
|
34
|
+
text = result.content[0].text
|
|
35
|
+
assert "Search Failed" not in text
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@pytest.mark.asyncio
|
|
39
|
+
async def test_search_notes_note_types_as_string(mcp_server, app, test_project):
|
|
40
|
+
"""search_notes should accept note_types as a JSON string via MCP protocol."""
|
|
41
|
+
async with Client(mcp_server) as client:
|
|
42
|
+
await client.call_tool(
|
|
43
|
+
"write_note",
|
|
44
|
+
{
|
|
45
|
+
"project": test_project.name,
|
|
46
|
+
"title": "Note Type Coerce Test",
|
|
47
|
+
"directory": "test",
|
|
48
|
+
"content": "# Test\nContent for note type coercion",
|
|
49
|
+
},
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
result = await client.call_tool(
|
|
53
|
+
"search_notes",
|
|
54
|
+
{
|
|
55
|
+
"project": test_project.name,
|
|
56
|
+
"query": "coercion",
|
|
57
|
+
"note_types": '["note"]',
|
|
58
|
+
},
|
|
59
|
+
)
|
|
60
|
+
text = result.content[0].text
|
|
61
|
+
assert "Search Failed" not in text
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@pytest.mark.asyncio
|
|
65
|
+
async def test_search_notes_tags_as_string(mcp_server, app, test_project):
|
|
66
|
+
"""search_notes should accept tags as a JSON string via MCP protocol."""
|
|
67
|
+
async with Client(mcp_server) as client:
|
|
68
|
+
await client.call_tool(
|
|
69
|
+
"write_note",
|
|
70
|
+
{
|
|
71
|
+
"project": test_project.name,
|
|
72
|
+
"title": "Tags Coerce Test",
|
|
73
|
+
"directory": "test",
|
|
74
|
+
"content": "# Test\nTagged content for coercion",
|
|
75
|
+
"tags": "alpha",
|
|
76
|
+
},
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
result = await client.call_tool(
|
|
80
|
+
"search_notes",
|
|
81
|
+
{
|
|
82
|
+
"project": test_project.name,
|
|
83
|
+
"query": "tagged",
|
|
84
|
+
"tags": '["alpha"]',
|
|
85
|
+
},
|
|
86
|
+
)
|
|
87
|
+
text = result.content[0].text
|
|
88
|
+
assert "Search Failed" not in text
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@pytest.mark.asyncio
|
|
92
|
+
async def test_search_notes_metadata_filters_as_string(mcp_server, app, test_project):
|
|
93
|
+
"""search_notes should accept metadata_filters as a JSON string via MCP protocol."""
|
|
94
|
+
async with Client(mcp_server) as client:
|
|
95
|
+
await client.call_tool(
|
|
96
|
+
"write_note",
|
|
97
|
+
{
|
|
98
|
+
"project": test_project.name,
|
|
99
|
+
"title": "Metadata Coerce Test",
|
|
100
|
+
"directory": "test",
|
|
101
|
+
"content": "# Test\nMetadata content for coercion",
|
|
102
|
+
},
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
result = await client.call_tool(
|
|
106
|
+
"search_notes",
|
|
107
|
+
{
|
|
108
|
+
"project": test_project.name,
|
|
109
|
+
"query": "metadata",
|
|
110
|
+
"metadata_filters": '{"type": "note"}',
|
|
111
|
+
},
|
|
112
|
+
)
|
|
113
|
+
text = result.content[0].text
|
|
114
|
+
assert "Search Failed" not in text
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@pytest.mark.asyncio
|
|
118
|
+
async def test_write_note_metadata_as_string(mcp_server, app, test_project):
|
|
119
|
+
"""write_note should accept metadata as a JSON string via MCP protocol."""
|
|
120
|
+
async with Client(mcp_server) as client:
|
|
121
|
+
result = await client.call_tool(
|
|
122
|
+
"write_note",
|
|
123
|
+
{
|
|
124
|
+
"project": test_project.name,
|
|
125
|
+
"title": "String Metadata Note",
|
|
126
|
+
"directory": "test",
|
|
127
|
+
"content": "# Test\nWith string metadata",
|
|
128
|
+
"metadata": '{"priority": "high"}',
|
|
129
|
+
},
|
|
130
|
+
)
|
|
131
|
+
text = result.content[0].text
|
|
132
|
+
assert "Created note" in text or "Updated note" in text
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
@pytest.mark.asyncio
|
|
136
|
+
async def test_canvas_nodes_edges_as_string(mcp_server, app, test_project):
|
|
137
|
+
"""canvas should accept nodes and edges as JSON strings via MCP protocol."""
|
|
138
|
+
import json
|
|
139
|
+
|
|
140
|
+
nodes = [
|
|
141
|
+
{
|
|
142
|
+
"id": "n1",
|
|
143
|
+
"type": "text",
|
|
144
|
+
"text": "Hello",
|
|
145
|
+
"x": 0,
|
|
146
|
+
"y": 0,
|
|
147
|
+
"width": 200,
|
|
148
|
+
"height": 100,
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
edges = [
|
|
152
|
+
{"id": "e1", "fromNode": "n1", "toNode": "n1", "label": "self"}
|
|
153
|
+
]
|
|
154
|
+
|
|
155
|
+
async with Client(mcp_server) as client:
|
|
156
|
+
result = await client.call_tool(
|
|
157
|
+
"canvas",
|
|
158
|
+
{
|
|
159
|
+
"project": test_project.name,
|
|
160
|
+
"title": "Coerce Canvas Test",
|
|
161
|
+
"directory": "test",
|
|
162
|
+
"nodes": json.dumps(nodes),
|
|
163
|
+
"edges": json.dumps(edges),
|
|
164
|
+
},
|
|
165
|
+
)
|
|
166
|
+
text = result.content[0].text
|
|
167
|
+
assert "Created" in text or "Updated" in text
|
|
@@ -237,6 +237,29 @@ class TestBuildChunkRecords:
|
|
|
237
237
|
records = self.repo._build_chunk_records(rows)
|
|
238
238
|
assert any("99" in r["chunk_key"] for r in records)
|
|
239
239
|
|
|
240
|
+
def test_duplicate_rows_collapse_to_unique_chunk_keys(self):
|
|
241
|
+
rows = [
|
|
242
|
+
_make_row(
|
|
243
|
+
row_type=SearchItemType.ENTITY.value,
|
|
244
|
+
title="Spec",
|
|
245
|
+
permalink="spec",
|
|
246
|
+
content_snippet="shared content",
|
|
247
|
+
row_id=77,
|
|
248
|
+
),
|
|
249
|
+
_make_row(
|
|
250
|
+
row_type=SearchItemType.ENTITY.value,
|
|
251
|
+
title="Spec",
|
|
252
|
+
permalink="spec",
|
|
253
|
+
content_snippet="shared content",
|
|
254
|
+
row_id=77,
|
|
255
|
+
),
|
|
256
|
+
]
|
|
257
|
+
|
|
258
|
+
records = self.repo._build_chunk_records(rows)
|
|
259
|
+
|
|
260
|
+
assert len(records) == 1
|
|
261
|
+
assert records[0]["chunk_key"] == "entity:77:0"
|
|
262
|
+
|
|
240
263
|
|
|
241
264
|
# --- SQLite SemanticSearchDisabledError ---
|
|
242
265
|
|