fix: rename Note.metadata → entity_meta (reserved by SQLAlchemy Declarative API)
SQLAlchemy reserves 'metadata' as a class attribute on declarative models. Renamed to 'entity_meta' with explicit column name 'metadata' so the DB column is unchanged but the Python attribute no longer conflicts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -54,7 +54,8 @@ class Note(Base, TimestampMixin):
|
|||||||
# Entity type — 'note' (default), 'person', 'place', 'list'
|
# Entity type — 'note' (default), 'person', 'place', 'list'
|
||||||
note_type: Mapped[str] = mapped_column(Text, default="note", server_default="note")
|
note_type: Mapped[str] = mapped_column(Text, default="note", server_default="note")
|
||||||
# Structured metadata for entity types (person/place/list)
|
# Structured metadata for entity types (person/place/list)
|
||||||
metadata: Mapped[dict | None] = mapped_column(JSONB, nullable=True)
|
# Named 'entity_meta' to avoid collision with SQLAlchemy's reserved 'metadata' attribute
|
||||||
|
entity_meta: Mapped[dict | None] = mapped_column("metadata", JSONB, nullable=True)
|
||||||
|
|
||||||
__table_args__ = (
|
__table_args__ = (
|
||||||
Index("ix_notes_tags", "tags", postgresql_using="gin"),
|
Index("ix_notes_tags", "tags", postgresql_using="gin"),
|
||||||
@@ -97,7 +98,7 @@ class Note(Base, TimestampMixin):
|
|||||||
),
|
),
|
||||||
"is_task": self.is_task,
|
"is_task": self.is_task,
|
||||||
"note_type": self.entity_type,
|
"note_type": self.entity_type,
|
||||||
"metadata": self.metadata or {},
|
"metadata": self.entity_meta or {},
|
||||||
"created_at": self.created_at.isoformat(),
|
"created_at": self.created_at.isoformat(),
|
||||||
"updated_at": self.updated_at.isoformat(),
|
"updated_at": self.updated_at.isoformat(),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ _SNIPPET_LEN = 200
|
|||||||
|
|
||||||
|
|
||||||
def _note_to_item(note: Note) -> dict:
|
def _note_to_item(note: Note) -> dict:
|
||||||
meta = note.metadata or {}
|
meta = note.entity_meta or {}
|
||||||
item: dict = {
|
item: dict = {
|
||||||
"id": note.id,
|
"id": note.id,
|
||||||
"note_type": note.entity_type,
|
"note_type": note.entity_type,
|
||||||
@@ -184,14 +184,14 @@ async def get_people_and_places_context(user_id: int) -> str:
|
|||||||
if people:
|
if people:
|
||||||
parts = []
|
parts = []
|
||||||
for p in people:
|
for p in people:
|
||||||
meta = p.metadata or {}
|
meta = p.entity_meta or {}
|
||||||
rel = meta.get("relationship", "")
|
rel = meta.get("relationship", "")
|
||||||
parts.append(f"{p.title}" + (f" ({rel})" if rel else ""))
|
parts.append(f"{p.title}" + (f" ({rel})" if rel else ""))
|
||||||
lines.append("Known people: " + ", ".join(parts))
|
lines.append("Known people: " + ", ".join(parts))
|
||||||
if places:
|
if places:
|
||||||
parts = []
|
parts = []
|
||||||
for p in places:
|
for p in places:
|
||||||
meta = p.metadata or {}
|
meta = p.entity_meta or {}
|
||||||
addr = meta.get("address", "")
|
addr = meta.get("address", "")
|
||||||
parts.append(f"{p.title}" + (f" – {addr}" if addr else ""))
|
parts.append(f"{p.title}" + (f" – {addr}" if addr else ""))
|
||||||
lines.append("Known places: " + "; ".join(parts))
|
lines.append("Known places: " + "; ".join(parts))
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ async def create_note(
|
|||||||
due_date: date | None = None,
|
due_date: date | None = None,
|
||||||
recurrence_rule: dict | None = None,
|
recurrence_rule: dict | None = None,
|
||||||
note_type: str = "note",
|
note_type: str = "note",
|
||||||
metadata: dict | None = None,
|
entity_meta: dict | None = None,
|
||||||
) -> Note:
|
) -> Note:
|
||||||
# Auto-populate project_id from milestone when not explicitly provided
|
# Auto-populate project_id from milestone when not explicitly provided
|
||||||
if milestone_id is not None and project_id is None:
|
if milestone_id is not None and project_id is None:
|
||||||
@@ -85,7 +85,7 @@ async def create_note(
|
|||||||
due_date=due_date,
|
due_date=due_date,
|
||||||
recurrence_rule=recurrence_rule,
|
recurrence_rule=recurrence_rule,
|
||||||
note_type=note_type,
|
note_type=note_type,
|
||||||
metadata=metadata,
|
entity_meta=entity_meta,
|
||||||
)
|
)
|
||||||
session.add(note)
|
session.add(note)
|
||||||
await session.commit()
|
await session.commit()
|
||||||
|
|||||||
@@ -2043,7 +2043,7 @@ async def execute_tool(
|
|||||||
body="\n".join(body_lines),
|
body="\n".join(body_lines),
|
||||||
tags=["person"],
|
tags=["person"],
|
||||||
note_type="person",
|
note_type="person",
|
||||||
metadata=meta,
|
entity_meta=meta,
|
||||||
)
|
)
|
||||||
_schedule_embedding(note.id, user_id, name, note.body)
|
_schedule_embedding(note.id, user_id, name, note.body)
|
||||||
return {"success": True, "type": "person", "data": {"id": note.id, "name": name}}
|
return {"success": True, "type": "person", "data": {"id": note.id, "name": name}}
|
||||||
@@ -2075,7 +2075,7 @@ async def execute_tool(
|
|||||||
body="\n".join(body_lines),
|
body="\n".join(body_lines),
|
||||||
tags=["place"],
|
tags=["place"],
|
||||||
note_type="place",
|
note_type="place",
|
||||||
metadata=meta,
|
entity_meta=meta,
|
||||||
)
|
)
|
||||||
_schedule_embedding(note.id, user_id, name, note.body)
|
_schedule_embedding(note.id, user_id, name, note.body)
|
||||||
return {"success": True, "type": "place", "data": {"id": note.id, "name": name}}
|
return {"success": True, "type": "place", "data": {"id": note.id, "name": name}}
|
||||||
@@ -2101,7 +2101,7 @@ async def execute_tool(
|
|||||||
body=body,
|
body=body,
|
||||||
tags=tags,
|
tags=tags,
|
||||||
note_type="list",
|
note_type="list",
|
||||||
metadata=meta,
|
entity_meta=meta,
|
||||||
)
|
)
|
||||||
_schedule_embedding(note.id, user_id, name, body)
|
_schedule_embedding(note.id, user_id, name, body)
|
||||||
return {"success": True, "type": "list", "data": {"id": note.id, "name": name, "item_count": len(items)}}
|
return {"success": True, "type": "list", "data": {"id": note.id, "name": name, "item_count": len(items)}}
|
||||||
|
|||||||
Reference in New Issue
Block a user