feat(briefing): add Message.msg_metadata and RssItem.topics/classified_at columns

msg_metadata maps to the 'metadata' DB column ('metadata' is reserved
by SQLAlchemy Declarative API). to_dict() exposes the key as 'metadata'
for frontend compatibility.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-25 10:30:37 -04:00
parent 8fa850534c
commit 5665f484ed
3 changed files with 33 additions and 1 deletions
@@ -67,6 +67,9 @@ class Message(Base, CreatedAtMixin):
Integer, ForeignKey("notes.id", ondelete="SET NULL"), nullable=True
)
tool_calls: Mapped[list | None] = mapped_column(JSONB, nullable=True)
# 'metadata' is reserved by SQLAlchemy Declarative — use msg_metadata as the
# Python attribute name, mapped to the 'metadata' DB column.
msg_metadata: Mapped[dict | None] = mapped_column("metadata", JSONB, nullable=True)
conversation: Mapped["Conversation"] = relationship(back_populates="messages")
@@ -83,5 +86,6 @@ class Message(Base, CreatedAtMixin):
"status": self.status,
"context_note_id": self.context_note_id,
"tool_calls": self.tool_calls,
"metadata": self.msg_metadata,
"created_at": self.created_at.isoformat(),
}
+9 -1
View File
@@ -1,6 +1,6 @@
from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, Index, Integer, Text, UniqueConstraint
from sqlalchemy import ARRAY, DateTime, ForeignKey, Index, Integer, Text, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column, relationship
from fabledassistant.models import Base
@@ -49,6 +49,12 @@ class RssItem(Base):
fetched_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
topics: Mapped[list[str]] = mapped_column(
ARRAY(Text), nullable=False, default=list, server_default="{}"
)
classified_at: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True), nullable=True
)
feed: Mapped["RssFeed"] = relationship(back_populates="items")
@@ -67,4 +73,6 @@ class RssItem(Base):
"url": self.url,
"published_at": self.published_at.isoformat() if self.published_at else None,
"content": self.content,
"topics": self.topics or [],
"classified_at": self.classified_at.isoformat() if self.classified_at else None,
}