mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
remove EntityContent from markdown
This commit is contained in:
@@ -4,7 +4,6 @@ from basic_memory.file_utils import ParseError
|
||||
from basic_memory.markdown.entity_parser import EntityParser
|
||||
from basic_memory.markdown.schemas import (
|
||||
EntityMarkdown,
|
||||
EntityContent,
|
||||
EntityFrontmatter,
|
||||
Observation,
|
||||
Relation,
|
||||
@@ -12,7 +11,6 @@ from basic_memory.markdown.schemas import (
|
||||
|
||||
__all__ = [
|
||||
"EntityMarkdown",
|
||||
"EntityContent",
|
||||
"EntityFrontmatter",
|
||||
"EntityParser",
|
||||
"Observation",
|
||||
|
||||
@@ -15,7 +15,6 @@ from basic_memory.markdown.plugins import observation_plugin, relation_plugin
|
||||
from basic_memory.markdown.schemas import (
|
||||
EntityMarkdown,
|
||||
EntityFrontmatter,
|
||||
EntityContent,
|
||||
Observation,
|
||||
Relation,
|
||||
)
|
||||
@@ -103,18 +102,13 @@ class EntityParser:
|
||||
rels = token.meta["relations"]
|
||||
relations.extend([Relation.model_validate(r) for r in rels])
|
||||
|
||||
# Create EntityContent
|
||||
entity_content = EntityContent(
|
||||
return EntityMarkdown(
|
||||
frontmatter=entity_frontmatter,
|
||||
content=post.content,
|
||||
observations=observations,
|
||||
relations=relations,
|
||||
)
|
||||
|
||||
return EntityMarkdown(
|
||||
frontmatter=entity_frontmatter,
|
||||
content=entity_content,
|
||||
)
|
||||
|
||||
def parse_tags(self, tags: Any) -> list[str]:
|
||||
"""Parse tags into list of strings."""
|
||||
if isinstance(tags, str):
|
||||
|
||||
@@ -104,23 +104,28 @@ class MarkdownProcessor:
|
||||
frontmatter_dict = {
|
||||
"type": markdown.frontmatter.type,
|
||||
"permalink": markdown.frontmatter.permalink,
|
||||
"created": markdown.frontmatter.created.isoformat() if markdown.frontmatter.created else None,
|
||||
"modified": markdown.frontmatter.modified.isoformat() if markdown.frontmatter.modified else None,
|
||||
**metadata
|
||||
"created": markdown.frontmatter.created.isoformat()
|
||||
if markdown.frontmatter.created
|
||||
else None,
|
||||
"modified": markdown.frontmatter.modified.isoformat()
|
||||
if markdown.frontmatter.modified
|
||||
else None,
|
||||
**metadata,
|
||||
}
|
||||
frontmatter_dict = {k: v for k, v in frontmatter_dict.items() if v is not None}
|
||||
|
||||
# Start with user content (or minimal title for new files)
|
||||
content = markdown.content.content or f"# {markdown.frontmatter.title}\n"
|
||||
content = markdown.content or f"# {markdown.frontmatter.title}\n"
|
||||
|
||||
# Add structured sections if present
|
||||
if markdown.content.observations:
|
||||
content += (
|
||||
"\n\n## Observations\n\n"
|
||||
+ self.format_observations(markdown.content.observations)
|
||||
# Add structured sections with proper spacing
|
||||
content = content.rstrip() # Remove trailing whitespace
|
||||
|
||||
if markdown.observations:
|
||||
content += "\n\n## Observations\n\n" + self.format_observations(
|
||||
markdown.observations
|
||||
)
|
||||
if markdown.content.relations:
|
||||
content += "\n## Relations\n\n" + self.format_relations(markdown.content.relations)
|
||||
if markdown.relations:
|
||||
content += "\n\n## Relations\n\n" + self.format_relations(markdown.relations)
|
||||
|
||||
# Create Post object for frontmatter
|
||||
post = Post(content, **frontmatter_dict)
|
||||
|
||||
@@ -66,16 +66,11 @@ class EntityFrontmatter(BaseModel):
|
||||
def modified(self) -> datetime:
|
||||
return self.metadata.get("modified") if self.metadata else None
|
||||
|
||||
class EntityContent(BaseModel):
|
||||
"""Content sections of an entity markdown file."""
|
||||
|
||||
content: Optional[str] = None
|
||||
observations: List[Observation] = []
|
||||
relations: List[Relation] = []
|
||||
|
||||
|
||||
class EntityMarkdown(BaseModel):
|
||||
"""Complete entity combining frontmatter, content, and metadata."""
|
||||
|
||||
frontmatter: EntityFrontmatter
|
||||
content: EntityContent
|
||||
content: Optional[str] = None
|
||||
observations: List[Observation] = []
|
||||
relations: List[Relation] = []
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
from typing import Optional
|
||||
|
||||
from basic_memory.markdown import EntityMarkdown, EntityFrontmatter, EntityContent, Observation, Relation
|
||||
from basic_memory.markdown import EntityMarkdown, EntityFrontmatter, Observation, Relation
|
||||
from basic_memory.models import Entity
|
||||
|
||||
|
||||
class EntityModel:
|
||||
pass
|
||||
|
||||
|
||||
def entity_model_to_markdown(entity: EntityModel, content: Optional[str] = None) -> EntityMarkdown:
|
||||
def entity_model_to_markdown(entity: Entity, content: Optional[str] = None) -> EntityMarkdown:
|
||||
"""Convert entity model to markdown schema.
|
||||
|
||||
Args:
|
||||
@@ -17,18 +14,15 @@ def entity_model_to_markdown(entity: EntityModel, content: Optional[str] = None)
|
||||
Returns:
|
||||
EntityMarkdown schema
|
||||
"""
|
||||
metadata=entity.entity_metadata or {}
|
||||
metadata = entity.entity_metadata or {}
|
||||
metadata["permalink"] = entity.permalink
|
||||
metadata["type"] = entity.entity_type or "note"
|
||||
metadata["title"] = entity.title
|
||||
metadata["created"] = entity.created_at
|
||||
metadata["modified"] = entity.updated_at
|
||||
|
||||
entity_frontmatter = EntityFrontmatter(
|
||||
metadata=metadata
|
||||
)
|
||||
|
||||
entity_content = EntityContent(
|
||||
return EntityMarkdown(
|
||||
frontmatter=EntityFrontmatter(metadata=metadata),
|
||||
content=content, # Use provided content
|
||||
observations=[
|
||||
Observation(
|
||||
@@ -37,11 +31,7 @@ def entity_model_to_markdown(entity: EntityModel, content: Optional[str] = None)
|
||||
for obs in entity.observations
|
||||
],
|
||||
relations=[
|
||||
Relation(type=r.relation_type, target=r.to_entity.title, context=r.context) for r in entity.outgoing_relations
|
||||
Relation(type=r.relation_type, target=r.to_entity.title, context=r.context)
|
||||
for r in entity.outgoing_relations
|
||||
],
|
||||
)
|
||||
|
||||
return EntityMarkdown(
|
||||
frontmatter=entity_frontmatter,
|
||||
content=entity_content,
|
||||
)
|
||||
|
||||
@@ -6,13 +6,10 @@ from typing import Optional, Tuple
|
||||
from loguru import logger
|
||||
|
||||
from basic_memory import file_utils
|
||||
from basic_memory.markdown import EntityFrontmatter, EntityContent, EntityMarkdown, Observation, Relation
|
||||
from basic_memory.markdown.markdown_processor import MarkdownProcessor
|
||||
from basic_memory.markdown.utils import entity_model_to_markdown
|
||||
from basic_memory.services.exceptions import FileOperationError
|
||||
from basic_memory.models import Entity as EntityModel
|
||||
|
||||
|
||||
from basic_memory.services.exceptions import FileOperationError
|
||||
|
||||
|
||||
class FileService:
|
||||
@@ -75,7 +72,7 @@ class FileService:
|
||||
# merge content with entity
|
||||
# if content is supplied use it or existing content
|
||||
markdown = entity_model_to_markdown(
|
||||
entity, content=content or existing_markdown.content.content
|
||||
entity, content=content or existing_markdown.content
|
||||
)
|
||||
else:
|
||||
# Create new file structure with provided content
|
||||
@@ -109,7 +106,7 @@ class FileService:
|
||||
try:
|
||||
file_path = self.get_entity_path(entity)
|
||||
markdown = await self.markdown_processor.read_file(file_path)
|
||||
return markdown.content.content or ""
|
||||
return markdown.content or ""
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to read entity content: {e}")
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
"""Service for managing entities in the database."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from loguru import logger
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
from basic_memory.models import Entity as EntityModel, Observation, Relation, ObservationCategory
|
||||
from basic_memory.markdown.schemas import EntityMarkdown
|
||||
from basic_memory.utils import generate_permalink
|
||||
from basic_memory.models import Entity as EntityModel, Observation, Relation, ObservationCategory
|
||||
from basic_memory.repository import EntityRepository, ObservationRepository, RelationRepository
|
||||
from basic_memory.services.exceptions import EntityNotFoundError
|
||||
from basic_memory.services.link_resolver import LinkResolver
|
||||
from basic_memory.utils import generate_permalink
|
||||
|
||||
|
||||
def entity_model_from_markdown(file_path: str, markdown: EntityMarkdown) -> EntityModel:
|
||||
@@ -38,7 +39,7 @@ def entity_model_from_markdown(file_path: str, markdown: EntityMarkdown) -> Enti
|
||||
updated_at=markdown.frontmatter.modified,
|
||||
observations=[
|
||||
Observation(content=obs.content, category=get_valid_category(obs), context=obs.context)
|
||||
for obs in markdown.content.observations
|
||||
for obs in markdown.observations
|
||||
],
|
||||
)
|
||||
return model
|
||||
@@ -78,18 +79,18 @@ class EntitySyncService:
|
||||
# Set timestamps from frontmatter
|
||||
created_at = markdown.frontmatter.created
|
||||
updated_at = markdown.frontmatter.modified
|
||||
|
||||
|
||||
model.created_at = created_at
|
||||
model.updated_at = updated_at
|
||||
|
||||
|
||||
for obs in model.observations:
|
||||
obs.created_at = created_at
|
||||
obs.updated_at = updated_at
|
||||
|
||||
|
||||
for rel in model.relations:
|
||||
rel.created_at = created_at
|
||||
rel.updated_at = updated_at
|
||||
|
||||
|
||||
return await self.entity_repository.add(model)
|
||||
|
||||
async def update_entity_and_observations(
|
||||
@@ -108,7 +109,7 @@ class EntitySyncService:
|
||||
# Update fields from markdown
|
||||
db_entity.title = markdown.frontmatter.title
|
||||
db_entity.entity_type = markdown.frontmatter.type
|
||||
db_entity.summary = markdown.content.content
|
||||
db_entity.summary = markdown.content
|
||||
|
||||
# Clear observations for entity
|
||||
await self.observation_repository.delete_by_fields(entity_id=db_entity.id)
|
||||
@@ -121,7 +122,7 @@ class EntitySyncService:
|
||||
category=obs.category,
|
||||
context=obs.context,
|
||||
)
|
||||
for obs in markdown.content.observations
|
||||
for obs in markdown.observations
|
||||
]
|
||||
await self.observation_repository.add_all(observations)
|
||||
|
||||
@@ -153,13 +154,13 @@ class EntitySyncService:
|
||||
await self.relation_repository.delete_outgoing_relations_from_entity(db_entity.id)
|
||||
|
||||
# Process each relation
|
||||
for rel in markdown.content.relations:
|
||||
for rel in markdown.relations:
|
||||
# Resolve the target permalink
|
||||
target_entity = await self.link_resolver.resolve_link(
|
||||
rel.target,
|
||||
)
|
||||
|
||||
# if the target is found, store the id
|
||||
# if the target is found, store the id
|
||||
target_id = target_entity.id if target_entity else None
|
||||
# if the target is found, store the title, otherwise add the target for a "forward link"
|
||||
target_name = target_entity.title if target_entity else rel.target
|
||||
|
||||
Reference in New Issue
Block a user