Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/DOMAIN_MODEL.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ which graph and search projections attach.
- `permalink` is the human/agent-facing semantic address for Markdown content. It is
project-scoped, may be absent when permalinks are disabled or inapplicable, and changes only
according to the configured move and permalink policies.
- Non-Markdown entities always have `permalink=None`. `external_id` is their stable API identity,
and `file_path` locates the stored resource; a database-only permalink would not round-trip
through the source file.
- `title` is mutable display metadata, not identity.
- For Markdown notes, `created_at` and `updated_at` project the canonical `created` and `modified`
frontmatter values. Missing values fall back independently to file ctime and mtime for legacy
Expand Down
3 changes: 2 additions & 1 deletion src/basic_memory/indexing/batch_indexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,8 @@ async def _upsert_regular_file(self, file: IndexInputFile) -> _PreparedEntity:
is_new_entity = existing is None

if existing is None:
await self.entity_service.resolve_permalink(file.path, skip_conflict_check=True)
# Non-Markdown resources cannot persist a semantic address back to source bytes.
# Their stable API identity is external_id; file_path locates the stored resource.
entity = Entity(
note_type="file",
file_path=file.path,
Expand Down
8 changes: 8 additions & 0 deletions tests/indexing/test_batch_indexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ async def test_batch_indexer_indexes_non_markdown_files(
search_service,
file_service,
project_config,
monkeypatch,
):
pdf_path = "assets/doc.pdf"
image_path = "assets/image.png"
Expand All @@ -357,6 +358,10 @@ async def test_batch_indexer_indexes_non_markdown_files(
pdf_path: await _load_input(file_service, pdf_path),
image_path: await _load_input(file_service, image_path),
}
resolve_permalink = AsyncMock(
side_effect=AssertionError("non-Markdown files must not resolve permalinks")
)
monkeypatch.setattr(entity_service, "resolve_permalink", resolve_permalink)
batch_indexer = _make_batch_indexer(
app_config,
entity_service,
Expand All @@ -380,8 +385,11 @@ async def test_batch_indexer_indexes_non_markdown_files(
image_entity = await entity_repository.get_by_file_path(session, image_path)
assert pdf_entity is not None
assert pdf_entity.content_type == "application/pdf"
assert pdf_entity.permalink is None
assert image_entity is not None
assert image_entity.content_type == "image/png"
assert image_entity.permalink is None
resolve_permalink.assert_not_awaited()


@pytest.mark.asyncio
Expand Down
Loading