Commit Graph

561 Commits

Author SHA1 Message Date
phernandez b367ccbdb8 fix: update tests and fix bugs for project-prefixed permalinks
- Fix update_entity overwriting project-prefixed permalink with
  non-prefixed one during metadata merge
- Fix memory:// URL path traversal validation bypass in read_note
  and read_content tools
- Fix pyright type error in claude_projects_importer
- Update test assertions across 12 test files to use project-prefixed
  permalinks (test-project/path instead of path)
- Fix monkeypatch in search test to use resolve_project_and_path
  instead of removed get_active_project

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2026-02-13 15:39:11 -06:00
phernandez c6511aa745 feat: enable project-prefixed permalinks
Signed-off-by: phernandez <paul@basicmachines.co>
2026-02-13 15:39:10 -06:00
Paul Hernandez 8bc03d1357 feat(mcp): add MCP UI variants and TUI output (#545)
Signed-off-by: phernandez <paul@basicmachines.co>
2026-02-13 15:21:48 -06:00
Paul Hernandez 7624a20d8d feat: isolate default sqlite db by config dir (#567)
Signed-off-by: phernandez <paul@basicmachines.co>
2026-02-13 11:11:13 -06:00
Paul Hernandez d84708ca7f feat: add per-project local/cloud routing with API key auth (#555)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 09:52:50 -06:00
Paul Hernandez 1428d18de1 fix: make semantic search dependencies optional extras (#566)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 21:46:26 -06:00
Paul Hernandez 312662f382 feat: Add cloud discovery touchpoints to CLI and MCP (#546)
Signed-off-by: phernandez <paul@basicmachines.co>
2026-02-12 21:01:45 -06:00
Paul Hernandez ed9487708e feat: enable default_project_mode by default (#560)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 20:34:46 -06:00
Paul Hernandez 8df88e4d02 feat: add basic-memory watch CLI command (#559)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 20:10:09 -06:00
Paul Hernandez 07778790d3 feat: add semantic vector search for SQLite and Postgres (#550)
Signed-off-by: phernandez <paul@basicmachines.co>
Signed-off-by: bm-clawd <clawd@basicmemory.com>
Co-authored-by: bm-clawd <clawd@basicmemory.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 15:44:47 -06:00
Paul Hernandez b609c4e531 fix: use global --header for Tigris consistency on all rclone transactions (#564)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 15:43:05 -06:00
phernandez 2b94d9a278 fix formatting for tigris headers
Signed-off-by: phernandez <paul@basicmachines.co>
2026-02-12 13:22:31 -06:00
Paul Hernandez c97733d785 feat: Schema system for Basic Memory (#549)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 15:04:42 -06:00
Paul Hernandez 8489a3d37e fix: add X-Tigris-Consistent headers to all rclone commands (#558)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 14:22:49 -06:00
Paul Hernandez a47c9c021f feat: add --format json to CLI tool commands (#552)
Signed-off-by: phernandez <paul@basicmachines.co>
Signed-off-by: bm-clawd <clawd@basicmemory.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: bm-clawd <clawd@basicmemory.com>
2026-02-08 14:56:29 -06:00
Paul Hernandez 343a6e118b fix: Handle EntityCreationError as conflict (#541)
Signed-off-by: phernandez <paul@basicmachines.co>
2026-02-03 22:28:58 -06:00
phernandez a0e754b7ae fix: restore legacy /projects/projects endpoint for older CLI versions
Older versions of basic-memory CLI (v0.17.4 and earlier) call
GET /projects/projects to list projects. This endpoint was removed
when we migrated to v2 routers.

Add explicit route at /projects/projects (without trailing slash) to
avoid 307 redirects that the cloud proxy doesn't follow.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2026-02-02 22:26:48 -06:00
Paul Hernandez 24ca5f6804 fix: recent_activity prompt defaults (#533)
Signed-off-by: phernandez <paul@basicmachines.co>
2026-02-02 19:22:33 -06:00
Paul Hernandez f1d50c2ba7 feat: Support tag: query shorthand in search (#535)
Signed-off-by: phernandez <paul@basicmachines.co>
2026-02-02 19:22:16 -06:00
Paul Hernandez 8072449a78 chore: Add fast feedback loop tooling (#538)
Signed-off-by: phernandez <paul@basicmachines.co>
2026-02-01 23:04:59 -06:00
Paul Hernandez 009e84926d fix: stabilize metadata filters on postgres (#536)
Signed-off-by: phernandez <paul@basicmachines.co>
2026-01-31 22:31:00 -06:00
phernandez 8838571509 Add metadata filter tests and fix fast write external_id
Signed-off-by: phernandez <paul@basicmachines.co>
2026-01-31 15:27:05 -06:00
Paul Hernandez 530cbac73f feat: fast edit entities, refactors for webui, enhance search (#532)
Signed-off-by: phernandez <paul@basicmachines.co>
2026-01-31 15:16:52 -06:00
Paul Hernandez e3ced49d9d fix: prevent spurious 'metadata: {}' in frontmatter output (#530)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 12:17:10 -06:00
Drew Cain 0023e736ab feat: add context-aware wiki link resolution with source_path support (#527)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 19:11:41 -06:00
Paul Hernandez 0b2080114b feat: add directory support to move_note and delete_note tools (#518)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 19:52:10 -06:00
Paul Hernandez 8730067f3a feat: Feature/517 local mcp cloud mode (#522)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 19:51:49 -06:00
Drew Cain e14ba92631 fix: resolve MCP prompt rendering errors (#524)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 19:14:41 -06:00
Paul Hernandez 17c0e0a29b fix: check config default_project only in local mode for remove_project (#523)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 12:53:44 -06:00
Paul Hernandez 6888effef2 fix: correct get_default_project() query to check for True instead of not NULL (#521)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 11:37:05 -06:00
Paul Hernandez 369ad37b3d feat: add SPEC-29 Phase 3 bucket snapshot CLI commands (#476)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 17:55:01 -06:00
Paul Hernandez c7835a9d5c fix: ensure external_id is set on entity creation (#512) (#513)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 11:14:48 -06:00
Paul Hernandez 85835ae533 chore: Remove OpenPanel telemetry (#514)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 22:24:27 -06:00
Paul Hernandez 863e0a4e24 fix: prevent CLI commands from hanging on exit (Python 3.14) (#505)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 16:47:35 -06:00
Paul Hernandez 26f7e98932 fix: preserve search index across server restarts (#503)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude <noreply@anthropic.com>
2026-01-05 21:31:35 -06:00
Paul Hernandez 5947f04bd3 refactor: composition roots, deps split, and typed API clients (#490 roadmap) (#502)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 11:05:58 -06:00
Paul Hernandez b4486d20bd test: remove stdlib mocks, strengthen integration coverage (#489)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 14:22:01 -06:00
jope-bm a4000f64ce feat: add stable external_id (UUID) to Project and Entity models (#485)
Signed-off-by: Joe P <joe@basicmemory.com>
Signed-off-by: Paul Hernandez <60959+phernandez@users.noreply.github.com>
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Paul Hernandez <60959+phernandez@users.noreply.github.com>
Co-authored-by: phernandez <paul@basicmachines.co>
2026-01-02 13:00:35 -06:00
phernandez 4ce21984a4 fix: use upsert to prevent IntegrityError during parallel search indexing
Replace delete-then-insert pattern with INSERT ... ON CONFLICT for
PostgreSQL search index operations. This fixes race conditions where
parallel entity indexing could cause UniqueViolationError on the
uix_search_index_permalink_project constraint.

Changes:
- Add index_item() override in PostgresSearchRepository with upsert
- Update bulk_index_items() to use ON CONFLICT (permalink, project_id)
- Add CREATE_POSTGRES_SEARCH_INDEX_PERMALINK DDL for test fixtures
- Add tests for upsert behavior on duplicate permalinks

Technical note: Use column-based ON CONFLICT syntax instead of
ON CONSTRAINT (which only works for table constraints, not indexes).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2025-12-30 21:55:43 -06:00
phernandez 8adf1f4ed4 fix: use relative file paths in importers for cloud storage compatibility
Importers now use relative file paths (based on permalink) instead of
absolute paths. This enables proper S3 key generation in cloud environments.

Changes:
- write_entity() accepts str | Path for file_path parameter
- ensure_folder_exists() uses relative paths directly
- All importers pass relative paths to FileService
- FileService handles base_path resolution internally

This prevents S3 keys from including container filesystem paths like
`/app/basic-memory/imports/...` and instead uses clean relative paths
like `imports/20241010-file.md`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2025-12-30 20:29:01 -06:00
phernandez 45ce1813e4 refactor: use FileService in importers for cloud compatibility
Refactor importers to use FileService for all file operations instead of
direct filesystem calls. This enables cloud environments to override file
operations via dependency injection (e.g., S3FileService).

Changes:
- Add `to_markdown_string()` method to MarkdownProcessor for content
  serialization without file I/O
- Update Importer base class to accept FileService and use it for:
  - `write_entity()` - now uses FileService.write_file()
  - `ensure_folder_exists()` - now async, uses FileService.ensure_directory()
- Fix direct `mkdir()` calls in:
  - claude_projects_importer.py
  - memory_json_importer.py
- Update deps.py to inject FileService into all importers (v1 and v2)
- Update CLI commands to create and pass FileService to importers
- Update tests to work with new FileService dependency

This follows the pattern used by /knowledge API and SyncService, enabling
cloud to override file operations by providing S3FileService via DI.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2025-12-30 19:21:32 -06:00
Paul Hernandez fd732aa6fe fix: set_default_project skips config file update in cloud mode (#486)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 09:05:48 -06:00
Paul Hernandez 537e58ad7d fix: make RelationResponse.from_id optional to handle null permalinks (#484)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 08:12:29 -06:00
phernandez 0bcda4a14a fix: allow recent_activity discovery mode in cloud mode
Add `allow_discovery` parameter to `resolve_project_parameter()` that
enables tools like `recent_activity` to work across all projects in
cloud mode without requiring a project parameter.

- Add `allow_discovery: bool = False` param to resolve_project_parameter
- In cloud mode with allow_discovery=True, return None instead of error
- Update recent_activity to use allow_discovery=True
- Fix circular import by deferring call_get import inside functions
- Add comprehensive tests for resolve_project_parameter

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2025-12-29 16:22:48 -06:00
Paul Hernandez 856737fe3c feat: add anonymous usage telemetry (Homebrew-style opt-out) (#478)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 22:09:48 -06:00
Paul Hernandez 1fd680c3f1 feat: add auto-format files on save with built-in Python formatter (#474)
Signed-off-by: Cedric Hurst <cedric@spantree.net>
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Cedric Hurst <cedric@spantree.net>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Sebastian B Otaegui <feniix@users.noreply.github.com>
Co-authored-by: Cedric Hurst <cedric@divideby0.io>
2025-12-24 15:39:22 -06:00
phernandez 85684f848f fix: handle UTF-8 BOM in frontmatter parsing
Fixes #452 - Imported conversations not fully indexed

Files with UTF-8 BOM (Byte Order Mark) at the start would fail frontmatter
detection, causing:
- Title to fall back to filename instead of frontmatter value
- Permalink to be null in the database

Added strip_bom() helper function and updated all frontmatter-related
functions to strip BOM before processing:
- has_frontmatter()
- parse_frontmatter()
- remove_frontmatter()
- EntityParser.parse_markdown_content()

Added comprehensive tests for BOM handling with various scenarios.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2025-12-24 14:28:50 -06:00
Paul Hernandez 14ce5a3bd0 fix: handle null titles in ChatGPT import (#475)
Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-24 13:50:30 -06:00
phernandez 45d6caf723 fix: remove MaxLen constraint from observation content
The API Pydantic schema had a MaxLen(1000) constraint on observation
content while the database uses SQLAlchemy's Text type (unlimited).
This mismatch caused validation errors when observations exceeded
1000 characters (e.g., JSON schemas with 1458+ chars).

Removed the MaxLen constraint to match the DB schema. Retained:
- BeforeValidator(str.strip) for whitespace cleaning
- MinLen(1) to ensure non-empty content

Added comprehensive tests to verify:
- Long content (10K+ chars) is accepted
- Very long content (50K+ chars) is accepted
- Empty/whitespace-only content is still rejected
- Whitespace stripping still works

Fixes #385

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2025-12-24 13:41:28 -06:00
phernandez 1652f862dd fix: handle FileNotFoundError gracefully during sync
When a file exists in the database but is missing from the filesystem,
the sync worker now treats this as a deletion instead of crashing.

The sync_file() method catches FileNotFoundError specifically and calls
handle_delete() to clean up the orphaned database record. This prevents
the sync from failing on database/filesystem inconsistencies that can
occur due to race conditions, manual file deletions, or cloud storage
caching issues.

Includes a test to verify the graceful handling behavior.

Fixes #386

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
2025-12-24 13:34:59 -06:00